How to get the result from a forEach loop?

I have the code below, which is working (i.e. I can print the index to the console). However, I’d like to use that index outside of the forEach loop. I have tried random things like returning the tabIndex, wrapping it all in a function etc. but I don’t get it right or understand the steps needed.

The plan is to use the index to fetch data from a JSON file.

Any suggestions on how to make the result from tabIndex globally available?

/* DESTINATION TABS */
    const destinationTabs = document.querySelectorAll(".destination-info--tab");
    
    /* Get index of the clicked tab */
    destinationTabs.forEach((destinationTab) => {
      destinationTab.addEventListener("click", (e) => {
        const tabIndex = Array.from(destinationTabs).indexOf(e.target);
        console.log(tabIndex);
      });
    });

WordPress Category & Sub-category Dropdown search

Is there any way to create a select search with 2 dropdowns in WordPress – 1 for the Parent Category & 1 For the Sub-Category which changes based on the parent category chosen?

It’s for future projects I just need to know if it’s possible and which route to go with this functionality. I’m aware of the normal WordPress category search and I’ve tried the https://free.searchandfilter.com plugin but this displays all categories even the subs into one dropdown.

It would basically look something like the snippet below:

<!-- Parent Category Select -->
<select>
  <option value="slow">Slow</option>
  <option value="Fast">Fast</option>
  <option value="Fastest">Fastest</option>
</select>


<!-- Sub-Category Select -->
<select>
  <option value="Toyota">Toyota</option> <!-- Slow category -->
  <option value="Subaru">Subaru</option> <!-- Fast category -->
  <option value="mercedes">Mercedes</option> <!-- Slow category -->
  <option value="audi">Audi</option> <!-- Fastest category -->
</select>

<button>
Submit
</button>

Подключение БД к JS-проекту [closed]

Создаю приложение с использованием Яндекс Карт. Суть: получение из БД координат и показ точек на карте. Карты и подключение к БД по отдельности работают корректно. Но когда делаю подключение к БД до создания карты, то на карте не отображаются точки. Если подключаюсь к БД после создания карты, точки есть, но в консоли браузера ошибка “Uncaught TypeError: Net.connect is not a function”
Код:

const mysql = require('mysql2');

let sqlArr = [];


const conn = mysql.createConnection({
    host: "localhost", 
    user: "логин сервера",
    database: "база данных",
    password: "пароль",
    port: 3307
});

conn.connect(function (err) {
    if (err) {
        return console.error("Ошибка: " + err.message);
    }
    else {
        console.log("Подключение к серверу MySQL успешно установлено");
    }
});

let query="SELECT * FROM test";

conn.query(query, (err, result, field) =>{

    console.log(result);
    sqlArr = result;

});


ymaps.ready(init);


let placemarks = [
    {
        latitude: 59.97,
        longitude: 30.31,
        hintContent: 'This is hint',
        balloonContent: 'This is balloon'
    },
    {
        latitude: 59.95,
        longitude: 30.31,
        hintContent: 'This is hint2',
        balloonContent: 'This is balloon2'
    },
    {
        latitude: 59.96,
        longitude: 30.31,
        hintContent: 'This is hint2',
        balloonContent: 'This is balloon2'
    }
];

let geoObjects = [];

function init(){

    let map = new ymaps.Map("map", {
        center: [59.94, 30.32],
        zoom: 12,
        controls: ['zoomControl'],
        behaviors: ['drag']
    });

    for(let i = 0; i < placemarks.length; i++){
 
        geoObjects[i] = new ymaps.Placemark([placemarks[i].latitude, placemarks[i].longitude], 
        {
            hintContent: placemarks[i].hintContent,
            balloonContent: placemarks[i].balloonContent
        }, 
        {
            iconLayout: 'default#image'

        },
        {
            iconContent: 'Hello'
        }
        );
        
    }; 

    let clusterer = new ymaps.Clusterer({});

    map.geoObjects.add(clusterer);
    clusterer.add(geoObjects);

}

Использую NodeJS + Parcel

Jest – testing Link (next/link)

I am trying to write unit tests to confirm my nav links work correctly.
My MainNavigation.js file:

import Link from 'next/link';

const MainNavigation = () => {
  return (
    <header>
      <div>
        <Link href='/'>The React Parks</Link>
      </div>
      <nav>
        <ul>
          <li>
            <Link href='/all-parks'>All Parks</Link>
          </li>
          <li>
            <Link href='/new-park'>Add a New Park</Link>
          </li>
        </ul>
      </nav>
    </header>
  )
};

export default MainNavigation;

My test file:

import '@testing-library/jest-dom'
import { fireEvent, render, screen } from '@testing-library/react';
import MainNavigation from './MainNavigation';

describe('MainNavigation', () => {
    describe('links', () => {
    jest.mock('next/link', () => ({ children }) => children);

    it('should redirect to '/' when clicking on "The React Parks" text', () => {
      render(<MainNavigation />);

      const parksString = screen.getByText('The React Parks');
      fireEvent.click(parksString);
      expect(parksString.closest('link')).toHaveAttribute('href', 'https://');
    })
  });
});

How can I maybe include checking if the URL matches certain string? Or would it make sense to do something like assign a constant to render different pages and expect that constant to match some text on the other pages? How would one go about testing this functionality?

How can I get the event when user type a URL and go to it?

I saw on a website that we can see when a use try to refresh the page ( using F5 or clicking the refresh button ) in this way:

if (performance.navigation.type === 1)

My question is: Let’s say the user don’t refresh the page but he type another URL to my other page. How can I get that event?

I say that because I have stored in my Redux state if user is logged in. When the page is type another URL, my state is lost. So, I want to catch that moment and check if I have a token in localstorage.

Is it possible to insert a span at a paragraph range? It gets problematic if the paragraph already has spans

I am trying to insert a new span into a paragraph that already has spans. If the paragraph doesn’t have any spans the inserting of the new span works perfectly.

But it gets messed up when one or more spans already exists in the paragraph. Is it even possible to make this work?

At the last 3 lines of the function is where the paragraph gets put back together to insert the new span in between. I am having trouble converting the split paragraph back into a HTML format, it always seems to stay like a string or something else is getting in the way. You can get an idea by running the code and selecting some text, it will insert the span at the mouseup event.

function replaceSelectedParagraphTextBySpan() {
  // get range and text of selected text in paragraph
  let text = "";
  if (window.getSelection) {
    text = window.getSelection().toString();
  } else if (document.selection && document.selection.type != "Control") {
    text = document.selection.createRange().text;
  }
  
  const storedSelections = []
  const currSelection = window.getSelection();
  for (let i = 0; i < currSelection.rangeCount; i++) {
    storedSelections.push(currSelection.getRangeAt(i))
  }
  const rangeStart = storedSelections[0].startOffset
  const rangeEnd = storedSelections[0].endOffset

  // our paragraph
  const textObject = document.getElementById('textObject')

  const frontParagraph = textObject.innerHTML.substring(0, rangeStart)
  const backParagraph = textObject.innerHTML.substring(rangeEnd, textObject.length)
  // I tried here to convert the front and backParagraph into a paragraph element because instead it
  // just remains a string
  const pElementFront = document.createElement('p').innerHTML = frontParagraph
  const pElementBack = document.createElement('p').innerHTML = backParagraph

  // create our span for inserting
  const span = document.createElement('span')
  span.innerHTML = " <this text got added> "

  // insert new span into paragraph at selected range
  textObject.innerHTML = pElementFront
  textObject.appendChild(span)
  textObject.innerHTML = textObject.innerHTML + pElementBack
}

const paragraph = document.getElementById('textObject')
paragraph.addEventListener('mouseup', e => {
  replaceSelectedParagraphTextBySpan()
})
<p id="textObject"><span>Select some </span>text and the selected text will get replaced by a span</p>

Google sheets API sorting by date

I’m using nodejs with google sheets API and I’m trying to sort data by column with date string that looks like this: ‘dd.mm’, for example ‘01.03’. Currently I’m trying to do it by using batchUpdate, but it doesnt work. It sorts by day, 01 is first, 02 is second etc… My request looks like this:

await googleSheets.spreadsheets.batchUpdate({
    spreadsheetId,
    requestBody: {
      requests: [
        {
          sortRange: {
            range: {
              sheetId,
              startRowIndex,
              endRowIndex,
              startColumnIndex,
              endColumnIndex,
            },
            sortSpecs: [
              {
                dimensionIndex,
                sortOrder,
              },
            ],
          },
        },
      ],
    },
  });

How can I make google sheets API see the columns as dates, not as strings? Because I assume thats where the problem is, the date string is sorted like a normal string.

Adding auto expand functionality to collapsible Content script

I have used THIS SCRIPT to create collapsible sections into my website: LINK

as you can see I have problem since inside the collapsible section, I inserted a drop down menu’,
when I expand section and I click on drop down menu’ to see more voices, the collapsible section doesn’t expand automatically with the content. How can I make the collapsible section automatically expandcontract according to its content?

this is the Whole Code (Javascrip,CSS and HTML) and you can run snipet to see what happens (Section doesn’t expand according to it’s content):

window.addEventListener("DOMContentLoaded", e => {

  const getContainerHeight = el => {
    return window.getComputedStyle(el).getPropertyValue("height");
  };

  const setTransitionHeights = el => {

    let containerWasOpen = el.classList.contains("open");

    el.style.height = null;

    el.classList.remove("open", "ready");
    el.dataset.initial = getContainerHeight(el);

    el.classList.add("open");
    el.dataset.final = getContainerHeight(el);
    el.classList.remove("open");

    if(containerWasOpen) {
      el.classList.add("open");
      el.style.height = el.dataset.final;
    } else {
      el.style.height = el.dataset.initial;
    }

    el.classList.add("ready");

  };

  document.querySelectorAll(".collapsible.slow").forEach(current => {

    let toggler = document.createElement("div");
    toggler.className = "toggler";
    current.appendChild(toggler);

    setTransitionHeights(current);

    toggler.addEventListener("click", e => {
      current.style.height = current.classList.toggle("open") ? current.dataset.final : current.dataset.initial;
    });

  });

  window.addEventListener("resize", e => {

    document.querySelectorAll(".collapsible.slow").forEach(current => {
      setTransitionHeights(current);
    });

  });

});

</script>
<style>
ul, #myUL {
  list-style-type: none;
}

#myUL {
  margin: 0;
  padding: 0;
}

.caret {
  cursor: pointer;
  -webkit-user-select: none; /* Safari 3.1+ */
  -moz-user-select: none; /* Firefox 2+ */
  -ms-user-select: none; /* IE 10+ */
  user-select: none;
}

.caret::before {
  content: "25B6";
  color: black;
  display: inline-block;
  margin-right: 6px;
}

.caret-down::before {
  -ms-transform: rotate(90deg); /* IE 9 */
  -webkit-transform: rotate(90deg); /* Safari */'
  transform: rotate(90deg);  
}

.nested {
  display: none;
}

.active {
  display: block;
}
html *
{
   font-family: verdana !important;
}

body {
  background-image: url("bg.jpg");
  background-repeat: repeat;
}

.container {
  position: relative;
}

.vertical-center {
  width: 350;
  margin: 0;
  position: absolute;
  top: 12%;
  left: 5%;
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

.content {
  width: 850;
  margin: 0;
  padding-bottom: 25px;
}

.empty {
  width: 100%;
}


/* Tooltip container */
.tooltip {
  position: relative;
  display: inline-block;
  border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
}

/* Tooltip text */
.tooltip .tooltiptext {
  visibility: hidden;
  top: -5px;
  left: 105%;
  width: 220px;
  background-color: black;
  color: #fff;
  text-align: center;
  padding: 5px 0;
  border-radius: 6px;
 
  /* Position the tooltip text - see examples below! */
  position: absolute;
  z-index: 1;
}

/* Show the tooltip text when you mouse over the tooltip container */
.tooltip:hover .tooltiptext {
  visibility: visible;
}
.tooltip .tooltiptext::after {
  content: " ";
  position: absolute;
  top: 20%;
  right: 100%; /* To the left of the tooltip */
  margin-top: -5px;
  border-width: 5px;
  border-style: solid;
  border-color: transparent black transparent transparent;
}


  .boxed {
    border: 1px solid #ccc;
    padding: 1em 2em;
  }

  .collapsible.slow {
    position: relative;
    overflow: hidden;
    padding-bottom: 0.5em;
    transition: height 0.5s ease-out;
  }
  .collapsible.slow > * {
    display: none;
  }
  .collapsible.slow > p:first-child,
  .collapsible.slow.open > *,
  .collapsible.slow.ready > * {
    display: revert;
  }

  .collapsible.slow > .toggler {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    background: #fff;
    text-align: center;
    cursor: pointer;
  }
  .collapsible.slow > .toggler::after {
    content: "25bc";
  }
  .collapsible.slow.open > .toggler::after {
    content: "25b2";
  }
</style>
<div class="collapsible slow boxed">
<p align="center"><i> <strong>ONTOLOGICAL</strong></i></p>
<ul class="nested">
      <li><span class="caret">Voice One</span>
        <ul class="nested">
          <li><span class="caret">First Way</span>
            <ul class="nested">
              <li>01 Item one</li>
              <li>02 Item two</li>
              <li>03 Item three</li>
              <li>04 Item four</li>
            </ul>
          <li><span class="caret">Second Way</span>
            <ul class="nested">
              <li>01 Item one</li>
              <li>02 Item two</li>
              <li>03 Item three</li>
              <li>04 Item four</li>
            </ul>
          <li><span class="caret">Third Way</span>
            <ul class="nested">
              <li>01 Item one</li>
              <li>02 Item two</li>
              <li>03 Item three</li>
              <li>04 Item four</li>
            </ul>
          </li>
        </ul>
<li><span class="caret">Voice Two</span>
        <ul class="nested">
          <li><span class="caret">First Way</span>
            <ul class="nested">
              <li>01 Item one</li>
              <li>02 Item two</li>
              <li>03 Item three</li>
              <li>04 Item four</li>
            </ul>
          <li><span class="caret">Second Way</span>
            <ul class="nested">
              <li>01 Item one</li>
              <li>02 Item two</li>
              <li>03 Item three</li>
              <li>04 Item four</li>
            </ul>
          <li><span class="caret">Third Way</span>
            <ul class="nested">
              <li>01 Item one</li>
              <li>02 Item two</li>
              <li>03 Item three</li>
              <li>04 Item four</li>
            </ul>
          </li>
        </ul>
      </li>  
    </ul>
  </li>
</ul>
<p></p>
</div>
<script>
var toggler = document.getElementsByClassName("caret");
var i;

for (i = 0; i < toggler.length; i++) {
  toggler[i].addEventListener("click", function() {
    this.parentElement.querySelector(".nested").classList.toggle("active");
    this.classList.toggle("caret-down");
  });
}
</script>

in media printing, the header is broken on two pages except for first three

enter image description here

enter image description here

As shown in two images, after the 5th page in my printed report the header begin to be broken on two pages and all the styles are broken.

CSS:

  table {
    page-break-inside: auto;
  }
  tr {
    page-break-inside: avoid;
    page-break-after: auto;
  }
  thead {
    display: table-header-group;
  }
  tfoot {
    display: table-footer-group;
  }

How to get value of updated state immediatly in useEffect

In the following I am updating the value of a state and then trying to use it inside useEffect only but cannot get the value of the updated state can anyone help me regarding how can i get updated state immediately inside useEffect only

Thank you

    useEffect(() => {
                dispatch(setSecondaryInvName(barcodeData))
                console.log("secondaryInventoryName == ", secondaryInventoryName)
            }
    })

cypress test webservice response (xml)

Is there a simple way to test API calls and test the response of that calls? For now we do stuck at a simple xml response from within the reponse itself. We like to use xpath (cypress plugin) to crawl the xml like:

cy.request(`${DOCUMENT_FACADE}`).then((response) => {
  //response is a valid JSON and its body property holds a string (xml)  

  cy.get(response.body).xpath("//*[name() = 'myName']") //this fails by "Not a DOM Object"
  
  //Then we tried to give it a DOM object
  var parser = new DOMParser(),
      doc = parser.parseFromString(response.body, 'text/xml');
  cy.get(doc).xpath("//*[name() = 'myName']").should('have.length', 1) //fails with "expected undefined to have a length of 1 but got 0
});

Maybe we totally got something wrong about this quite important part of testing I assume.

jQuery $.parseJSON(); behaving differently in two calls

I’m using jQuery to get and parse some JSON from my ASP.Net MVC backend. I’m recieving the data correctly:

data: "{"0":"Imgs/staticResistor.png","1":"Imgs/wire.png"}"

Function to get data:

$.getJSON('https://localhost:44338/Editor/GetImgUrlFromTypeID/')
                .done((data) => {
                    console.log("JSON: " + $.parseJSON(data)[0]);
                    let json = $.parseJSON(data)[0];
                    //return $.parseJSON(data);
                })
                .fail((error) => {
                    console.log("GET request failed: " + error);
                    return "didnt work";
                });

However, when I assign $.parseJSON(data)[0]; to a variable or return it, it’s undefined:

json: undefined

I can’t discern why the method is behaving differently in different calls.

Don’t accept variables in AJax function

function clear_yes_button(clicked_id) {
  var myVar = "test";
  document.getElementById("yes_" + clicked_id).innerHTML = " ";
  <% if current_user.present? %>
  $.ajax({
    type: "PATCH",
    url: "<%= read_report_path(clicked_id) %>",
  })
  <% end %>
  }

But “clicked_id” in read_report_path(clicked_id)
undefined local variable or method `clicked_id’ for #ActionView::Base:0x00000000019370

How to pass clicked_id?

React useState, adding new object to array of objects

This a doubt I have regarding the best practice when pushing a new object in an array of objects via setState.

In the below implementation the ‘prevObjects’ are being spread into the new array to set the state. This passes the references of the old objects, but does not mutate the array or the objects. Hence does that mean the below implementation is good? It is working, but could it be problematic in some edge cases?

const [objArray, setObjArray] = useState([{ name: John }, { name: Jane }]);

setObjArray((prevObjects) => [...prevObjects, newObject])