Making a Tile Follow Another Tile in Phaser 3

This is more of a logic question than a Phaser 3 question. I am trying to make the game ‘snake’. I can move 1 body up, down, left, and right easily, however, I do have issues when there is more than 1 body of ‘snake’. In snake, when the front of a snake switches directions, the others follow suit in such a way so that they stay behind the snake. I cannot seem to figure out how to do this- changing the direction respectively for all of the ‘other’ bodies behind the ‘snake’. In short, this is basically one sprite following another sprite. I would appreciate some help on this. Here is my code so far:

create() {
    this.snake = this.physics.add.group()
    this.front = this.snake.create(25,25,"tile").setScale(0.12)
}

This is where I create my snake, as well as the ‘front’ of the snake.

 update() {
    this.cursors = this.input.keyboard.createCursorKeys()
    if (this.cursors.right.isDown) {
        this.x_vel = this.vel
        this.y_vel = 0
        this.DIRECTION = "right"
    } if (this.cursors.left.isDown) {
        this.x_vel = -this.vel
        this.y_vel = 0
        this.DIRECTION = "left"
    } if (this.cursors.up.isDown) {
        this.x_vel = 0
        this.y_vel = -this.vel
        this.DIRECTION = "up"
    } if (this.cursors.down.isDown) {
        this.x_vel = 0
        this.y_vel = this.vel
        this.DIRECTION = "down"
    }
    this.front.x += this.x_vel
    this.front.y += this.y_vel

}

This is how I will move my snake. I am only moving the ‘front’ of the snake because I want all of the other snake ‘bodies’ to follow the ‘front’ of the snake.

I have tried looking at other snake projects, especially those on phaser discussions and on medium, but they don’t go over the details that much and I have trouble following their code.

In short, I would appreciate any hints or pointers you’d give me. Thanks in advance.

scanner.nextInt() not reading the input?

I have a loop where the user needs to enter an integer between 0 and 19, and if the number is indeed between 0 and 19, a number from an array is written. If it is not, the program ends. However, the nextInt does not work when the loop starts for the first time.





import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    int inputNum, num1, num2, done;
    int[] fiboArray;

    fiboArray = new int[20];

    Scanner kb = new Scanner(System.in);
    System.out.println("Enter an integer between 0 and 19: ");
    inputNum = kb.nextInt();

    num1 = 0;
    num2 = 1;

    fiboArray[0] = num1;
    fiboArray[1] = num2;
    for (int i = 2; i < 20; ++i) {
      fiboArray[i] =  num1 + num2;
      num2 = fiboArray[i];
      num1 = fiboArray[i-1];
    }

    done = 0;
    while (done == 0) {
      System.out.println("Enter an integer between 0 and 19: ");
      inputNum = kb.nextInt();

      System.out.println("test");
      
      if (inputNum > 19 || inputNum < 0) {
        done = 1;
      }
      else
        System.out.println(fiboArray[inputNum]);
      }
  }
}

It doesnt even print test. The loop just restarts and asks the user to write an input again. After that the program works as intended.

How do I get it to work at first time? What is the problem here?

Node v20.11.1 mjs Addressing path error “is not supported resolving ES modules imported”

I want to figure out how the ESM module finds dependencies in nodejs.

For example, I have an test.mjs file

import value from 'test-a'

console.log(value)

‘test-a’ It is a nodeModule dependency package.

test-a has such a directory

  • index.js
  • package.json
// test-a/index.js
module.exports = {
  name: 'Jack'
}
// test-a/package.json
{
  // ...
  "main": "index.js"
}

When I execute test.mjs get { name: ‘Jack’ }, this is expected, as a main field was declared in test-a package.json.

But when I have another deep directory in test-a, For example, this structure

test-a

  • deep
    • pacakge.json
    • index.js
  • index.js
  • pacakge.json
// test-a/deep/index.js
module.exports = {
  value: 'deep'
}
// test-a/deep/package.json
{
  // ...
  "main": "index.js"
}

When I modify the content of file test.mjs:

import value from 'test-a/deep'

console.log(value)

got [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import xxx is not supported resolving ES modules imported from ...

I have clearly declared the main field of the deep/package.json file in the nested directory.
Why does this problem occur in the nested directory?

when i used commonjs module in test.js(require), everything seemed normal again.

I wanted to understand what was happening in the ESM.

I checked the relevant documentation and couldn’t find the description of nested directories under ESM

multiple vimeo video in multiple modals

I have several popup modals each with it’s own video in autoplay.

Each popups work and close correctly and video autoplays but when I click on the second one, the first one autoplays in the background and the second one doesn’t autoplay.

Not sure what I am doing wrong. I have been working on it at:Codepen example

// Get the button that opens the modal
var btn = document.querySelectorAll("a.modal-button");

// All page modals
var modals = document.querySelectorAll(".modal");

// Get the <span> element that closes the modal
var spans = document.querySelectorAll(".close");


// When the user clicks the button, open the modal
let iframe = document.querySelector('iframe');
let player = new Vimeo.Player(iframe);

for (var i = 0; i < btn.length; i++) {
  btn[i].onclick = function (e) {
    e.preventDefault();
    modal = document.querySelector(e.target.getAttribute("href"));
    modal.style.display = "block";
        player.play();
  };
}

// When the user clicks on <span> (x), close the modal
for (var i = 0; i < spans.length; i++) {
  spans[i].onclick = function () {
    for (var index in modals) {
      if (typeof modals[index].style !== "undefined")
        modals[index].style.display = "none";
        player.pause();     
    }
  };
}

// When the user clicks anywhere outside of the modal, close it
window.onclick = function (event) {
  if (event.target.classList.contains("modal")) {
    for (var index in modals) {
      if (typeof modals[index].style !== "undefined")
        modals[index].style.display = "none";
                player.pause();
    }
  }
};
.modal {
    display: none;
    padding-top: 100px;
    overflow: auto;
    background-color: rgb(0, 0, 0);
    background-color: rgba(0, 0, 0, 0.4);
    margin-bottom: auto;
    padding: 40px;
    border-radius: 8px;
    position: fixed;
    z-index: 9999999;
}
.modal-content {
    background-color: #fff;
    padding: 1rem;
    border: 1px solid #333;
    padding: 40px;
    border-radius: 8px;
    display: flex;
        align-items: center;
        justify-content: center;
        margin: auto;
}

.close {
    position: absolute;
    right: 0;
    top: 0;
    transform: rotate(-45deg);
    font-size: 28px;
    font-weight: bold;
}

iframe {
      width: 100%;
    height: 100%;
}
<script src="https://player.vimeo.com/api/player.js"></script>

<div class="modal" id="modal1">
    <div class="modal-content">
  <iframe src="https://player.vimeo.com/video/1053959997?title=0&amp;byline=0&amp;portrait=0&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" width="1080" height="1620" frameborder="0" allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media" title="long - dynamic content"></iframe>
  </div>
</div>

<div class="modal" id="modal2">
  <div class="modal-content">
  <iframe src="https://player.vimeo.com/video/1054046699?title=0&amp;byline=0&amp;portrait=0&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" width="1080" height="1620" frameborder="0" allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media" title="long - dynamic content"></iframe>
  </div>
</div>

<a href="#modal1" class="modal-button">modal 1</a>

<a href="#modal2" class="modal-button">modal 2</a>

Front-end looking for back-end. Partner up on projects

I’m a designer / frontend dev that wants to partner with a backend dev on a few projects to get myself back up to speed whilst creating some sites/apps that can make money. I’m open to project ideas and have a few of my own. The first idea is to make a simple calculator app and collect leads for lawyers. Those leads can be very profitable. This would be a 50/50 partnership with us both contributing equal time and effort. I’m happy to discuss any other ideas to make money as well. Thanks in advance.

I’ve built webistes, apps and founded startups in the past with varying success. I had hoped I would have found a true partner by now but remote locations and the need to break and take high paying jobs has gotten in the way.

how do I add my Xbox account to my computer

my computer shows that it is blocked but I want every thing to be unblocked.

I try Xbox.com PlayStation.com but it didn’t work,and I was expecting it to be not blocked but it was blocked and I wanted to play fornite and all of the games but the it showed that it was blocked.

Saving the state of a Shiny application with multiple tabs

I have a shiny app with multiple tabs where I need to upload a data from a .xlsx file. After the file is uploaded, “n” number of tabs are displayed depending on the number of worksheets (n) in excel. In each tab, you can plot the x value and multiple y values depending on the worksheet you select
Here is the sample app and the sample excel data (save_state_data.xlsx) to upload
https://filebin.net/9a9miurr5iwytjc4/save_state_data.xlsx

I opened the app in a browser, plotted the graphs and saved as complete html webpage, it still does not render the state properly. What is the best way to do it? Maybe bookmarks – but I am not sure how to use them for multi tabs and an excel file upload

Create a function for a stacked plot

plotly_stacked <- function(df, x_colName, cols){
      
      DF <- df[, cols] %>%
        tidyr::gather(variable, value, -x_colName ) %>%
        transform(id = as.integer(factor(variable)))
    
      DF$variable<- factor( DF$variable, levels = unique( DF$variable))
      
      p <- plot_ly(data = DF, x = ~get(names(DF[1])) , y = ~value, color = ~variable, colors = "Dark2",
                   yaxis = ~paste0( "y",sort(id, decreasing = F))) %>%
        
        add_lines() %>%
        layout(
         xaxis = list(
           title = ""), 
          legend = list(
                  orientation = "h",   
                  xanchor = "center",  
                  x = 0.5)) %>%
        plotly::subplot(nrows = length(unique(DF$variable)), shareX = TRUE)
      
      return(p)
    }

app.R

# Set maximum request size
options(shiny.maxRequestSize = 30 * 1024^2)

# Load required libraries
library(DT)
library(plotly)
library(shiny)
library(data.table)
library(readr)
library(openxlsx)
library(readxl)
library(tidyverse)
library(corrplot)
library(corrr)
library(psych)

# UI ------------------------------------------------------------
ui <- fluidPage(
  titlePanel(title = "Data"),
  fileInput("file", "Choose .xlsx file", accept = c(".xlsx")),
  mainPanel(
    tabsetPanel(id = "tabsetPanelID")
  )
)

# Server ------------------------------------------------------------
server <- function(input, output, session) {
  
  # UI Elements ------------------------------------------------------------
  ui_elementsUI <- function(x, y, data) {
    tagList(
      h4("Select X and Y datasets"),
      fluidRow(
        column(12, selectizeInput(inputId = x, label = "X data", choices = names(data)))
      ),
      fluidRow(
        column(12, selectizeInput(inputId = y, label = "Y data", choices = names(data), multiple = TRUE, selected = names(data)[3]))
      )
    )
  }

  # Sheet Elements ------------------------------------------------------------
  sheet_elementsUI <- function(sheet) {
    tagList(
      fluidRow(
        column(12, selectInput(inputId = sheet, label = "Sheet", choices = excel_sheets(input$file$datapath)))
      )
    )
  }

  # Render Sheet Elements after File Upload ------------------------------------
  n <- reactive({
    req(input$file)
    length(excel_sheets(input$file$datapath))
  })

  observe({
    lapply(1:n(), function(val) {
      output[[paste0("sheet_elements", val)]] <- renderUI({
        sheet_elementsUI(paste0("sheet", val))
      })

      output[[paste0("ui_elements", val)]] <- renderUI({
        ui_elementsUI(paste0("x", val), paste0("y", val), data_list()[[val]]())
      })

      output[[paste0("plot", val)]] <- renderPlotly({
        plot_render()(paste0("x", val), paste0("y", val), data_list()[[val]]())
      })
    })
  })

  # Plot Rendering ------------------------------------------------------------
  plot_render <- reactive({
    validate(
      need(input$file != "", "Plots will display after choosing the .xlsx file.")
    )
    function(x, y, data) {
      labels <- c("xy", paste0("xy", 2:length(input[[y]])))
      labels_json <- jsonlite::toJSON(labels)

      js_code <- sprintf(
        'function(el, x){el.on("plotly_hover", function(d) {
            Plotly.Fx.hover(el.id, {xval: d.xvals[0]}, %s);
          })}',
        labels_json
      )

      plotly_stacked(df = data, x_colName = input[[x]], cols = c(input[[x]], input[[y]])) %>%
        layout(hovermode = "x") %>%
        htmlwidgets::onRender(js_code)
    }
  })

  # Data Processing Function ---------------------------------------------------
  foo <- function(sheet) {
    df <- read_xlsx(input$file$datapath, sheet = input[[sheet]], na = "empty")
    n <- which(!is.na(as.numeric(df[[1]])))[1]
    df[is.na(df)] <- " "
    colnames(df) <- apply(df[1:(n - 1), ], 2, paste, collapse = ",")
    df <- df[-c(1:(n - 1)), ]
    names(df)[1] <- "Time"
    df[, 2:ncol(df)] <- apply(df[, 2:ncol(df)], 2, as.numeric)
    
    if (class(df[[1]])[1] != "POSIXct") {
      df$Time <- as.POSIXct(as.numeric(df$Time) * 86400, origin = "1899-12-30", tz = "UTC")
    }
    
    return(df)
  }

  # Generate Reactive Datasets -------------------------------------------------
  generate_data <- function(sheet_name) {
    reactive({
      req(input$file)
      foo(sheet_name)
    })
  }

  data_list <- reactive({
    lapply(paste0("sheet", 1:n()), generate_data)
  })

  # Generate Tabs --------------------------------------------------------------
  generateTabUI <- function(tab_id) {
    tab_name <- paste("Tab", tab_id)
    plot_output <- plotlyOutput(paste("plot", tab_id, sep = ""))
    ui_elements <- uiOutput(paste("ui_elements", tab_id, sep = ""))
    sheet_elements <- uiOutput(paste("sheet_elements", tab_id, sep = ""))

    tabPanel(tab_name, value = tab_id, sheet_elements, ui_elements, plot_output)
  }

  observe({
    for (i in 1:n()) {
      insertTab(
        inputId = "tabsetPanelID",
        tab = generateTabUI(i)
      )
    }
  })
}

# Run the Shiny App -----------------------------------------------------------
shinyApp(ui = ui, server = server)

Select2 Drop downs not loading in multi-modals django page

I have an issue with a Django front I’m trying to implement. I’m using select2 to show dropdown menus in which I can search in. The problem is that I have two different modals, each has it’s dropdown menus. When I click on the button that shows the first modal, dropdown menus data load and the search bar appears and is functional.
However, when I quit the first modal (no page reload) and I click on the button that shows the second modal, the dropdown menus are empty, and the search bar doesn’t show.

Here the HTML code I use for this page :

{% extends 'listings/base.html' %}
{% block content %}
{% load static %}

<script type="text/javascript">
    $(document).ready(function () {
        $('#createCustomerModal').on('shown.bs.modal', function () {
            console.log("Modal create opened");
            $('.django-select2').djangoSelect2('destroy');
            $('.django-select2').djangoSelect2({
                dropdownParent: $('#createCustomerModal .modal-content')
            });
        });
        
        $('#modifycustomerModal').on('show.bs.modal', function (event) {
            console.log("Modal modify closed");
            var button = $(event.relatedTarget);
            var affectation_id = button.data('id');
            
            var modal = $(this);
            $.ajax({
                url: "{% url 'customer-update' %}",
                type: 'GET',
                data: {
                    'id': affectation_id
                },
                success: function (data) {
                    modal.find('.modal-body').html(data);
                    $('.django-select2').djangoSelect2('destroy');
                    $('.django-select2').djangoSelect2({
                        dropdownParent: $('#modifycustomerModal .modal-content')
                    });
                }
            })
        });
    });
</script>
    

<div class="d-flex justify-content-between align-items-center mb-3">
    <h1>Customer list</h1>
</div>
<div class="d-flex justify-content-between align-items-center mb-3">
    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        {{ csv_form.as_p }}
        <button type="submit" class="btn btn-primary">Import CSV file</button>
    </form>
    <button type="button" class="btn btn-primary btn-lg custom-large" data-toggle="modal" data-target="#createCustomerModal">
        +
    </button>
</div>




<!-- Modal -->
<div class="modal fade" id="createCustomerModal" role="dialog" aria-labelledby="createCustomerModalLabel"
    aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="createCustomerModalLabel">New customer</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <form id="myForm" method="post">{% csrf_token %}
                    {{ form.as_p }}
                    <br><br>
                    <button type='submit' class='btn btn-primary'>Add</button>
                </form>
            </div>
        </div>
    </div>
</div>

<!-- Modal Modify-->
<div class="modal fade" id="modifycustomerModal" tabindex="-1" role="dialog" aria-labelledby="modifycustomerModalLabel" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="modifycustomerModalLabel">Modify customer</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body"></div>
    </div>
  </div>
</div>

{% if customers %}
<div class="tab-content">
  <div class="table-responsive">
    <table id="customers" class="table table-sm table-hover table-striped" style="table-layout:auto;width:100%;border-collapse:collapse;">
      <thead class="thead-dark">
        <tr>
          <th>Customer
            <i class="fas fa-sort"></i>
          </th>
          <th>Company
            <i class="fas fa-sort"></i>
          </th>
          <th>
            Salesperson
            <i class="fas fa-sort"></i>
          </th>
          <th>Function</th>
          <th>Actions</th>
        </tr>
      </thead>
      <tbody>
        {% for customer in customers %}
        <tr>
          <td>{{ customer.full_name }}</td>
          <td>{{ customer.societe.company_name}}</td>
          <td>{{ customer.commercial.full_name_salesperson}}</td>
          <td>{{ customer.function}}</td>
          <td>
            <div class="d-flex align-items-center justify-content-center ">
              <a href="" class="btn btn-outline-primary me-1" data-toggle="modal" data-target="#modifycustomerModal"
                data-id="{{ customer.id }}">Update</a>
            </div>
          </td>
        </tr>
        {% endfor %}
      </tbody>
    </table>
  </div>
</div>
{% else %}
<p>No customer found.</p>
{% endif %}

<script type="text/javascript">
    document.getElementById('myForm').onsubmit = function (event) {
        event.preventDefault();

        var formData = new FormData(this);

        fetch(this.action, {
            method: 'POST',
            body: formData,
            headers: {
                'X-CSRFToken': '{{ csrf_token }}'
            },
        }).then(response => {
            if (!response.ok && response.status === 400) {
                response.json().then(data => {
                    alert(data.error);
                });
            } else if (response.ok) {
                window.location.reload();
            }
        }).catch(error => console.error('Erreur:', error));
    };
</script>

{% endblock %}

Thanks in advance if you read this, and even more if you help. If you need any complementary code please ask.

Why is submit button getting enabled even when required inputs are empty?

I’ve got a form and a submit button that needs to be disabled until all required inputs are filled in. Some inputs are text, and some are dropdowns. I’ve read through lots of threads on how to handle this, and I think I’m doing it correctly, but for some reason the submit button gets enabled as soon as the user fills out the text input, even though the dropdown inputs are still empty.

For the text input, I’m checking whether the string length is 0. For the dropdowns, I’m checking whether the value is “select”. Why does the submit button get enabled once the text input string is > 0, even when the dropdown values are still “select”? Here’s a working codepen and see code below as well.

// Input Variables
let createDigestModal = $("#create-digest-modal");
let createDigestFormContainer = $("#create-digest-modal-form-container");
let createDigestModalSubmitBtn = $("#create-digest-modal-btn");

// ========================================================================
// Toggle the submit button to disabled / enabled based on required inputs
// ========================================================================
const enableSubmitBtn = () => {
  // Create digest form
  $(createDigestFormContainer).on("keyup click", () => {
    let createDigestInputs = createDigestFormContainer.find(".required");
    let requiredCreateDigestInputs = true;

    for (let i = 0; i < createDigestInputs.length; i++) {
      console.log(createDigestInputs[i].value);
      if (createDigestInputs[i].value == "") {
        requiredCreateDigestInputs = false;
      }
    }

    createDigestModalSubmitBtn.prop("disabled", !requiredCreateDigestInputs);
  });
};

// Invoke Function to toggle submit button
enableSubmitBtn();
.row {
  margin-bottom: 1rem;
}

/* Required Fields */

.required-field::after {
  content: "*";
  color: red;
  margin-left: 2px;
}

.required-field-margin-left::after {
  content: "*";
  color: red;
  margin-left: -2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<!-- Create Digest Modal -->
<div class="modal fade" id="create-digest-modal" tabindex="-1" aria-labelledby="create-digest-modal-label">

  <form id="create-digest-modal-form-container">
    <!-- Project Input -->
    <div class="row">
      <div class="col-40">
        <label class="required-field" for="create-digest-modal-project-input">Project</label>
      </div>
      <div>
        <select class="form-select required" id="create-digest-modal-project-input" type="select">

          <option value="select">Select</option>
          <option value="1">Project 1</option>
          <option value="2">Project 2</option>
        </select>
      </div>
    </div>
    <!-- /Project Input -->

    <!-- name input -->
    <div class="row">
      <div id="create-digest-name-input">
        <label id="create-digest-modal-name-input-label" for="create-digest-modal-name-input" class="required-field">Digest Name</label>
      </div>

      <div>
        <input name="create-digest-modal-name-input" type="text" id="create-digest-modal-name-input" class="required" />
      </div>
    </div>
    <!-- /name input -->

    <!-- Type input -->
    <div class="row">
      <div class="col-40">
        <label class="required-field" for="create-digest-modal-type-input">Type</label>
      </div>
      <div class="col-75 flex">
        <select class="form-select required" aria-label="create-digest-modal-type-input" id="create-digest-modal-type-input" type="select">
          <option value="select">Select</option>
          <option value="D">Daily</option>
          <option value="W">Weekly</option>
        </select>
      </div>
    </div>
    <!-- /Type input -->

    <!-- include summary input -->
    <div id="create-digest-modal-summary-input-container" class="row">
      <div class="col-40">
        <label class="form-check-label" for="create-digest-modal-summary-input">
          Include Summary
        </label>
      </div>
      <div class="col-75 flex">
        <input checked class="form-check-input" type="checkbox" id="create-digest-modal-summary-input" />
      </div>
    </div>
    <!-- /include summary input -->
  </form>

  <!-- Close/Update Buttons -->
  <div class="modal-footer">
    <button type="button" class="btn btn-secondary modal-close-btn" data-bs-dismiss="modal" id="create-modal-close-btn">
      Close
    </button>
    <button type="button" id="create-digest-modal-btn" class="btn btn-success" disabled>
      Add Digest
    </button>
  </div>

</div>
<!-- Create Digest Modal -->

I am unable to correctly send a POST request to http://localhost:3001/api/conversations. It returns a 500 error. Can you help me? [closed]

“In the file NextMessangersrcappapiconversationsroute.js, there might be a problem with the logic for handling the POST request. It could also be an issue with the payload or somewhere else, as after the request, it returns:

 TypeError: The "payload" argument must be of type object. Received null
    at POST (file://D%3A/ph/OneDrive/%D0%A0%D0%BE%D0%B1%D0%BE%D1%87%D0%B8%D0%B9%20%D1%81%D1%82%D1%96%D0%BB/Love/untitled19/NextMessanger/src/app/api/conversations/route.js:75:16)
  73 |         return NextResponse.json(newConversation);
  74 |     } catch (error) {
> 75 |         console.error(error); // Log the error for debugging
     |                ^
  76 |         return new NextResponse('Internal Error', { status: 500 });
  77 |     }
  78 | } {
  code: 'ERR_INVALID_ARG_TYPE'

And nothing is being created in the MongoDB database.

import { getCurrentUser } from "../../../../actions/getCurrantUser";
import { NextResponse } from "next/server";
import prisma from '../../../../libe/prismadb'

export async function POST(request) {
    try {
        const currentUser = await getCurrentUser();
        const body = await request.json();

        const {
            userId,
            isGroup,
            members,
            name
        } = body;

        if (!currentUser?.id || !currentUser?.email) {
            return new NextResponse('Unauthorized', { status: 401 });
        }

        if (isGroup && (!members || members.length < 2 || !name)) {
            return new NextResponse('Internal data', { status: 400 });
        }

        if (isGroup) {
            const newConversation = await prisma.conversation.create({
                data: {
                    name,
                    isGroup,
                    users: {
                        connect: [
                            ...members.map((member) => ({
                                id: member.value
                            })),
                            { id: currentUser.id }
                        ]
                    }
                },
                include: {
                    users: true
                }
            });

            return NextResponse.json(newConversation);
        }

        const existingConversations = await prisma.conversation.findMany({
            where: {
                OR: [
                    { userIds: { equals: [currentUser.id, userId] } },
                    { userIds: { equals: [userId, currentUser.id] } }
                ]
            }
        });

        const singleConversation = existingConversations[0];

        if (singleConversation) {
            return NextResponse.json(singleConversation);
        }

        const newConversation = await prisma.conversation.create({
            data: {
                users: {
                    connect: [
                        { id: currentUser.id },
                        { id: userId }
                    ]
                }
            }
        });

        return NextResponse.json(newConversation);
    } catch (error) {
        console.error(error); // Log the error for debugging
        return new NextResponse('Internal Error', { status: 500 });
    }
}
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mongodb"
  url      = env("DATABASE_URL")
}

model User {
  id             String    @id @default(auto()) @map("_id") @db.ObjectId
  name           String?
  email          String?   @unique
  emailVerified  DateTime?
  image          String?
  hashedPassword String?
  createdAt      DateTime  @default(now())
  updateAt       DateTime  @default(now())

  conversationIds String[]       @db.ObjectId
  conversation    Conversation[] @relation(fields: [conversationIds], references: [id])

  seenMassageIds String[]  @db.ObjectId
  seenMessages   Message[] @relation("Seen", fields: [seenMassageIds], references: [id])

  accounts Account[]
  messages Message[]
}

model Account {
  id               String  @id @default(auto()) @map("_id") @db.ObjectId
  userId           String  @db.ObjectId
  type             String
  provider         String
  providerAcountId String
  refresh_token    String? @db.String
  access_token     String? @db.String
  expires_at       Int?
  token_type       String?
  score            String?
  id_token         String? @db.String
  session_state    String?

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAcountId])
}

model Conversation {
  id String @id @default(auto()) @map("_id") @db.ObjectId

  createdAt     DateTime @default(now())
  lastMessageAt DateTime @default(now())
  name          String
  isGroup       Boolean

  messagesIds String[]  @db.ObjectId
  message     Message[]

  userIds String[] @db.ObjectId
  user    User[]   @relation(fields: [userIds], references: [id])
}

model Message {
  id        String   @id @default(auto()) @map("_id") @db.ObjectId
  body      String?
  image     String?
  createdAt DateTime @default(now())

  seenIds String[] @db.ObjectId
  user    User[]   @relation("Seen", fields: [seenIds], references: [id])

  conversationId String[]     @db.ObjectId
  conversation   Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)

  senderIds String @db.ObjectId
  sender    User   @relation(fields: [senderIds], references: [id], onDelete: Cascade)
}
'use client'

import Image from "next/image";
import noPhotoPic from '../sideBar/360_F_186293166_P4yk3uXQBDapbDFlR17ivpM6B1ux0fHG.jpg'
 import { useRouter } from 'next/navigation';
import {useCallback, useState} from "react";
import axios from "axios";

export default function Message({ lastMessage, photo, name , find , data}) {
    const router = useRouter();

    const getTime = () => {
        const date = new Date();
        const hours = String(date.getHours()).padStart(2, '0');
        const minutes = String(date.getMinutes()).padStart(2, '0');
        return `${hours}:${minutes}`;
    };

     const [isLoading, setIsLoading] = useState(false);

    const handleClick = useCallback(() => {
        setIsLoading(true);
        axios.post('/api/conversations', { userId: data.id }, {
            headers: { 'Content-Type': 'application/json' }
        })
            .then((response) => {
                router.push(`/conversations/${response.data.id}`);
            })
            .catch((error) => {
                console.error('Error creating conversations:', error);
            })
            .finally(() => setIsLoading(false));
    }, [data, router]);

    return (
        <div onClick={handleClick} className={'flex justify-start items-center hover:bg-[#141416] p-[15px] flex-row space-x-2'}>
            <Image



                src={photo || noPhotoPic}
                className={'w-[48px] border-2 border-gray-800 h-[48px] rounded-[100%] bg-white flex-shrink-0'}
                alt="image"
            />
            <div className={'flex flex-col w-[100%] '}>
                <div className={'flex justify-between'}>
             `enter code here`       <p>{name}</p>
                    {!find && <p>{getTime()}</p>}
                </div>
                <div className="w-full relative overflow-hidden">
                    <p className="whitespace-nowrap overflow-hidden text-ellipsis">
                        {!find && lastMessage }
                    </p>
                </div>
            </div>
            <div>
                {find && '=>'}
            </div>
        </div>
    );
}

I’ve tried a lot of logging, but nothing has helped. I will leave a link to my GitHub project and a link to the project from which I am taking the idea.

an error occurs when creating a newConversation

my – https://github.com/SashaChun/NextMessanger
I am taking the idea – https://github.com/AntonioErdeljac/messenger-video/tree/master

jQuery, why is submit button getting enabled even when required inputs are empty?

I’ve got a form and a submit button that needs to be disabled until all required inputs are filled in. Some inputs are text, and some are dropdowns. I’ve read through lots of threads on how to handle this, and I think I’m doing it correctly, but for some reason the submit button gets enabled as soon as the user fills out the text input, even though the dropdown inputs are still empty.

For the text input, I’m checking whether the string length is 0. For the dropdowns, I’m checking whether the value is “select”. Why does the submit button get enabled once the text input string is > 0, even when the dropdown values are still “select”? Here’s a working codepen and see code below as well.

// Input Variables
let createDigestModal = $("#create-digest-modal");
let createDigestFormContainer = $("#create-digest-modal-form-container");
let createDigestModalSubmitBtn = $("#create-digest-modal-btn");

// ========================================================================
// Toggle the submit button to disabled / enabled based on required inputs
// ========================================================================
const enableSubmitBtn = () => {
  // Create digest form
  $(createDigestFormContainer).on("keyup click", () => {
    let createDigestInputs = createDigestFormContainer.find(".required");
    let requiredCreateDigestInputs = true;

    for (let i = 0; i < createDigestInputs.length; i++) {
      console.log(createDigestInputs[i].value);
      if (
        createDigestInputs[i].value.length == "" &&
        createDigestInputs[i].value != "select"
      ) {
        requiredCreateDigestInputs = false;
      }
    }

    if (requiredCreateDigestInputs === false) {
      $(createDigestModalSubmitBtn).attr("disabled", true);
    } else {
      $(createDigestModalSubmitBtn).attr("disabled", false);
    }
  });
};

// Invoke Function to toggle submit button
enableSubmitBtn();
.row {
  margin-bottom: 1rem;
}

/* Required Fields */

.required-field::after {
  content: "*";
  color: red;
  margin-left: 2px;
}

.required-field-margin-left::after {
  content: "*";
  color: red;
  margin-left: -2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<!-- Create Digest Modal -->
<div class="modal fade" id="create-digest-modal" tabindex="-1" aria-labelledby="create-digest-modal-label">

  <form id="create-digest-modal-form-container">
    <!-- Project Input -->
    <div class="row">
      <div class="col-40">
        <label class="required-field" for="create-digest-modal-project-input">Project</label>
      </div>
      <div>
        <select class="form-select required" id="create-digest-modal-project-input" type="select">

          <option value="select">Select</option>
          <option value="1">Project 1</option>
          <option value="2">Project 2</option>
        </select>
      </div>
    </div>
    <!-- /Project Input -->

    <!-- name input -->
    <div class="row">
      <div id="create-digest-name-input">
        <label id="create-digest-modal-name-input-label" for="create-digest-modal-name-input" class="required-field">Digest Name</label>
      </div>

      <div>
        <input name="create-digest-modal-name-input" type="text" id="create-digest-modal-name-input" class="required" />
      </div>
    </div>
    <!-- /name input -->

    <!-- Type input -->
    <div class="row">
      <div class="col-40">
        <label class="required-field" for="create-digest-modal-type-input">Type</label>
      </div>
      <div class="col-75 flex">
        <select class="form-select required" aria-label="create-digest-modal-type-input" id="create-digest-modal-type-input" type="select">
          <option value="select">Select</option>
          <option value="D">Daily</option>
          <option value="W">Weekly</option>
        </select>
      </div>
    </div>
    <!-- /Type input -->

    <!-- include summary input -->
    <div id="create-digest-modal-summary-input-container" class="row">
      <div class="col-40">
        <label class="form-check-label" for="create-digest-modal-summary-input">
          Include Summary
        </label>
      </div>
      <div class="col-75 flex">
        <input checked class="form-check-input" type="checkbox" id="create-digest-modal-summary-input" />
      </div>
    </div>
    <!-- /include summary input -->
  </form>

  <!-- Close/Update Buttons -->
  <div class="modal-footer">
    <button type="button" class="btn btn-secondary modal-close-btn" data-bs-dismiss="modal" id="create-modal-close-btn">
      Close
    </button>
    <button type="button" id="create-digest-modal-btn" class="btn btn-success" disabled>
      Add Digest
    </button>
  </div>

</div>
<!-- Create Digest Modal -->

I am unable to correctly send a POST request to http://localhost:3001/api/conversations. It returns a 500 error. Can you help me?

“In the file NextMessangersrcappapiconversationsroute.js, there might be a problem with the logic for handling the POST request. It could also be an issue with the payload or somewhere else, as after the request, it returns:

 TypeError: The "payload" argument must be of type object. Received null
    at POST (file://D%3A/ph/OneDrive/%D0%A0%D0%BE%D0%B1%D0%BE%D1%87%D0%B8%D0%B9%20%D1%81%D1%82%D1%96%D0%BB/Love/untitled19/NextMessanger/src/app/api/conversations/route.js:75:16)
  73 |         return NextResponse.json(newConversation);
  74 |     } catch (error) {
> 75 |         console.error(error); // Log the error for debugging
     |                ^
  76 |         return new NextResponse('Internal Error', { status: 500 });
  77 |     }
  78 | } {
  code: 'ERR_INVALID_ARG_TYPE'

And nothing is being created in the MongoDB database.

import { getCurrentUser } from "../../../../actions/getCurrantUser";
import { NextResponse } from "next/server";
import prisma from '../../../../libe/prismadb'

export async function POST(request) {
    try {
        const currentUser = await getCurrentUser();
        const body = await request.json();

        const {
            userId,
            isGroup,
            members,
            name
        } = body;

        if (!currentUser?.id || !currentUser?.email) {
            return new NextResponse('Unauthorized', { status: 401 });
        }

        if (isGroup && (!members || members.length < 2 || !name)) {
            return new NextResponse('Internal data', { status: 400 });
        }

        if (isGroup) {
            const newConversation = await prisma.conversation.create({
                data: {
                    name,
                    isGroup,
                    users: {
                        connect: [
                            ...members.map((member) => ({
                                id: member.value
                            })),
                            { id: currentUser.id }
                        ]
                    }
                },
                include: {
                    users: true
                }
            });

            return NextResponse.json(newConversation);
        }

        const existingConversations = await prisma.conversation.findMany({
            where: {
                OR: [
                    { userIds: { equals: [currentUser.id, userId] } },
                    { userIds: { equals: [userId, currentUser.id] } }
                ]
            }
        });

        const singleConversation = existingConversations[0];

        if (singleConversation) {
            return NextResponse.json(singleConversation);
        }

        const newConversation = await prisma.conversation.create({
            data: {
                users: {
                    connect: [
                        { id: currentUser.id },
                        { id: userId }
                    ]
                }
            }
        });

        return NextResponse.json(newConversation);
    } catch (error) {
        console.error(error); // Log the error for debugging
        return new NextResponse('Internal Error', { status: 500 });
    }
}
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mongodb"
  url      = env("DATABASE_URL")
}

model User {
  id             String    @id @default(auto()) @map("_id") @db.ObjectId
  name           String?
  email          String?   @unique
  emailVerified  DateTime?
  image          String?
  hashedPassword String?
  createdAt      DateTime  @default(now())
  updateAt       DateTime  @default(now())

  conversationIds String[]       @db.ObjectId
  conversation    Conversation[] @relation(fields: [conversationIds], references: [id])

  seenMassageIds String[]  @db.ObjectId
  seenMessages   Message[] @relation("Seen", fields: [seenMassageIds], references: [id])

  accounts Account[]
  messages Message[]
}

model Account {
  id               String  @id @default(auto()) @map("_id") @db.ObjectId
  userId           String  @db.ObjectId
  type             String
  provider         String
  providerAcountId String
  refresh_token    String? @db.String
  access_token     String? @db.String
  expires_at       Int?
  token_type       String?
  score            String?
  id_token         String? @db.String
  session_state    String?

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAcountId])
}

model Conversation {
  id String @id @default(auto()) @map("_id") @db.ObjectId

  createdAt     DateTime @default(now())
  lastMessageAt DateTime @default(now())
  name          String
  isGroup       Boolean

  messagesIds String[]  @db.ObjectId
  message     Message[]

  userIds String[] @db.ObjectId
  user    User[]   @relation(fields: [userIds], references: [id])
}

model Message {
  id        String   @id @default(auto()) @map("_id") @db.ObjectId
  body      String?
  image     String?
  createdAt DateTime @default(now())

  seenIds String[] @db.ObjectId
  user    User[]   @relation("Seen", fields: [seenIds], references: [id])

  conversationId String[]     @db.ObjectId
  conversation   Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)

  senderIds String @db.ObjectId
  sender    User   @relation(fields: [senderIds], references: [id], onDelete: Cascade)
}
'use client'

import Image from "next/image";
import noPhotoPic from '../sideBar/360_F_186293166_P4yk3uXQBDapbDFlR17ivpM6B1ux0fHG.jpg'
 import { useRouter } from 'next/navigation';
import {useCallback, useState} from "react";
import axios from "axios";

export default function Message({ lastMessage, photo, name , find , data}) {
    const router = useRouter();

    const getTime = () => {
        const date = new Date();
        const hours = String(date.getHours()).padStart(2, '0');
        const minutes = String(date.getMinutes()).padStart(2, '0');
        return `${hours}:${minutes}`;
    };

     const [isLoading, setIsLoading] = useState(false);

    const handleClick = useCallback(() => {
        setIsLoading(true);
        axios.post('/api/conversations', { userId: data.id }, {
            headers: { 'Content-Type': 'application/json' }
        })
            .then((response) => {
                router.push(`/conversations/${response.data.id}`);
            })
            .catch((error) => {
                console.error('Error creating conversations:', error);
            })
            .finally(() => setIsLoading(false));
    }, [data, router]);

    return (
        <div onClick={handleClick} className={'flex justify-start items-center hover:bg-[#141416] p-[15px] flex-row space-x-2'}>
            <Image



                src={photo || noPhotoPic}
                className={'w-[48px] border-2 border-gray-800 h-[48px] rounded-[100%] bg-white flex-shrink-0'}
                alt="image"
            />
            <div className={'flex flex-col w-[100%] '}>
                <div className={'flex justify-between'}>
                    <p>{name}</p>
                    {!find && <p>{getTime()}</p>}
                </div>
                <div className="w-full relative overflow-hidden">
                    <p className="whitespace-nowrap overflow-hidden text-ellipsis">
                        {!find && lastMessage }
                    </p>
                </div>
            </div>
            <div>
                {find && '=>'}
            </div>
        </div>
    );
}

I’ve tried a lot of logging, but nothing has helped. I will leave a link to my GitHub project and a link to the project from which I am taking the idea.

my – https://github.com/SashaChun/NextMessanger
I am taking the idea – https://github.com/AntonioErdeljac/messenger-video/tree/master

How to prevent repeat padding when recursively rendering elements in React Native?

I currently have a project in React Native where I need to render the comments to a post. The comments themselves can have replies that I’m recursively rendering.

For the replies, I want it to be similar to Instagram or TikTok’s look where the parent comment is not indented but the replies are indented by adding paddingLeft to them. However, in my recursive implementation, the replies to a reply have further padding added to them on top of the initial paddingLeft which resembles Reddit’s system where a reply to a reply is further indented. How do I make it so that the replies to a reply are on the same indentation level?

This is what I currently have:

const renderCommentItem = ({ item }) => (
        <View style={{ paddingLeft: item.parent && !item.parent.parent ? 30 : 0 }}>
            <View style={{flexDirection: 'row'}}>
                <Image 
                    source={item.author_profilepic ? {uri: creation_user.profile_pic} : FallbackPhoto}
                    style={styles.commentImage}
                />
                <View style={{paddingLeft: 5}}>
                    <Text style={{fontWeight: 'bold'}}>{item.author_username}</Text>
                    <View style={{flexDirection: 'row'}}>
                        <TouchableOpacity onPress={() => handleUserPress(item.mentioned_username)}>
                            <Text style={{color: 'blue', paddingRight: 5}}>@{item.mentioned_username ? item.mentioned_username : creation_user}</Text>
                        </TouchableOpacity>
                        <Text style={{color: item.parent ? '#bd7979' : 'black'}}>{item.message}</Text>
                    </View>
                </View>
            </View>
            <View style={{flexDirection: 'row', justifyContent: 'space-evenly', padding: 5}}>
                <TouchableOpacity onPress={() => {setReplyingTo(item.id); setMSG(`@${item.author_username} `); inputRef.current.focus();}}>
                    <Text style={{fontSize: 12}}>Reply</Text>
                </TouchableOpacity>
                {item.author_username == user.username && (
                    <View>
                        <TouchableOpacity onPress={() => confirmDeleteComment(item.id)}>
                            <Text style={{fontSize: 12, color: 'red'}}>Delete</Text>
                        </TouchableOpacity>
                    </View>
                )}
            </View>
            {(item.replies.length > 0) && (
                <View>
                    <TouchableOpacity onPress={() => toggleReplies(item.id)} style={{alignSelf: 'center'}}>
                        <Text style={{color: 'gray'}}>{showReplies[item.id] ? "Hide Replies" : "View Replies"}</Text>
                    </TouchableOpacity>
                </View>
            )}
            {showReplies[item.id] && (
                <FlatList 
                    data={item.replies}
                    keyExtractor={(item) => item.id}
                    renderItem={({ item }) => renderCommentItem({item})}
                />
            )}
        </View>
    );

but the relevant line is here:

<View style={{ paddingLeft: item.parent && !item.parent.parent ? 30 : 0 }}>

I’m currently checking if an item (the reply/comment) has a parent of a parent (which means it is a reply to a reply) and if so to add no padding as I want both the replies to a parent comment and the replies to a reply to all be at the same indentation level.

This is what it looks like right now:
enter image description here

but I want the “reply to 2nd reply” comment to be aligned with “reply test” and “2nd reply”.

Why Does My Async Form Fail to Post Inputs to PHP File from Safari but not Chrome/Edge/FireFox?

I dug through a lot of past posts here and elsewhere, but I still can’t find a solution to my situation. My form handling is done by javascript, and I only use PHP to email the form data to myself, and for at least the past year it seems, I would receive submission with empty inputs when it’s submitted from a Safari browser but not when I submit it from Chrome, Edge, or FireFox. It happens regardless if I fill in every field or leave an optional field blank, so I don’t think it’s related the (old?) Safari bug that occurs when submitting a form with an empty file input, but I don’t know. The odd thing is that my site also has an async contact form handled by very similar javascript and PHP, yet I’m not getting this Safari-related empty inputs bug with that form. I would really appreciate any ideas or insight anyone may have on my code and situation.

Below are my HTML, Javascript, and PHP:

<script src="_private/javascript/submit-appt.js" defer></script>

...
...
...

<form id="appointment">
  <legend>Request An Appointment!</legend>
  <fieldset>
    <input id="appt-name" placeholder="Name" name="name">
    <div id="appt-nameError" class="appt-errorVal"></div>
  </fieldset>
  <fieldset>
    <input id="appt-phone" placeholder="XXX-XXX-XXXX" name="phone">
    <div id="appt-phoneError" class="appt-errorVal"></div>
  </fieldset>
  <fieldset>
    <input id="appt-date" type="date" name="date">
    <div id="appt-dateError" class="appt-errorVal"></div>
  </fieldset>
  <fieldset>
    <select id="appt-location" name="location">
      <option value="" disabled selected>-- Location --</option>
      <option value="X_____X">X_____X</option>
      <option value="X_____X">X_____X</option>
      <option value="X_____X">X_____X</option>
    </select>
    <div id="appt-locationError" class="appt-errorVal"></div>
  </fieldset>
  <fieldset>
    <input id="appt-email" placeholder="Email (Optional)" name="email">
  </fieldset>
  <button id="appt-button" name="submit" type="submit">Submit</button>
  <img src="images/loader.gif" id="appt-loader">
</form>

<div id="appt-successMsg" class="appt-successSub">
  SUCCESS: Your Request Has Been Sent!
</div><!-- #appt-successMsg -->

<div id="appt-failureMsg" class="appt-failureSub">
  ERROR: Please <a href="tel:+X_________X">Call</a> Or 
  <a href="mailto:X________X">Email</a> Me Instead.
</div><!-- #appt-errorMsg -->

submit-appt.js

const apptReq = document.getElementById('appointment');

apptReq.addEventListener('submit', (e) => {
  e.preventDefault();

  let aname = document.getElementById('appt-name').value;
  let anameError = document.getElementById('appt-nameError');
  let aphone = document.getElementById('appt-phone').value;
  let aphoneError = document.getElementById('appt-phoneError');
  let adate = document.getElementById('appt-date').value;
  let adateError = document.getElementById('appt-dateError');
  let alocation = document.getElementById('appt-location').value;
  let alocationError = document.getElementById('appt-locationError');
  let asuccessMsg = document.getElementById('appt-successMsg');
  let afailureMsg = document.getElementById('appt-failureMsg');
  let asubButton = document.getElementById('appt-button');
  let aloader = document.getElementById('appt-loader');

  anameError.textContent = '';
  aphoneError.textContent = '';
  adateError.textContent = '';
  alocationError.textContent = '';

  if (!aname) return anameError.textContent = 'Please enter your name';
  if (!aphone) return aphoneError.textContent = 'Please enter a phone number';
  if (!validatePhoneNumber(aphone)) return aphoneError.textContent = 'Please enter a valid number';
  if (!adate) return adateError.textContent = 'Please request an appt date';
  if (Date.parse(`${adate}T00:00:00.000`) < Date.now()) return adateError.textContent = 'Please request a future appt date';
  if (!alocation) return alocationError.textContent = 'Please select a clinic';
  
    const data = new FormData(apptReq);

    asubButton.style.display = 'none';
    aloader.style.display = 'block';

    postData();

  async function postData() {
    try {
      const response = await fetch('_private/php_scripts/submit-appt.php', {
        method: 'POST',
        body: data,
      })

      if (!response.ok) {
        aloader.style.display = 'none';
        asubButton.style.display = 'block';
        afailureMsg.style.display = 'block';
      } else {
        aloader.style.display = 'none';
        asubButton.style.display = 'block';
        asuccessMsg.style.display = 'block';
      }
    } catch (error) {
      aloader.style.display = 'none';
      asubButton.style.display = 'block';
      afailureMsg.style.display = 'block';
    }
  }
});

function validatePhoneNumber() {
  let regEx = /^+?([0-9]{3}))?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/;
  if (aphone.match(regEx)) {
    return true;
  } else {
    return false;
  }
};

submit-appt.php

<?php

$name = htmlspecialchars($_POST['name']);
$phone = htmlspecialchars($_POST['phone']);
$date = htmlspecialchars($_POST['date']);
$location = htmlspecialchars($_POST['location']);
$email = htmlspecialchars($_POST['email']);

$receiver = "X___X@X____X.com";
$subject = "WLA Appointment Request";
$msgBody = "<h5>Name:</h5> <p>$name</p>
            <h5>Phone Number:</h5> <p>$phone</p>
            <h5>Requested Date:</h5> <p>$date</p>
            <h5>Requested Location:</h5> <p>$location</p>

$headers = "From: <$email>" . "rn";
$headers .= "MIME-Version: 1.0" . "rn";
$headers .= "Content-type:text/html;charset=UTF-8" . "rn";
mail($receiver, $subject, $msgBody, $headers);

?>

Thank you for your help.

JavascriptException “Cyclic object value” with Python Selenium ActionChains after logging in

A straightforward use of ActionChains is giving me “JavascriptException: Message: Cyclic object value”. This just started happening today and wasn’t giving me problems last week so I’m very confused. I’m using Python 3 in Jupyter Notebook.

Code:

# Open each link in a new tab
for elem in elems:
    ActionChains(driver) 
        .key_down(Keys.CONTROL) 
        .click(elem) 
        .key_up(Keys.CONTROL) 
        .perform()

There’s a login function called prior to this that also uses the same driver, and ActionChains only stops working when it’s invoked downstream of this login function. The login function:

def login(driver, username, password):
    driver.implicitly_wait(5)
    driver.get("http://mywebsite.com")
    elem = driver.find_element(By.ID, "Username")
    elem.clear()
    elem.send_keys(username)
    elem = driver.find_element(By.ID, "Password")
    elem.clear()
    elem.send_keys(password)
    
    elem.send_keys(Keys.RETURN)

    # Click on link for next section
    link = driver.find_element(By.ID, "NextSection")
    link.send_keys(Keys.RETURN)
    
    return 

My test code:

import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys

driver = webdriver.Firefox()

driver.get('http://google.com')
element = driver.find_element(By.LINK_TEXT, 'Terms')

for x in range(1,5):
    ActionChains(driver) 
        .key_down(Keys.CONTROL) 
        .click(element) 
        .key_up(Keys.CONTROL) 
        .perform()
print("Upstream of login ActionChains successful")

login(driver)

element2 = driver.find_element(By.LINK_TEXT, 'About')

ActionChains(driver) 
    .key_down(Keys.CONTROL) 
    .click(element2) 
    .key_up(Keys.CONTROL) 
    .perform()
print("Downstream of login ActionChains successful")

driver.quit()

What I expected:

Upstream of login ActionChains successful
Downstream of login ActionChains successful

What I get:

Upstream of login ActionChains successful

---------------------------------------------------------------------------
JavascriptException                       Traceback (most recent call last)
Cell In[41], line 29
     21 login(driver)
     23 element2 = driver.find_element(By.LINK_TEXT, 'About')
     25 ActionChains(driver) 
     26     .key_down(Keys.CONTROL) 
     27     .click(element2) 
     28     .key_up(Keys.CONTROL) 
---> 29     .perform()
     30 print("Downstream of login ActionChains successful")
     32 driver.quit()

File ~AppDataLocalanaconda3Libsite-packagesseleniumwebdrivercommonaction_chains.py:94, in ActionChains.perform(self)
     92 def perform(self) -> None:
     93     """Performs all stored actions."""
---> 94     self.w3c_actions.perform()

File ~AppDataLocalanaconda3Libsite-packagesseleniumwebdrivercommonactionsaction_builder.py:96, in ActionBuilder.perform(self)
     94         enc["actions"].append(encoded)
     95         device.actions = []
---> 96 self.driver.execute(Command.W3C_ACTIONS, enc)

File ~AppDataLocalanaconda3Libsite-packagesseleniumwebdriverremotewebdriver.py:384, in WebDriver.execute(self, driver_command, params)
    382 response = self.command_executor.execute(driver_command, params)
    383 if response:
--> 384     self.error_handler.check_response(response)
    385     response["value"] = self._unwrap_value(response.get("value", None))
    386     return response

File ~AppDataLocalanaconda3Libsite-packagesseleniumwebdriverremoteerrorhandler.py:232, in ErrorHandler.check_response(self, response)
    230         alert_text = value["alert"].get("text")
    231     raise exception_class(message, screen, stacktrace, alert_text)  # type: ignore[call-arg]  # mypy is not smart enough here
--> 232 raise exception_class(message, screen, stacktrace)

JavascriptException: Message: Cyclic object value
Stacktrace:
RemoteError@chrome://remote/content/shared/RemoteError.sys.mjs:8:8
WebDriverError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:197:5
JavaScriptError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:476:5
cloneObject@chrome://remote/content/marionette/json.sys.mjs:46:11
cloneJSON@chrome://remote/content/marionette/json.sys.mjs:207:12
cloneObject@chrome://remote/content/marionette/json.sys.mjs:59:24
cloneJSON@chrome://remote/content/marionette/json.sys.mjs:207:12
cloneObject@chrome://remote/content/marionette/json.sys.mjs:59:24
cloneJSON@chrome://remote/content/marionette/json.sys.mjs:207:12
cloneObject@chrome://remote/content/marionette/json.sys.mjs:59:24
cloneJSON@chrome://remote/content/marionette/json.sys.mjs:207:12
json.clone@chrome://remote/content/marionette/json.sys.mjs:212:22
receiveMessage@chrome://remote/content/marionette/actors/MarionetteCommandsChild.sys.mjs:306:19

Why is this happening? Help is much appreciated.