Can I use both Scroll-Snap and Background transition at the same time?

const observer = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
        if (entry.isIntersecting) {
            entry.target.classList.add('show');
        } else {
            entry.target.classList.remove('show');
        }
    });
});

$(window).scroll(function() {
  
    // selectors
    var $window = $(window),
        $body = $('body'),
        $panel = $('.panel');
    
    // Change 33% earlier than scroll position so colour is there when you arrive.
    var scroll = $window.scrollTop() + ($window.height() / 3);
   
    $panel.each(function () {
      var $this = $(this);
      
      // if position is within range of this panel.
      // So position of (position of top of div <= scroll position) && (position of bottom of div > scroll position).
      // Remember we set the scroll to 33% earlier in scroll var.
      if ($this.position().top <= scroll && $this.position().top + $this.height() > scroll) {
            
        // Remove all classes on body with color-
        $body.removeClass(function (index, css) {
          return (css.match (/(^|s)color-S+/g) || []).join(' ');
        });
         
        // Add class of currently active div
        $body.addClass('color-' + $(this).data('color'));
      }
    });    
    
  }).scroll();

const hiddenElements = document.querySelectorAll('.hidden');
hiddenElements.forEach((el) => observer.observe(el));
body {
    margin: 0;
    padding: 0;
    font-family: sans-serif;
    background-color: rgb(36, 164, 138);
    transition: background-color 1s ease;
}

div {
    place-items: center;
    align-content: center;
    min-height: 100vh;
    color: white;
    position: relative;
    scroll-snap-align: start;
}

.panel {
    min-height: 100vh;
    display: flex;
    justify-content: space-around;
    align-items: center;
    font-family: sans-serif;
}

main {
    scroll-snap-type: y mandatory;
    overflow-y: scroll;
    /* When I remove the height, the color transition works, but the scroll-snap breaks */
    height: 100vh;
}

.color-green {
    background-color: rgb(36, 164, 138);
}
.color-red {
    background-color: rgb(211, 79, 79);
}
.color-blue {
    background-color: rgb(67, 91, 175);
}
.color-salmon {
    background-color: lightsalmon;
}

.hidden {
    opacity: 0;
    filter: blur(5px);
    transform: translateX(-100%);
    transition: all 1s;
}

.show {
    opacity: 1;
    filter: blur(0);
    transform: translateX(0);
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS SNAP EFFECT</title>
    <link rel="stylesheet" href="styles.css">
    <script defer src="app.js"></script>
    <script
        src="https://code.jquery.com/jquery-3.7.0.js"
        integrity="sha256-JlqSTELeR4TLqP0OG9dxM7yDPqX1ox/HfgiSLBj8+kM="
        crossorigin="anonymous">
    </script>
</head>
<body>
    <main>
            <div class="panel" data-color="green">
                    <h1 class="hidden">First</h1>
            </div>
            <div class="panel" data-color="red">
                    <h1 class="hidden">Second</h1>
            </div>
            <div class="panel" data-color="blue">
                    <h1 class="hidden">Third</h1>
            </div>        
            <div class="panel" data-color="salmon">
                    <h1 class="hidden">Last</h1>
            </div>
        
    </main>
</body>
</html>

I am new to programming and this is the beginnings of what will be my biggest project so far. I want to have my website have a scroll-snap feature, and I want the background color to have a fade-transition as you scroll. I noticed that it seems like I can only have one feature at a time though.

I have found some source of the problem. Whenever I delete the height property within the main element in my css file, my background transition works but my scroll-snap doesn’t. And when I put it back, my scroll-snap works but my background doesn’t. Can someone help me to figure out a way to use both features at once?

Feedback On Code Academy’s Full-Stack Software Engineer Portfolio Project, “Mixed Messages” [closed]

I have just completed the “Mixed Messages” project in the Full-Stack Engineer career path. Our final task in the project is to post our code to the forum and solicit feedback.

Was this an efficient, viable way of completing the project? Or is there something that you would have done differently?

const noun = ['God', 'Creator', 'Great Spirit', 'Universe'];

const adjective = ['All Powerful', 'All Seeing', 'All Knowing', 'Almighty'];

let randomNoun = noun[Math.floor(Math.random() * noun.length + 1)];

let randomAdjective = adjective[Math.floor(Math.random() * adjective.length + 1)];

let message = `Our ${randomNoun} is ${randomAdjective}`;

console.log(message); 

My code worked as expected in the terminal.

how to clear url arguments in flask after using form

I currently have a form that when its submitted it redirects with all of the required parameters(see below),

My problem is that when it redirects from the form page to the results page, if I refresh the results page it re runs the logic, and I want the user to have to input the form information again before seeing new results.

javascript redirect:

document.location.href = "/results?age=" + encodeURIComponent(userage) + "&price=" + encodeURIComponent(price);

python logic:

@application.route("/results")
def get_response():
    age = request.args.get("age")
    price = request.args.get("price")
    htmltext = age+price
    return render_template("results.html",html=str(htmltext))

Reading data from a webview in adroid and storing the data in kotlin array

I am trying to create an app that takes user selections from some HTML drop downs (select tags) and stores them in the android app. I am trying to do this so I can create a autofill of sorts where users can decide what prefilled form they want to start with to save time and mitigate mistakes.

In the app I have a webview. The webview loads a webpage external to my device. I am struggling to find a way to read data from the webview. I want to be able to read and store user inputs from the webview in an array in kotlin.

I want to be able to run these java script commands but some how send the results to kotlin:


var v=document.getElementsByName("dropDownOne");

var ddO= v[0].value;



var f = document.getElementsByName("dropDownTwo");

var ddT= f[0].value;

I ran this in the chrome console and it provides me the data I need, I just need to figure out how to send this data to android.

I have tried using AndroidJSInterface but I am not able to get my head around it.

Here is my kotlin main activity class:


    object AndroidJSInterface {

        @JavascriptInterface
        fun onClicked() {
            Log.d("HelpButton", "Help button clicked")
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        val view = findViewById<WebView>(R.id.webView) as WebView
        val webViewClient = object : WebViewClient() {
            override fun onPageFinished(view: WebView, url: String) {
                loadJs(view)
            }
        }


        val webView = WebView(this)
        webView.webViewClient = webViewClient

        webView.settings.javaScriptEnabled = true
        webView.addJavascriptInterface(AndroidJSInterface, "Android")

        setContentView(webView)
        webView.loadUrl(url)

        //ensures webview is embedded and no browser with address bar can be opened
        //view.setWebViewClient(WebViewClient())
        //view.settings.javaScriptEnabled = true
        //view.loadUrl(url)

    }

    private fun loadJs(webView: WebView) {
        webView.loadUrl(
            """javascript:(function f() {
                var v=document.getElementsByName("dropDownOne");
                var ddO= v[0].value;
                
                var f = document.getElementsByName("dropDownTwo");
                var ddT= f[0].value;    
                
                alert(ddO+ " > " + ddT);
                })()"""
        )
    }

why does window.open(”); usually work as expected; but sometimes fails?

My Test Case:

  • I browse to a webpage;
  • open DevTools console;
  • and execute windows.open('');

it usually works fine and I get a new blank window.

But if I browse to [NSFW] spankbang.com and do the same; it fails.

1-2yrs ago I wrote a bookmarklet for YouTube. It grabs <meta> tags and <script type="application/json"> blocks and dumps them to a blank page. It has worked great on YouTube and a ton of other sites.
But, today I tried using it on [NSFW] spankbang.com and it fails!

This is on Windows 10 Pro using Edge.

When select option All request it change to Pending Request after display data why it clear after display data?

I work on asp.net MVC I face issue selected value All requests cleared after display result data and back to Pending Request automatically .

so my issue on selected value option if I select option All requests it display all requests success but drop down selected option change to Pending Request .

so How to solve issue selected option clear after display data

action GetSelectedDropDownChanged on controller WorkforceRequests hit and catched when make debug and detect value 1 if i select pending request and 2 if i select all request

but issue when select option All request it back to option Pending Request why and so How to prevent this behavior from happen

code details

<form action="/WorkforceRequests/GetSelectedDropDownChanged"  method="post">
            <select class="form-control" id="statusselect" name="statusselect">
                <option value="1">Pending Request</option>
                <option value="2">All requests </option>
            </select>
        </form>

on controller WorkforceRequestsController


        public async Task<ActionResult> GetSelectedDropDownChanged() //Assuming key in your dropdown is string
        {
            string selectedValue = Request.Form["statusselect"].ToString();
            List<WorkforceRequest> workforceRequest = new List<WorkforceRequest>();
            if (selectedValue == "1")
            {


          workforceRequest = Workforce.GetPendingOnPalnningSection(RoleKey.PLS);


            }
            else

                workforceRequest = Workforce.GetAllRequestsOnPalnningSection(RoleKey.PLS);

            return View(workforceRequest);

        }

Unexpected key value pairs wrapping my state when using Redux mapStateToProps

I have been working on a React Native app with Firebase and Redux for a few weeks now without any issues with respect to my Redux usage. However, while I was working on something today I began to see this strange problem that seemed to start happening for no reason I can discern.

When I login with Firebase I call a Redux action to set my user object in the store like so.

await signInWithEmailAndPassword(auth, email, pass)
  .then(async (userCredential) => {
    const user = userCredential.user;
    const token = await auth.currentUser?.getIdToken();
    props.setUser({
      id: user['uid'],
      email: user['email'],
      token: token
    });
    props.navigation.navigate('Home');
  })

Here are the corresponding action and reducer.

export const setUser = (payload: User) => (
    {
        type: 'SET_USER',
        payload: payload
    }
);
const userReducer = async (state = INITIAL_USER_STATE, action: { type: string; payload: User; }) => {
  switch (action.type) {
    default:
      return state;
    case 'SET_USER':
      alert('payload: ' + JSON.stringify(action.payload));
      state = action.payload;
      return state;
};

You’ll notice I’ve put an alert in the reducer to make sure the state is getting set how I intend (and it is).

user object

In one of my components I want access to this user object. So, I make use of connect() like so.

const mapStateToProps = (state: { user: User }) => {
  const { user } = state;
  return { user };
};


export default connect(mapStateToProps, null)(PlaidBackDrop);

In the same file I alert the user object with alert(JSON.stringify(props.user));. Here is what I get (yikes!).

what

So I can add this random _z to my code and it works again. But I really, really don’t want to do that.

const mapStateToProps = (state: { user: User }) => {
  const { user } = state;
  return { user: user['_z'] };
};


export default connect(mapStateToProps, null)(PlaidBackDrop);

To make matters worse, sometimes the state I get is different. Here are two more random sets of keys and values wrapping my object that I got without changing anything in my code.

what the heck
seriously now its nesting

So, sometimes I get the object, sometimes I get the action and sometimes I get the object wrapped in these inexplicable _x, _y and _z things.

Can someone please help? đŸ™‚

I have tried uninstalling and re-installing redux and react-redux. I have tried re-building my app. I have tried restarting my laptop. I have tried simplifying my reducer, getting rid of the async call to auth.currentUser?.getIdToken() on the login page and just indexing like user: user['_z']['_z']['_z'].

Passing jinja variable to external JS

Sorry if duplicate. But couldn’t find it, besides doing some workaround calling functions etc. Is there any straight forward method nowadays? If so, how to do that? Thanks!

It works normally if I use {{ var }} inside the script tag in html, but if I import the js file, it won’t work.

MeteorJS Session Object

I lately dived into MeteorJS.

I tried using the Session object once to make a simple todo list but when using methods such as Session.get() or Session.set() it doesn’t work. When calling the Session object in the console by itself, it gives an error of Session is not defined

So is it still working and I am implementing it wrong or has the Session object been replaced with something else, perhaps the ReactiveVar. Thank you.

RTK query – Query lazyload and cache data append problem

I’m facing problem while trying to append a cached data with a new data in rtk query. The api is paginated and I want to append the data with the previous data.

If I hardcode the query

    loadPosts: builder.query<DefaultResponse<FetchedPostDataType[]>, undefined>(
      {
        query: () => ({
          url: '/diary/648391e4838df5201b4e85e8/all-posts',
          method: 'GET',
          params: {
            page: 1,
          },
        }),

        providesTags: ['DiaryFeed'],
      },
    ),

like this only then I can update it’s cache using

 loadPaginatedPosts: builder.query<
      DefaultResponse<FetchedPostDataType[]>,
      {
        diaryId: string;
        page: number;
      }
    >({
      query: ({diaryId, page}: {diaryId: string; page: number}) => ({
        // query: page => ({
        // url: '/diary/648391e4838df5201b4e85e8/all-posts',
        url: `/diary/${diaryId}/all-posts`,
        method: 'GET',
        params: {
          page: page,
        },
      }),

      onQueryStarted: async (arg, {dispatch, queryFulfilled}) => {
        try {
          const {data} = await queryFulfilled;

          dispatch(
            diaryApiSlice.util.updateQueryData('loadPosts', arg, draft => {
              draft.data.push(...data.data);
            }),
          );
        } catch (error) {
          console.log('error', error);
        }
      },
    }),

But if it’s dynamic and has arg like this

    loadPosts: builder.query<
      DefaultResponse<FetchedPostDataType[]>,
      {
        diaryId: string;
        page: number;
      }
    >({
      query: ({diaryId, page}: {diaryId: string; page: number}) => ({
        url: `/diary/${diaryId}/all-posts`,
        method: 'GET',
        params: {
          page: page,
        },
      }),

      providesTags: ['DiaryFeed'],
    }),

then it doesn’t work anymore.

I also tried

   providesTags: (result, error, {diaryId, page}) => {
     return [{type: 'DiaryFeed', diaryId, page}];
   },

Tried dispatching the updateQueryData using args and even with hardcoded arg

    dispatch(
            diaryApiSlice.util.updateQueryData(
              'loadPosts',
              {diaryId: arg.diaryId, page: arg.page}, // also tried by giving hardcoded page number
              draft => {
                draft.data.push(...data.data);
              },
            ),
          );

I’m not understanding the cache mechanism of RTK query even after going through the documentation. It’ll be a great if anyone can help me with it?

Thanks in advance!

How to disable VSCode’s tab highlighting for files with problems?

When a file in VSCode has problems in it (e.g. unreachable code), the title of it’s tab turns orange/yellow, which overwrites git’s highlighting (that signalizes modified or new file).

I want to disable this. I tried about every setting I could find, but none changes the tab’s appearance when there are problems in it. There is a setting for errors, but not for problems.

A screenshot of a file that has a problem in it, and it’s tab’s title is orange

An example screenshot of normal git highlighting

Cannot position two D3 charts side by side using CSS Grid

I’ve created two charts using Javascript and D3 and I’m trying to position them side by side (horizontally). To achieve this I’m using CSS Grid and I’ve housed both charts (#mainChart) and (#barChart) inside a container class “.grid-container”. Whilst barChart is displayed on the right hand side of the container (as expected), mainChart is displayed underneath the container (on the left side). I’m struggling to position mainChart inside the container (still on the left side). I’ve tried using Flexbox and got the exact same problem, which tells me it’s not the CSS tool that is the problem.

<!DOCTYPE html>
<html>
<head>
  <script src="https://d3js.org/d3.v7.min.js"></script>
  <link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap" rel="stylesheet">

  <style>
    body {
      max-width: 1000px; /* Set the maximum width of the page */
      margin: 0 auto; /* Center the page horizontally */
      padding: 20px; /* Add padding to the content */
      background-color: lightblue;
    }

    svg {
      font-family: "Lato", sans-serif;
    }

    .grid-container {
      display: grid;
      grid-template-columns: 1fr 1fr; /* Two columns with equal width */
      border: 5px solid blue;

    }

    #mainChart {
      border: 5px solid green;
    }

    #barChart {
      border: 5px solid rgb(255, 0, 0);
    }
  </style>
</head>
<body>
  <div class="grid-container">
    <div id="mainChart"></div>
    <div id="barChart"></div>
  </div>

  <script src="main.js"></script>
  <script src="year_bar.js"></script>

</body>
</html>

main.js (JS/D3 for creating the mainChart)

// Define SVG dimensions and margins
const svgWidth = 500;
const svgHeight = 130;
const margin = { top: 70, right: 10, bottom: 30, left: 250 };
const height = svgHeight - margin.top - margin.bottom;
const width = svgWidth - margin.left - margin.right;

// Add the SVG to the body
let svg = d3
  .select("body")
  .append("svg")
  .attr("width", svgWidth)
  .attr("height", svgHeight * 5)
  .attr("id", "mainChart")

// Initialize the selected label index
let selectedLabelIndex = -1;

function createStrandKDEPlot(dataFileName, index, color, label, opacity) {
  // Load data from CSV
  d3.csv(dataFileName).then((data) => {
    // Convert strings to numbers
    data.forEach((d) => {
      d.effect_size = +d.effect_size;
      d.frequency = +d.frequency;
    });

    // Set initial data points to zero
    const initialData = data.map((d) => ({
      effect_size: d.effect_size,
      frequency: 0,
    }));

    const xScale = d3.scaleLinear().domain([-4, 4]).range([0, width]);
    const yScale = d3.scaleLinear().domain([0, d3.max(data, (d) => d.frequency)]).range([height, 0]);

    // Define the line for the initial flat curve
    const initialLine = d3
      .line()
      .curve(d3.curveBasis)
      .x((d) => xScale(d.effect_size))
      .y((d) => yScale(0)); // Change y-value to 0 for initial flat curve

    // Define the line for the animated curve
    const animatedLine = d3
      .line()
      .curve(d3.curveBasis)
      .x((d) => xScale(d.effect_size))
      .y((d) => yScale(d.frequency));

    // Define the area under the curve
    const area = d3
      .area()
      .curve(d3.curveBasis)
      .x((d) => xScale(d.effect_size))
      .y1((d) => yScale(d.frequency))
      .y0(yScale(0));

    // Add a group for each plot
    const g = svg
      .append("g")
      .attr(
        "transform",
        `translate(${margin.left - 30}, ${index * (svgHeight - 110) + margin.top})`
      );

    // Draw the curve border line
    g.append("path")
      .datum(data)
      .attr("fill", "none")
      .attr("stroke", "#5A5A5A")
      .attr("stroke-width", 1)
      .attr("d", initialLine);

    // Define the area under the curve for the initial flat curve
    const initialArea = d3
      .area()
      .curve(d3.curveBasis)
      .x((d) => xScale(d.effect_size))
      .y1((d) => yScale(0))
      .y0(yScale(0));

    // Add the initial flat curve area
    g.append("path")
      .datum(initialData)
      .attr("fill", "none") // Set fill to none
      .attr("d", initialArea);

    // Transition the area under the curve
    g.select("path")
      .transition()
      .duration(500) // Set the duration of the transition
      .attr("fill", color) // Set the fill color
      .attr("d", area);

    // Draw the area under the curve with the specified color and opacity
    g.append("path")
      .datum(initialData) // Use initialData instead of data for initial flat curve
      .style("fill", color)
      .style("opacity", opacity) // Set the opacity
      .attr("stroke", color) // Set the stroke color
      .attr("d", area);

    // Animate the curve and label after a time delay
    setTimeout(() => {
      g.selectAll("path")
        .transition()
        .duration(1000) // Set the duration of the transition
        .ease(d3.easeQuad) // Set the easing function for the transition
        .attr("d", animatedLine); // Transition the curve from initial flat curve to the actual curve

      textLabel.transition().duration(250).attr("opacity", 1);
      circle.transition().duration(250).attr("opacity", 1);
    }, index * 0); // Adjust the delay duration as per your preference

    // Add the text label
    const textLabel = g
      .append("text")
      .attr("x", -margin.left / 12)
      .attr("y", height / 1)
      .attr("text-anchor", "end")
      .attr("alignment-baseline", "middle")
      .style("font-size", "12px")
      .attr("opacity", 0)
      .text(label)
      .classed("text-label", true); // Add class for text label

    const circle = g
      .append("circle")
      .attr("cx", -margin.left / 25) // Adjust the position of the circle
      .attr("cy", height / 1)
      .attr("r", 4) // Set the radius of the circle
      .style("fill", color)
      .attr("opacity", 0);

    // Draw the curve border line
    g.append("path")
      .datum(data)
      .attr("fill", "none")
      .attr("stroke", "#5A5A5A")
      .attr("stroke-width", 1)
      .attr("d", initialLine)
      .classed("curve-outline", true) // Add class for curve outline
      .attr("id", `curve-outline-${index}`); // Add id for each curve outline

    // Get the bounding box of the text label
    const labelBBox = textLabel.node().getBBox();

    // Add a background rectangle behind the text label
    const labelBackground = g
      .insert("rect", "text") // Insert before the text label
      .attr("x", labelBBox.x - 4)
      .attr("y", labelBBox.y - 2)
      .attr("width", labelBBox.width + 8)
      .attr("height", labelBBox.height + 4)
      .attr("rx", 2)
      .attr("ry", 2)
      .style("fill", "none")
      .classed("label-background", true); // Add a class for the background rectangle

    // Add event listeners for hover and click
    textLabel.on("mouseenter", function () {
      if (index !== selectedLabelIndex) {
        labelBackground.style("fill", "black");
        textLabel.style("fill", "white");
        g.select("path")
          .style("stroke", "#5A5A5A") // Set the border color of the curve to black
          .style("stroke-width", 3);

        svg.style("cursor", "pointer"); // Change the cursor style to "pointer"
      }
    });

    textLabel.on("mouseleave", function () {
      if (index !== selectedLabelIndex) {
        labelBackground.style("fill", "none");
        textLabel.style("fill", "black");
        g.select("path")
          .style("stroke", "#5A5A5A") // Revert the border color of the curve to the original color
          .style("stroke-width", 1);
      }

      svg.style("cursor", "auto"); // Revert the cursor style to the default value
    });

    let selectedCurveOutlines = {};

    textLabel.on("click", function () {
      if (selectedLabelIndex !== index) {
        // Remove black background from previously selected label
        svg.selectAll(".label-background").style("fill", "none");
        svg.selectAll(".text-label").style("fill", "black");

        // Revert the previously selected curve outline to default stroke width
        if (selectedCurveOutlines[selectedLabelIndex]) {
          selectedCurveOutlines[selectedLabelIndex].style("stroke-width", 1);
        }

        // Set black background for the clicked label
        labelBackground.style("fill", "black");
        textLabel.style("fill", "white");

        // Set the border color and width of the curve outline for the clicked label
        const curveOutline = g.select("path");
        curveOutline
          .style("stroke", "#5A5A5A") // Set the border color of the curve to black
          .style("stroke-width", 1);

        // Update the selected label index and curve outline
        selectedLabelIndex = index;
        selectedCurveOutlines[selectedLabelIndex] = curveOutline;

        if (selectedLabelIndex === 0) {
          // Load new data from CSV (replace "ry_year_bar.csv" with the path to your new data file)
          d3.csv("ry_year_bar.csv").then(yearBarData => {
            // Update the existing chart with the new data
            const container = document.getElementById("barChart");
            container.innerHTML = ""; // Clear the chart container
            const chart = createYearBarChart(yearBarData, "steelblue", 13); // Manually set the maximum value to 13
            container.appendChild(chart.svg.node());
          });
        } else if (selectedLabelIndex === 1) {
          // Load data from "sets.csv"
          d3.csv("sets_year_bar.csv").then(setsData => {
            // Update the existing chart with the sets data
            const container = document.getElementById("barChart");
            container.innerHTML = ""; // Clear the chart container
            const chart = createYearBarChart(setsData, "steelblue", 30);
            container.appendChild(chart.svg.node());
          });
        } else if (selectedLabelIndex === 2) {
          // Load data from "sets.csv"
          d3.csv("rc_year_bar.csv").then(setsData => {
            // Update the existing chart with the sets data
            const container = document.getElementById("barChart");
            container.innerHTML = ""; // Clear the chart container
            const chart = createYearBarChart(setsData, "steelblue", 50);
            container.appendChild(chart.svg.node());
          });
        } else {
          // Load the default data from CSV (replace "alphabet.csv" with the path to your default data file)
          d3.csv("alphabet.csv").then(defaultData => {
            // Update the existing chart with the default data
            const container = document.getElementById("barChart");
            container.innerHTML = ""; // Clear the chart container
            const chart = createYearBarChart(defaultData, "steelblue", 42);
            container.appendChild(chart.svg.node());
          });
        }
      }
    });

    labelBackground.on("click", function () {
      if (selectedLabelIndex !== index) {
        // Remove black background from previously selected label
        svg.selectAll(".label-background").style("fill", "none");

        // Set black background for the clicked label
        labelBackground.style("fill", "black");

        // Update the selected label index
        selectedLabelIndex = index;

        // Rest of your code...
      }
    });

    // Add the x-axis line with ticks and numbers
    const xAxis = d3.axisBottom(xScale);
    const xAxisGroup = svg
      .append("g")
      .attr(
        "transform",
        `translate(${margin.left - 20}, ${svgHeight - margin.bottom + 480})`
      ) // Adjust the y-coordinate value here
      .call(xAxis);

    // Modify the stroke color of the x-axis line
    xAxisGroup.select(".domain").attr("stroke", "#5A5A5A");
  });
}

// Array of data file names
let dataFileNames = [
  "ry.csv",
  "ss.csv",
  "rc.csv",
  "m.csv",
  "pp.csv",
  "ap.csv",
  "pa.csv",
  "sgt.csv",
  "ii.csv",
  "bi.csv",
  "est.csv",
  "ss.csv",
  "fb.csv",
  "ol.csv",
  "pt.csv",
  "sel.csv",
  "pe.csv",
  "ml.csv",
  "cl.csv",
  "ph.csv",
  "hw.csv",
  "one_one.csv",
  "ta.csv",
  "rc.csv",
  "msr.csv",
];

let colors = [
  "#ff0000", // Red
  "#ff3300",
  "#ff6600",
  "#ff9900",
  "#ffcc00",
  "#ffef00",
  "#ccff00", // Yellow-Green
  "#99ff00",
  "#66ff00",
  "#33ff00",
  "#00ff00", // Green
  "#00ff33",
  "#00ff66",
  "#00ff99",
  "#00ffcc",
  "#00ffff", // Cyan
  "#00ccff",
  "#0099ff",
  "#0066ff",
  "#0033ff",
  "#0000ff", // Blue
  "#3300ff",
  "#6600ff",
  "#9900ff",
  "#cc00ff",
  "#ff00ff", // Magenta
];

let labels = [
  "Repeating a Year",
  "Setting/Streaming",
  "Reading Comprehension",
  "Mentoring",
  "Performance Pay",
  "Arts Participation",
  "Physical Activity",
  "Small Group Tuition",
  "Individualised Instruction",
  "Behavior Interventions",
  "Earlier Starting Time",
  "Summer Schools",
  "Feedback",
  "Oral Language",
  "Peer Tutoring",
  "Social & Emotional Learning",
  "Parental Engagement",
  "Mastery Learning",
  "Collaborative Learning",
  "Phonics",
  "Homework",
  "One to One",
  "Teaching Assistants",
  "Reading Comprehension",
  "Metacognition & Self-Regulation",
];

// Define x and y scales
const xScale = d3.scaleLinear().domain([-4, 4]).range([0, width]);
const yScale = d3.scaleLinear().domain([0, 1]).range([height, 0]);

// Initialize a delay counter
let delay = 0;

// Reverse the dataFileNames array to start with the first plot at the top
dataFileNames.reverse().forEach((fileName, index) => {
  const opacity = 0.8; // Set the desired opacity value

  // Use setTimeout to introduce a time delay between each plot rendering
  setTimeout(() => {
    createStrandKDEPlot(fileName, index, colors[index], labels[index], opacity);
  }, delay);

  // Increment the delay counter
  delay += 50; // Adjust the delay duration as per your preference
});

year_bar.js (JS/D3 for creating barChart)

function createYearBarChart(data, color, maxYValue) {
    // Specify the chart’s dimensions.
    const width = 500;
    const height = 300;
    const marginTop = 20;
    const marginRight = 20;
    const marginBottom = 30;
    const marginLeft = 40;
  
    // Declare the x (horizontal position) scale and the corresponding axis generator.
    const x = d3
      .scaleBand()
      .domain(data.map((d) => d.letter))
      .range([marginLeft, width - marginRight])
      .paddingInner(0.2)
      .paddingOuter(0.2);
  
    const xAxis = d3.axisBottom(x).tickSizeOuter(0);
  
    // Declare the y (vertical position) scale.
    const y = d3.scaleLinear().range([height - marginBottom, marginTop]);
  
    // Adjust the y-axis tick format
    const yAxis = d3.axisLeft(y).tickFormat((y) => y.toFixed());
  
    // Create the SVG container.
    const svg = d3
      .create("svg")
      .attr("viewBox", [0, 0, width, height])
      .style("background-color", "green");
  
    // Create a group for the bars.
    const barsGroup = svg.append("g");
  
    // Create the axes.
    const gx = svg
      .append("g")
      .attr("transform", `translate(0,${height - marginBottom})`)
      .call(xAxis)
      .selectAll("text")
      .attr("transform", "rotate(-45)")
      .style("text-anchor", "end")
      .attr("dx", "-0.5em")
      .attr("dy", "0.5em");
  
    const gy = svg.append("g").attr("transform", `translate(${marginLeft},0)`).call(yAxis);
  
    // Function to update the chart with new data
    function update(newData) {
      // Update the domain of the y-scale with the new data
        // Update the domain of the y-scale with the fixed maxYValue
        y.domain([0, maxYValue]).nice();
  
      const bars = barsGroup.selectAll("rect").data(newData);
  
      bars
        .enter()
        .append("rect")
        .attr("x", (d) => x(d.letter))
        .attr("width", x.bandwidth())
        .attr("y", y(0))
        .attr("height", 0)
        .attr("fill", color)
        .merge(bars)
        .transition()
        .duration(500)
        .attr("y", (d) => y(d.frequency))
        .attr("height", (d) => y(0) - y(d.frequency));
  
    bars.exit().remove();
  
    gx.transition().duration(500).call(xAxis);
    gy.transition().duration(500).call(yAxis);
    
    // Update the SVG viewbox with the new dimensions
    svg.attr("viewBox", [0, 0, width, height]);
  }
  
    // Initial chart rendering
    update(data);
  
    // Return the chart with the update method
    return {
      svg,
      update,
    };
  }
  
  // Load the initial data (alphabet.csv in this case)
  d3.csv("alphabet.csv").then((data) => {
    // Create the chart with the initial data and color
    const yearBarChart = createYearBarChart(data, "red", 42);
  
    // Append the chart's SVG to the barChartContainer div
    const container = document.getElementById("barChart");
    container.appendChild(yearBarChart.svg.node());
  
    // Add click event listeners to the text elements
    const textLabels = document.querySelectorAll(".text-label");
    textLabels.forEach((label, index) => {
      label.addEventListener("click", () => handleTextClick(index));
    });

  });
  

Any help is appreciated.

Lambda DynamoDocument isn’t unmarshalling results

I have a lambda function to fetch some records from DynamoDB. I setup a ddbDocClient like in the AWS docs. I have a ddbDocClient.js file like this:

const { DynamoDBDocumentClient } = require("@aws-sdk/lib-dynamodb");
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");

const REGION = "us-west-2"

const ddbClient = new DynamoDBClient({ region: REGION });

const marshallOptions = {
    convertEmptyValues: false, // false, by default.
    removeUndefinedValues: false, // false, by default.
    convertClassInstanceToMap: false, // false, by default.
};

const unmarshallOptions = {
    wrapNumbers: false, // false, by default.
};

const translateConfig = { marshallOptions, unmarshallOptions };

const ddbDocClient = DynamoDBDocumentClient.from(ddbClient, translateConfig);

module.exports.ddbDocClient = ddbDocClient;

Then I use it to fetch some records:

const { ddbDocClient } = require("./ddbDocClient.js");
const { QueryCommand } = require("@aws-sdk/client-dynamodb");

const listsTableName = "my_list_name";

/// Fetches lists owned by the current user
async function getListIDs(userid) {

    const params = {
        TableName: listsTableName,
        IndexName: 'owner-index',
        KeyConditionExpression: '#owner = :owner',
        ExpressionAttributeNames: { "#owner": "owner" },
        ExpressionAttributeValues: {":owner": { "S": userid }}
    };
    const command = new QueryCommand(params);

    const dynamoData = await ddbDocClient.send(command);
    const lists = dynamoData.Items;
    console.log(lists);
}

The results I get back are like this:

[
  {
    things: { SS: [Array] },
    owner: { S: '0d5e789b-009b-4ba0-80a7-12065d0908b5' },
    collaborator: { S: 'A845E8EF-956B-467D-B57B-6D959BB78C98' },
    id: { S: '0C629140-6651-43E9-8D9F-3E52EBAD94F3' }
  },
  {
    owner: { S: '0d5e789b-009b-4ba0-80a7-12065d0908b5' },
    things: { SS: [Array] },
    collaborator: { S: 'ttttt' },
    id: { S: 'xxxxx89b-009b-4ba0-80a7-12065d0908b5' }
  }
]

I’m pretty sure the Document classes are supposed to unmarshall this, or am I wrong? It even mentions middleware you can use before and after marshalling.

I am having to manually unmarshall which needs extra steps to convert the SS Set‘s to Array‘s like this:

const lists = dynamoData.Items;

// From DynamoDB JSON
var unmarshalledLists = lists.map((i) => unmarshall(i));

if (unmarshalledLists.length > 0) {
    // If we have at least 1 list we need to convert the things Set to Array
    unmarshalledLists.forEach(function(list) {
        const things = Array.from(list.things);
        list.things = things;
    });
    return unmarshalledLists;
} else {
    // No results to return
    throw("No lists found");
}

What am I doing wrong to not have it unmarshall automatically? And it there a cleaner solution for converting the SS results to Array‘s?

Insert an element (tag) on a Page with Playwright

What is the correct way to insert a <style> tag into a Page using Playwright:

private void insertStyleBeforeElement(Page page, ElementHandle element, String cssContent) {
        String js = "(element, cssContent) => {" +
                "    if (!element) {" +
                "        console.log('Element is null or undefined');" +
                "        return;" +
                "    }" +
                "    console.log('Element:', element);" +
                "    let styleElem = document.createElement('style');" +
                "    styleElem.type = 'text/css';" +
                "    styleElem.innerHTML = cssContent;" +
                "    element.parentNode.insertBefore(styleElem, element);" +
                "}";
        page.evaluate(js, Arrays.asList(element, cssContent));
    }

This method throws:

com.microsoft.playwright.PlaywrightException: Error {
  message='element.parentNode is undefined
@debugger eval code line 191 > eval:1:280
evaluate@debugger eval code:198:19
@debugger eval code:1:44

  name='Error
  stack='Error: element.parentNode is undefined
@debugger eval code line 191 > eval:1:280

Though, when I check the debugger there is a parent node.

enter image description here