How do I dynamically load elements of existing HTML when I click a button?

I will try to briefly explain the logic behind it: the form for entering the recipe data appears –> once the recipe has been saved the hidden buttons appear –> I click on the Add Ingredient button –> the contents of AddIngredientRecipe.html.

When I go to click on the Load Ingredient from Inventory button, in the modal body, nothing appears. Instead, when, once the recipe has been saved, I go to add only the ingredient, by clicking the Load Ingredient from Inventory button the ingredients present in the inventory appear. Also the Save button of addIngredientRecipe.html works, so I don’t know why Load Ingredient from Inventory doesn’t work too.

P.s.: I decided not to embed addIngredientRecipe.html in addrecipe.html for code reuse reasons. Because once the recipe has been saved, I can only insert the ingredients.

Now I leave you the codes to make you understand better.

addRecipe.html

{% extends 'beerRecipe/baseHome.html' %}
{% load static %}
{% load crispy_forms_tags %}

{% block content %}
    {% spaceless %}
        {% if user.is_authenticated %}
            <div id="message-container" class="d-none">
                <div class="alert alert-dismissible" role="alert">
                    <span id="message-content"></span>
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
                </div>
            </div>
            <h3 style="margin-left: 12px">Recipe</h3>
            <div class="container-fluid" id="recipe-container">
                <form id="recipe-form" method="post"
                      action="{% if recipe %}
                                {% url 'add-recipe' recipe.id %}
                                {% else %}
                                {% url 'add-recipe' %}
                                {% endif %}">
                    {% csrf_token %}
                    {% crispy recipe_form %}
                </form>
                <button class="btn btn-success" type="button" id="saveRecipeButton">Save Recipe</button>
                {% if not hide_button %}
                    <a class="btn btn-secondary" href="{% url 'home' %}" style="margin-left: 5px">Back Home</a>
                    {% else %}
                    <a class="btn btn-secondary" href="{% url 'view-recipe' recipe.id %}" style="margin-left: 5px">Back</a>
                {% endif %}
            </div>
            <div class="container-fluid d-none" id="action-buttons">
                <button type="button" id="addIngredientButton" class="btn btn-primary"
                        data-url-template="{% url 'add-ingredient-recipe' 0 %}">
                    Add Ingredient
                </button>
                <button type="button" id="addStepButton" class="btn btn-primary"
                        data-url-template="{% url 'add-step-recipe' 0 %}"
                        style="margin-left: 5px">
                    Add Step
                </button>
                <button class="btn btn-success" type="button" id="updateRecipeButton" style="margin-left: 5px"
                        data-base-url="{% url 'add-recipe' %}">
                    Update Recipe
                </button>
            </div>

            <div class="container-fluid" id="ingredient-container" style="margin-top: 25px"></div>

            <div class="container-fluid" id="step-container" style="margin-top: 25px"></div>
        {% endif %}

        <script src="{% static 'formset/jquery_formset.js' %}"></script>
        <script type="text/javascript">
            let globalRecipeId = null;
            $(document).ready(function () {

                $('#saveRecipeButton').on('click', function () {
                    const form_data = new FormData();

                    form_data.append('csrfmiddlewaretoken', document.getElementsByName('csrfmiddlewaretoken')[0].value);
                    form_data.append('name', document.getElementById('id_name').value);
                    form_data.append('litre', document.getElementById('id_litre').value);
                    form_data.append('ebc', document.getElementById('id_ebc').value);
                    form_data.append('ibu', document.getElementById('id_ibu').value);

                    $.ajax({
                        type: 'POST',
                        url: event.target.action,
                        data: form_data,
                        success: function (response) {
                            if (response.recipe_id) {
                                $('#saveRecipeButton').hide();
                                $('#action-buttons').removeClass('d-none');
                                globalRecipeId = response.recipe_id;
                            }
                            $('#message-content').text('Recipe added successfully');
                            $('#message-container').removeClass('d-none alert-danger').addClass('alert-success show');
                            console.log(response)
                        },
                        error: function (error) {
                            $('#message-content').text('An error occurred. Please try again.');
                            $('#message-container').removeClass('d-none alert-success').addClass('alert-danger show');
                            console.log(error);
                        },
                        contentType: false,
                        processData: false,
                    });
                    event.preventDefault();
                });

                $('#updateRecipeButton').on('click', function () {
                    const form_data = new FormData(document.getElementById('recipe-form'));
                    form_data.append('csrfmiddlewaretoken', document.getElementsByName('csrfmiddlewaretoken')[0].value);
                    const baseUrl = $(this).data('base-url');
                    const url = baseUrl + (globalRecipeId ? globalRecipeId + '/' : '');

                    $.ajax({
                        type: 'POST',
                        url: url,
                        data: form_data,
                        success: function (response) {
                            $('#message-content').text('Recipe update successfully');
                            $('#message-container').removeClass('d-none alert-danger').addClass('alert-success show');
                            console.log(response)
                        },
                        error: function (error) {
                            $('#message-content').text('An error occurred. Please try again.');
                            $('#message-container').removeClass('d-none alert-success').addClass('alert-danger show');
                            console.log(error);
                        },
                        contentType: false,
                        processData: false,
                    });
                    event.preventDefault();
                });

                $('#addIngredientButton').on('click', function () {

                    if (globalRecipeId) {
                        let url = $(this).data('url-template').replace('0', globalRecipeId);
                        $('#addIngredientButton').hide();
                        $('#ingredient-container').load(url);
                    }
                });

                $('#addStepButton').on('click', function () {

                    if (globalRecipeId) {
                        let url = $(this).data('url-template').replace('0', globalRecipeId);
                        $('#addStepButton').hide();
                        $('#step-container').load(url);
                    }
                });
            });
        </script>
    {% endspaceless %}
{% endblock %}

addIngredientRecipe.html

{% extends 'beerRecipe/baseHome.html' %}
{% load crispy_forms_tags %}
{% load static %}

{% block content %}
    {% spaceless %}
        {% if user.is_authenticated %}
            <div id="message-container" class="d-none">
                <div class="alert alert-dismissible" role="alert">
                    <span id="message-content"></span>
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
                </div>
            </div>

            <div class="container-fluid">
                <form method="post" id="ingredient-form"
                      action="{% if ingredient %}
                            {% url 'add-ingredient-recipe' recipe.id ingredient.id_ingredient.id %}
                            {% else %}
                            {% url 'add-ingredient-recipe' recipe.id %}
                            {% endif %}">
                    <h3>Recipe Ingredients</h3>
                    {% csrf_token %}
                    {% crispy ingredient_form %}
                    <h5>Property</h5>
                    <table class="table table-striped">
                        {{ property_ingredient_recipe.management_form }}
                        {% for form in property_ingredient_recipe.forms %}
                            {% if forloop.first %}
                                <thead>
                                <tr>
                                    {% for field in form.visible_fields %}
                                        <th>{{ field.label|capfirst }}</th>
                                    {% endfor %}
                                </tr>
                                </thead>
                            {% endif %}
                            <tr class="{% cycle 'row1' 'row2' %} formset_row">
                                {% for field in form.visible_fields %}
                                    <td>
                                        {% if forloop.first %}
                                            {% for hidden in form.hidden_fields %}
                                                {{ hidden }}
                                            {% endfor %}
                                        {% endif %}
                                        {{ field.errors.as_ul }}
                                        {{ field }}
                                    </td>
                                {% endfor %}
                            </tr>
                        {% endfor %}

                    </table>
                    <div role="group" style="margin-bottom: 10px">
                        <button class="btn btn-success" type="submit" id="saveIngredientButton"
                                style="margin-bottom: 15px">Save Ingredient
                        </button>
                        <input type="hidden" id="ingredient_selected" name="ingredient_selected" value="">
                        <button type="button" class="btn btn-primary" data-bs-toggle="modal"
                                data-bs-target="#ingredientModal" style="margin-bottom: 15px; margin-left: 10px"
                                data-url="{% url 'load-ingredient' %}">
                            Load ingredient from {{ default_inventory.name }}
                        </button>
                        {% if not hide_button %}
                            <a class="btn btn-secondary" type="button" href="{% url 'view-recipe' recipe.id %}" style="margin-bottom: 15px; margin-left: 10px">Back</a>
                        {% endif %}
                    </div>
                </form>

                <!-- Modal for load ingredient from default inventory-->
                <div class="modal fade" id="ingredientModal" tabindex="-1" aria-labelledby="ingredientModalLabel"
                     aria-hidden="true" role="dialog">
                    <div class="modal-dialog" role="document">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title" id="ingredientModalLabel">Ingredient
                                    of {{ default_inventory.name }}</h5>
                                <button type="button" class="btn-close" data-bs-dismiss="modal"
                                        aria-label="Close"></button>
                            </div>
                            <div class="modal-body">
                                <div id="availableIngredients"></div>
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                                <button type="button" class="btn btn-primary" id="addSelectedIngredients">
                                    Add Selected Ingredients
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        {% endif %}

        <script src="{% static 'formset/jquery_formset.js' %}"></script>
        <script type="text/javascript">
            $('.formset_row').formset({
                prefix: 'property',
                addText: 'Add',
                deleteText: 'Delete',
                formCssClass: 'dynamic-formset1',
                addCssClass: 'add-row btn btn-primary',
                deleteCssClass: 'delete-row btn btn-danger',
                added: function (row) {
                    row.find('input[name*="name"]').removeAttr('disabled')
                }
            });

            $('#div_id_name_category').hide();
            $('#div_id_name_new_category').hide();
            const loadIngredientUrl = "{% url 'load-ingredient' %}";
            const addSelectedIngredientUrl = "{% url 'add-selected-ingredients' %}";

            $(document).ready(function () {
                let name_category = $('#id_category_choices_0');
                let name_new_category = $('#id_category_choices_1');
                let toggle_category = function () {
                    $('#div_id_name_category').toggle();
                };
                let toggle_new_category = function () {
                    $('#div_id_name_new_category').toggle();
                };
                name_category.click(function () {
                    if (name_new_category.is(":checked")) {
                        toggle_new_category();
                        name_new_category.prop('checked', false);
                    }
                    toggle_category();
                });
                name_new_category.click(function () {
                    if (name_category.is(":checked")) {
                        toggle_category();
                        name_category.prop('checked', false);
                    }
                    toggle_new_category();
                });
                $('.popover-dismiss').popover({
                    trigger: 'focus'
                });

                $('#saveIngredientButton').on('click', function () {
                    const form_data = new FormData();
                    const ingredientId = $('#ingredient_selected').val() || '';
                    form_data.append('csrfmiddlewaretoken', document.getElementsByName('csrfmiddlewaretoken')[0].value);
                    form_data.append('name_ingredient', document.getElementById('id_name_ingredient').value);
                    form_data.append('name_category', document.getElementById('id_name_category').value);
                    form_data.append('name_new_category', document.getElementById('id_name_new_category').value);
                    form_data.append('quantity', document.getElementById('id_quantity').value);
                    form_data.append('measurement_unit', document.getElementById('id_measurement_unit').value);
                    form_data.append('comment', document.getElementById('id_comment').value);
                    form_data.append('ingredient_selected', ingredientId);

                    if (document.getElementById('id_name_category').value && document.getElementById('id_name_new_category').value) {
                        alert("Both 'Name Category' and 'New Category Name' cannot be filled at the same time.");
                    }
                    document.querySelectorAll('.formset_row').forEach((element, index) => {
                        if (element.style.display !== 'none') {
                            let propertyName = element.querySelector('input[name$="-name"]').value;
                            let propertyValue = element.querySelector('input[name$="-value"]').value;

                            if (propertyName && propertyValue) {
                                form_data.append(`property-${index}-name`, propertyName);
                                form_data.append(`property-${index}-value`, propertyValue);
                            }
                        }
                    });
                    const formIngredientActionUrl = $('#ingredient-form').attr('action');
                    $.ajax({
                        type: 'POST',
                        url: formIngredientActionUrl,
                        data: form_data,
                        success: function (response) {
                            clearFormFields();
                            $('#message-content').text('Ingredient added successfully');
                            $('#message-container').removeClass('d-none alert-danger').addClass('alert-success show');
                            console.log(response)
                        },
                        error: function (error) {
                            $('#message-content').text('An error occurred. Please try again.');
                            $('#message-container').removeClass('d-none alert-success').addClass('alert-danger show');
                            console.log(error);
                        },
                        contentType: false,
                        processData: false,
                    });
                    event.preventDefault();
                });

                $('#ingredientModal').on('show.bs.modal', function () {
                    $.ajax({
                        url: loadIngredientUrl,
                        type: 'GET',
                        success: function (response) {
                            $('#availableIngredients').empty();
                            response.forEach(function (ingredient) {
                                $('#availableIngredients').append(
                                    `<input type="radio" name="ingredient" value="${ingredient.id}"> ${ingredient.name}<br>`
                                );
                            });
                            console.log(response)
                        },
                        error: function (error) {
                            console.log(error);
                        }
                    });
                });

                $('#addSelectedIngredients').on('click', function () {
                    const selectedIngredientId = $('#availableIngredients input[name="ingredient"]:checked').val();
                    $('#ingredient_selected').val(selectedIngredientId);

                    if (!selectedIngredientId) {
                        alert('Please select an ingredient before adding.')
                        return;
                    }

                    $.ajax({
                        url: addSelectedIngredientUrl,
                        type: 'GET',
                        data: {
                            'ingredient_id': selectedIngredientId,
                        },
                        success: function (data) {
                            $('#id_name_ingredient').val(data.name_ingredient);
                            $('#id_name_category').val(data.name_category);
                            $('#id_quantity').val(data.quantity);
                            $('#id_measurement_unit').val(data.measurement_unit);
                            updateFormset(data);
                            $('#ingredientModal').modal('hide');
                            $('#message-content').text('Ingredient added successfully');
                            $('#message-container').removeClass('d-none alert-danger').addClass('alert-success show');
                        },
                        error: function (error) {
                            $('#message-content').text('An error occurred. Please try again.');
                            $('#message-container').removeClass('d-none alert-success').addClass('alert-danger show');
                            console.log(error)
                        }
                    });
                });
            });

            function updateFormset(data) {
                let totalForms = $('#id_property-TOTAL_FORMS');
                let maxForms = parseInt(totalForms.val());
                let dataLength = data.properties.length;

                if (dataLength < maxForms) {
                    for (let i = dataLength; i < maxForms; i++) {
                        $(`#id_property-${i}-name`).closest('tr').remove();
                    }
                }
                totalForms.val(dataLength);

                data.properties.forEach((property, index) => {
                    let nameField = $(`#id_property-${index}-name`);
                    let valueField = $(`#id_property-${index}-value`);

                    if (nameField.length && valueField.length) {
                        nameField.val(property.name).prop('disabled', false);
                        valueField.val(property.value);
                    } else {
                        addForm(property,index);
                    }
                });
            }

            function addForm(property, index) {
                let rowClass = (index % 2 == 0) ? 'row1' : 'row2';
                let newRow = $(` <tr class="${rowClass} formset_row dynamic-formset1">
                                    <td>
                                        <input type="text" name="property-${index}-name" value="${property.name}" class="form-control form-control-sm">
                                    </td>
                                    <td>
                                        <input type="number" name="property-${index}-value" value="${property.value}" class="form-control form-control-sm" step="any">
                                    </td>
                                    <td>
                                        <input type="hidden" name="property-${index}-DELETE">
                                        <a class="delete-row btn btn-danger" href="javascript:void(0)">Delete</a>
                                    </td>
                                </tr>`
                );
                $('.dynamic-formset1').closest('table').find('tbody').find('.dynamic-formset1-add').before(newRow);
            }

            function clearFormFields() {
              $('#ingredient-form input[type="text"], #ingredient-form input[type="number"]').val('');
              $('#ingredient-form select').prop('selectIndex', 0);
              document.querySelectorAll('.formset_row').forEach((element) => {
                  element.querySelectorAll('input[type="number"]').forEach((input) => {
                      input.value = '';
                  });
              });
            }
        </script>
    {% endspaceless %}
{% endblock %}

views.py

@login_required
def load_ingredients_from_inventory(request):
    inventory = Inventory.objects.filter(id_user=request.user)
    default_inventory = inventory.filter(is_default=True).first()

    if default_inventory:
        inventory_ingredients = InventoryIngredient.objects.filter(id_inventory=default_inventory).select_related(
            'id_ingredient')
        ingredients = [{
            'id': inv_ingredient.id_ingredient.id,
            'name': inv_ingredient.id_ingredient.name,
            'quantity': inv_ingredient.quantity,
            'measurement_unit': inv_ingredient.measurement_unit
        } for inv_ingredient in inventory_ingredients]
    else:
        ingredients = []
    return JsonResponse(list(ingredients), safe=False)

My views.py method is correct, because when I go to add an ingredient from an already created recipe (so I go to directly load addIngredientRecipe.html) it loads the ingredients correctly. What I can’t figure out is why the script to load ingredients from inventory doesn’t work when I load addIngredientRecipe.html into addRecipe.html.

I would like to know how to solve this problem, and also if maybe I messed up the implementation to load addIngredientRecipe.html into addRecipe.html.

why V8 ByteCode interperter can generates it and execute it,without turn bytecode to machine code [closed]

Why V8 ByteCode interperter can generates code and execute it,without turn bytecode to machine code

What I learned before is that machines can only understand machine code

I think V8 ByteCode interperter must convert ByteCode into machine code, otherwise the machine will not recognize it and will not get the running result.

I think V8 ByteCode interperter must convert ByteCode into machine code, otherwise the machine will not recognize it and will not get the running result.

Javascript setTimeout not working properly on iOS

I have a website where I stream audio using VideoJS.
The website is quite simple as it is plain HTML + Javascript + CSS

When the page is loaded this function is executed (for simplicity I have inserted some pseudo code):

function SetTimeouts(){
    fetch('https://storage.googleapis.com/storage/v1/b/path/to/file.csv?alt=media',
    {
        method: "GET",
    }).then(response => response.text()).then(csvData => {
             for each row {
                  //...
                  // parses CSV file and calculates milliseconds until the time written in the row
                  //...
                  setTimeout(SetSource, millsecondsToNext);
              }
         }
    })
}

This is the SetSource function:

async function SetSource(fetchMetadata = true) {
    player.src({ type: 'application/x-mpegURL', src: 'https://storage.googleapis.com/path/to/file.m3u8' });
    player.play();
}

Where player is previously intialized as:

player = videojs('stream', {
        controls: false, autoplay: true, preload: 'auto',
        html5: {
            vhs: {overrideNative: false},
            nativeAudioTracks: true
        }
    });

The audio source is correctly updated and automatically reproduced in every platform except in iOS.
In iOS, at the time set in the setTimeout the streaming stops and the page must be manually reloaded.

It seems that Javascript on iOS browsers behaves differently.
Has someone experienced a similar issue? What could be causing this behaviour?

I use this approach because I would like to avoid reloading the entire page.
I specify that the streaming works fine on iOS, the problem occurs when the setTimeout is triggered.

Thanks

How do I create an email body using a textbox in HTML?

I have a form with a text box element in it.

I want to be able to use the textbox the same way it would work in an email body.

Where you can have:

  1. HTML code in the body
  2. In line Images

So something like this should be doable:

Text here
Image Here
Text here
HTML here
Text Here

I am unfortunately only limited to 1 HTML file so CSS and Scripting has to be done in one file along with the HTML body. Since I am using this as a front end that we’ll be attaching to a separate system.

So actually something like this textbox I am using to post this question with a formatting header would work as well.

Any help is appreciated

Thank you!

Right now I am just working on a simple one.
It sort of works and allows drag and drop of images but the drag and drop portion is separate.
Also, it does not allow HTML elements like this text box would.

Sample below:

<!DOCTYPE html>
<html>
<head>
  <title>HTML Textbox with In-line Images</title>
  <style>
    #description {
      border: 1px solid black;
      padding: 10px;
      min-height: 200px;
    }

    #dropArea {
      border: 1px solid black;
      padding: 10px;
      min-height: 100px;
      width: 200px;
    }
  </style>
</head>
<body>
  <div id="description" contenteditable="true"></div>
  <input type="hidden" id="htmlInput" name="htmlInput">
  <button onclick="getHTML()">Submit</button>
  <br><br>
  <div id="dropArea" ondragover="allowDrop(event)" ondrop="drop(event)"></div>

  <script>
    function allowDrop(ev) {
      ev.preventDefault();
    }

    function drag(ev) {
      ev.dataTransfer.setData("text", ev.target.src);
    }

    function drop(ev) {
      ev.preventDefault();
      var data = ev.dataTransfer.getData("text");
      var img = document.createElement("img");
      img.src = data;
      img.style.width = "100px";
      img.style.height = "100px";
      ev.target.appendChild(img);
      document.getElementById("description").focus();
      document.execCommand("insertHTML", false, " " + img.outerHTML + " ");
      document.getElementById("htmlInput").value = document.getElementById("description").innerHTML;
    }

    function getHTML() {
      document.getElementById("htmlInput").value = document.getElementById("description").innerHTML;
    }
  </script>
</body>
</html>

Grabbing key/value pairs of a Object-like string (similar to JSON) using regex

With a string like {float: 'null', another: 'foo'}, I’d like to grab each set of key/values pairs so that the groups would output float null, and another and foo.
My current regex is /{(?<set>(?<key>w*)s*:s*(?<value>.*)?s?)*}/g
It grabs the key correctly, but anything past from the comma on receives it as the value. I’m using named groups mainly just for clarity. Can’t figure out how to extract each key/value pair especially when there are multiple.
Thanks for any help

Currently am trying /{(?<set>(?<key>w*)s*:s*(?<value>.*)?s?)*}/g but the output is:

the group ‘set’: float: 'null', another: 'foo' (correct)

the group ‘key’: float (correct)

the group ‘value’: 'null', another: 'foo' (incorrect, I want just null)

Would like it to capture all key/value pairs if possible

Is there a way to define field types for Parse Objects?

I am using Parse Server and Parse JS SDK to develop an application. I recently started using typescript for my project. The question is, Can I define field types for Parse Objects?

For example, I have defined a Parse object for a post, and I want it to have a title field of type string

const Post = Parse.Object.extend("Post");

First of all I don’t understand why the type of Post is any

Secondly, I want the following code to throw an error or warning:

const post = new Post();
post.set("title", 123) // title should be a string and not a number

How can I do this?
Thanks

I have searched parse github and the internet for hours and found nothing.
I have tried experimenting with the second and third argument of the extend function. But I couldn’t figure it out. I don’t know if it is related to what I am trying to do or not.

Efficient Image Processing and Storage for Web and App Assets Using Sharp and AWS

I am creating an API. In which I am storing marketplace data web images and app images.

So what I want to do is that I want to reduce the size of the image and then convert that image into webp. and want to store it on AWS. But I am getting the error.

Error: Error compressing and converting the image: TypeError [ERR_INVALID_ARG_TYPE]: The “path” argument must be of type string or an instance of Buffer or URL. Received undefined.
at readFile (fs.js:343:10)
at internal/util.js:341:30
at new Promise ()
at readFile (internal/util.js:340:12)
at convertAndCompress

To convert the image I am using the Sharp library. But what the sharp library does is it accesses the image from its local path and then converts the image. However, on the live website, we cannot access the local file path.

This is my middleware function of converting the image. If my environment is local then I am storing the image locally otherwise on upload it on AWS s3. This code is working fine in local but in live I am getting error.

add_marketplace_banner_images: async (req, res, next) => {
      // const admin_id = req.user.user_id;
      const admin_id = 12;
      try {
        const upload = multer({
          storage: Config.environment === "local" ? storage_marketplace_banner_images : multerS3Config,
          limits: {
            fileSize: 6242880, // Compliant: 5MB
          },
          fileFilter: (req, file, cb) => {
            const allowedExtensions = ['.png', '.jpg', '.webp', '.jpeg'];
            const ext = path.extname(file.originalname).toLowerCase();
            if (allowedExtensions.includes(ext)) {
              const validateImage = validatingImage(module.exports.schemas.marketplace_banner_data);
              if (validateImage) {
                cb(null, true);
              }
            } else {
              cb(new Error('Only images with .png, .jpg, .webp, and .jpeg extensions are allowed!'), false);
            }
          },
        }).fields([
          { name: "web_image", maxCount: 1 },
          { name: "app_image", maxCount: 1 },
        ]);

        upload(req, res, async function (err) {
          if (err) {
            return res.status(400).json({ status: 2, errors: { file: err.message } });
          }

          const processImage = async (fieldName) => {
            if (req.files && req.files[fieldName]) {
              const originalImage = req.files[fieldName][0];
              const compressedImage = await sharp(originalImage.path)
                .webp({ quality: 80 })
                .toBuffer()
                .catch((err) => {
                  console.error("Error compressing and converting the image:", err);
                  throw err;
                });

              if (Config.environment === "local") {
                const outputPath = `${originalImage.destination}/${originalImage.filename}.webp`;
                await fs.promises.writeFile(outputPath, compressedImage);
                fs.unlinkSync(originalImage.path); // Remove the original image file

                req.files[fieldName] = [{
                  fieldname: fieldName,
                  originalname: `${path.parse(originalImage.originalname).name}.webp`,
                  encoding: '7bit',
                  mimetype: 'image/webp',
                  destination: path.dirname(originalImage.destination),
                  filename: path.basename(outputPath),
                  path: outputPath,
                  size: fs.statSync(outputPath).size,
                }];
              } else {
                const image_name = `${Math.floor(Date.now() / 1000)}-${admin_id}-${uuid()}`;
                const s3Params = {
                  Bucket: Config.aws.bucketName,
                  Key: `uploads/marketplace_banner_image/${image_name}.webp`,
                  Body: compressedImage,
                  ContentType: "image/webp",
                };
                await s3.putObject(s3Params).promise();
              }
            }
          };

          const processedImages = await Promise.allSettled([
            req.files.web_image && processImage("web_image"),
            req.files.app_image && processImage("app_image"),
          ]);

          const rejectedImages = processedImages.filter((result) => result.status === "rejected");
          if (rejectedImages.length > 0) {
            console.error("Error processing images:", rejectedImages.map((result) => result.reason));
            return res.status(500).json({ status: 3, message: "Error processing images" });
          }

          next();
        });
      } catch (err) {
        console.error("Server error:", err);
        res.status(500).json({ status: 3, message: "Server error" });
      }
    },

Is there any way to achieve this task? I don’t want to store the image somewhere, convert it, and then store it on AWS. Apart from this, is there any other solution to do this task?

JS client for elasticsearch times out on scroll

For a particular usecase I’m trying to benchmark how long it would take to fetch all the entries for a particular search. I used the official client helper for scrolling all the entries like below, but it times out if the entries are above 10K. And I can see hits < 10K also take more time.

https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/scroll_examples.html

 const client = new Client({
    node: process.env.ELASTIC_NODE,
    auth: {
        username: process.env.ELASTIC_U,
        password: process.env.ELASTIC_P
    },
    tls: {
        rejectUnauthorized: false
    }
 })

 async function * scrollSearch (params) {
    let response = await client.search(params);

    while (true) {
      const sourceHits = response.hits.hits
  
      if (sourceHits.length === 0) {
        break
      }
      
      yield sourceHits.length

  
      if (!response._scroll_id) {
        break
      }
  
      response = await client.scroll({
        scroll_id: response._scroll_id,
        scroll: params.scroll
      })
    }
  }
  
  async function run (query) {
    let hits = 0;

    const params = {
        index: process.env.INDEX,
        scroll: '1m',
        size: 10000,
        query : {
            bool : {
                must : query
            }
        }
      }
    
    for await (const noOfHits of scrollSearch(params)) {
      hits += noOfHits;
    }

    return hits;
  }

Am I doing something wrong here ?

How to Implement a Scroll-Triggered Text Opacity Change in a Split-Section Layout Using HTML, CSS, & JS?

Hello Stack Overflow community,

I’ve come across a compelling visual effect on a split layout and am trying to recreate a similar functionality. You can see the effect in action here: https://stb-hornauer.de/. The layout features a static image on one side and text that changes on the other as the user scrolls down. I’m focused on the text opacity change that occurs with scrolling, not the image slider component.

I have a foundational understanding of HTML, CSS, and a bit of JavaScript. Any pointers or a sample code snippet that could help guide me toward achieving this scroll-linked text opacity effect would be greatly appreciated.

Thank you in advance for your time and help!

I’ve come this far so far, but it’s not like the example:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Scroll Animation</title>
    <style>
      .left-t {
        width: 50%;
        height: 100vh;
        padding-bottom: 14%;
        padding-left: 150px;
        padding-right: 100px;
        position: -webkit-sticky;
        position: sticky;
        top: 14%;
        bottom: 0;
        overflow: hidden;
      }

      .left_content_wrap {
        height: 100%;
        justify-content: flex-start;
        align-items: center;
        display: flex;
        position: relative;
      }

      .text_wrap {
        z-index: 1;
        height: auto;
        flex-flow: column;
        justify-content: flex-start;
        align-items: flex-start;
        padding-top: 40%;
        display: flex;
        position: absolute;
        top: 0%;
        bottom: 0%;
        left: 0%;
        right: 0%;
      }

      @media screen and (min-width: 1280px) {
        .text_wrap {
          flex-direction: column;
          display: flex;
        }
      }

      .div-block-22 {
        align-items: center;
        padding-bottom: 80px;
        display: flex;
      }

      .heading_h1.text_home {
        color: #363940;
        text-transform: none;
        flex: 0 auto;
        padding-bottom: 0;
        font-size: 35px;
        line-height: 38px;
      }

      .div-block-23 {
        height: 50%;
        align-items: flex-start;
        display: flex;
      }

      @media screen and (min-width: 1280px) {
        .div-block-23,
        .div-block-25 {
          max-width: 500px;
        }
      }

      .text_main {
        flex: 0 auto;
        padding-top: 0;
        display: block;
      }

      .text_wrap_2 {
        z-index: 2;
        max-width: 520px;
        flex-direction: column;
        justify-content: flex-start;
        align-items: flex-start;
        padding-top: 40%;
        display: flex;
        position: absolute;
        top: 0%;
        bottom: 0%;
        left: 0%;
        right: 0%;
        position: fixed;
      }

      @media screen and (min-width: 1280px) {
        .text_wrap_2 {
          display: flex;
        }
      }

      .div-block-24 {
        align-items: center;
        padding-bottom: 80px;
        display: flex;
      }

      .div-block-25 {
        flex-direction: column;
        align-items: flex-start;
        display: flex;
      }

      .text_wrap_3 {
        z-index: 3;
        height: 100%;
        max-width: 520px;
        flex-direction: column;
        justify-content: flex-start;
        align-items: flex-start;
        padding-top: 40%;
        display: flex;
        position: absolute;
        top: 0%;
        bottom: 0%;
        left: 0%;
        right: 0%;
        position: fixed;
      }
    </style>
  </head>
  <body style="height: 500vh">
    <div class="left-t">
      <div class="left_content_wrap">
        <div style="opacity: 1" class="text_wrap">
          <div class="div-block-99">
            <div class="div-block-22">
              <h2 class="heading_h1 text_home">Die Kanzlei</h2>
            </div>
            <div class="div-block-23">
              <p class="text_main">
                Herzlich willkommen bei Ihrer Steuerkanzlei Hornauer! Bei uns
                erwartet Sie, neben einem seriösen leistungsbezogenen
                Arbeitsethos, eine herzliche und kollegiale Atmosphäre, in deren
                Fokus der Mandant mit seinen Belangen und Wünschen steht.
              </p>
            </div>
          </div>
        </div>
        <div style="opacity: 0" class="text_wrap_2">
          <div class="div-block-99">
            <div class="div-block-24">
              <h2 class="heading_h1 text_home">Katrin Hornauer</h2>
            </div>
            <div class="div-block-25">
              <p class="text_main">
                Katrin Hornauer absolvierte ihr Studium der
                Betriebswirtschaftslehre an der Universität Leipzig, welches sie
                1995 als Diplom-Kauffrau abschloss. Nach Jahren in der
                betriebswirtschaftlichen Praxis legte sie 1999 die Prüfung zur
                Steuerberaterin ab. Seit Oktober 2001 führt sie erfolgreich ihre
                eigene Kanzlei in der Landeshauptstadt Magdeburg.
              </p>
            </div>
          </div>
        </div>
        <div style="opacity: 0" class="text_wrap_3">
          <div class="div-block-99">
            <div class="div-block-24">
              <h2 class="heading_h1 text_home">Unser Team</h2>
            </div>
            <div class="div-block-25">
              <p class="text_main">
                Unsere Kanzlei vereint qualifizierte und engagierte
                Steuerfachangestellte. So gewährleisten wir unseren Mandanten
                eine kompetente und individuelle Betreuung. Davon profitieren
                Sie sowohl als Unternehmen, Selbstständige, Freiberufler oder
                Privatperson, unabhängig davon, welcher Branche Sie angehören.
              </p>
            </div>
          </div>
        </div>
      </div>
    </div>

    <script>
      window.addEventListener("scroll", function () {
        let num = window.scrollY / window.innerHeight;
        let index = Math.floor(num);
        let opacity = num - index;

        // Determine the total number of text_wrap elements
        let totalElements = document.querySelectorAll(
          ".text_wrap, .text_wrap_2, .text_wrap_3"
        ).length;

        // Set the opacity of the target .text_wrap element
        document
          .querySelectorAll(".text_wrap, .text_wrap_2, .text_wrap_3")
          .forEach(function (element, i) {
            if (i === index) {
              if (i === 0) {
                // For the first text_wrap, start at opacity 1 and decrease to 0
                element.style.opacity = 1 - opacity;
              } else if (i === 1) {
                // For the second text_wrap, start at opacity 0, increase to 1, then decrease to 0
                element.style.opacity =
                  opacity < 0.5 ? 2 * opacity : 2 * (1 - opacity);
              } else {
                // For the third text_wrap, start at opacity 0 and increase to 1, maintaining 1 opacity at the end
                element.style.opacity = opacity < 0.5 ? 2 * opacity : 1;
              }
            } else if (i === totalElements - 1 && index >= totalElements - 1) {
              // For the last text_wrap, maintain opacity at 1 when scrolling out of the container
              element.style.opacity = 1;
            } else {
              element.style.opacity = 0;
            }
          });
      });
    </script>
  </body>
</html>

In React, how do I make an element expand when it is displayed?

Please take a look at this sandbox:

https://playcode.io/1852293

Desired effect:

  1. After clicking the button, the yellow box show up by expanding from left to right. It looks like a animation where its width grows from 0 to 100px.

  2. The inner blue box doesn’t get rendered until its parent yellow box is fully expanded (width = 100px).

I know that I can make the element always mounted, set its initial width to 0, and use transition to achieve this effect, but it causes some other issues, so I wonder if I can do it via conditional rendering.

Thanks in advance!

Scatter letter on screen and image appearing on hover debug

I am having trouble with debugging the scatter letters and my project link aspects. I can’t figure out why on media screen it’s not working, and now I have also made the contact links disappear on both.

I am new to programming and would appreciate support to help me learn!

Below is the link to my repo.

https://github.com/milanawood/portfolio

Thank you,
Milana

I have tried changing CSS and is and keep making sure they’re correctly working together but each time I fix one thing I seem to create another issue.

VSCode Autocomplete Not Displaying

I am currently running Visual Studio Code in WSL, and for some reason autocomplete doesn’t work. I’m not sure why autocomplete isn’t working. Any solution would be greatly appreciated. It doesn’t even work when I’m not in WSL. So i’m not sure what the issue is.
clearBtn. only shows variables within the scope of the class

I have tried checking my settings to make sure that built in typescript and javascript features are enabled, which they are. In this case, when I want innerHTML to appear for clearBtn. I have to type everything in manually.

Can I load basemap without center or set view in map initialization

I have the center coming from a different layer, however, that layer is loading slowly so initially you see a blank map container.so, I want the basemap to be visible.

view.map = L.map('map_' + mapId, {
  gestureHandling: true,
  zoom: 8,
  layers: [osm, EsriStreets, EsriImagery, EsriTopo],
  fullscreenControl: {
    pseudoFullscreen: false // if true, fullscreen to page width and height
  }
});

react router dom only works when navigating via links but not back button window.scrollTo(0, 0) only works

I have a react app that I want to automatically start at the top of the page whenever I navigate to that page, regardless of how a user gets there (i.e. clicking a Link component that links to that page, or using back button to go back and forward)

I have a ScrollToTop component that uses window.scrollTo(0, 0) method that scrolls to the top whenever the pathname changes. However, this only works on navigating via Links but not back and forward buttons on the browser.

ScrollToTop.tsx

...Imports

const useBackButton = (): boolean => {
  const navType = useNavigationType()
  return navType === NavigationType.Pop
}

const ScrollToTop: React.FC = () => {
  const { pathname } = useLocation()
  const isPop = useBackButton()

  const scrollToTop = (): void => {
    window.scrollTo(0, 0)
  }

  useEffect(() => {
    console.log(pathname, isPop)
    scrollToTop()
  }, [pathname, isPop])

  useEffect(() => {
    window.addEventListener('beforeunload', scrollToTop)
    console.log('On Mount')
    return () => {
      window.removeEventListener('beforeunload', scrollToTop)
      console.log('On Unmount')
    }
  }, [])

  return (
    <>
      <Outlet />
    </>
  )
}

export default ScrollToTop

App.tsx

...Imports

const router = createBrowserRouter(
  createRoutesFromElements(
    <Route element={<ScrollToTop />}>
      <Route path='/' element={<RootLayout />}>
        <Route path='*' element={<NotFound />} />
        <Route index element={<Landing />} />
        <Route path='auth' element={<Auth />} />
        <Route path='ideate' element={<IdeatorLayout />}>
          <Route path=':sessionID' element={<Display />} />
        </Route>
        <Route path='privacy' element={<Privacy />} />
      </Route>
    </Route>
  )
)

export const App: React.FunctionComponent = () => {
  useAuthControl()

  return <RouterProvider router={router} />
}

Any help would be appreciated. Thanks in advance!