Visibilitychange listener that works when switching workspaces

I have an iframe inside a HTML page.html that loads iframe.html. The iframe.html code has an event Listener for the iframe content to be reloaded when the document becomes visible (e.g., when bringing a tab forward):

window.addEventListener('visibilitychange', function() {
    if (document.visibilityState === 'visible') refreshImgArray(); 
});

However, this listener is not triggered when the window is in other “virtual workspace” (e.g., the different workspaces provided by Gnome and KDE), and I switch to the workspace containing the browser, despite the fact that the whole workspace became visible and not just the browser window.

Which is the proper javascript event listener to include in iframe.html for it to be reloaded when the browser window becomes visible after switching workspaces?

Save progress – Bypass required fields

I have a form that contains different types of inputs including several radio buttons with the required attribute. I am attempting to add a ‘Save progress’ link that when clicked, will override the required attributes (by selecting a choice) and submit the form. To make this work, I added another choice (N/A) to all of the radio buttons. That choice is made non-visible with the help of jquery. When that submit link is clicked, it’s supposed to select all radio buttons that don’t have a selection and set them to the ‘N/A’ choice, then submit the form. Upon returning to the form (on page load), all radio buttons with ‘N/A’ selected, are made unselected.

At least this is the way it’s supposed to work. What’s actually happening, is all radio buttons end up being unselected. Even the ones that had choices other than ‘N/A’ selected.

Below is the code I’m currently using:

// On page load, hide the 'N/A' choice for all radio buttons
$('input[type=radio][value="N/A"]').hide().parent().hide();

// On page load, uncheck/unset all radio buttons that have 'N/A' selected
$('input[type=radio][value="N/A"]').each(function() {
    //var selectedValue = $('input[name="survey"]:checked').val();
    //$(this).val("");
    $(this).prop("checked",false);
     
});

// When 'quick save' button is clicked, set value of all unslected radio buttons to 'N/A' (to override required attribute) and submit.
$(document).on('click', '.qksv', function() {   
    $('input[type=radio]:not(:checked)').each(function() {
        //if(this.checked == false) {
            $(this).val("N/A");
                $(this).prop('checked',true);
                //$(this).attr("required", false);              
        //}
    });
    $(this).submit();       
});

What am I doing wrong? I get the same results even when I comment out those two sections of code that are triggered on page load.

Javascript: Efficient method to remove multiple items from an array based on an object property

I have a javascript array of objects, say 4 elements; I am trying to remove 1 or 2 or 3 or 4 items based on an object’s property. I tried the below code and it removed 2 elements, but not the third element; something similar to Why doesn’t the splice method remove all the items from an array with matching property values?

selItems.forEach((item, index) =>{
    var itemName = item.name.toLowerCase();
    if((itemName === 'hello') || (itemName === 'world') || (itemName === 'diem')){
        selItems.splice(index, 1);
    }
    
});

I ended up writing the the below code, but am not sure how efficient it is.

function isRemoved(item)
{
    var itemName = item.name.toLowerCase();
    if( (itemName === 'hello') || (itemName  === 'world') || (itemName  === 'diem'))
    {
        return false;
    }
    return true;
}

var selItems = [];
selItems.push({ id: '1', name: 'Hello'} );
selItems.push({ id: '2', name: 'World'});
selItems.push({ id: '3', name: 'Carpe'});
selItems.push({ id: '4', name: 'Diem'});

selItems = selItems.filter(isRemoved);

Is this an efficient way of removing multiple elements from an array?

Validate and submit laravel from external JavaScript file

I have a laravel project I am making a slight change to but moving from angular framework, there is some confusion I am running into when trying to validate and submit a form from external js file.

I have 2 forms in the laravel blade folder. One form id is payment, which is the original form that collects user information. This form is what I am trying to validate and submit in the external js file. I will provide the form below.

payment form in blade file:

<form method="POST" id="payment" enctype="multipart/form-data">
            @if ($errors->any())
                <div class="alert alert-danger">
                    <ul>
                        @foreach ($errors->all() as $error)
                            <li>{{ $error }}</li>
                        @endforeach
                    </ul>
                </div>
            @endif
            @csrf
            <div class="container">
                <div class="row">
                    <div class="col-12 mb-5">
                        <div class="table">
                            <div class="shop-title-box">
                                <h3>{{$keywords["Serving Method"] ?? __('Serving Method') }}</h3>
                            </div>
                            <table class="cart-table shipping-method">
                                <thead class="cart-header">
                                <tr>
                                    <th>#</th>
                                    <th>{{$keywords["Method"] ?? __('Method') }}</th>
                                </tr>
                                </thead>
                                <tbody>

                                @foreach ($smethods as $sm)
                                    <tr>
                                        @if(!empty($packagePermissions) && in_array($sm->name, $packagePermissions))
                                            <td>

                                                <input type="radio" name="serving_method" class="shipping-charge"
                                                       value="{{$sm->value}}"
                                                       @if(empty(old()) && $loop->first)
                                                           checked
                                                       @elseif(old('serving_method') == $sm->value)
                                                           checked
                                                       @endif
                                                       data-gateways="{{$sm->gateways}}">
                                            </td>
                                            <td>
                                                @php
                                                    $smname = str_replace(' ','_',$sm->name);
                                                @endphp

                                                <p class="mb-1">
                                                    <strong>{{ $keywords[$smname] ?? __($sm->name) }}</strong></p>
                                                <p class="mb-0"><small>{{ __($sm->note) }}</small></p>
                                            </td>

                                        @else
                                            <td class="d-none">
                                                <input type="radio" name="serving_method" class="shipping-charge"
                                                       value="{{$sm->value}}"
                                                       @if(empty(old()) && $loop->first)
                                                           checked
                                                       @elseif(old('serving_method') == $sm->value)
                                                           checked
                                                       @endif
                                                       data-gateways="{{$sm->gateways}}">
                                            </td>
                                        @endif
                                    </tr>
                                @endforeach
                                </tbody>
                            </table>
                            @error('serving_method')
                            <p class="text-danger mb-0">{{ convertUtf8($message) }}</p>
                            @enderror
                        </div>
                    </div>
                </div>
                <input type="hidden" name="ordered_from" value="website">
                <div class="form-container" id="home_delivery">
                    @includeIf('user-front.qrmenu.partials.home_delivery_form')
                </div>
                <div class="form-container d-none" id="pick_up">
                    @includeIf('user-front.qrmenu.partials.pick_up_form')
                </div>
                <div class="form-container d-none" id="on_table">
                    @includeIf('user-front.qrmenu.partials.on_table_form')
                </div>
                <div class="row">
                    <div class="col-12">
                        <div class="field-label">{{$keywords["Order Notes"] ?? __('Order Notes') }} </div>
                        <div class="field-input">
                            <textarea name="order_notes" cols="30" rows="10"></textarea>
                        </div>
                    </div>
                </div>
                <div id="paymentInputs"></div>
            </div>
            <div class="bottom">
                <div class="container">
                    <div class="row">
                        <div class="col-xl-8 col-lg-8 col-md-12 col-sm-12">
                            <div class="table">
                                <div class="shop-title-box">
                                    <h3>{{$keywords["Order Summary"] ?? __('Order Summary') }}</h3>
                                </div>
                                @if (!empty($cart))
                                    <table class="cart-table">
                                        <thead class="cart-header">
                                        <tr>
                                            <th class="prod-column"
                                                width="10%">{{$keywords["Product"] ?? __('Product') }}</th>
                                            <th width="70%">{{$keywords["Product Title"] ??  __('Product Title') }}</th>
                                            <th>{{$keywords["Quantity"] ?? __('Quantity') }}</th>
                                            <th>{{$keywords["Total"] ?? __('Total') }}</th>
                                        </tr>
                                        </thead>
                                        <tbody>
                                        @foreach ($cart as $key => $item)
                                            @php
                                                $id = $item["id"];
                                                 if(session()->has('user_lang')){
                                                    $lang = AppModelsUserLanguage::where('code',session()->get('user_lang'))->where('user_id',getUser()->id)->first();
                                                }else{
                                                   $lang = AppModelsUserLanguage::where('is_default',1)->where('user_id',getUser()->id)->first();
                                                }
                                                $product = Product::query()
                                                    ->join('product_informations', 'product_informations.product_id', 'products.id')
                                                    ->where('product_informations.language_id', $lang->id)
                                                    ->where('products.user_id', $user->id)
                                                    ->where('products.id', $id)
                                                    ->first();
                                            @endphp
                                            <tr class="remove{{ $id }}">
                                                <td class="prod-column" width="10%">
                                                    <div class="column-box">
                                                        <div class="prod-thumb">
                                                            <a
                                                                href="{{ route('user.front.product.details', [getParam(), $product->slug, $product->product_id]) }}"
                                                                target="_blank">
                                                                <img class="lazy"
                                                                     data-src="{{ Uploader::getImageUrl(Constant::WEBSITE_PRODUCT_FEATURED_IMAGE,$item['photo'],$userBs) }}"
                                                                     alt="" width="100">
                                                            </a>
                                                        </div>
                                                    </div>
                                                </td>
                                                <td width="70%">
                                                    <div class="title">
                                                        <a
                                                            href="{{ route('user.front.product.details', [getParam(), $product->slug, $product->product_id]) }}"
                                                            target="_blank">
                                                            <h5 class="prod-title">
                                                                {{ strlen($product->title) > 27 ? mb_substr($product->title, 0, 27, 'UTF-8') . '...' : $product->title }}
                                                            </h5>
                                                            @if (!empty($item["variations"]))

                                                                @php
                                                                    $variations = $item['variations'];
                                                                    $prokeywords = json_decode($product->keywords, true);
                                                                    $addonkeywords = json_decode($product->addon_keywords, true);
                                                                    $sessionLang = session()->get('user_lang');

                                                                @endphp

                                                                <p><strong>{{$keywords["Variation"] ?? __("Variation")}}
                                                                        :</strong> <br>
                                                                    @php
                                                                        $variations = $item["variations"];
                                                                    @endphp
                                                                    @foreach ($variations as $vKey => $variation)
                                                                        @php

                                                                            $vname = $userCurrentLang->code . '_' . str_replace('_', ' ', $vKey);
                                                                            $voption = $userCurrentLang->code . '_' . $variation['name'];

                                                                        $variationName = isset($prokeywords['variation_name'][$vname]) ? $prokeywords['variation_name'][$vname] : '';
                                                                        $optionName = isset($prokeywords['option_name'][$voption]) ? $prokeywords['option_name'][$voption] : '';
                                                                        @endphp
                                                                        @if(!empty($variationName))
                                                                            <span
                                                                                class="text-capitalize font-weight-bold {{ $userCurrentLang->rtl == 1 ? 'text-right' : '' }}">{{ $variationName }}:</span>
                                                                            <span
                                                                                class="{{ $userCurrentLang->rtl == 1 ? 'text-right' : '' }}">{{ $optionName }}</span>

                                                                            @if (!$loop->last)
                                                                                <span
                                                                                    class="{{ $userCurrentLang->rtl == 1 ? 'text-right' : '' }}"> ,</span>
                                                                            @endif
                                                                        @endif
                                                                    @endforeach
                                                                </p>
                                                        </a>
                                                        @endif
                                                        @if (!empty($item['addons']))
                                                            <p>
                                                                <strong>{{$keywords["Addons"] ?? __("Addons") }}
                                                                    :</strong>
                                                                @php
                                                                    $addons = $item["addons"];
                                                                @endphp
                                                                @foreach ($addons as $addon)
                                                                    @php
                                                                        $addonkeywords = json_decode($product->addon_keywords, true);
                                                                        if (!empty($sessionLang)) {
                                                                            $aname = $sessionLang . '_' . $addon['name'];
                                                                        } else {
                                                                            $aname = $userCurrentLang->code . '_' . $addon['name'];
                                                                        }

                                                                    @endphp

                                                                    {{ $addonkeywords['addon_name'][$aname] }}
                                                                    @if (!$loop->last)
                                                                        ,
                                                                    @endif
                                                                @endforeach
                                                            </p>
                                                        @endif
                                                    </div>
                                                </td>
                                                <td class="qty">
                                                    {{ $item['qty'] }}
                                                </td>
                                                <input type="hidden" value="{{ $id }}" class="product_id">
                                                <td class="sub-total">
                                                    {{ $userBe->base_currency_symbol_position == 'left' ? $userBe->base_currency_symbol : '' }}
                                                    {{ $item['total'] }}
                                                    {{ $userBe->base_currency_symbol_position == 'right' ? $userBe->base_currency_symbol : '' }}
                                                </td>
                                                <script>
                                                    window.userBe = "{{ json_encode($userBe) }}";
                                                </script>
                                            </tr>

                                        @endforeach
                                        @else
                                            <div class="py-5 bg-light text-center">
                                                <h5>{{$keywords["Cart is empty"] ?? __('Cart is empty!') }}</h5>
                                            </div>
                                        @endif
                                        </tbody>
                                    </table>
                                    <div class="text-center my-4">
                                        <a href="{{ route('user.front.index',getParam()) }}"
                                           class="main-btn main-btn-2">{{$keywords["Return to Website"] ?? __('Return to Website') }}</a>
                                    </div>
                            </div>
                        </div>
                        <div class="col-xl-4 col-lg-4 col-md-12 col-sm-12">
                            @includeIf('user-front.qrmenu.partials.order_total')
                        </div>
                    </div>
                </div>
            </div>
        </form>

I also have another clover payment form that has and iframe for payment. This form uses the html used here and references the form submission and processing is managed in an external js file names clover-checkout.js which is:

$.ajax({
    url: "http://localhost:4000/api/cloverPay/getapikey",
    type: "GET",
    headers: {
        'Access-Control-Allow-Origin': '*',
        'Content-Type': 'application/json',
        'Authorization': 'Bearer JSON.parse(window.userBe.replace(/&quot;/g,'"')).token
    },
    success: function (result) {
        setupCloverIframe(result.pakms);
    },
    error:function(data)
    {
        console.log('error ', data);
    }
});
function setupCloverIframe(pakms) {
    const clover = new Clover(pakms.apiAccessKey, {
        merchantId: pakms.merchantId
    });
    const elements = clover.elements();
    const styles = {
        body: {
            fontFamily: 'Roboto, Open Sans, sans-serif',
            fontSize: '16px',
        },
        input: {
            fontSize: '16px',
            width: '80%',
        },
    };
    const cardNumber = elements.create('CARD_NUMBER', styles);
    const cardDate = elements.create('CARD_DATE', styles);
    const cardCvv = elements.create('CARD_CVV', styles);
    const cardPostalCode = elements.create('CARD_POSTAL_CODE', styles);

    cardNumber.mount('#card-number');
    cardDate.mount('#card-date');
    cardCvv.mount('#card-cvv');
    cardPostalCode.mount('#card-postal-code');

    const cardResponse = document.getElementById('card-response');

    const displayCardNumberError = document.getElementById('card-number-errors');
    const displayCardDateError = document.getElementById('card-date-errors');
    const displayCardCvvError = document.getElementById('card-cvv-errors');
    const displayCardPostalCodeError = document.getElementById('card-postal-code-errors');

    // Handle real-time validation errors from the card Element.
    cardNumber.addEventListener('change', function (event) {
        console.log(`cardNumber changed ${JSON.stringify(event)}`);
    });

    cardNumber.addEventListener('blur', function (event) {
        console.log(`cardNumber blur ${JSON.stringify(event)}`);
    });

    cardDate.addEventListener('change', function (event) {
        console.log(`cardDate changed ${JSON.stringify(event)}`);
    });

    cardDate.addEventListener('blur', function (event) {
        console.log(`cardDate blur ${JSON.stringify(event)}`);
    });

    cardCvv.addEventListener('change', function (event) {
        console.log(`cardCvv changed ${JSON.stringify(event)}`);
    });

    cardCvv.addEventListener('blur', function (event) {
        console.log(`cardCvv blur ${JSON.stringify(event)}`);
    });

    cardPostalCode.addEventListener('change', function (event) {
        console.log(`cardPostalCode changed ${JSON.stringify(event)}`);
    });

    cardPostalCode.addEventListener('blur', function (event) {
        console.log(`cardPostalCode blur ${JSON.stringify(event)}`);
    });

    // TODO: Register event handlers
    const form = document.getElementById('payment-form');
    form.addEventListener('submit', function (event) {
        event.preventDefault();

        clover.createToken()
            .then(function (result) {
                if (result.errors) {
                    Object.values(result.errors).forEach(function (value) {
                        console.log(value);
                    });
                } else {
                    let un = window.location.pathname.split('/')[1];

                    $.post('/dinengo/processOrderAndPayment/' + result.token + '/' + un, function (response) {
                        // handle your response here
                        $('#payment')[0].submit();
                        alert("result.token");
                    });
                }
            }).catch(function (data) {
            console.log(data);
        });
    });

    const paymentReqData = {
        country: 'US',
        currency: 'usd',
        total: {
            label: 'Demo total',
            amount: 1099,
        },
        requestPayerName: true,
        requestPayerEmail: true,
    };

    const paymentRequest = clover.paymentRequest(paymentReqData);
    const paymentRequestButton = elements.create('PAYMENT_REQUEST_BUTTON', {
        paymentReqData
    });
    // Check the availability of the Payment Request API first.
    paymentRequest.canMakePayment().then(function (result) {
        if (result) {
            paymentRequestButton.mount('#payment-request-button');
        } else {
            document.getElementById('payment-request-button').style.display = 'none';
        }
    });
    paymentRequestButton.addEventListener('paymentMethod', function (ev) {
        alert(JSON.stringify(ev));
    })

    // Submit the form with the token ID.
    function cloverTokenHandler(token) {
        // Insert the token ID into the form so it gets submitted to the server
        var form = document.getElementById('payment-form');
        var hiddenInput = document.createElement('input');
        hiddenInput.setAttribute('type', 'hidden');
        hiddenInput.setAttribute('name', 'cloverToken');
        hiddenInput.setAttribute('value', token);
        form.appendChild(hiddenInput);
        alert(token);
        // Submit the form
        // form.submit();
    }

    function processCloverIframPayment(event) {
        event.preventDefault();
        debugger;
        console.log('in button click ', event);

        clover.createToken()
            .then(function (result) {
                if (result.errors) {
                    Object.values(result.errors).forEach(function (value) {
                        console.log(value);
                    });
                } else {
                    debugger;
                    let un = window.location.pathname.split('/')[1];

                    $.post('/dinengo/processOrderAndPayment/' + result.token + '/' + un, function (response) {
                        // handle your response here
                        //alert(result.token);
                        $('#payment').submit();
                    });
                }
            }).catch(function (data) {
            console.log(data);
        });
    }

}

There are a couple things I am trying to accomplish but an running into trouble. Firstly, I want to have it so that in the external js, it validates that the form with id ‘payment’ has no errors before processing the form with id “payment-form”. Once that payment-form is completed, then I want to submit and process the form with id payment which is the original laravel form.

Although I can click the form payment from the external js, I need a way to first validate that the payment form is valid, process payment, then successfully submit the laravel payment form.

Note: currently, when $(‘#payment’).submit(); is called, it returns and error I believe due to it not having context anymore. Can someone help me resolve this issue as well as understand the cause and solution.

Also, The error handling should be intact. If an error exists, it should set that error as it did previously when submitting the form.

How to compress json files while Vite build?

I have a project on Vite + Vue.js, and there are many large static reference files in public/data with .json extension. How can I compress them during build without turning them into javascript?

I tried to do it via esbuild:

esbuild public/data/*.json --outdir=/dist/public/data/ --allow-overwrite --minify

but it makes .js output files with module export [...] I don’t need that, since I get them at runtime via fetch as needed, not via import.

I whant only compress pretty-print spaces and tabs inside json.

Writing js tags for the window of an html facade

I am trying to serve a group of native svg files into the keys of a keyboard interface facade. There is no backend presently, and all that is needed is one or two script tags to allow for the switching of glyphs in the keys of the interface. The files are external, and provided I can understand the syntax for one, I can then complete the others.

The main html code is here:

<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>AITI-L</title>
        <link rel="stylesheet" href="aiti-lp-81.css">
    <link rel="stylesheet" href="aiti-btns-by-id.css">
    <link rel="stylesheet" href="aiti-actv-btns.css">
</head>
<body>
        <div class="display">
            <div class="textarea-div">
            <button class=”text-toggle”>e95e</button>
            <textarea></textarea>
            </div>
            <div class="textarea-div">
            <button class=”text-toggle”>e95f</button>
            <textarea></textarea>
            </div>    
                <div class="row">
                    <select name="IGB" id="e900" size="1">
                <option href="" value="Auretech">Auretech</option>
                <option href="" value="Blochert">Blochert</option>
                <option href="" value="Chauta">Chauta</option>
                <option href="" value="Crill">Crill</option>
                <option href="" value="Dua Senna">Dua Senna</option>
                <option href="" value="Embot">Embot</option>
                <option href="" value="Engraph">Engraph</option>
                <option href="" value="Feuix">Feuix</option>
                <option href="" value="Gyopyo">Gyopyo</option>
                <option href="" value="Kernsky">Kernsky</option>
                <option href="" value="Khazh">Khazh</option>
                <option href="" value="Koko">Koko</option>
                <option href="" value="Lukshing">Lukshing</option>
                <option href="" value="Mfon">Mfon</option>
                <option href="" value="Nenya">Nenya</option>
                <option href="" value="Omni">Omni</option>
                <option href="" value="Orbes">Orbes</option>
                <option href="" value="Punck">Punck</option>
                <option href="" value="Tadrusba">Tadrusba</option>
                <option href="" value="Yuyui">Yuyui</option>
                <option href="" value="Zyto">Zyto</option>
            </select>   
            <button id="e902">IGB</button>
            <button id="e903" data-svg="e903"</button>
            <button id="e904" data-svg="e904"></button>
            <button id="e905" data-svg="e905"></button>
            <button id="e906" data-svg="e906"></button>
            <button id="e907" data-svg="e907"></button>
            <button id="e908" data-svg="e908"></button>
            <button id="e909" data-svg="e909"></button>
            <button id="e90a" data-svg="e90a"></button>
            <button id="e90b" data-svg="e90b"></button>
            <button id="e90c" data-svg="e90c"></button>
        </div>

<div class="row">
            <button id="e910-b-frc" data-svg="e910-b-frc.svg"></button>
            <button id="e911-d-frc" data-svg="e911-d-frc.svg"></button>
            <button id="e912-pa-frc" data-svg="e912-pa-frc.svg"></button>
            <button id="e913-p-frc" data-svg="e913-p-frc.svg"></button>
            <button id="e914-u-frc" data-svg="e914-u-frc.svg"></button>
            <button id="e915-g-frc" data-svg="e915-g-frc.svg"></button>
            <button id="e916-cf" data-svg="e916-cf.svg"></button>
            <button id="e917-cb" data-svg="e917-cb.svg"></button>
            <button id="e918-g-pls" data-svg="e918-g-pls.svg"></button>
            <button id="e919-u-pls" data-svg="e919-u-pls.svg"></button>
            <button id="e91a-p-pls" data-svg="e91a-p-pls.svg"></button>
            <button id="e91b-pa-aff" data-svg="e91b-pa-aff.svg"></button>
            <button id="e91c-a-pls" data-svg="e91c-a-pls.svg"></button>
            <button id="e91d-b-pls" data-svg="e91d-b-pls.svg"></button>
        </div>     

<div class="row">
            <button id="e920-l-frc" data-svg="e920-l-frc.svg"></button>
            <button id="e921-a-frc" data-svg="e921-a-frc.svg"></button>
            <button id="e922-rf-frc" data-svg="e922-rf-frc.svg"></button>
            <button id="e923-v-frc" data-svg="e923-v-frc.svg"></button>
            <button id="e924-ph-frc" data-svg="e924-ph-frc.svg"></button>
            <button id="e925-fr" data-svg="e925-fr.svg"></button>
            <button id="e926-cn" data-svg="e926-cn.svg"></button>
            <button id="e927-bk" data-svg="e927-bk.svg"></button>
            <button id="e928-u-trl" data-svg="e928-u-trl.svg"></button>
            <button id="e929-v-pls" data-svg="e929-v-pls.svg"></button>
            <button id="e92a-rf-pls" data-svg="e92a-rf-pls.svg"></button>
            <button id="e92b-a-trl" data-svg="e92b-a-trl.svg"></button>
            <button id="e92c-b-trl" data-svg="e92c-b-trl.svg"></button>
        </div>
        <div class="row">
            <button id="e930-b-nsl" data-svg="e930-b-nsl.svg"></button>
            <button id="e931-a-nsl" data-svg="e931-a-nsl.svg"></button>
            <button id="e932-rf-nsl" data-svg="e932-rf-nsl.svg"></button>
            <button id="e933-p-nsl" data-svg="e933-p-nsl.svg"></button>
            <button id="e934-v-nsl" data-svg="e934-v-nsl.svg"></button>
            <button id="e935-c" data-svg="e935-c.svg"></button>
            <button id="e936-cm" data-svg="e936-cm.svg"></button>
            <button id="e937-om" data-svg="e937-om.svg"></button>
            <button id="e938-o" data-svg="e938-o.svg"></button>
            <button id="e939-v-app" data-svg="e939-v-app.svg"></button>
            <button id="e93a-p-app" data-svg="e93a-p-app.svg"></button>
            <button id="e93b-rf-app" data-svg="e93b-rf-app.svg"></button>
            <button id="e93c-a-app" data-svg="e93c-a-app.svg"></button>
            <button id="e93d-l-app" data-svg="e93d-l-app.svg"></button>
        </div>
        <div class="row">
            <button id="e940-l-nsl" data-svg="e940-l-nsl.svg"></button>
            <button id="e941-a-ltx" data-svg="e941-a-ltx.svg"></button>
            <button id="e942-rf-ltx" data-svg="e942-rf-ltx.svg"></button>
            <button id="e943-p-ltx" data-svg="e943-p-ltx.svg"></button>
            <button id="e944-v-ltx" data-svg="e944-v-ltx.svg"></button>
            <button id="e945-nc" data-svg="e945-nc.svg"></button>
            <button id="e946-m" data-svg="e946-m.svg"></button>
            <button id="e947-no" data-svg="e947-no.svg"></button>
            <button id="e948-u-nsl" data-svg="e948-u-nsl.svg"></button>
            <button id="e949-rf-tof" data-svg="e949-rf-tof.svg"></button>
            <button id="e94a-a-ltf" data-svg="e94a-a-ltf.svg"></button>
            <button id="e94b-a-tof" data-svg="e94b-a-tof.svg"></button>
            <button id="e94c-l-tof" data-svg="e94c-l-tof.svg"></button>
        </div>

<div class="row">
            <button id="e950" data-svg="e950"></button>
            <button id="e951" data-svg="e951"></button>
            <button id="e952" data-svg="e952"></button>
            <button id="e953" data-svg="e953"></button>
            <!--button id="e954" data-svg="e954"></button-->
            <button id="e955" data-svg="e955"></button>
            <!--button id="e956" data-svg="e956"></button>
            <button id="e957" data-svg="e957"></button>
            <button id="e958" data-svg="e958"></button-->
            <button id="e959" data-svg="e959"></button>
            <!--button id="e95a" data-svg="e95a"></button-->
            <button id="e95b" data-svg="e95b"></button>
            <button id="e95c" data-svg="e95c"></button>
            <button id="e95d" data-svg="e95d"></button>
        </div>
    </div>
    <!--script>
    </script-->          
</body>         
</html>


The files containing the native glyph paths I am seeking to serve are below. While there are more files to be served than these two, they should be sufficient for me to iterate a solution over all the files I am seeking to implement, if and when I have need to start.

Feuix:

<!--”Feuix” aiti-fux-svg-path.html-->
<!--script-->

<svg style="position: absolute” version="1.1" >
<defs>

/* start e910~e91d */

<symbol id="e910-b-frc" viewBox="0 0 19 32">
<path d="M9.319 12.927c0.901-0.037 1.669 0.252 2.305 0.868 0.182 0.211 0.238 0.445 0.167 0.701-0.406 0.057-0.807 0.134-1.203 0.234-0.678-0.378-1.335-0.356-1.971 0.067-0.056 0.803-0.044 1.604 0.033 2.405 0.659 0.439 1.305 0.417 1.937-0.067 1.5-0.291 1.745 0.133 0.735 1.269-1.148 0.782-2.306 0.794-3.474 0.033-0.271-0.249-0.46-0.549-0.568-0.902-0.045-1.047-0.045-2.093 0-3.14 0.181-0.47 0.481-0.837 0.902-1.102 0.375-0.159 0.754-0.281 1.136-0.367z"></path>
</symbol>
<symbol id="e911-d-frc" viewBox="0 0 19 32">
<path d="M9.319 12.927c0.966-0.052 1.756 0.282 2.372 1.002 0.067 0.156 0.134 0.312 0.2 0.468 0.045 1.047 0.045 2.093 0 3.14-0.287 0.796-0.855 1.253-1.704 1.37-1.079 0.191-1.981-0.11-2.706-0.902-0.184-0.261-0.24-0.539-0.167-0.835 0.424-0.083 0.847-0.094 1.269-0.033 0.632 0.484 1.278 0.506 1.937 0.067 0.078-0.801 0.089-1.602 0.033-2.405-0.056-0.056-0.111-0.111-0.167-0.167-0.629-0.211-1.253-0.2-1.871 0.033-0.391-0.074-0.781-0.141-1.169-0.2 0.012-0.394 0.179-0.716 0.501-0.969 0.451-0.301 0.941-0.49 1.47-0.568z"></path>
</symbol>

</defs>
</svg>

<!--/script-->

Gyopyo:

<!--"Gyopyo" aiti-gpo-svg-path.html-->
<!--script src="aiti-lp-81.html"-->

<svg style="position: absolute" version="1.1">
<defs>

/* start e910~e91d */

<symbol id="e910-b-frc" viewBox="0 0 19 32">
<path d="M7.182 11.19c0.477-0.101 0.867 0.033 1.169 0.401 0.033 1.091 0.045 2.182 0.033 3.274 0.668-0.011 1.337 0 2.004 0.033 0.345 0.157 0.501 0.424 0.468 0.802 0.040 0.342-0.093 0.587-0.401 0.735-0.69 0.033-1.38 0.044-2.071 0.033 0 0.891 0 1.782 0 2.672 1.203-0.011 2.405 0 3.608 0.033 0.443 0.268 0.588 0.658 0.434 1.169-0.078 0.167-0.2 0.289-0.367 0.367-1.626 0.045-3.251 0.045-4.877 0-0.164-0.097-0.309-0.22-0.434-0.367-0.045-2.917-0.045-5.834 0-8.752 0.138-0.149 0.283-0.283 0.434-0.401z"></path>
</symbol>
<symbol id="e911-d-frc" viewBox="0 0 19 32">
<path d="M11.257 11.19c0.477-0.101 0.867 0.033 1.169 0.401 0.045 2.917 0.045 5.834 0 8.752-0.125 0.148-0.27 0.27-0.434 0.367-1.626 0.045-3.251 0.045-4.877 0-0.308-0.148-0.441-0.392-0.401-0.735-0.034-0.378 0.122-0.645 0.468-0.802 1.202-0.033 2.405-0.045 3.608-0.033 0-0.891 0-1.782 0-2.672-0.691 0.011-1.381 0-2.071-0.033-0.308-0.148-0.441-0.392-0.401-0.735-0.034-0.378 0.122-0.645 0.468-0.802 0.668-0.033 1.336-0.044 2.004-0.033-0.011-1.091 0-2.183 0.033-3.274 0.138-0.149 0.283-0.283 0.434-0.401z"></path>
</symbol>


</defs>
</svg>
<!--/script-->

Any help would be appreciated, especially reading about the requirements for serving external svg elements. Thanky kindly…

I’ve worked diligently for some time, but have had difficulty finding people who address the service of multiple external html files in the context of a simple facade. As I said, any help would be appreciated, even where might be best to read about it. Thanks again…

React Beautiful DnD: Unable to Drop Songs into Folders After Fetching Data

I’m working on a React application using react-beautiful-dnd to implement drag-and-drop functionality for songs and folders. The drag-and-drop works perfectly with locally created folders, but I’m encountering issues when trying to drop songs into folders that are fetched from the backend. After fetching, the folders become undroppable, and there’s no hover effect.

Here’s a simplified version of my setup:

CatalogComponent.tsx

import React, { useCallback, useEffect, useState } from 'react'
import { DragDropContext, DropResult } from 'react-beautiful-dnd'
import { useDispatch } from 'react-redux'
import { fetchCatalog, fetchFolders } from './catalogSlice'
import { unwrapResult } from '@reduxjs/toolkit'
import { toast } from 'react-toastify'
import CatalogFolder from './CatalogFolder'
import SongList from './SongList'
import { Folder, Song } from '../../../app/layout/models/catalog'
import { createStandardFolder, getFolderDroppableId } from '../../../app/layout/utils/folderUtils'

export default function CatalogComponent() {
  const dispatch = useDispatch()
  const [localCatalog, setLocalCatalog] = useState<{ songs: Song[] } | null>(null)
  const [localFolders, setLocalFolders] = useState<Folder[]>([])
  const [isLoading, setIsLoading] = useState(true)

  useEffect(() => {
    const fetchData = async () => {
      setIsLoading(true)
      try {
        const [catalogResult, foldersResult] = await Promise.all([
          dispatch(fetchCatalog()),
          dispatch(fetchFolders()),
        ])

        const catalogData = unwrapResult(catalogResult)
        const foldersData = unwrapResult(foldersResult)

        const standardizedFolders = foldersData.map(createStandardFolder)
        setLocalCatalog(catalogData)
        setLocalFolders(standardizedFolders)
      } catch (error) {
        toast.error('Error fetching data')
      } finally {
        setIsLoading(false)
      }
    }

    fetchData()
  }, [dispatch])

  const handleDragEnd = useCallback((result: DropResult) => {
    if (!result.destination) return

    const { source, destination, draggableId } = result

    if (source.droppableId === 'song-list' && destination.droppableId.startsWith('folder-')) {
      const folderId = parseInt(destination.droppableId.split('-')[1], 10)
      const songId = parseInt(draggableId, 10)

      const song = localCatalog?.songs.find(s => s.songId === songId)
      if (!song) return

      setLocalFolders(prevFolders => {
        return prevFolders.map(folder => {
          if (folder.id === folderId) {
            return {
              ...folder,
              nodes: [...folder.nodes, { id: Date.now(), songId: song.songId, name: song.name, nodes: [] }]
            }
          }
          return folder
        })
      })
    }
  }, [localCatalog])

  if (isLoading) return <div>Loading...</div>

  return (
    <DragDropContext onDragEnd={handleDragEnd}>
      <CatalogFolder folders={localFolders} />
      <SongList songs={localCatalog?.songs || []} />
    </DragDropContext>
  )
}

CatalogFolder.tsx

import React from 'react'
import { Droppable } from 'react-beautiful-dnd'
import { Folder } from '../../../app/layout/models/catalog'

interface Props {
  folders: Folder[]
}

const CatalogFolder: React.FC<Props> = ({ folders }) => {
  return (
    <div>
      {folders.map(folder => (
        <Droppable key={folder.id} droppableId={`folder-${folder.id}`}>
          {(provided, snapshot) => (
            <div
              ref={provided.innerRef}
              {...provided.droppableProps}
              style={{
                background: snapshot.isDraggingOver ? 'lightblue' : 'lightgrey',
                padding: 4,
                width: 250,
                minHeight: 500,
              }}
            >
              <h4>{folder.name}</h4>
              {provided.placeholder}
            </div>
          )}
        </Droppable>
      ))}
    </div>
  )
}

export default CatalogFolder

Problem:

  • Issue: After fetching folders from the backend, I can’t drop songs
    into them. The hover effect doesn’t appear, indicating that the
    droppable area isn’t being recognized.
  • Expected Behavior: Songs should be draggable into any folder, and the
    folder should highlight when a song is dragged over it.

What I’ve Tried:

  • Ensured that droppableId is correctly set for each folder.
  • Verified that the DragDropContext and Droppable components are
    correctly implemented.
  • Checked that the folders are correctly fetched and standardized.

Question:
What could be causing the fetched folders to become undroppable, and how can I resolve this issue?

Memory consumption by object in v8

I’m trying to find a way to track the memory of a specific object in v8.
I want to write tests, on memory consumption in v8, to prevent leaks and use these tests to look for bottlenecks
The first thing that comes to mind is just queryObjects, but I want to understand how to understand the memory consumption of a particular object.

I tried to track this on node using node:inspector and ChromeDevTools, but I didn’t find an option to track memory consumption without using snapshots (as an option you can parse the snapshot and find the necessary object).

Date Picker, dynamically enable / disable dates

I’m trying to work out how to dynamically enable and disable dates using MultiDatesPicker for jQuery UI. http://luca.lauretta.info/Multiple-Dates-Picker-for-jQuery-UI/

I can use addDisabledDates and pass an array of dates to the picker, these dates will then show as disabled. That works, but how do I enable them again ?

I’ve tried amending the array of dates, and recalling the date picker, but that doesn’t seem to load the new dates.. the old dates are still showing as disabled.

This is a sample of what I’m doing:

$(document).ready(function() {
    
    addeddates = ['1 January 1970', '5 November 2024', '6 November 2024']       
    datepicker()
    
    function datepicker() {
            
        $('.cals').multiDatesPicker({
        dateFormat: "d MM yy",
        minDate: 0, // today
        maxDate: 365, // +30 days from today
        multidate: true,
        defaultDate:"0d", 
        addDisabledDates: addeddates,
        beforeShow: function(d) {
            addeddates = ['1 January 1970']     
            datepicker()
            }
        })
    }

})

When the date picker is called 5th and 6th November are disabled. I was hoping updating the addeddates array to be only one day and then recalling the function would allow them to be usable.

Is there anyway to dynamically enable / disable the dates ?
I’m open to using another date picker if it supports multiple dates and can be using on multiple input fields on the same page.

Thanks

How can I write an Excel file in NodeJS and download it?

I want to retrieve data from the database and and write it on an Excel file. I use xlsx lib but there is a problem that shows to me when I open the file:

Excel cannot open the file ****.xlsx because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file.

Backend:

import express from 'express';
import cors from 'cors';
import db from './db/connect.js'; 
import bcrypt from 'bcrypt';   
import { body, validationResult } from 'express-validator';
import jwt from 'jsonwebtoken';
import dotenv from 'dotenv';
import multer from 'multer';
import * as xlsx from 'xlsx/xlsx.mjs';
import fs from 'fs'

const storage = multer.memoryStorage();


app.get('/export', async (req, res) => {
  const query = 'SELECT card_title, code, description_x, description_y FROM cards';

  db.query(query, (err, result) => {
    if (err) {
      console.error('Error fetching cards:', err);
      return res.status(500).json({ message: 'Database error' });
    }

    try {
      const workbook = xlsx.utils.book_new();
      const worksheet = xlsx.utils.json_to_sheet(result);
      xlsx.utils.book_append_sheet(workbook, worksheet, 'Cards');
      const excelFilePath = path.join(__dirname, 'cards.xlsx');
      xlsx.writeFile(workbook, excelFilePath);

      res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
      res.setHeader('Content-Disposition', 'attachment; filename=cards.xlsx');

      res.sendFile(excelFilePath, (err) => {
        if (err) {
          console.error('Error sending Excel file:', err);
          return res.status(500).json({ message: 'Error exporting data' });
        }

        setTimeout(() => {
          fs.unlink(excelFilePath, (unlinkErr) => {
            if (unlinkErr) {
              console.error('Error deleting temporary file:', unlinkErr);
            }
          });
        }, 5000);
      });
    } catch (error) {
      console.error('Error creating Excel file:', error);
      res.status(500).json({ message: 'Error generating Excel file' });
    }
  });
});

Frontend:


    const handleExport = async () => {
      try {
        const response = await axios.get('/export');
        const blob = new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
        const url = window.URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.setAttribute('download', 'cards.xlsx');
        document.body.appendChild(link);
        link.click();
        link.parentNode.removeChild(link);
      } catch (error) {
        console.error(error);
        alert('Error exporting data');
      }
    };

.....

<Dialog>
        <DialogTrigger><Button>Export</Button></DialogTrigger>
        <DialogContent>
            <DialogHeader>
            <DialogTitle>Export Cards in Excel Format</DialogTitle>
            <div className='flex justify-center items-center gap-2 '>
             <Button onClick={handleExport} className='my-9 p-5 '><RxDownload className='p-1 w-9 h-9' /></Button>               
            </div>
            </DialogHeader>
        </DialogContent>
</Dialog>

Selecting the first div with jQuery after removing the element before it

I have a bunch of <li> elements each with a different time in them and a jQuery counter that counts down to that time in m:ss.

I want to remove that element when we get to 0:00. I don’t want a load of counters all doing the same thing in each element so I’m just going to display the counter in the first element, when that reaches 0, remove it and continue in the next one in the list.

e.g.

    <ul>
      <li id="23460">12:40 (ending in 1:40)</li>
      <li id="23461">12:50</li>
      <li id="23462">13:00</li>
      <li id="23463">13:10</li>
    </ul>

This all happens in a setInterval function that runs every 1000 milliseconds.

The counter is fine, the trigger is fine. I’ve got it working perfectly on the first element but as soon as it removes that, it’s not automatically treating the next element as the first element.

Do I need to reinitialise something or am I just being stupid?

Here’s my code so far, I’ve got rid of the stuff that’s not important to this question:

var interval = setInterval(function() {
    topTime = $('.main-content li:first-child span').html();
    id=$('.main-content li:first-child').attr('id');
    
    // all the code that counts timer down to 0

    if (topTime == "0:00" ) {
      console.log("removing top list element");
      $("#"+id).hide('slow', function () { $("#"+id).remove(); });
    }
  }, 1000);

Cannot get provider component on jest test file

I’m implementing jest testing to my react project. I want to check if the correct component is displayed based on the user’s role and that comes from an AuthProvider. This is the test

import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import { MemoryRouter } from 'react-router-dom';
import KpiAdjustments from '../pages/SalesBonus/KpiAdjustments';
import { UserRole } from '../lib/types';
import { AuthProvider, useAuth } from '../providers/AuthProvider';

jest.mock('../providers/AuthProvider', () => ({
  useAuth: jest.fn(),
}));
const mockedUseAuth = useAuth as jest.Mock;

describe('KpiAdjustments - Role-based access', () => {
  console.log('AuthProviderAuthProviderAuthProviderAuthProvider', AuthProvider);

  beforeEach(() => {
    jest.clearAllMocks();
    mockedUseAuth({
      role: [UserRole.Admin],
      id: 'user-id',
    });
  });
  const renderComponent = () =>
    render(
      <MemoryRouter>
        <AuthProvider>
          <KpiAdjustments />
        </AuthProvider>
      </MemoryRouter>,
    );
  test.each([
    [UserRole.Admin, true],
    [UserRole.SalesBonusAdmin, true],
    [UserRole.SalesBonusUser, true],
    [UserRole.ForecastingUser, false],
    [UserRole.PricingAdmin, false],
    [UserRole.ProductUser, false],
  ])('renders table for role %s', (role, shouldRender) => {
    mockedUseAuth({ role: [role], id: 'user-id' });

    renderComponent();

    if (shouldRender) {
      // Check if the table header is in the document
      expect(screen.getByText('Adjustments Requiring Approval')).toBeInTheDocument();
    } else {
      // Ensure the header does not exist for unauthorized roles
      expect(screen.queryByText('Adjustments Requiring Approval')).not.toBeInTheDocument();
    }
  });
});

However, I get an error because AuthProvider is undefined even though the import is correct. I don’t get an error in the code, the AuthProvider component is exported explicity and in my index.ts it doesn’t give an error

This is my index.ts where AuthProvider is also implemented

import React from 'react';
import ReactDOM from 'react-dom/client';
import './assets/scss/_app.scss';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
import { SidebarProvider } from './providers/SidebarProvider';
import { AuthProvider } from './providers/AuthProvider';
import { ForecastProvider } from './providers/ForecastProvider';

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
  <BrowserRouter>
    <AuthProvider>
      <ForecastProvider>
        <SidebarProvider>
          <App />
          <Loading />
        </SidebarProvider>
      </ForecastProvider>
    </AuthProvider>
  </BrowserRouter>,
);

And this is the AuthProvider component

const [useAuth, Provider] = createSafeContext<IAuthContext>();

export { useAuth };

export const AuthProvider: React.FC<PropsWithChildren> = ({ children }) => {
  const [role, setRole] = useState<UserRole[] | undefined>();
  const [id, setId] = useState<string>('');

  return (
    <Provider
      value={{
        id,
        role,
      }}
    >
      {children}
    </Provider>
  );
};

Weird thing, if I log the useAuth into the test file, I get it correctly, but if I log AuthProvider I get undefined. I already tried using require and setting AuthProvider as a default export, same error.

Why is my object filled with incorrect values? [duplicate]

I’m querying a third party API (ESPN Fantasy) from my front end to clean the data and use it in my app. While adding new data details, I have an issue : when trying to apply detailed raters to my players, I end up getting wrong values. So I logged the data during the process and I get this weird result :

enter image description here

The first object is the raw data from the third party API, with the correct values. The second object is what I get when I parse them. As you can see, the collapsed version of my object has the correct values but the expanded version has wrong values. Those wrong values are the one I end up with in my app.

Here is the code where I parse the data for each player :

const basePlayerRaters: PlayerCategoriesRaters = {
  [StatsCategories.FG]: 0,
  [StatsCategories.FT]: 0,
  [StatsCategories["3PM"]]: 0,
  [StatsCategories.REB]: 0,
  [StatsCategories.AST]: 0,
  [StatsCategories.STL]: 0,
  [StatsCategories.BLK]: 0,
  [StatsCategories.TO]: 0,
  [StatsCategories.PTS]: 0,
};

const buildPlayerRaters = (
  rawRater: PlayerRatings | undefined
): PlayerCategoriesRaters => {
  const output = basePlayerRaters;
  if (rawRater) {
    rawRater.statRankings.forEach((value) => {
      const key = RaterCategories.get(value.forStat);
      if (key) {
        output[key] = value.rating;
      }
    });
  }
  console.log("build raters 2 : ", rawRater, output);

  return output;
};

While I’ve seen that console.log and object are not a good match because of async references, I don’t understand where these wrong values come from and why I get them and.