min-height behaviour in css [closed]

I don’t know what the problem of min-height is. I learned that it defines the minimum height of element but now it is behaving somehow. Until when I put it in a scrollable element that the scroll works as expected.

Is it a must I always set the min-height for a scrollable element before or for it to function well?

I was expecting the scrollable element not height beyond the viewport but it does not until I added min-height: 0; that it stops spanning beyond the viewport

Can I use quickbook API on node js client side application to access data?

I have created simple node js application using express for quick book authentication and get access token, Once I get access token I am try to get journalentry from my another client side node js application, when I write code to access journalentry it’s give me following error on console log

Access to fetch at
‘https://sandbox-quickbooks.api.intuit.com/v3/company/xxxx/query?minorversion=75&query=select%20*%20from%20journalentry%20startposition%201%20maxresults%20500’
from origin ‘https://localhost:3000’ has been blocked by CORS policy:
Response to preflight request doesn’t pass access control check: No
‘Access-Control-Allow-Origin’ header is present on the requested
resource.

When I put same code on node js express server, I am able access data.
So my conclusion is quickbook api doesn’t NOT support client-side API calls.

Am I right ? or is there any another way to achieve that?

Code sample for reference

const requestRootUrl = "https://sandbox-quickbooks.api.intuit.com";
const companyId = "xxxx";
  const selectQuery = "select * from journalentry startposition 1 maxresults 500";
  try {
    const response = await fetch(`${requestRootUrl}/v3/company/${companyId}/query?minorversion=75&query=${selectQuery}`, {
      headers: {
        Authorization: `Bearer ${accessToken}`,
        Accept: 'application/json'
      }
    });
    const responseData = await response.json();
    if (responseData.error) {
      alert("response Data Error: " + responseData.error_description);
      return;
    }
    console.log("response Data, ", responseData)
  } catch (error) {
    console.log("Error details", error)
  }

How to Fetch Other Posts on Scroll Without AJAX and Jquery in WordPress?

I want to fetch other posts in WordPress. I can fetch next post on scroll. But when I go to latest post, it fetches nothing. When I go to the second latest post, on scroll it fetches only first post. When I go to the third latest post, it fetches only first and second latest posts. And so on. I want to fetch all posts on scroll, one by one.

<?php
$next_post = get_next_post();
  if ($next_post) :
    $next_post_url = get_permalink($next_post->ID);
?>
    <a id="next-post-link" href="<?php echo esc_url($next_post_url); ?>" 
       style="display: none;">
    </a>
<?php endif; ?>

JavaScript

document.addEventListener("DOMContentLoaded", function()
  {
  let loading = false;

  window.addEventListener("scroll", function()
    {
    let nextPostLink = document.getElementById("next-post-link");

    if (!nextPostLink || loading) return;

    let scrollPosition = window.innerHeight + window.scrollY;
    let documentHeight = document.documentElement.scrollHeight;

    if (scrollPosition >= documentHeight - 200) 
      {
      loading = true;
      let url = nextPostLink.href;

      fetch(url)
      .then(response => response.text())
      .then(data => 
        {
        let parser  = new DOMParser();
        let doc     = parser.parseFromString(data, "text/html");
        let newPost = doc.querySelector("#post-container .post");

        if (newPost) 
          {
          document.getElementById("post-container").appendChild(newPost);

          let newNextPostLink = doc.querySelector("#next-post-link");
          if (newNextPostLink) 
            {
            nextPostLink.href = newNextPostLink.href;
            } 
          else 
            {
            nextPostLink.remove(); // No more posts
            }

          // Update URL without reloading
          history.pushState(null, "", url);
          }

        loading = false;
        })
      .catch(error =>
        {
        console.error("Error fetching next post:", error);
        loading = false;
        });
      }
    });
  });

React native reanimated Build issues

I made an app using supabase client and react native using expo, It runs fine on dev move in Expo go app, Now I tried to build it and faced issues. Later It compiled but ever since each build has blank screen after after each build. I decided now to try simple View tag with text in app/_layout.tsx, now compiling gave a working app. Now i decided to use bgm for testing and the BGM plays when i open the app but nothing shows. I have tries almost everything nothing resolved it, I think its caused by react-native-reanimated library but i add its requirement of plugin in my babel. here is my app/_layout.tsx and index.tsx as far as i have understood the error index is either not loading or not animating at all.
i have verified almost everything. Its an urgent project of sorts, can anyone give me idea, what should i do. And I also have added gesture handler and safe area provider in main _layout.tsx

import { pvpGameRole, roomIdAtom, selectedBoardAtom } from '@/utils/atoms/store';
import { useButtonAudio } from '@/utils/AudioProvider';
import { useFocusEffect } from '@react-navigation/native';
import { LinearGradient } from 'expo-linear-gradient';
import { useRouter } from 'expo-router';
import { useSetAtom } from 'jotai';
import { ChevronRight, Settings } from 'lucide-react-native';
import { useCallback } from 'react';
import { Image, Pressable, Text, TouchableOpacity, View } from 'react-native';
import Animated, { FadeInUp } from 'react-native-reanimated';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

export default function HomeScreen() {
  const router = useRouter();
  const insets = useSafeAreaInsets();
  const { playButtonSound } = useButtonAudio();
  const setSelectedBoard = useSetAtom(selectedBoardAtom);
  const setRoomId = useSetAtom(roomIdAtom);
  const setPvpGameRole = useSetAtom(pvpGameRole);

  useFocusEffect(
    useCallback(() => {
      setSelectedBoard(null);
      setRoomId(null);
      setPvpGameRole(null);
    }, [])
  );

  const handlePlayAIPress = () => {
    playButtonSound();
    router.replace({
      pathname: '/(tabs)/select',
      params: { from: 'AI' },
    });
  };

  const handlePlayPVPPress = () => {
    playButtonSound();
    router.replace({
      pathname: '/(tabs)/select',
      params: { from: 'PVP' },
    });
  };

  return (
    <View className="flex-1 bg-gray-50 p-5" style={{ paddingTop: insets.top }}>
      <Animated.View
        className="mt-4 rounded-2xl  overflow-hidden mb-8 relative"
        entering={FadeInUp.duration(1000).springify().delay(100)}
      >
        <View className="flex-row justify-between items-center px-4">
          <Text className="font-bold" style={{ fontSize: 32 }}>Bingo Blast</Text>
          <Pressable onPress={() => {
            playButtonSound();
            router.push("/settings");
          }}>
            <Settings size={28} color="#000" />
          </Pressable>
        </View>
      </Animated.View>
      <Animated.View
        className="mt-2 h-[200px] rounded-2xl overflow-hidden mb-8 relative"
        entering={FadeInUp.duration(1000).springify().delay(300)}
      >
        <Image source={icons.banner} className="w-full h-full" />
        <LinearGradient
          colors={['rgba(150, 120, 255, 0.3)', 'transparent']}
          className="absolute left-0 right-0 top-0 h-full"
        />
      </Animated.View>

      <View className="gap-y-4">
        <Animated.View entering={FadeInUp.duration(800).springify().delay(500)}>
          <TouchableOpacity
            className="rounded-xl overflow-hidden shadow-md"
            onPress={() => {
              playButtonSound();
              router.push('/(tabs)/boards');
            }}
          >
            <LinearGradient
              colors={['#4158D0', '#C850C0']}
              className="p-5 h-[110px]"
            >
              <Text className="font-poppins-bold text-xl text-white mb-2">Your Boards</Text>
              <Text className="font-poppins-regular text-sm text-white/90 w-4/5">
                Design & manage your own bingo boards
              </Text>
              <ChevronRight color="#fff" size={24} style={{ position: 'absolute', right: 20, bottom: 20 }} />
            </LinearGradient>
          </TouchableOpacity>
        </Animated.View>

        <Animated.View entering={FadeInUp.duration(800).springify().delay(700)}>
          <TouchableOpacity
            className="rounded-xl overflow-hidden shadow-md"
            onPress={handlePlayAIPress}
          >
            <LinearGradient
              colors={['#FF512F', '#F09819']}
              className="p-5 h-[110px]"
            >
              <Text className="font-poppins-bold text-xl text-white mb-2">Play Against AI (Beta)</Text>
              <Text className="font-poppins-regular text-sm text-white/90 w-4/5">
                Challenge our AI in an exciting game of bingo
              </Text>
              <ChevronRight color="#fff" size={24} style={{ position: 'absolute', right: 20, bottom: 20 }} />
            </LinearGradient>
          </TouchableOpacity>
        </Animated.View>

        <Animated.View entering={FadeInUp.duration(800).springify().delay(700)}>
          <TouchableOpacity
            className="rounded-xl overflow-hidden shadow-md"
            onPress={handlePlayPVPPress}
          >
            <LinearGradient
              colors={['#2D6A4F', '#95E1A8']}
              className="p-5 h-[110px]"
            >
              <Text className="font-poppins-bold text-xl text-white mb-2">PvP Showdown</Text>
              <Text className="font-poppins-regular text-sm text-white/90 w-4/5">
                Ready to test your skills in real battle?
              </Text>
              <ChevronRight color="#fff" size={24} style={{ position: 'absolute', right: 20, bottom: 20 }} />
            </LinearGradient>
          </TouchableOpacity>
        </Animated.View>
      </View>
    </View>
  );
}
import React from 'react';

export default function TabsLayout() {
    return (
        <Tabs
            screenOptions={{
                headerShown: false
            }}
            tabBar={() => null}
        >
            <Tabs.Screen name="index" />
            <Tabs.Screen name="ai" />
            <Tabs.Screen name="boards" />
            <Tabs.Screen name="create_lobby" />
            <Tabs.Screen name="join_lobby" />
            <Tabs.Screen name="pvp" />
            <Tabs.Screen name="room" />
            <Tabs.Screen name="select" />
            <Tabs.Screen name="settings" />
        </Tabs>
    );
}

Show only the current page on a scrollspy-type menu

I made a mouse-wheel horizontal-scrolling page, based on code that I found. As you see in the code, there are only 10 pages, but I want to add more. As you scroll through the pages, the menu at right shows your current page. Now, if there were 40 or 50 pages, the menu could not show all of them.

So, how do I show only the current page, or possibly one before the current and one after the current? In other words, pages 3, 4, and 5 in the menu. They would need to change as the user continue scrolling so that only the current page and the before and after pages are showing in the menu.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Animation</title>
<link rel="stylesheet" href="13.css">
</head>
<body>
<div class="container">

<section class="sectionA sliding">
<div id="slide1"   class="slide"    style="background-image:url(2.jpg)"></div>
<div id="slide2"   class="slide"    style="background-image:url(3.jpg)"></div>
<div id="slide3"   class="slide"    style="background-image:url(4.jpg)"></div>
<div id="slide4"   class="slide"    style="background-image:url(5.jpg)"></div>
<div id="slide5"   class="slide"    style="background-image:url(6.jpg)"></div>
<div id="slide6"   class="slide"    style="background-image:url(7.jpg)"></div>
<div id="slide7"   class="slide"    style="background-image:url(8.jpg)"></div>
<div id="slide8"   class="slide"    style="background-image:url(9.jpg)"></div>
<div id="slide9"   class="slide"    style="background-image:url(10.jpg)"></div>
<div id="slide10"  class="slide"    style="background-image:url(11.jpg)"></div></section>

<div class="navBar item">
<div class="line"></div>
<div class="navSectionContent active" id='section_1'>   <span>Page 1</span>   <button></button></div>
<div class="navSectionContent"        id='section_2'>   <span>Page 2</span>   <button></button></div>
<div class="navSectionContent"        id='section_3'>   <span>Page 3</span>   <button></button></div>
<div class="navSectionContent"        id='section_4'>   <span>Page 4</span>   <button></button></div>
<div class="navSectionContent"        id='section_5'>   <span>Page 5</span>   <button></button></div>
<div class="navSectionContent"        id='section_6'>   <span>Page 6</span>   <button></button></div>
<div class="navSectionContent"        id='section_7'>   <span>Page 7</span>   <button></button></div>
<div class="navSectionContent"        id='section_8'>   <span>Page 8</span>   <button></button></div>
<div class="navSectionContent"        id='section_9'>   <span>Page 9</span>   <button></button></div>
<div class="navSectionContent"        id='section_10'>  <span>Page 10</span>  <button></button></div></div>

<div class="loader"><img src="12.gif"></div></div>

<script src="14.js"></script>

</body></html>
html {
overflow:hidden;
}
body,html {
height:100vh;
}
body {
background:#000;
margin:0;
padding:0;
color:#fff;
font-family:arial;
font-size:12px;
}
div.container {
width:100%!important;
margin:0;
position:relative;
}
.container {
height:100%;
position:relative;
}
.loader {
background:#000;
width:100%;
height:100%;
position:absolute;
left:0;
top:0;
z-index:1000;
}
.loader img {
position:absolute;
margin:auto;
left:0;
right:0;
bottom:0;
top:0;
}
.sectionA {
height:100%;
}
.sectionA::after,.sectionA::before {
display:table;
content:"";
}
.sectionA::after {
clear:both;
zoom:1;
}
.sectionA.sliding {
-webkit-transition:all .4s ease;
-moz-transition:all .4s ease;
-o-transition:all .4s ease;
transition:all 1s ease-in-out .3s;
}
.navBar {
width:100px;
height:590px;
position:fixed;
right:.5vw;
margin:auto;
}
.navBar.item {
height:590px;
top:3vh;
}
.navBar.item .line {
position:absolute;
right:5px;
top:0vh;
height:590px;
width:12px;
border:1px solid #fff;
background:transparent;
}
.navBar::after,.navBar::before {
display:table;
content:"";
}
.navBar::after {
clear:both;
zoom:1;
}
.navBar .navSectionContent {
position:relative;
margin-bottom:46px;
text-align:right;
float:right;
display:inline-block;
clear:both;
}
.navBar button {
width:0;
height:0;
background:transparent;
position:absolute;
top:0;
right:0;
bottom:0;
margin:auto;
border:0;
}
.navBar .navSectionContent.active button {
background:rgba(0,255,0,.7);
width:12px;
height:43px;
position:absolute;
top:0;
right:6px;
bottom:0;
margin:auto;
}
.navBar span {
margin-right:30px;
cursor:pointer;
font-size:12px;
font-weight:200;
display:inline-block;
color:#fff;
background:rgba(0,0,0,.3);
padding:0 4px;
}
.navBar .navSectionContent.active span {
color:#fff;
background:rgba(0,255,0,.3);
padding:12px;
margin-right:18px;
border-radius:8px;
border-top-right-radius:0;
border-bottom-right-radius:0;
border:1px solid rgba(255,255,255,.3);
font-size:14px;
font-weight:400;
}
.slide {
height:100%;
float:left;
}
@media only screen and (max-width:1350px) {
.navBar {
right:19px;
}
}
.slide {
background:#skyblue;
}
var A_util = {
browser: {
hasTouchSupport: 'createTouch' in document,
version: (navigator.userAgent.toLowerCase().match(/.+(?:rv|it|ra|ie)[/: ]([d.]+)/) || []) [1],
androidversion: function () {
var e = navigator.userAgent.match(/s*Androids*([0-9]+).?([0-9]+)?.?([0-9]+)?s*/);
return e && e[1] && e[2] ? parseFloat(e[1] + '.' + e[2]) : !(!e || !e[1]) && parseFloat(e[1])},
isWebkit: - 1 < navigator.userAgent.indexOf('AppleWebKit/'),
isMobileSafari: /(ipad|iphone|ipod|android).*apple.*mobile.*safari/.test(navigator.userAgent.toLowerCase()),
isAppleChrome: /crios/.test(navigator.userAgent.toLowerCase()),
isAppleMobileDevice: /(ipad|iphone|ipod)/.test(navigator.userAgent.toLowerCase()),
isAndroidMobileDevice: /android/.test(navigator.userAgent.toLowerCase()),
isTansoDl: navigator.userAgent.toLowerCase().match(/TansoDL/i),
isWindowsPhone: function () {
return !!(navigator.userAgent.toLowerCase().match(/Windows CE|IEMobile|Windows Phone OS/i) || 'XDomainRequest' in window)},
highPixelDensityDisplay: 2 <= window.devicePixelRatio,
iPhone4: 2 <= window.devicePixelRatio && this.isMobileSafari,
currentOrientation: null,
isBlackBerry: function () {
return !!navigator.userAgent.match(/BlackBerry/i)},
isBB10: function () {
return !!navigator.userAgent.match(/BB10/i)},
iOSversion: function () {
var e = window.navigator.userAgent,
t = e.indexOf('OS ');
return ( - 1 < e.indexOf('iPhone') || - 1 < e.indexOf('iPad')) && - 1 < t ? window.Number(e.substr(t + 3, 3).replace('_', '.')) : 0 }},
addClass: function (e, t) {
var n = e && 'object' == typeof e.className ? e.className.baseVal : e.className;
this.hasClass(e, t) || ('object' == typeof e.className ? e.className.baseVal = n += n ? ' ' + t : t : e.className = n += n ? ' ' + t : t)},
addClassMultiple: function (e, t) {
for (var n = 0, a = e.length; n < a; n++) this.hasClass(e[n], t) || (e[n].className ? e[n].className += ' ' + t : e[n].className += t)},
addEventHandler: function (e, t, n) {
e.addEventListener ? e.addEventListener(t, n, !1) : e.attachEvent ? e.attachEvent('on' + t, n) : e['on' + t] = n},
extendSimple: function (e, t) {
for (var n in t) t.hasOwnProperty(n) && (e[n] = t[n]);
return e},
extendDefaults: function (e, t, n) {
var a,
o = Object.prototype.hasOwnProperty;
for (a in t) !o.call(t, a) || 'constructor' === a && e === window || (void 0 === t[a] ? delete e[a] : n && void 0 !== e[a] || (e[a] = t[a]));
return e},
hasClass: function (e, t) {
e = e && 'object' == typeof e.className ? e.className.baseVal : e.className;
return e && new RegExp('(\s|^)' + t + '(\s|$)').test(e)},
removeClass: function (e, t) {
var n = ' ' + (e && 'object' == typeof e.className ? e.className.baseVal : e.className).replace(/[trn]/g, ' ') + ' ';
if (this.hasClass(e, t)) {
for (; 0 <= n.indexOf(' ' + t + ' '); ) n = n.replace(' ' + t + ' ', ' ');
'object' == typeof e.className ? e.className.baseVal = n.replace(/^s+|s+$/g, '') : e.className = n.replace(/^s+|s+$/g, '')}},
removeClassMultiple: function (e, t) {
for (var n = 0, a = e.length; n < a; n++) {
var o = ' ' + e[n].className.replace(/[trn]/g, ' ') + ' ';
if (this.hasClass(e[n], t)) {
for (; 0 <= o.indexOf(' ' + t + ' '); ) o = o.replace(' ' + t + ' ', ' ');
e[n].className = o.replace(/^s+|s+$/g, '')}}},
removeEventHandler: function (e, t, n) {
e.removeEventListener ? e.removeEventListener(t, n, !1) : e.detachEvent ? e.detachEvent('on' + t, n) : e['on' + t] = null},
children: function (e) {
for (var t = e.childNodes, n = [], a = t.length; a--; ) 1 == t[a].nodeType && n.unshift(t[a]);
return n},
triggerEvent: function (e, t) {
var n;
document.createEvent ? ((n = document.createEvent('HTMLEvents')).initEvent(t, !0, !1), e.dispatchEvent(n)) : e.fireEvent('on' + t)},
ajaxGet: function (e) {
var t,n = '';
for (t in e.data) '' != n && (n += '&'),n += t + '=' + encodeURIComponent(e.data[t]);
var a = new XMLHttpRequest;
a.open('GET', e.url + '?' + n, !0),
a.onreadystatechange = function () {
4 === this.readyState && (200 <= this.status && this.status < 400 ? e.success && 'function' == typeof e.success && e.success(JSON.parse(this.responseText)) : console.error('Ajax error occured.'))},a.send()},
ajaxGetData: function (e) {
var t = '';
if (void 0 !== e.data) for (var n in e.data) '' != t && (t += '&'),t += n + '=' + encodeURIComponent(e.data[n]);
var a = e.url,
o = new XMLHttpRequest;
o.open('GET', a, !0),
o.onreadystatechange = function () {
4 === this.readyState && (200 <= this.status && this.status < 400 ? e.success && 'function' == typeof e.success && e.success(this.responseText) : console.error('Ajax error occured.'))},o.send()},
appendString: function (e, t) {
var n = document.createElement('div');
for (n.innerHTML = t; n.firstChild; ) e.appendChild(n.firstChild)},
nextElementSibling: function (e) {
for (; (e = e.nextSibling) && 1 !== e.nodeType; );
return e},
previousElementSibling: function (e) {
for (; (e = e.previousSibling) && 1 !== e.nodeType; );
return e},
closest: function (e, t) {
var n;
for (Element.prototype.matches || (Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector || function (e) {
for (var t = (this.document || this.ownerDocument).querySelectorAll(e), n = t.length; 0 <= --n && t.item(n) !== this; );
return - 1 < n});
null !== e; ) {
if (null !== (n = e.parentElement) && n instanceof Element && n.matches(t)) return n;
e = n}
return null},
setText: function (e, t) {e.textContent ? e.textContent = t : e.innerText = t},
setData: function (e, t, n) {
e.dataset ? (t = t.replace(/[-_]([a-z])/g, function (e) {
return e[1].toUpperCase()
}), e.dataset[t] = n) : e.setAttribute('data-' + t, n)},
getData: function (e, t) {
return e.dataset ? (t = t.replace(/[-_]([a-z])/g, function (e) {
return e[1].toUpperCase()}), e.dataset[t]) : e.getAttribute('data-' + t)},
domReady: function (e) {
function n() {
document.addEventListener ? (document.removeEventListener('DOMContentLoaded', t), window.removeEventListener('load', t)) : (document.detachEvent('onreadystatechange', t), window.detachEvent('onload', t))}
var a = !1,t = function () {
a || !document.addEventListener && 'load' !== event.type && 'complete' !== document.readyState || (a = !0, n(), e())};
if ('complete' === document.readyState) e();
else if (document.addEventListener) document.addEventListener('DOMContentLoaded', t),
window.addEventListener('load', t);
else {
document.attachEvent('onreadystatechange', t),window.attachEvent('onload', t);
var o = !1;
try {o = null == window.frameElement && document.documentElement} catch (e) {}
o && o.doScroll && !function t() {
if (!a) {
try {
o.doScroll('left')
} catch (e) {
return setTimeout(t, 50)}
a = !0,
n(),
e()}}()}},
  lastChild: function (e) {
    if (!e.children.length) return null;
    if (e.lastElementChild) return e.lastElementChild;
    for (var t = e.children.length - 1; 0 <= t; --t) {
      var n = e.children[t];
      if (1 === n.nodeType) return n
    }
  },
  offset: function (e) {
    var e = e.getBoundingClientRect(),
    t = document.body,
    n = document.documentElement,
    a = window.pageYOffset || n.scrollTop || t.scrollTop,
    o = window.pageXOffset || n.scrollLeft || t.scrollLeft,
    r = n.clientTop || t.clientTop || 0,
    n = n.clientLeft || t.clientLeft || 0,
    t = e.top + a - r,
    a = e.left + o - n;
    return {
      left: Math.round(a),
      top: Math.round(t)
    }
  },
  empty: function (e) {
    for (; e.firstChild; ) e.removeChild(e.firstChild)
  },
  preventDefault: function (e) {
    e.preventDefault ? e.preventDefault() : e.returnValue = !1
  },
  toggleClass: function (e, t) {
    if (e.classList) e.classList.toggle(t);
     else {
      for (var n = e.className.split(' '), a = - 1, o = n.length; o--; ) n[o] === t && (a = o);
      0 <= a ? n.splice(a, 1) : n.push(t),
      e.className = n.join(' ')
    }
  },
  debounce: function (e, t, n) {
    function a() {
      o = null
    }
    var o = null;
    return function () {
      n && n.apply(this, arguments),
      o || (e.apply(this, arguments), o = setTimeout(a, t))
}},
areCookiesEnabled: function () {
    var e = !!navigator.cookieEnabled;
    return void 0 !== navigator.cookieEnabled || e || (document.cookie = 'testcookie', e = - 1 != document.cookie.indexOf('testcookie')),
    e
  },
  isLocalStorageEnabled: function () {
    if ('undefined' == typeof localStorage) return !1;
    try {
      localStorage.removeItem('LsAccessSuccess'),
      localStorage.setItem('LsAccessSuccess', 'localStorageEnabledOk'),
      localStorage.removeItem('LsAccessSuccess')
    } catch (e) {
      return !1
    }
    var e;
    return !!A_util.areCookiesEnabled() && ( - 1 == document.cookie.indexOf('local_storage') && ((e = new Date).setTime(e.getTime() + 31536000000), e = ' expires = ' + e.toGMTString() + ';', document.cookie = 'local_storage = 1;' + e + ' path=/;'), !0)
  },
  storage: {
    hasLocalStorage: function () {
      try {
        localStorage.enableStorage = 1,
        localStorage.removeItem('enableStorage')
      } catch (e) {
        return !1
      }
      return !0
    }(),
    defaultExpiry: 1,
    saveWithExpiry: function (e, t, n) {
      this.hasLocalStorage && ((n = t.expires && !n ? t.expires : n) || (n = new Date).setDate(n.getDate() + this.defaultExpiry), n = n instanceof Date ? n.getTime() : parseInt(n), this.saveItem(e, {
        val: t,
        expires: n
      }))
    },
    getItem: function (t) {
      if (this.hasLocalStorage) {
        var e;
        try {
          e = JSON.parse(localStorage[t])
        } catch (e) {
          return localStorage[t]
        }
        return parseInt(e.expires) < (new Date).getTime() ? (this.deleteItem(t), null) : e.val || e
      }
    },
    saveItem: function (e, t) {
      this.hasLocalStorage && (t = JSON.stringify('object' == typeof t ? t : {
        val: t
      }), localStorage.setItem(e, t))
    },
    deleteItem: function (e) {
      this.hasLocalStorage && localStorage.removeItem(e)
    },
    saveExpiry: function (e, t, n) {
      return 'undefined' != typeof Storage && (n = {
        value: JSON.stringify(t),
        timestamp: (new Date).getTime() + n
      }, localStorage.setItem(e, JSON.stringify(n)), t)
    },
    getExpiry: function (e) {
      return 'undefined' != typeof Storage && !!(e = JSON.parse(localStorage.getItem(e))) && (new Date).getTime() < e.timestamp && JSON.parse(e.value)
    }
  },
  ajaxCall: function (n) {
    if (null == n || '' == n.url || '' == n.data || '' == n.type) return console.log('ajaxPost: Parameters can't be empty'),
    !1;
    a = new (1 == n.crossDomain && 'undefined' != typeof XDomainRequest ? XDomainRequest : XMLHttpRequest);
    var a,
    e,
    o = new CustomEvent('ajaxSuccess'),
    r = new CustomEvent('ajaxFail'),
    t = n.type ? n.type.toUpperCase() : 'GET',
    s = '',
    c = n.contentType || 'application/x-www-form-urlencoded; charset=UTF-8';
    for (e in n.data) '' != s && (s += '&'),
    s += e + '=' + encodeURIComponent(n.data[e]);
    if ('GET' === t && (0 == n.cache ? n.url += '&timestamp=' + Date.now() : n.url += s ? ( - 1 !== n.url.indexOf('?') ? '&' : '?') + s : ''), a.open(t, n.url, !0), '' != n.dataType && 'string' == typeof n.dataType ? a.responseType = n.dataType : a.responseType = 'json', a instanceof XMLHttpRequest && void 0 === n.requestType && (a.setRequestHeader('X-Requested-With', 'XMLHttpRequest'), a.setRequestHeader('Content-Type', c)), '' != n.requestType && 'string' == typeof n.requestType && (s = JSON.stringify(n.data), a.setRequestHeader('Content-Type', n.requestType)), n.headers && (Object.keys || (Object.keys = function (e) {
      var t,
      n = [
      ];
      for (t in e) e.hasOwnProperty(t) && n.push(t);
      return n
    }), Object.keys(n.headers).forEach(function (e) {
      a.setRequestHeader(e, n.headers[e])
    })), 'false' == n.cache && 'POST' == t && a.setRequestHeader('cache-control', 'no-cache'), n.xhrFields) for (i in n.xhrFields) a[i] = n.xhrFields[i];
    return 'function' == typeof n.beforeSend && !1 === n.beforeSend() ? a.abort() : (a.onreadystatechange = function () {
      var t = {
      };
      if (4 == a.readyState) if (200 <= a.status && a.status < 400) {
        try {
          t = JSON.parse(a.responseText)
        } catch (e) {
          t = a.response
        }
        'function' == typeof n.success && (a instanceof XMLHttpRequest ? n.success(t) : a.onload(function () {
          n.success(t)
        })),
        a.dispatchEvent(o)
      } else a.dispatchEvent(r),
      t = {
        error: 'Error getting data from AJAX call'
      };
      if (null != t && void 0 !== t.error) return console.log('ajaxPost: ' + t.error),
      !1
    }, a.send(s), a.done = function (e) {
      'function' == typeof e && (a instanceof XMLHttpRequest ? A_util.addEventHandler(a, 'ajaxSuccess', e) : a.onload = e())
    }, a.fail = function (e) {
      'function' == typeof e && (a instanceof XMLHttpRequest ? A_util.addEventHandler(a, 'ajaxFail', e) : a.onerror = e())
    }, a.always = function (e) {
      'function' == typeof e && (a instanceof XMLHttpRequest ? (A_util.addEventHandler(a, 'ajaxSuccess', e), A_util.addEventHandler(a, 'ajaxFail', e)) : (a.onload = e(), a.onerror = e()))
    }, a)
  },
  getEventTarget: function (e) {
    return (e = e || window.event).target || e.srcElement
  }
};
!function () {
  function e(e, t) {
    t = t || {
      bubbles: !1,
      cancelable: !1,
      detail: void 0
    };
    var n = document.createEvent('CustomEvent');
    return n.initCustomEvent(e, t.bubbles, t.cancelable, t.detail),
    n
  }
  'function' != typeof window.CustomEvent && (e.prototype = window.Event.prototype, window.CustomEvent = e)
}();

var url = window.location.toString(),
hash = url.substring(url.indexOf('#') + 1),
activeNum = null,
genericFunctionModule = function () {
var n = document.querySelectorAll('.slide'),l = null,i = null;
function r(e, t) {
e = document.querySelector(e);
t = ('0' + t).slice( - 2),e && (e.textContent = t)}
function t() {
var e,t,o,n = (new Date).getTime(),n = i - n;
n < 0 ? clearInterval(l) : n && (e = Math.floor(n / 86400000), t = Math.floor(n % 86400000 / 3600000), o = Math.floor(n % 3600000 / 60000), n = Math.floor(n % 60000 / 1000), r('.js-days', e), r('.js-hours', t), r('.js-mins', o), r('.js-secs', n))
}
return {
widthSlide: function () {
if (n.length) for (var e = 0;
e < n.length; e++) n[e].style.width = window.innerWidth + 'px';
document.querySelector('.sectionA') && (document.querySelector('.sectionA').style.width = window.innerWidth * n.length + 'px', document.querySelector('.sectionA').style.marginLeft = '-' + window.innerWidth * activeNum + 'px'),
      document.querySelector('#section_' + (activeNum + 1)) && A_util.addClass(document.querySelector('#section_' + (activeNum + 1)), 'active')
    },
    faqAlign: function () {
      window.innerHeight < 890 ? (document.querySelector('#faqContent') && A_util.addClass(document.querySelector('#faqContent'), 'scrollMin'), document.querySelector('.scrollBar') && (document.querySelector('.scrollBar').style.display = 'block'), document.querySelector('.track1') && (document.querySelector('.track1').style.display = 'block'), setTimeout(function () {
        AB_scroll.init({
          selector: document.querySelectorAll('#faqContent'),
          height: 'auto',
          width: 'auto',
          color: '#F39000',
          size: '7px',
          alwaysVisible: !0,
          railVisible: !0,
          railOpacity: 1,
          railColor: '#222',
          distance: - 2,
          railClass: 'track1',
          opacity: '1',
          wrapperClass: 'wrapper1'
        })
      }, 2000), document.querySelector('.modalMTubes') && A_util.addClass(document.querySelector('.modalMTubes'), 'smallModalMTubes')) : (document.querySelector('#faqContent') && A_util.removeClass(document.querySelector('#faqContent'), 'scrollMin'), document.querySelector('.scrollBar') && (document.querySelector('.scrollBar').style.display = 'none'), document.querySelector('.track1') && (document.querySelector('.track1').style.display = 'none'), document.querySelector('.modalMTubes') && A_util.removeClass(document.querySelector('.modalMTubes'), 'smallModalMTubes'))
    },
    urlActiveSection: function () {
      A_util.removeClassMultiple(n, 'active');
      for (var e = 0; e < n.length; e++) n[e].id.replace('Slide', '').toLowerCase() === hash.toLowerCase() && A_util.addClass(document.querySelector('#' + n[e].id), 'active')
    },
    getIndex: function (e) {
      if (e) for (var t = e.parentNode.childNodes, o = 0, n = 0; n < t.length; n++) {
        if (t[n] == e) return o;
        1 == t[n].nodeType && o++
      }
      return - 1
    },
    slideFunction: function (e) {
      var t = document.querySelectorAll('.navSectionContent'),
      o = document.querySelector('.sectionA');
      o && A_util.addClass(o, 'sliding'),
      e ? activeNum-- : activeNum++,
      e = n.length ? n[activeNum] : null,
      'undefined' != typeof WIDGET_PREMIUM_SIGNUP && (WIDGET_PREMIUM_SIGNUP.realEstateTracking = changeRealEstateTrackingObj(e, !1)),
      A_util.removeClassMultiple(t, 'active'),
      (t = document.querySelector('#section_' + (activeNum + 1))) && A_util.addClass(t, 'active'),
      o && (o.style.marginLeft = '-' + n[0].clientWidth * activeNum + 'px'),
      A_util.removeClassMultiple(n, 'active'),
      A_util.addClass(e, 'active')
    },
    tooltipPromo: function () {
      var e = document.querySelector('.tooltipPromoTrigger'),
      t = document.querySelector('.tooltipPromo'),
      o = (n = e.getBoundingClientRect()).left - (t.offsetWidth - e.offsetWidth) / 2,
      n = n.top + e.offsetHeight + 7 + 'px';
      t.style.left = o + 'px',
      t.style.right = 'auto',
      t.style.top = n,
      t.style.opacity = 1
    },
    startTimer: function (e) {
      i = new Date(e).getTime(),
      l = setInterval(t, 1000)
    }
  }
}(),
premiumEventHandlersModule = {
  faqDropDownClick: function () {
    var e = this.parentElement.children;
    A_util.toggleClass(this.querySelectorAll('p') [0], 'linearSlide');
    for (var t = 0; t < e.length; t++) e[t] !== this && (A_util.removeClass(e[t], 'active'), A_util.removeClassMultiple(e[t].querySelectorAll('p'), 'linearSlide'));
    A_util.toggleClass(this, 'active')
  },
  navBarClick: function () {
    var e = document.querySelectorAll('.navSectionContent');
    activeNum = genericFunctionModule.getIndex(this) - 1,
    allSlides = document.querySelectorAll('.slide'),
    'undefined' != typeof WIDGET_PREMIUM_SIGNUP && (WIDGET_PREMIUM_SIGNUP.realEstateTracking = changeRealEstateTrackingObj(allSlides[activeNum], !1)),
    document.querySelector('.sectionA') && (A_util.addClass(document.querySelector('.sectionA'), 'sliding'), document.querySelector('.sectionA').style.marginLeft = '-' + document.querySelector('.slide').clientWidth * activeNum + 'px'),
    A_util.removeClassMultiple(e, 'active'),
    A_util.addClass(this, 'active')
  },
  hashChangeEvent: function () {
    genericFunctionModule.urlActiveSection(),
    activeNum = genericFunctionModule.getIndex(document.querySelector('.navSectionContent.active')) - 1,
    A_util.removeClass(document.querySelector('.navSectionContent'), 'active'),
    document.querySelector('#section_' + (activeNum + 1)) && A_util.addClass(document.querySelector('#section_' + (activeNum + 1)), 'active'),
    genericFunctionModule.widthSlide()
  },
  resizeFunction: function () {
    document.querySelector('.sectionA') && A_util.removeClass(document.querySelector('.sectionA'), 'sliding'),
    genericFunctionModule.widthSlide(),
    genericFunctionModule.faqAlign()
  },
  mouseUpFunction: function (e) {
    joinPageUrlParam.reloadParamsOnModalClose(e.target)
  },
  mouseScrollFunction: function (e) {
    document.querySelector('.modalMTubes.premiumSignupModal') || 0 !== document.querySelectorAll('.scrollOn').length || (0 < e.wheelDelta || e.detail < 0 ? 0 < activeNum && genericFunctionModule.slideFunction(!0) : activeNum < document.querySelectorAll('.slide').length - 1 && genericFunctionModule.slideFunction(!1))
  }
};
function changeRealEstateTrackingObj(e, t) {
  return (jslide = t ? document.querySelector('.slide.active') : e) && jslide.dataset && jslide.dataset.tracking ? jslide.dataset.tracking : ''
}
A_util.domReady(function () {
  var e,
  t,
  o,
  n = document.querySelectorAll('.slide'),
  l = ('undefined' != typeof WIDGET_PREMIUM_SIGNUP && (WIDGET_PREMIUM_SIGNUP.realEstateTracking = changeRealEstateTrackingObj(n, !0)), 1 < url.indexOf('#') ? genericFunctionModule.urlActiveSection() : A_util.addClass(document.querySelector('#slide1'), 'active'), activeNum = genericFunctionModule.getIndex(document.querySelector('.navSectionContent.active')) - 1, document.querySelectorAll('.navSectionContent')),
  i = document.querySelectorAll('.dropDownContent'),
  n = document.querySelector('#faqContent');
  if (l.length) for (var r = 0; r < l.length; r++) A_util.addEventHandler(l[r], 'click', premiumEventHandlersModule.navBarClick);
  if (i.length) for (r = 0; r < i.length; r++) A_util.addEventHandler(i[r], 'click', premiumEventHandlersModule.faqDropDownClick),
  A_util.addEventHandler(i[r], 'keypress', premiumEventHandlersModule.faqDropDownClick);
  n && (A_util.addEventHandler(document.querySelector('#faqContent'), 'DOMMouseScroll', function (e) {
    e.stopPropagation()
  }), A_util.addEventHandler(document.querySelector('#faqContent'), 'mousewheel', function (e) {
    e.stopPropagation()
  }), A_util.addEventHandler(n, 'mouseover', function (e) {
    window.innerHeight < 860 && A_util.addClass(this, 'scrollOn')
  }), A_util.addEventHandler(n, 'mouseleave', function (e) {
    A_util.removeClass(this, 'scrollOn')
  })),
  A_util.addEventHandler(window, 'hashchange', premiumEventHandlersModule.hashChangeEvent),
  A_util.addEventHandler(window, 'resize', premiumEventHandlersModule.resizeFunction),
  A_util.addEventHandler(document, 'mouseup', premiumEventHandlersModule.mouseUpFunction),
  A_util.addEventHandler(window, 'mousewheel', premiumEventHandlersModule.mouseScrollFunction),
  A_util.addEventHandler(window, 'DOMMouseScroll', premiumEventHandlersModule.mouseScrollFunction),
  document.querySelector('.sectionA .logo a') && A_util.addEventHandler(document.querySelector('.sectionA .logo a'), 'click', function (e) {
    e.preventDefault(),
    document.querySelector('#section_1') && document.querySelector('#section_1').click()
  }),
  document.querySelector('.tooltipPromo') && (document.querySelector('.tooltipPromo span') && A_util.addEventHandler(document.querySelector('.tooltipPromo span'), 'click', function (e) {
    e.stopPropagation(),
    A_util.setCookie('promoTooltip', 1);
    e = document.querySelector('.tooltipPromo');
    e && e.parentNode.removeChild(e)
  }), e = setInterval(function () {
    0 !== document.querySelector('.tooltipPromoTrigger').getBoundingClientRect().top && (genericFunctionModule.tooltipPromo(), clearInterval(e), A_util.addEventHandler(window, 'resize', genericFunctionModule.tooltipPromo))
  }, 100)),
(n = document.querySelector('.promoDeal')) && (t = n.querySelector('span'), o = document.querySelector('.lifeTimeOffer'), n.addEventListener('click'), n.click()),
genericFunctionModule.faqAlign(),genericFunctionModule.widthSlide(),document.querySelector('.offerLifeTime') && document.querySelector('#offersBlock .offer') && (document.querySelector('.offerLifeTime').dataset.paymentType = document.querySelectorAll('#offersBlock .offer') [0].dataset.paymentType),
PREMIUM_SIGNUP.isPreBlackFriday && genericFunctionModule.startTimer('Nov 26, 2020 00:00:00 GMT-0500'),premiumSignupModal.init()}),
document.addEventListener('DOMContentLoaded', function () {document.querySelector('.loader') && (document.querySelector('.loader').style.display = 'none')});

Standard upload form on NodeJS has an empty file field

I want to upload a file to a NodeJS server. Following File uploading with Express 4.0: req.files undefined , I try this code in mre.js:

'use strict';

const path = require('path');
const express = require('express');
const app = express();

// Set up the view engine
app.set('view engine', 'pug');
app.set('views', path.join(__dirname, 'views'));


const UPLOAD = "/upload";

app.get(UPLOAD, async (req, res) => {
  
  return res.render("upload");
});


const fileUpload = require('express-fileupload');

app.post(UPLOAD, fileUpload(), async (req, res) => {
  let keys = Object.keys(req.files);
  fs.readFile(req.files[keys[0]].path, (err, e) => {
    if(err) console.log(err);
    fs.writeFile(keys[0], e, (err) => {
      console.log(err)
    })
  })

  req.flash("success", "File uploaded");
  return res.redirect(UPLOAD);
});



const http = require('http');
const httpServer = http.createServer(app);

let server = httpServer.listen(8080, () => {
  console.log("n# HTTP server started");
});

and the view is:

doctype html
html

  body
    form.left(method='POST')
    
      input(type='file', id="file", name="filename", accept=".xls,.xlsx,.txt")
      input(type="submit", name="submit", value="Upload")

I launch with node mre.js, I see the form at http://localhost:8080/upload, but when I upload a file, I get this error:

mre.js:24
  let keys = Object.keys(req.files);
TypeError: Cannot convert undefined or null to object

I tried several variations to no avail, for example I log the full request with console.log(req), and the filename I uploaded does not appear. But it seems to work on multiple answers of that thread, so I think there’s something obvious I am overlooking.

How can I get the file uploaded to a NodeJS server?

Need Javascript help – Popup-selected value not updating main page dropdown [closed]

I’m working on a web project involving interaction between a main HTML form and a popup window using JavaScript. The goal is:

The main page contains a dropdown with predefined values.

It also includes a button labeled “Additional LookUp”.

When clicked, the button opens a popup window that allows users to search and select a new value.

When the user clicks RETURN in the popup, the selected value should be passed back and update the main page dropdown. Main Page:

Get chat status in zendesk

We use the zendesk chat app on the shopify site. And I need to get the chat status: online, away or offline. I tried it, but now it doesn’t work, because it is related to an old version of the API:

zE('webWidget:on', 'chat:departmentStatus', function(dept) {
  if (dept.name === 'CRM' && dept.status === 'online') {
    zE('webWidget', 'updateSettings', {
      webWidget: {
        chat: {
          departments: {
            enabled: [''],
            select: 'CRM'
          },
          suppress: false
        }
      }
    });
  } else if (dept.name === 'CRM' && dept.status !== 'online') {
    zE('webWidget', 'updateSettings', {
      webWidget: {
        chat: {
          suppress: true
        }
      }
    });
  }
});

webWidget:on – no longer supported

But in the new documentation I didn’t find what I need. Please help.

google sheets app script use selection as input (e.g. C105:I105) [duplicate]

I want to call a custom function like this in Google Sheets:

=countColoredCells(C105:I105, "#ff0000")

Where C105:I105 is a range reference, the same way you would use it in =SUM(C105:I105). However, I’ve parsed the input string in my function, and what I get is this completely useless array of an array of empty strings:

function countColoredCells(input, color) {
  return JSON.stringify(input);
}

Result: [["","","","","",""]]

I thought I must be mistaken, but I’ve checked the type, the length, etc., and they seem to be empty strings. (upon further investigation, I see that it gives you the cell values, but I want the actual cell references so I can check the color of the cells)

How can I use this input to iterate these cells?

NOTE:
I know I can put it in as a string and parse it, but that defeats the purpose. I expect to be able to use it like any other Sheets function with a selection directly input into it.

I also know that most examples get a selection off the sheet, which is also not what I want. My end result is that I want to automatically run this on each row in a growing spreadsheet (i.e. C106:I106, C107:I107, etc.).

File uploading and reading in angular

I have file upload control which holds the selected file as below,

<div class="Block">
  <label id="lbl">File </label>
  <input #fileInput type='file'/>
</div>

I have a submit button as below,

<button type="button" class="btn btn-primary" 
     (click)="uploadDocument()">Upload File</button>

When I select a file and click on the upload button the file I need the contents inside the file without sending it to the server and reading from there and showing content of file in table format.

Note: Type of file will be txt

I have to do this without api

Why my animation frame is speeding at the end when using a condition?

I would like to build a simple game with UFOs that crosses the window and that can be the target for a tank. Below is the code to create a UFO crossing the window screen. I am using a class for that and set temporary hard coded conditions to keep animation frame working only when UFO is within the screen range. However with this condition at the end of the animation the UFO suddenly speeds up.


class flying_ufo {
    
    constructor(name) {
        this.name = name;
        this.ufo = document.querySelector('.ufo');
        this.angle = 0;
        this.x = 0;
        this.y = 0;
        this.rotate = 0;
        this.start = undefined;
        this.lastTimestamp = undefined;
        this.animate = this.animate.bind(this);
        this.scale = window.innerWidth / 50;
    }

   
animate(timestamp) {
    if (this.start === undefined) {
        this.start = timestamp;
        this.lastTimestamp = timestamp;
    }

    const delta = (timestamp - this.lastTimestamp) / 1000;
    this.lastTimestamp = timestamp;

    const speedX = 100; 
    const speedY = 20;

    this.x += speedX * delta;
    this.y -= speedY * delta;

    this.degreeValue = window.innerWidth > 900 ? 0.002 : 0.02;
    this.rotate -= ((window.innerWidth) * delta) * this.degreeValue;

    this.ufo.style.transform = `translate(${this.x}px, ${this.y / 2}px) rotate(${this.rotate}deg)`;

    const isInView = this.x <= window.innerWidth &&
                   this.x >= 0 &&
                   this.y / 2 < window.innerHeight / 2 &&
                   this.y / 2 + window.innerHeight > 0;


    // if (isInView) {
        requestAnimationFrame(this.animate);
    // }
}

    init_ufo() {

        requestAnimationFrame(this.animate);
    }

}



const my_ufo = new flying_ufo('name1');
my_ufo.init_ufo();

<body>
    <div class="ufo"><img src="ufo.png" alt="" width="100%"></div>
</body>

  html, body{
    position: relative;
    margin: 0; padding: 0; height: 100%;
    background: radial-gradient(circle at center, #1c1c3c, #0b0b16);
    overflow: hidden;
  }

  
  .ufo {
    width: 110px;
    position: absolute;
    top: 50%;
    filter: drop-shadow(0 0 15px #6cf3ff);
    transition: transform 0.3s ease-in-out;
    will-change: transform;
  }

If I remove the isInView condition it then moves smoothly and regularly. Can’t figure it out why? Can somebody explains why this is happening?

Issue with Recharts label (React.JS)

Faced an issue implementing text underline in the Recharts library, specifically in a Pie Chart. It should look like this:enter image description here

Here’s how it turns out for me:
enter image description here

CodeSandbox:
https://codesandbox.io/p/devbox/delicate-sun-lnvqkg?file=%2Fsrc%2Fstyles.css&workspaceId=ws_QyKMbtfzZ89mpAdWxtqWKL

Is it possible to make it look like in the first screenshot, so that the dashed line starts from the column and goes under the text? I would appreciate any help.

“Cloud Identity Groups” Advanced Service Missing in Apps Script “Services” List?

This page:

https://developers.google.com/apps-script/advanced/groups

says that there is an Advanced Service for Cloud Identity Groups that can be enabled, but my list of Services has no such option in the list. I am a Superadmin in a domain that has Groups for Business enabled. What am I missing?

* AdSense Management APIDocumentation
* Admin SDK API
* Analyticsreporting
* Area120 Tables API
* BigQuery API
* Campaign Manager 360 API
* Content API for Shopping
* Drive API
* Drive Activity API
* Drive Labels API
* Enterprise License Manager API
* Gmail API
* Google Analytics API
* Google Analytics Admin API
* Google Analytics Data API
* Google Calendar API
* Google Chat API
* Google Classroom API
* Google Docs API
* Google Sheets API
* Google Slides API
* Google Tasks API
* Google Workspace Events API
* Google Workspace Reseller API
* Groups Migration API
* Groups Settings API
* Merchant API
* Peopleapi
* Tag Manager API
* YouTube Analytics API
* YouTube Data API v3
* YoutubePartner

List of "Advanced Services" available to install in a new Apps Script project

Customizing button for save PDF

I want to use customize button to save my table to PDF and also hide the ‘PDF’ word which comes as default to save the pdf on top of data table. i want to use only the customized button

but my below code is not working.

<script>
   $(document).ready(function () {
  var table = $('#example').DataTable({
    "bLengthChange": false,
    "bFilter": false,
    "bInfo": false,
    "pagingType": "simple",
    "lengthMenu": [15, 25, 50, -1],
    "paging": true,
    "paging.numbers": true,
    "ordering": false,
    dom: 'Bfrtip',
  buttons: ['pdfHtml5']
    });
    table.button( '.buttons-pdfHtml5' ).css('display', 'none');
     $("#btn").on("click", function() {
    table.button( '.buttons-pdfHtml5' ).trigger();
});
});
</script>

<button type="button" id="btn">save pdf</button>

Making a ChatApp Two – Way

So, basically, I have created a basic chat app using html, css, and javascript. I am also using SocketIO, so that I can make the chat app real-time. The problem is, I am not able to figure out how I can make this chat app two – way, Ie, a user can only connect with one other user. Right now, everyone can connect with each other.
Here is the sample html code and the javascript code. :

NOTE: I am running this with node server.js to run my program. :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel = "stylesheet" type = "text/css" href = "style.css"/>
</head>
<body>
    <div class="app">
        <div class="screen join-screen active">
            <div class="form">
                <h2>Join Chatroom</h2>
                <div class="form-input">
                    <label>Username</label>
                    <input type = "text" id = "username"/>
                </div>
                <div class="form-input">
                    <button id="join-user">Join</button>
                </div>
            </div>
        </div>
        <div class="screen chat-screen">
            <div class="header">
                <div class="logo">Chatroom</div>
                <button id = "exit-chat">Exit</button>
            </div>
            <div class="messages">
                <!--all of the message will appear here!-->
            </div>
            <div class="typebox">
                <input type = "text" id = "message-input"/>
                <button id="send-message">Send</button>
            </div>
        </div>
    </div>
    <script type = "text/javascript" src = "socket.io/socket.io.js"></script>
    <script type = "text/javascript" src="code.js"></script>
</body>
</html>
(function() {
    const app = document.querySelector(".app");
    const socket = io();

    let uname;

    app.querySelector(".join-screen #join-user").addEventListener("click", function() {
        let username = app.querySelector(".join-screen #username").value;
        if (username.length == 0) {
            return;
        }
        socket.emit("newuser", username);
        uname = username;
        app.querySelector(".join-screen").classList.remove("active");
        app.querySelector(".chat-screen").classList.add("active");
    });
    app.querySelector(".chat-screen #send-message").addEventListener("click", function() {
        let message = app.querySelector(".chat-screen #message-input").value;
        if (message.length == 0) {
            return;
        }
        renderMessage("my", {
            username:uname,
            text:message
        })
        socket.emit("chat", {
            username:uname,
            text:message
        })
        app.querySelector(".chat-screen #message-input").value = "";
    });
    app.querySelector(".chat-screen #exit-chat").addEventListener("click", function() {
        socket.emit("exituser", uname);
        window.location.href = window.location.href;
    })
    socket.on("update",function(update) {
        renderMessage("update", update);
    })
    socket.on("chat",function(message) {
        renderMessage("other", message);
    })
    function renderMessage(type,message) {
        let messageContainer = app.querySelector(".chat-screen .messages");
        console.log(type)
        if (type == "my") {
            let el = document.createElement("div");
            el.setAttribute("class","message my-message");
            el.innerHTML = `<div>
                                <div class = "name">You</div>
                                <div class = "text">${message.text}</div>
                            </div>`;
            messageContainer.appendChild(el);
        } else if (type == "other") {
            let el = document.createElement("div");
            el.setAttribute("class","message other-message");
            el.innerHTML = `<div>
                                <div class = "name">${message.username}</div>
                                <div class = "text">${message.text}</div>
                            </div>`;
            messageContainer.appendChild(el);
        } else if (type == "update") {
            let el = document.createElement("div");
            el.setAttribute("class","update");
            el.innerHTML = message;
            messageContainer.appendChild(el);
        }
        //scroll the chat to the end.
        messageContainer.scrollTop = messageContainer.scrollHeight - messageContainer.clientHeight;
    };
})();

I appreciate any pointers and/or tips you may give.

Honestly, I do not have that much internet knowledge, so, I was pretty clueless on how to go about this.