React Native – Unexpected Token Error when Zipping and Downloading Files JSZip. Is it in a supported JavaScript type (String, Blob, ArrayBuffer)

I’m working on a React Native project where I need to fetch data from the backend, zip it, and download the zipped file using jszip and rn-fetch-blob. The code I’ve implemented is resulting in an “Unexpected Token” error, and I’m seeking guidance to understand and resolve this issue.


`import {useState, useEffect} from 'react';
import RNFetchBlob from 'rn-fetch-blob';
import JSZip from 'jszip';
import {Toast} from 'native-base';
const useDownloadZipNestedArray = async (data: any[]) => {
  try {
    const allUrlsData: {url: string; path: string}[] = [];
    const handleRecursion = (data: any[], folder: string) => {
      data?.forEach(item => {
        if (item?.naacFiles?.length) {
          item?.naacFiles?.forEach((inner: any) => {
            allUrlsData?.push({
              path: `${folder}/${item?.title}/${inner?.title}`,
              url: inner?.documentUrl,
            });
          });
        }
        if (item?.internalFolder?.length) {
          handleRecursion(item?.internalFolder, `${folder}/${item?.title}`);
        }
      });
    };

    data?.forEach(item => {
      if (item?.naacFiles?.length) {
        item?.naacFiles?.forEach((inner: any) => {
          allUrlsData?.push({
            path: `${item?.title}/${inner?.title}`,
            url: inner?.documentUrl,
          });
        });
      }

      if (item?.internalFolder?.length) {
        handleRecursion(item?.internalFolder, item?.title);
      }
    });
    // console.log(allUrlsData);
    const zip = new JSZip();

    await Promise.all(
      allUrlsData?.map(
        async item =>
          new Promise(async (resolve, reject) => {
            try {
              console.log('Fetching data for file:', item.url);

              // Fetch the image as a blob
              const response = await fetch(item?.url);

              if (!response.ok) {
                console.error(
                  'Failed to fetch data for file:',
                  item.url,
                  response.status,
                  response.statusText,
                );
                resolve(false);
                return;
              }

              const imageBlob = await response.blob();

              const fileExtension = item?.url?.split('.').at(-1);

              // Extract the filename from the URL (assuming it's the last part after '/')
              const filename =
                item?.path + '.' + fileExtension ||
                item?.url?.substring(item?.url?.lastIndexOf('/') + 1);

              // Add the blob to the ZIP archive with the extracted filename
              zip.file(filename, imageBlob);
              resolve(true);
            } catch (error) {
              console.error('Error fetching data for file:', item.url, error);
              resolve(false);
            }
          }),
      ),
    );

    const zipBlob = await zip.generateAsync({type: 'blob'});
    console.log({zipBlob});
    // const {config, fs} = RNFetchBlob;
    // let DOCUMENT_DIR = fs.dirs.DownloadDir;
    // let date = new Date();

    // let options = {
    //   fileCache: true,
    //   addAndroidDownloads: {
    //     useDownloadManager: true,
    //     notification: true,
    //     title: 'Export Zip',
    //     path:
    //       DOCUMENT_DIR +
    //       '/Erp/' +
    //       Math.floor(date.getTime() + date.getSeconds() / 2) +
    //       '.zip',
    //     description: 'Downloading....',
    //   },
    // };
    // console.log({options});
  } catch (e) {
    console.log(e);
  }
};

export default useDownloadZipNestedArray;



//here When I press this button 
 <Pressable
   onPress={() => {checkPermission();}}
   p={4}
   justifyContent={'center'}
  alignItems={'center'}
   borderRadius={'full'}
   bgColor={COLORS.secondary}
  position={'absolute'}
  shadow={2}
  bottom={5}
  right={5}>
 <AppIcon
  MaterialCommunityIconsName="download"
  size={25}
  color={'white'}
 />
</Pressable>

//here I handle the permissions
 const checkPermission = async () => {
    if (Platform.OS === 'android') {
      try {
        const granted = await PermissionsAndroid.request(
          PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
          {
            title: 'Storage Permission Required',
            message: 'Needs access to your storage to download',
            buttonPositive: 'OK',
          },
        );
        if (granted === PermissionsAndroid.RESULTS.GRANTED) {
          console.log('Storage Permission Granted.');
          useDownloadZipNestedArray(naacData?.data?.data);
        } else {
          Alert.alert('Storage Permission Not Granted');
        }
      } catch (err) {
        console.warn(err);
      }
    }
  }; 
`


Environment:

React Native version: 0.72.1
Packages: "rn-fetch-blob": "^0.12.0", "jszip": "^3.10.1"
Issue:
Encountering "Unexpected Token" error with the provided code. Seeking insights into the possible causes and solutions for this error. [enter image description here][1]

I expected the zipping and downloading process to work smoothly, resulting in a downloadable zipped file containing the converted data.

Facing Issues Sending FormData with ‘multipart/form-data’ In fetch API

I’ve this form with pug code

form.form.form-user-data
 .form__group
   label.form__label(for='name') Name
   input#name.form__input(type='text', value=`${user.name}`, required)
 .form__group.ma-bt-md
   label.form__label(for='email') Email address
   input#email.form__input(type='email', value=`${user.email}`, required)
 .form__group.form__photo-upload
   img.form__user-photo(src=`/img/users/${user.photo}`, alt=`Photo of${user.name}`)
   input.form__upload(type='file' accept='image/*' id='photo' name='photo' )
   label(for='photo') Choose new photo

This is the Backend with Node&Epress

const multerStorage = multer.memoryStorage();
const multerFitler = (req, file, cb) => {
  if (file.mimetype.startsWith('image')) {
    cb(null, true);
  } else cb(new AppError('Not an image! Please upload an image.', 400));
};
const upload = multer({
  storage: multerStorage,
  fileFilter: multerFitler,
});
exports.uploadUserPhoto = upload.single('photo');
exports.resizeUserPhoto = (req, res, next) => {
  console.log('resizeUserPhoto', req.body.file);
  if (!req.file) return next();

  req.file.filename = `user-${req.user._id}-${Date.now()}.jpeg`;

  // console.log(req.file);

  sharp(req.file.buffer)
    .resize(500, 500)
    .toFormat('jpeg')
    .jpeg({ quality: 90 })
    .toFile(`public/img/users/${req.file.filename}`);

  next();
};
function filterObj(obj, ...allowedFields) {
  const newObj = {};

  Object.keys(obj).forEach((key) => {
    if (allowedFields.includes(key)) newObj[key] = obj[key];
  });

  return newObj;
}
exports.updateMe = catchAsync(async (req, res, next) => {
  if (req.body.password || req.body.passwrodConfirm)
    return next(
      new AppError(
        'This route is not for password updates. Please use /updatePassword route',
        400,
      ),
    );

  const filterdBody = filterObj(req.body, 'name', 'email');
  if (req.file) filterdBody.photo = req.file.filename;

  const updatedUser = await User.findByIdAndUpdate(req.user._id, filterdBody, {
    new: true,
    runValidators: true,
  });

  res.status(200).json({
    status: 'success',
    data: {
      user: updatedUser,
    },
  });
});

This is my route for handling the request

router.patch('/updateMe', uploadUserPhoto, resizeUserPhoto, updateMe);

This is my Frontend code

async function updateData(endpoint, body) {
  const res = await fetch(`http://127.0.0.1:3000/api/v1/users/${endpoint}`, {
    method: 'PATCH',
    body,
  });
  const data = await res.json();

  console.log(data);
}

updateDataForm.addEventListener('submit', (e) => {
    e.preventDefault();
    const form = new FormData(updateDataForm);
    form.append('name', updateNameInput.value);
    form.append('email', updateEmailInput.value);
    form.append('photo', updatePhotoInput.files[0]);

    updateData('updateMe', form);
});

The console.log(data) Gives me this error

{
code: “LIMIT_UNEXPECTED_FILE”
field: “photo”
message: “Unexpected field”
name: “MulterError”
}

This error comes from the browser but Postman works very fine

I tried to add headers to the fetch options object

headers: { 'Content-Type': 'multipart/form-data' }

but this me another error which is

{
message: 'Multipart: Boundary not found'
}

In Postman ‘multipart/form-data; boundary=calculated when request is sent’

It’s just the error happens when the URL requested from the browser I’ve asked Chatgpt but nothing

Shadcdn DataTable: How to retrieve multiple objects?

I am using NextJS and Tailwind. The datatable I used is from shadcdn. This is the

types:
  export interface Order {
    order_id: string;
    created_at: Date;
    customers: {
      firstName: string;
      lastName: string;
      address: string;
    };
    order_items: {
      quantity: number;
      type: {
        name: string;
      };
    }[];
  }

The column:

export const columns: ColumnDef<Order>[] = [
  //rest of the codes
  {
    accessorKey: 'order_items',
    accessorFn: (row) => row.order_items,
    cell: ({ row }) => (
        console.log(row.getValue('order_items'), "row")
      ),
    header: "Orders",
  }
]

I cannot access the data for the order_items, when I tried that code above, this is what is shows inside the console:

[
  { quantity: 1, type: { name: 'Distilled Water' } },
  { quantity: 1, type: { name: 'Alkaline Water' } }
] row
[ { quantity: 2, type: { name: 'Distilled Water' } } ] row
[ { quantity: 3, type: { name: 'Distilled Water' } } ] row

How to minify my files before deploying them to the server

I want to enhance the performance of my front-end website and I found that one of the best practices is minifying my files. After searching I decided to use terser package. I’ve never done this before so some points are confusing me.

1- Do I have to change the script and CSS link in the HTML header with the minified files before building the project (I’m using parcel)?

so they will become :

<!-- <link rel="stylesheet" href="old-style.css" /> -->
<link rel="stylesheet" href="style.min.css" />
<!-- <script type="module" defer src="old-app.js"></script> -->
<script type="module" defer src="app.min.js"></script>

2- In my case, I have app.js file that imports other files:

import { revealContent } from "./script/revealContent.js";
import { gsapAnimation } from "./script/gsapAnimation.js";
import { map } from "./script/map.js";
import { showPopup, closePopup } from "./script/reservationPopup.js";
import { validateDate, validatePhone, validateForm, errorMessage} from "./script/validateData.js";
import { slider } from "./script/slider.js";

should I minify them before app.js or the order doesn’t matter?

3- If the previous script files get minified and they are now inside ./script/min-script/ folder, is terser able to know their new destination when minifying app.js so the process gets done correctly?

4- After finishing the minifying process, I guess the parcel build command should be for the new minified HTML that has the links to minified CSS/JavaScript files right?

I’d highly appreciate your help

Using animejs with webdriver > ReferenceError: NodeList is not defined

Using webdriverio to create a SaaS test. I’d like to add mouse animation using animejs so I can record the test to produce a how-to video.

In my webdriverio test (addAdditionalUsers.spec.js), I have

await closeBtn.animateMouse(); //line 34

I am importing animateMouse from functions.js:

export async function animateMouse() {
    await browser.addCommand('animateMouse', async function() {
        await this.waitForExist();
        const rect = await browser.execute(elem => elem.getBoundingClientRect(), await this);
        const targetX = rect.x;
        const targetY = rect.y;
        anime({                             //line 32
            targets: '#webdriver-mouse',
            left: targetX + 'px',
            top: targetY + 'px',
            duration: 1000, // Duration of the animation in milliseconds
            easing: 'linear'
        })
    }, true);
}

When I ran the test I received an error:

ReferenceError: NodeList is not defined
    at toArray (/node_modules/animejs/lib/anime.js:321:20)
    at parseTargets (/node_modules/animejs/lib/anime.js:644:87)
    at getAnimatables (/node_modules/animejs/lib/anime.js:649:16)
    at createNewInstance (/node_modules/animejs/lib/anime.js:845:21)
    at anime (/node_modules/animejs/lib/anime.js:933:18)
    at Element.<anonymous> (/test/includes/functions.js:32:14)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
            at Context.<anonymous> (/test/specs/addAdditionalUsers.spec.js:34:9)

I would like animejs to move the mouse to the closeBtn element.

Shopify Custom Contact Form

<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/css/select2.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/js/select2.full.min.js"></script>


<style>

.select2-selection__clear {
    display: none;
}
span.select2-dropdown.select2-dropdown--below {
  border-radius: 10px;
}
span.select2-search.select2-search--dropdown {
  display: none !important;
}
ul#select2-test-results
  li.select2-results__option:first-child
  > ul.select2-results__options--nested
  li.select2-results__option:first-child {
  display: none !important;
}
.select2-results__group {
  cursor: pointer !important;
  font-weight: 600 !important;
}
.select2-container .select2-selection--single {
  height: 55.25px !important;
  border-radius: 10px !important;
}
.select2-container--default
  .select2-selection--single
  .select2-selection__rendered {
  line-height: 55.25px !important;
  padding-left: 20px !important;
  font-size: 15px !important;
  font-weight: 100 !important;
}
.select2-container--default
  .select2-selection--single
  .select2-selection__arrow
  b {
  border-color: #000 transparent transparent transparent !important;
}
.select2-container--default
  .select2-selection--single
  .select2-selection__arrow {
  height: 55.25px !important;
  right: 5px !important;
}
.normal-field {
  border: none !important;
  animation: none !important;
}
.inquire-now .error {
  position: relative;
  animation: shake 0.1s linear;
  animation-iteration-count: 3;
  border: 2px solid red !important;
  outline: none;
}
@keyframes shake {
  0% {
    left: -2px;
  }
  100% {
    right: -2px;
  }
}
.inquire_formbody {
  margin-bottom: 2rem !important;
  padding-top: 40px !important;
}
.inquire-now .title_kwikpospages {
  color: #000 !important;
  padding-top: 5px !important;
}
.inquire-now label,
.inquire-now p {
  color: #000 !important;
}
.inquire-now p {
  padding: 8px;
}
[type=radio] {
    height: 12px !important;
}
.inquire-now input,
.inquire-now select,
.inquire-now textarea {
  height: 55.25px;
  border-radius: 10px !important;
  border: 1px solid #00b24f !important;
}
.inquire_formbody td {
  width: 50%;
}
form.inquire-now {
  background-color: #00b24f !important;
  padding: 20px;
  border-radius: 10px;
  box-shadow: -5px 7px 10px #00b24f6b !important;
  border: 1px solid #00b24f6b;
}
.inquire_formbody {
  width: 100%;
  padding: 10px 10%;
  height: 600px;
}
.inquire-now {
  width: 100%;
  padding: 0px;
  border: none;
}
.inquire-now h3 {
  font-size: 41px;
  font-weight: 700;
  color: #222;
  text-align: left;
  padding: 0px 0px 40px 0px;
}
.inquire-now table,
th,
td {
  border: none;
  padding: 10px;
}
th,
td {
  border: none;
  padding: 10px;
}
.inquire-now textarea {
  width: 100%;
  height: 150px;
  padding: 12px 20px;
  border: 0px solid #ccc;
  border-radius: 5px;
  background-color: #f4f4f4;
  font-size: 20px;
  resize: none;
  color: #ababab;
}
.inquire-now input,
.inquire-now select {
  width: 100%;
  padding: 12px 20px !important;
  display: inline-block;
  border: none;
  border-radius: 4px;
  font-size: 20px;
  border-radius: 5px;
  background-color: #f4f4f4;
}
input[type="text"]:focus {
  background-color: #f8f8f8;
  border: 0px;
}
.inquire-now input[type="submit"] {
  width: 250px;
  font-size: 20px;
  text-transform: uppercase;
  background-color: #fff;
  color: #000 !important;
  padding: 10px 20px;
  border: 1px solid #00b24f;
  border-radius: 30px;
  cursor: pointer;
}
.inquire-now input[type="submit"]:hover {
  background-color: transparent !important;
  color: #fff !important;
  border: 1px solid #fff !important;
}
@media (max-width: 767px) {
  .inquire_formbody td {
    width: 100%;
  }
  .inquire_formbody tr {
    display: grid;
  }
}
@media screen and (max-width: 720px) {
  .inquire_formbody {
    width: 100%;
    padding: 10px 2%;
    height: 600px;
  }
}


</style>


<div class="inquire_formbody">
<div class="inquire-now">
{% form 'contact', class: 'inquire-now' %}
<h2 class="title_kwikpospages">Ready To Improve Your Business Operations?</h2>
{% if form.posted_successfully? %}
<script type="text/javascript">
<!--
window.location = "/pages/thank-you-about-us";
//-->
</script>
{% endif %}

{{ form.errors | default_errors }}

<table class="inquire-now" style="padding: 0px; border:none; important!">
<tr>
<td><input class="inquire-now" type="text" id="fullname" name="contact[fullname]" placeholder="Full Name*" required></td>
<td><input class="inquire-now" type="text" id="company" name="contact[company]" placeholder="Company Name"></td>
</tr>
<tr>
<td><input class="inquire-now" type="text" id="phone" name="contact[phone]" placeholder="Phone*" onkeypress="return (event.charCode !=8 && event.charCode ==0 || (event.charCode >= 48 && event.charCode <= 57))" required></td>
<td><input class="inquire-now" type="email" id="email" name="contact[email]" placeholder="Email*" required></td>
</tr>

<tr>
<td>
<div id="select-container"></div>
<input type="hidden" id="businessType" name="contact[businessType]">
</td>
<td>
<select id="branch" name="contact[branch]">
<option value="" disabled selected>How many store/branches?</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10 or more</option>
</select>
</td>
</tr>

<tr>
<td>
<select id="region" name="contact[region]" onchange="fetchCities()">
<option value="" disabled selected>Location/Region</option>
<option value="NCR">NCR</option>
<option value="CAR">CAR</option>
<option value="Region I – Ilocos Region">Region I – Ilocos Region</option>
<option value="Region II – Cagayan Valley">Region II – Cagayan Valley</option>
<option value="Region III – Central Luzon">Region III – Central Luzon</option>
<option value="Region IV‑A – CALABARZON">Region IV‑A – CALABARZON</option>
<option value="MIMAROPA">MIMAROPA</option>
<option value="Region V – Bicol Region">Region V – Bicol Region</option>
<option value="Region VI – Western Visayas">Region VI – Western Visayas</option>
<option value="Region VII – Central Visayas">Region VII – Central Visayas</option>
<option value="Region VIII – Eastern Visayas">Region VIII – Eastern Visayas</option>
<option value="Region IX – Zamboanga Peninsula">Region IX – Zamboanga Peninsula</option>
<option value="Region X – Northern Mindanao">Region X – Northern Mindanao</option>
<option value="Region XI – Davao Region">Region XI – Davao Region</option>
<option value="Region XII – SOCCSKSARGEN">Region XII – SOCCSKSARGEN</option>
<option value="Region XIII – Caraga">Region XIII – Caraga</option>
<option value="BARMM">BARMM</option>
</select>
</td>
<td>
<select id="city" name="contact[city]">
<option value="" disabled selected>City/Province</option>
</select>
</td>
</tr>

<tr>
<td>
<p style="padding: 0 8px !important;">Do you have an existing POS System?</p>
<input type="radio" id="yes" name="contact[pos]" value="Yes"> <label for="yes">Yes</label>
<input type="radio" id="no" name="contact[pos]" value="No"> <label for="no">No</label>
</td>
</tr>

<tr>
<td colspan="2">
<textarea class="inquire-now" name="contact[requirement]" placeholder="Brief detail of your requirement"></textarea></td>
</tr>
<tr>
<td colspan="2"><input class="inquire-now" type="submit" value="Inquire Now"></td>
</tr>
</table>
<input type="hidden" name="contact[siteref]" id="siteRef">
<input type="hidden" name="contact[referrer_url]" id="referrerUrl">
<input type="hidden" name="contact[inquiry-type]" value="ABOUT US">
{% endform %}

</div>
</div>

<script>
$(document).ready(function() {
$('#select2-test-results li').on('click', function() {
$('#select2-test-results li').not(this).find('ul').hide();
$(this).find('ul').toggle();
});

// Create default select and give it an ID
var test = document.createElement("SELECT");
test.setAttribute("id", "test");
test.setAttribute("style", "width:100%");

// Populate options

var og1 = document.createElement("optgroup");
og1.label = "Food & Beverages";

var og2 = document.createElement("optgroup");
og2.label = "Retail";

var og3 = document.createElement("optgroup");
og3.label = "Services";

var opt0 = document.createElement("option");
opt0.text = "Type of Business";
var opt1 = document.createElement("option");
opt1.text = "Cafe/Bakery";
var opt2 = document.createElement("option");
opt2.text = "Casual Dining";
var opt3 = document.createElement("option");
opt3.text = "Fine Dining";
var opt4 = document.createElement("option");
opt4.text = "Bar/Lounge";
var opt5 = document.createElement("option");
opt5.text = "Food Truck";
var opt6 = document.createElement("option");
opt6.text = "Food Kiosk";
var opt7 = document.createElement("option");
opt7.text = "Fast Food";
var opt8 = document.createElement("option");
opt8.text = "Grocery";
var opt9 = document.createElement("option");
opt9.text = "Pharmacy";
var opt10 = document.createElement("option");
opt10.text = "Supermarket";
var opt11 = document.createElement("option");
opt11.text = "Clothing & Apparel";
var opt12 = document.createElement("option");
opt12.text = "Retail Store/Kiosk";
var opt13 = document.createElement("option");
opt13.text = "Flower Shop";
var opt14 = document.createElement("option");
opt14.text = "Spa & Wellness Center";
var opt15 = document.createElement("option");
opt15.text = "Auto Repair Shop";
var opt16 = document.createElement("option");
opt16.text = "Laundry & Dry Cleaning";
var opt17 = document.createElement("option");
opt17.text = "Health Care/Medical Clinic";
var opt18 = document.createElement("option");
opt18.text = "Hair Salon";
var opt19 = document.createElement("option");
opt19.text = "Pet Grooming";
var opt20 = document.createElement("option");
opt20.text = "Sports & Country Club";

og1.appendChild( opt0 );
og1.appendChild( opt1 );
og1.appendChild( opt2 );
og1.appendChild( opt3 );
og1.appendChild( opt4 );
og1.appendChild( opt5 );
og1.appendChild( opt6 );
og1.appendChild( opt7 );

og2.appendChild( opt8 );
og2.appendChild( opt9 );
og2.appendChild( opt10 );
og2.appendChild( opt11 );
og2.appendChild( opt12 );
og2.appendChild( opt13 );

og3.appendChild( opt14 );
og3.appendChild( opt15 );
og3.appendChild( opt16 );
og3.appendChild( opt17 );
og3.appendChild( opt18 );
og3.appendChild( opt19 );
og3.appendChild( opt20 );

test.add( og1 );
test.add( og2 );
test.add( og3 );

// Actually add to correct location
document.getElementById("select-container").appendChild( test );

// Give select2 class to this
$('#test').select2({
placeholder: "Business Type",
allowClear: true
}).on('change', function () {
var selectedValue = $(this).val();
$('#businessType').val(selectedValue);
});

// Onclick event to expand/collapse optgroups
$("body").on('click', '.select2-container--open .select2-results__group', function(e) {
//console.log("e: ", e);
$(this).siblings().toggle();
console.log("this: ", this);
console.log("innerHTML: ", this.innerHTML);
var grpName = this.innerHTML;
let groups = $('.select2-container--open .select2-results__group');
console.log("groups: ", groups);
$.each(groups, (index, grp) => {
let childName = grp.innerHTML;
console.log("childName: ", childName);
if (grpName.includes("Food")) {
if (childName.includes("Food") == false) {
$(grp).siblings().hide();
}
}
if (grpName.includes("Retail")) {
if (childName.includes("Retail") == false) {
$(grp).siblings().hide();
}
}
if (grpName.includes("Services")) {
if (childName.includes("Services") == false) {
$(grp).siblings().hide();
}
}

})

});

// Open event to collapse all optgroups by default
$('#test').on('select2:open', function() {
$('.select2-dropdown--below').css('opacity', 0);
setTimeout(() => {
let groups = $('.select2-container--open .select2-results__group');
console.log("groups: ", groups);
$.each(groups, (index, v) => {
$(v).siblings().hide();
console.log("v: ", v);
})
$('.select2-dropdown--below').css('opacity', 1);
}, 0);
});
});
</script>

<script>
function fetchCities() {
var region = document.getElementById('region').value;
var citySelect = document.getElementById('city');
citySelect.innerHTML = '';

if (region === 'NCR') {
var cities = ['City/Province', 'Caloocan City', 'Las Piñas City', 'Makati City', 'Malabon City', 'Mandaluyong City', 'Manila City', 'Marikina City', 'Muntinlupa City', 'Navotas City', 'Parañaque City', 'Pasay City', 'Pasig City', 'Quezon City', 'San Juan City', 'Taguig City', 'Valenzuela City'];
} else if (region === 'CAR') {
var cities = ['City/Province', 'Abra', 'Apayao', 'Benguet', 'Ifugao', 'Kalinga', 'Mountain Province'];
} else if (region === 'Region I – Ilocos Region') {
var cities = ['City/Province', 'La Union', 'Ilocos Norte', 'Ilocos Sur', 'Pangasinan', 'Alaminos City', 'Batac City', 'Candon City', 'Dagupan City', 'Laoag City', 'San Carlos City', 'San Fernando City', 'Urdaneta City', 'Vigan City'];
} else if (region === 'Region II – Cagayan Valley') {
var cities = ['City/Province', 'Batanes', 'Cagayan', 'Isabela', 'Nueva Vizcaya', 'Quirino', 'Cauayan City', 'Ilagan City', 'Santiago City', 'Tuguegarao City'];
} else if (region === 'Region III – Central Luzon') {
var cities = ['City/Province', 'Aurora', 'Bataan', 'Bulacan', 'Nueva Ecija', 'Pampanga', 'Tarlac', 'Zambales', 'Angeles City', 'Balanga City', 'Cabanatuan City', 'Gapan City', 'Mabalacat City', 'Malolos City', 'Meycauayan City', 'Muñoz City', 'Olongapo City', 'Palayan City', 'San Fernando City', 'San Jose City', 'San Jose Del Monte City', 'Tarlac City'];
} else if (region === 'Region IV‑A – CALABARZON') {
var cities = ['City/Province', 'Batangas', 'Cavite', 'Laguna', 'Quezon', 'Rizal', 'Antipolo City', 'Bacoor City', 'Batangas City', 'Biñan City', 'Cabuyao City', 'Calamba City', 'Cavite City', 'Dasmariñas City', 'Imus City', 'Lipa City', 'Lucena City', 'San Pablo City', 'Santa Rosa City', 'Tagaytay City', 'Tanauan City', 'Tayabas City', 'Trece Martires City'];
} else if (region === 'MIMAROPA') {
var cities = ['City/Province', 'Marinduque', 'Occidental Mindoro', 'Oriental Mindoro', 'Palawan', 'Romblon', 'Calapan City', 'Puerto Princesa City'];
} else if (region === 'Region V – Bicol Region') {
var cities = ['City/Province', 'Albay', 'Camarines Norte', 'Camarines Sur', 'Catanduanes', 'Sorsogon', 'Masbate', 'Iriga City', 'Legazpi City', 'Ligao City', 'Masbate City', 'Naga City', 'Sorsogon City', 'Tabaco City'];
} else if (region === 'Region VI – Western Visayas') {
var cities = ['City/Province', 'Aklan', 'Antique', 'Capiz', 'Guimaras', 'Iloilo', 'Negros Occidental', 'Bacolod City', 'Bago City', 'Cadiz City', 'Escalante City', 'Himamaylan City', 'Iloilo City', 'Kabankalan City', 'La Carlota City', 'Passi City', 'Roxas City', 'Sagay City', 'San Carlos City', 'Silay City', 'Sipalay City', 'Talisay City', 'Victorias City'];
} else if (region === 'Region VII – Central Visayas') {
var cities = ['City/Province', 'Bohol', 'Cebu', 'Negros Oriental', 'Siquijor', 'Bais City', 'Bayawan City', 'Bogo City', 'Canlaon City', 'Carcar City', 'Cebu City', 'Danao City', 'Dumaguete City', 'Guihulngan City', 'Lapu-Lapu City', 'Mandaue City', 'Naga City', 'Tagbilaran City', 'Talisay City', 'Tanjay City', 'Toledo City'];
} else if (region === 'Region VIII – Eastern Visayas') {
var cities = ['City/Province', 'Biliran', 'Leyte', 'Eastern Samar', 'Northern Samar', 'Samar', 'Southern Leyte', 'Baybay City', 'Borongan City', 'Calbayog City', 'Catbalogan City', 'Maasin City', 'Ormoc City', 'Tacloban City'];
} else if (region === 'Region IX – Zamboanga Peninsula') {
var cities = ['City/Province', 'Zamboanga Del Norte', 'Zamboanga Del Sur', 'Zamboanga Sibugay', 'Dapitan City', 'Dipolog City', 'Isabela City', 'Pagadian City', 'Zamboanga City'];
} else if (region === 'Region X – Northern Mindanao') {
var cities = ['City/Province', 'Bukidnon', 'Camiguin', 'Lanao Del Norte', 'Misamis Occidental', 'Misamis Oriental', 'Cagayan De Oro City', 'El Salvador City', 'Gingoog City', 'Iligan City', 'Malaybalay City', 'Oroquieta City', 'Ozamiz City', 'Tangub City', 'Valencia City'];
} else if (region === 'Region XI – Davao Region') {
var cities = ['City/Province', 'Davao De Oro', 'Davao Del Norte', 'Davao Occidental', 'Davao Oriental', 'Davao Del Sur', 'Davao City', 'Digos City', 'Mati City', 'Panabo City', 'Samal City', 'Tagum City'];
} else if (region === 'Region XII – SOCCSKSARGEN') {
var cities = ['City/Province', 'Cotabato', 'South Cotabato', 'Sultan Kudarat', 'Sarangani', 'Cotabato City', 'General Santos City', 'Kidapawan City', 'Koronadal City', 'Tacurong City'];
} else if (region === 'Region XIII – Caraga') {
var cities = ['City/Province', 'Agusan Del Norte', 'Agusan Del Sur', 'Dinagat Islands', 'Surigao Del Norte', 'Surigao Del Sur', 'Bayugan City', 'Bislig City', 'Butuan City', 'Cabadbaran City', 'Surigao       City', 'Tandag City'];
    } else if (region === 'BARMM') {
    var cities = ['City/Province', 'Basilan', 'Lanao Del Sur', 'Maguindanao', 'Sulu', 'Tawi-Tawi'];
    }
    for (var i = 0; i < cities.length; i++) {
    var option = document.createElement('option');
    option.value = cities[i];
    option.text = cities[i];
    citySelect.appendChild(option);
    }
    }
</script>

<script>

    var params = window.location.search.substr(1).split('&');
    if (localStorage.getItem('siteref') != null) {
    document.getElementById("siteRef").value = localStorage.getItem('siteref');
    }

    if (localStorage.getItem('referrer_url') != null) {
    document.getElementById("referrerUrl").value = localStorage.getItem('referrer_url');
    }

</script>

I created a custom form for my website unfortunately when I tried it again yesterday the submit button redirected me to a challenge page it supposed to be redirected to a thank you page then when I tried to click the submit button of the reCAPTCHA it did not go anywhere it stucked me on that page but before it was working fine and it is not redirecting to a challenge page I don’t understand why it is acting weird lately.

https://www.loom.com/share/30bda5b9626e4dbd943f18ea415b92cf?sid=9397382e-af10-4df4-a5c5-9c7649cdd444

Can someone help me? Thanks in advance.

Also I tried to disable the reCAPTCHA but it is affecting the submit button of the actual form

https://www.loom.com/share/0ac4f85328b14ede8dde6d54e83e712b?sid=26b82a1c-6a33-41d9-92d7-fc0d182410f6

chrome to edge formdata api call

<form id="frm" method="post" action="http://aa.com/loginProc" entype="multipart/form-data">
  <button id="btn" onclick="Action()">실행</button>
  <input type="hidden" name="userId" value="${userId}">
  <input type="hidden" name="passWd" value="test123">
</form>

<script>
function Action(){
  var form = document.getElementById("frm");
  var newWindow = window.open('http://aa.com/main','_blanck');
  form.target = newWindow.name;
  form.submit();
}
</script>

지금 위에 소스는 한 브라우저에서 새탭으로 열려 form action을 성공하여 main으로 가지는 것까지는 구현을 하였지만,

크롬에서 btn 버튼 클릭시 http://aa.com/loginProc가 실행되고 성공이면

form 데이터를 가지고 엣지브라우저로 http://aa.com/main으로 넘길 수 있을까요?

JavaScript library for dealing with merging two conflicting changes to an underlying text file (like git)?

I am imagining sort of recreating the Wikipedia edit experience, but in Next.js/React/JS. According to ChatGPT, when two users are editing a Wikipedia page at the same time and save close together:

MediaWiki will detect the conflict and generate an “edit conflict” page. This page will display both versions of the text, highlighting the conflicting parts. Editors can then manually merge the changes or choose one version over the other. They can also make further edits to resolve the conflict.

The only UI example I can see of that currently is this:

enter image description here


How can this be implemented in JavaScript-land? Is there a library for doing this? I have seen jsdiff, for generating visual text diffs in JS, but the “resolving the conflict” part I’m not so sure how to accomplish that. Maybe that is kind of a UX question.

I would only really like to have a simple solution as follows (not a full git alternative): multiple users are editing a file. When you start editing, it creates a “fork” or “branch” of the file, in draft mode. When you are complete, you try and merge your branch draft into the original file. If changes were made since you last branched, then it does a diff, and shows you the diff. The question is, what should be done to allow for resolving the diff?

One solution would be a “take one or the other” solution. Another solution would be to do like git does and how I fix merge conflicts in git manually in the text editor, with the >>>>>> etc. boundaries. Is there a tool to do that in JS? Or could I hack git on the CLI to do that against two files somehow (that would be fast)?

What are the options here basically?

Sidenote: The more I think about this, the more I’m considering just having users add their blog posts directly into a “blog post git repo”, and deal with it that way. There are barriers to entry and also problems with that approach, but at least then I wouldn’t have to reinvent the wheel on this complex problem so much.

Next.js : serve different page for same url for different domains

I have single Next.js application in which i have to maintain the different pages for same url, but there are some common pages which can be access by both domains.

E.g. I have a domain like abc.com and xyz.com,
When abc.com/home is called i want to serve a home page for website abc and same for xyz.com/home it should open home page for website xyz

but there is a common page for both like contact, so for both abc.com/contact and xyz.com/contact should open the same page, just a layout for that page will be different

I have tried this with server.ts

const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')
 
const dev = process.env.NODE_ENV !== 'production'
const hostname = 'localhost'
const port = 3000
// when using middleware `hostname` and `port` must be provided below
const app = next({ dev, hostname, port })
const handle = app.getRequestHandler()
 
app.prepare().then(() => {
  createServer(async (req, res) => {
    try {
      // Be sure to pass `true` as the second argument to `url.parse`.
      // This tells it to parse the query portion of the URL.
      const host = req.headers.host;

       if (host === 'abc.com') {
         await app.render(req, res, '/abc', req.query)
       } else if (host === 'xyz.com') {
         await app.render(req, res, '/xyz',req.query)
       } else {
        await handle(req, res)
       }
    } catch (err) {
      console.error('Error occurred handling', req.url, err)
      res.statusCode = 500
      res.end('internal server error')
    }
  })
    .once('error', (err) => {
      console.error(err)
      process.exit(1)
    })
    .listen(port, () => {
      console.log(`> Ready on http://${hostname}:${port}`)
    })
})

and my file structure is like

my-project
  --src
    --app
      --page.tsx
      --layout.tsx
      --abc
        --layout.tsx
        --home
          --page.tsx
      --xyz
        --layout.tsx
        --home
          --page.tsx
      --contact (in this layout should be used from abc or xyz as per domain)
        page.tsx
  -- other nextjs folders

but in this i cannot access the contact page both the domain

What should i do to achieve this in nextjs?

HTTP Request Header Transfer-Encoding: chunked not getting set even when Body is a ReadableStream

We are trying to look at a solution to upload large files through a React web application. We are thinking of File Streaming solution, to reduce the time take for upload as files can be as large as 20 GB. I had created converted the file uploaded through React File Upload UI Component, converted it to ReadableStream, and used it as the RequestBody.

As I know that Transfer-Encoding is a Restricted header in an Http Request, I didnt set it manually, but have to allow the user agent to set it. Based on other answers I found on StackOverflow, I hoped that a ReadableStream in the RequesteBody would make the user agent set the Request Header ‘Transfer-Encoding’ : ‘chunked’ request header, but I dont see that. Below is the piece of code I used:

const blob = new Blob([tarFile])    
    const tarStream = blob.stream()
    post(upgradeUrl, tarStream, oidcUser.access_token, {
      'Content-Type': 'text/plain'
    }).then(
      () => {
        console.log('upload completed')
      },
      (error) => {
        setErrorMessage(getGlopErrorMessage(error, t))
      }
    )    
  }

Does anyone know the correct way of doing this? Thanks.

requestVideoFrameCallback not firing when tab in background

Here’s a snippet showing the problem in action, but basically the requestVideoFrameCallback stops running when the tab is backgrounded in Chrome.

function startTest() {
    video = document.querySelector('video');
    canvas = document.querySelector('canvas');
    ctx = canvas.getContext('2d');

    let start_time = 1.0, paint_count = 0, raf_count = 0;
    let last_time = 0;
    var paintFrame = function(timestamp, metadata) {
      if (start_time == 1.0)
        start_time = timestamp;
      updateCanvas(ctx, video);
      last_counter = metadata.presentedFrames;

      var elapsed_frame = 0;
      var elapsed = (timestamp - start_time) / 1000.0;
      
      if(last_time == 0){
        console.log('init')
        elapsed_frame = 0
      }else{
         elapsed_frame = (new Date()).getTime() - last_time
      }
      last_time = (new Date()).getTime()
      
      var fps_text = document.querySelector('#fps');
      var presented = metadata.presentedFrames + 1;
      fps_text.innerText =
          'actual fps: ' + (++paint_count / elapsed).toFixed(3) + ', ideal fps: ' +
          (presented / elapsed).toFixed(3) + ', missed: ' +
          (presented - paint_count) + '/' + presented +
          '(' +  ((presented - paint_count)/presented*100.0).toFixed(1) + '%)';
      
      if(elapsed_frame > 100){
        console.log('Long clock-time', elapsed_frame, 'missed', (presented - paint_count));
      }
      
      video.requestVideoFrameCallback(paintFrame);
    };
    video.onplay = function(){
      v = video.requestVideoFrameCallback(paintFrame);
    };

    video.playbackRate = 1.0;

    video.src="https://tguilbert-google.github.io/vid/buck360p_vp9.webm"

  };

https://codepen.io/jerodvenemafm/pen/gOqqWmJ

Here’s a reference to the Chrome docs:

https://developer.chrome.com/blog/background_tabs/

and specifically stating how this should run in the background if audio is on:

https://bugs.chromium.org/p/chromium/issues/detail?id=1012063

Both seem to imply that this is not the expected behavior, so I’m at a bit of a loss here. Is this a Chrome bug, or is there some sort of setting I’m missing?

How do I subtract only the time in my javascript array

I want to subtract the time of period 8 to 7.
I originally got this code from chat gpt but needed to rewrite everything so im trying to learn now so this may not make since due to me being a newbie

const periods = [
  { time: 9.11, name: "advisory" },
  { time: 9.57, name: "second period" },
  { time: 10.48, name: "third period" },
  { time: 11.39, name: "fourth period" },
  { time: 12.30, name: "fifth period" },
  { time: 13.05, name: "lunch" },
  { time: 13.56, name: "sixth period" },
  { time: 14.47, name: "seventh period" },
  { time: 15.40, name: "eighth period" }
];

console.log(periods[8] – periods[7])

As I stated i’m new to this and don’t know if there is a way to only get the time so i can do the math.

I tried doing periods.time but that didn’t work. I have basically 0 clue how I could do this
I read some documentation on w3schools but I still couldn’t understand. If you could help explain this would be very helpful.