Recommendations for integrating external fingerprint scanner with a mobile web app (Cordova/Capacitor, PHP backend) [closed]

I have a web application built with JavaScript and PHP, and now I have a requirement to create a system for tracking workers’ clock-in and clock-out times in the field. The idea is that workers will register their fingerprints, and then the foreman will use a fingerprint scanner to log both entry and exit times along with the corresponding hours.

The system needs to scan fingerprints when workers arrive and leave. Since this is for fieldwork, it must be portable and should be done using mobile phones. The idea is to use external hardware to keep it consistent, avoiding issues with varying quality of fingerprint readers on different phones.

I’m mentioning the web app built with JS because, in the near future, we plan to package it using Cordova or Capacitor, and ideally, we’d like to handle everything from the same application without having to install a second app on the phone. As for the PHP backend, the hardware should authenticate the device, check if the employee is registered on the backend, and log the working hours. However, I have no idea how this information would be sent. Maybe a photo?

Since I have no experience with this kind of system, I’m not sure how to approach the problem or what type of hardware to look for. Obviously, I wouldn’t program the hardware with PHP or JS, but with the SDK language it offers.

Can’t hide bottom navigation bar inside nested stack navigator that is nested inside Drawer Navigator react navigation v6

I have a DrawerNavigator. Inside which are multiple screens and one of which (Initial Home screen) is a Bottom Tab Navigator which further have Stack navigators in each tab. I am unable to hide the bottom navigation bar of the Tab navigator while I am inside the details screen of a tab i.e. stack navigator. How can I achieve this?

DrawerNavigator

<Navigator
  backBehavior="history"
  drawerContent={(props) => (
    <DrawerContent {...props} isArabic={isArabic} keyData={keyData} />
  )}
  screenOptions={{
    drawerPosition: isArabic ? "right" : "left",
    animation: "fade",
    headerShown: false,
    drawerType: "slide",
    overlayColor: "transparent",
    drawerStyle: {
      backgroundColor: "#2F2F2F",
      width: "84%",
    },
  }}
>
  <Screen
    name={Routes.HOME_SCREEN}
    component={BottomNavigator}
    options={{ headerShown: false }}
  />
  <Screen
    name={Routes.X_HOME_SCREEN}
    component={XNavigator}
    options={{ headerShown: false, unmountOnBlur: true }}
  />
  <Screen
    name={Routes.Y_SCREEN}
    component={YScreen}
    options={{ headerShown: false }}
  />
</Navigator>

BottomNavigator

<Navigator
  barStyle={[
    styles.barStyle(insets),
    { transform: [{ scaleX: isArabic ? -1 : 1 }] },
  ]}
  activeColor={white}
  keyboardHidesNavigationBar={false}
  inactiveColor={white}
  screenOptions={{ animation: "fade" }}
>
  <Screen
    options={{
      headerShown: false,
    }}
    name={Routes.DASHBOARD}
    component={Dashboard}
  />
  <Screen
    name={Routes.A_NAVIGATOR}
    component={ANavigator}
    options={{
      headerShown: false,
      }}
  />
  <Screen
    name={Routes.B_Navigator}
    component={BNavigator}
    options={{
      headerShown: false,
      }}
  />
  <Screen
    name={Routes.C_Navigator}
    component={CNavigator}
    options={{
      headerShown: false,
      }}
  />
  <Screen
    name={Routes.D_NAVIGATOR}
    component={DNavigator}
    options={{
      headerShown: false,
    }}
  />
</Navigator>

Each Navigator inside the BottomNavigator is like this

<Navigator screenOptions={{ animation: "fade" }}>
  <Screen
    name={Routes.A_SCREEN}
    component={AScreen}
    options={{ headerShown: false }}
    initialParams={route?.params}
  />
  <Screen
    name={Routes.B_SCREEN}
    component={BScreen}
    options={{ headerShown: false }}
  />
</Navigator>

I need the bottom tab bar in AScreen but don’t need in BScreen. However, React Navigation is not allowing me to do so or I am missing something. Regards

Avoid we rerendering of Speckle 3D viewer in MudBlazor

I am working on a MudBlazor application where I am integrating a Speckle 3D viewer. The issue is that the 3D viewer reloads every time I navigate between different pages. I would like the model to be loaded only once and remain active in the background when navigating between pages that use the 3D viewer. Additionally, the model needs to be dynamic since it is used across multiple pages. Is there a way to achieve this without the 3D viewer being re-rendered on every page navigation?

Does anyone have an idea how I can solve the problem with an example?

React Component Collapsing Issue: Ref Not Initialized During URL Parsing

I have a component that should expand if it is selected. Here’s my current approach:

<Element 
   ref={elementRef}
   style={{ height: isSelected ? `${elementRef.current.scrollHeight}px` : '0px' }} 
/>

Now, I’ve added routing, which parses the URL. For example, if I am at host:port/selected/1, the first element should automatically expand.

The URL parsing works fine, but it happens just at the beginning of the creation of the website.

This results that while the function is returning the JSX-Element, isSelected evaluates to true which causes an issue because the ref has not yet been initialized. (elementRef.current is null)

Or to put it in different words: the scrollHeight of a non-rendered object doesn’t make sense and React tells me so.

I’m struggling to figure out the best way to handle this. I think I need to use a different hook than useRef, but which one?

I tried using useState with the dependencies isSelected and elementRef which is not fired after rendering, but before (or during).

SPA SEO dynamically updating metatags on node.js express route

I want to dynamically update my meta tags when a POST is received at /source/:uuid

I did:


    app.get('*', function(req, res, next) {
         const userAgent = req.headers['user-agent'] || ''; 
         if (isbot(userAgent)) next();
         else res.sendFile(path.join(__dirname, '/static/index.html'));
    });`

And the route:

   app.post("/source/:uuid", function(req,res){
          const userAgent = req.headers['user-agent'] || ''; 
          if (isbot(userAgent)){
              dbCall(data=>{
                   const raw = fs.readFileSync(path.join(__dirname, '/static/index.html'))
                   const updated = raw.replace('<title>The New Library of The Atlantis</title>',       "<meta name='description' content="
                   + "'Download" + data.format + " here!'><title>" data.title + "</title>")
                   return res.sendFile(updated)
              })

          }
          else{
               //browser code
          }
    })    

`

But curl and a browser bot checker shows the default meta from index.html

Any help?

I tried placing next() for bots in the * route before the source route and serving a custom index.html with new meta tags for the /source/:uuid POST route, but it’s not showing up when I check the bots.

Why does my array keep returning “Undefined array key”

I want to retrieve the api data from timezone api by clicking the submit button, for the first table row. Unfortunetly it is showing an error message whenever I visit the url link http://localhost/task/geonamesExample/libs/php/getTimezone.php?lang=en&country=GB. to see the error (even when I try it without going to the link).

I expect it to return a value of latitude once I click on the submit, and it’s suppose to display in the last row.

I tried deleting geonames a couple, I’ve tried using var_dump($decode).

Moreover this is the error message I keep getting
Warning: Undefined array key “geonames” in /Applications/XAMPP/xamppfiles/htdocs/task/geonamesExample/libs/php/getTimezone.php on line 25
{“status”:{“code”:”200″,”name”:”ok”,”description”:”success”,”returnedIn”:”98 ms”},”data”:null}

index.html:


    <!doctype html>
    
    <html lang="en">
    
        <head>
            <link rel="stylesheet" href="style.css">
            <meta charset="utf-8">
    
            <title>AJAX/PHP/CURL/JSON example</title>
            <meta name="description" content="AJAX/PHP/CURL/JSON example">
            <meta name="author" content="Paddy Evans">
    
        </head>
    
        <body>
    
            <select id="selCountry">
                <option value="GB">Great Britain</option>
                <option value="FR">France</option>
                <option value="DE">Germany</option>
                <option value="US">USA</option>
            </select>
    
            <select id="selLanguage">
                <option value="en">English</option>
                <option value="fr">Francais</option>
                <option value="de">Deutsche</option>
            </select>
    
            <button id="btnRun">Run</button>
    
            <br><br>
    
            <div id="divResults">
                
                <table>
    
                    <tr>
                        <td>
                            API name
                        </td>
                        <td>
                            API description
                        </td>
                        <td>
                            
                        </td>
                    </tr>
                    
                    <tr>
                        <td>
                            1.PostalCodeLookup
                        </td>
    
                        <td>        
                            Timezone:
                        </td>
    
                        <td>
                            <select id="selCountry2">
                                <option value="47.01">47.01</option>
                            </select>
                        </td>
    
                        <td>
                            <button id="btnRun_2">Submit</button>
                        </td>
                    </tr>
    
                    <tr>
                        <td>
                            2.Weather
                        </td>
                        <td>
                            description
                        </td>
                        <td>
                            <button type="submit">Submit</button>
                        </td>
                    </tr>
    
                    <tr>
                        <td>
                            
                        </td>
                        <td>
                            description
                        </td>
                        <td>
                            <button type="submit">Submit</button>
                        </td>
                    </tr>
    
                    <tr>
                        <td align="right">
                            Continent: 
                        </td>
                        <td id="txtContinent">
                            
                        </td>
    
                    </tr>
    
                    <tr>
                        <td align="right">
                            Capital: 
                        </td>
                        <td id="txtCapital">
                            
                        </td>
    
                    </tr>
    
                    <tr>
                        <td align="right">
                            Languages: 
                        </td>
                        <td id="txtLanguages">
                            
                        </td>
    
                    </tr>
    
                    <tr>
                        <td align="right">
                            Population: 
                        </td>
                        <td id="txtPopulation">
                            
                        </td>
    
                    </tr>
    
                    <tr>
                        <td align="right">
                            Area (km<sup>2</sup>): 
                        </td>
                        <td id="txtArea">
                            
                        </td>
    
                    </tr>
    
    
                    <tr>
                        <td align="right">
                            Latitude:
                        </td>
                        <td id="txtLatitude">
                            
                        </td>
    
                    </tr>
                </table>
    
                
    
            </div>
    
            <script type="application/javascript" src="libs/js/jquery-2.2.3.min.js"></script>
            <script type="application/javascript" src="libs/js/script.js"></script>
    
        </body>
    
    </html>

script.js:

    $('#btnRun').click(function() {
    
            $.ajax({
                url: "libs/php/getCountryInfo.php", 
                type: 'POST',
                dataType: 'json',
                data: {
                    country: $('#selCountry').val(),
                    lang: $('#selLanguage').val()
                },
                success: function(result) {
    
                    console.log(JSON.stringify(result));
    
                    if (result.status.name == "ok") {
    
                        $('#txtContinent').html(result['data'][0]['continent']);
                        $('#txtCapital').html(result['data'][0]['capital']);
                        $('#txtLanguages').html(result['data'][0]['languages']);
                        $('#txtPopulation').html(result['data'][0]['population']);
                        $('#txtArea').html(result['data'][0]['areaInSqKm']);
    
                    }
                
                },
                error: function(jqXHR, textStatus, errorThrown) {
                    // your error code
                }
            }); 
    
        
        });
    
        $('#btnRun_2').click(function() {
            $.ajax({
                url: "libs/php/getTimeZone.php",
                type: 'POST',
                dataType: 'json',
                data: {
                    country: $('#selCountry2').val(),
                    lang: $('#selLanguage2').val()
                },
                success: function(result) {
    
                    console.log(JSON.stringify(result));
    
                    if (result.status.name == "ok") {
    
                        $('#txtLatitude').html(result['data'][0]['lat']);
                        $('#txtLongitude').html(result['data'][0]['lng']);
                        $('#Timezone').html(result['data'][0]['timezone']);
    
                }
                },
                error: function(jqXHR, textStatus, errorThrown) {
                    // your error code
                }
            });
    
    
        });

getTimezone.php


    <?php
    
    ini_set('display_errors', 'On');
    error_reporting(E_ALL);
    
    $executionStartTime = microtime(true);
    
    $url='http://api.geonames.org/timezoneJSON?formatted=true&lat=' . $_REQUEST['lang'] . '&country=' . $_REQUEST['country'] . '&username=adeyinka_25';
    
    $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL,$url);
    
        $result=curl_exec($ch);
    
        curl_close($ch);
    
        $decode = json_decode($result,true);    
    
        $output['status']['code'] = "200";
        $output['status']['name'] = "ok";
        $output['status']['description'] = "success";
        $output['status']['returnedIn'] = intval((microtime(true) - $executionStartTime) * 1000) . " ms";
        $output['data'] = $decode['geonames'];
        
        header('Content-Type: application/json; charset=UTF-8');
    
        echo json_encode($output);
    
    ?>

How MAX_SAFE_INTEGET 2 ** 53 – 1

We Know in Javascript it uses the STD IEEE 754 Double precision and we know that the Mantissa Section is 52 bit and there is implicit 1 bit but is not stored

But if it isn’t stored how it’s actually we represent it because we can store 52 bit that 1 bit what we are using for ?

Adding transform in vega-lite hides the data

I’m building a simple stacked bar chart using vega-lite.
On X-axis – we have a country name, on Y-axis we have bars of count stacked by product name
My goal is to show the top 3 countries in the chart.

Working example here.

Full Working Code

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "description": "A stacked bar chart showing the individual count by product and country.",
  
  "data": {
    "values": [
      {"product_name": "Product A", "country_name": "Country 1", "individual_count": 100},
      {"product_name": "Product B", "country_name": "Country 1", "individual_count": 150},
      {"product_name": "Product C", "country_name": "Country 1", "individual_count": 200},
      {"product_name": "Product D", "country_name": "Country 1", "individual_count": 50},
      {"product_name": "Product E", "country_name": "Country 1", "individual_count": 80},
      {"product_name": "Product A", "country_name": "Country 2", "individual_count": 120},
      {"product_name": "Product B", "country_name": "Country 2", "individual_count": 80},
      {"product_name": "Product C", "country_name": "Country 2", "individual_count": 150},
      {"product_name": "Product D", "country_name": "Country 2", "individual_count": 100},
      {"product_name": "Product E", "country_name": "Country 3", "individual_count": 60},
      {"product_name": "Product E", "country_name": "Country 3", "individual_count": 60},
      {"product_name": "Product E", "country_name": "Country 3", "individual_count": 60},
      {"product_name": "Product A", "country_name": "Country 3", "individual_count": 60},
      {"product_name": "Product C", "country_name": "Country 3", "individual_count": 60},
      {"product_name": "Product A", "country_name": "Country 4", "individual_count": 60},
      {"product_name": "Product C", "country_name": "Country 4", "individual_count": 90},
      {"product_name": "Product A", "country_name": "Country 5", "individual_count": 60},
      {"product_name": "Product C", "country_name": "Country 5", "individual_count": 60},
      {"product_name": "Product A", "country_name": "Country 5", "individual_count": 60},
      {"product_name": "Product C", "country_name": "Country 5", "individual_count": 90}
    ]
  },
  "mark": "bar",
  "encoding": {
    "x": {
      "field": "country_name",
      "type": "nominal",
      "axis": {"labelAngle": -45},
      "sort": {"field": "individual_count", "order": "descending", "op": "sum"}
    },
    "y": {
      "aggregate": "sum",
      "field": "individual_count",
      "type": "quantitative",
      "title": "Total Individual Count"
    },
    "color": {"field": "product_name", "type": "nominal"},
    "tooltip": [
      {"field": "country_name", "type": "nominal"},
      {"field": "product_name", "type": "nominal"},
      {
        "aggregate": "sum",
        "field": "individual_count",
        "type": "quantitative",
        "title": "Individual Count"
      }
    ]
  }
}

If I add a transformation, my chart becomes blank. I want to add this transformation so I can show top 3 countries (by stack total). Not sure what am I doing wrong


  "transform": [
    {"aggregate": [{"op": "sum", "field": "individual_count", "as": "total_count"}], "groupby": ["country_name"]},
    {"window": [{"op": "rank", "field": "total_count", "as": "rank"}], "sort": [{"field": "total_count", "order": "descending"}]},
    {"filter": "datum.rank <= 3"}
  ],

Method to Utilize NodeJS Array from Sequelize into the Script Tag of a Pug Template

So I am having an issue with figuring out how to get the variable that is passed from NodeJS into my Pug Template into a variable within the Pug Template’s Script tag. The issue is that it is a Sequelize Object, and the front-end JavaScript doesn’t recognize it as a basic object. Since I am most of the way through my project, I don’t want to force it to return a raw object since most of my application is built around how it returns the Sequelize Object itself.

So here is my code:

script.
    let keys = '#{nodejskeys}'

This in itself returns just the Sequelize Object, but I need the array within it to parse on the front-end. Any thoughts?

I tried utilizing for-loops to no avail.

swiper js slide disappear after showing bootstrap 5 modal popup

I’m trying to use SwiperJS and Bootstrap 5’s popup modal on the same page. When I click on the button inside a slide, it opens the popup modal and show the content according to the slider (the slides contain different pastries menu options)

but somehow when I click on the .btn-view-gallery button, the leftmost slide disappears as the modal appears.. why is that? and how do I fix that behavior?

this is the code:

HTML

<div class="swiper menu-list-container">
  <div class="swiper-wrapper">
    <!-- item #1 -->
    <div class="swiper-slide">
      <img
        src="img/menu/bluder/000.png"
        class="card-img-top"
        alt="Kue Bluder"
      />
      <div class="slide-content">
        <h3 class="my-title">Kue Bluder</h3>
        <p class="my-description">
          Jelajahi dunia rasa dengan bluder <span class="fw-bold">Food Happy Tummy</span>, kualitas premium, varian lengkap.
        </p>
        <button type="button" class="btn btn-warning btn-view-gallery" role="button" 
        data-menu-name="bluder"
        data-bs-toggle="modal" data-bs-target="#modalMenu">Gallery Kue Bluder</button>    
      </div>
    </div>
    <div class="swiper-slide">
      <!-- content about item #2 -->
    </div>
    <div class="swiper-slide">
      <!-- content about item #3 -->
    </div>
    <div class="swiper-slide">
      <!-- content about item #4 -->
    </div>
    <div class="swiper-slide">
      <!-- content about item #5 -->
    </div>
  </div>
  <div class="swiper-pagination"></div>
</div>

<!-- Modal -->
<div class="modal fade" id="modalMenu" tabindex="-1" aria-labelledby="modalMenuLabel" aria-hidden="true">
  <div class="modal-dialog">

    <div class="modal-content" data-menu-name="bluder">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="modalMenuBluderLabel">Kue Bluder</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ...
      </div>
    </div>

  </div>
</div>

CSS

.swiper {
    width: 100%;
    padding-top: 50px;
    padding-bottom: 50px;
  }

  .swiper-slide {
    background-position: center;
    background-size: cover;
    width: 300px;
    height: 300px;
    position: relative;
  }

  .swiper-slide img {
    display: block;
    width: 100%;
  }

  .slide-content {
    position: absolute;
    bottom: 0;
    background: linear-gradient(
      to top,
      rgb(238, 238, 238) 0%,
      rgba(238, 238, 238, 0.7) 50%,
      transparent 100%
    );
    width: 100%;
    padding: 0 1.2rem 1.2rem 1.2rem;
  }

JS

var swiper = new Swiper(".menu-list-container", {
  effect: "coverflow",
  loop: true,
  grabCursor: true,
  centeredSlides: true,
  slidesPerView: "auto",
  coverflowEffect: {
    rotate: 50,
    stretch: 0,
    depth: 100,
    modifier: 1,
    slideShadows: true,
  },
  pagination: {
    el: ".swiper-pagination",
  },
});

I tried putting the example in jsfiddle and in the code snippet but it wouldn’t show the same result I’m having in my browser so I’m uploading a screenshot showing the results instead.. I hope it’s allowed.

original condition screenshot shows 5 slides.

after clicking the modal Button screenshot only shows 4 slides.

any help is appreciated..

WMTS layer misalignment with WMS GetFeatureInfo

Just curious if anyone has encountered this before.

I have a 1m raster dataset tiled cached and served as WMTS layer. And I’m displaying it on a web map while also querying it for the raster pixel values using a WMS GetFeatureInfo request.

The data is being served by Geoserver, version 2.25.2.

Here is an example of what I mean:
image showing raster / GetFeatureInfo misalignment

The offset is small in spatial terms, given that this is 1m data. But I don’t see why it should exist at all if both requests are using the same coordinate system.

Here is an example GetFeatureInfo request that returns null:

https://nrri-atlas2.d.umn.edu/geoserver/ows?&REQUEST=GetFeatureInfo&SERVICE=WMS&SRS=EPSG:3857&STYLES=&VERSION=1.1.1&FORMAT=image/png&INFO_FORMAT=application/json&BBOX=-10333651.873837,5735740.039195868,-10333628.789705174,5735755.005625718&HEIGHT=802&WIDTH=1237&LAYERS=nra:dnr_chm_imagemosaic&QUERY_LAYERS=nra:dnr_chm_imagemosaic&X=501&Y=401&FEATURE_COUNT=1

And here is an example WMTS request:

https://nrri-atlas2.d.umn.edu/geoserver/gwc/service/wmts/rest/nra:dnr_chm_imagemosaic/nra:dnr_chm_keep/EPSG:900913/EPSG:900913:23/2993680/2031236?format=image%2Fpng

Here is the JavaScript code I am using to make the GetFeatureInfo request:

// Function to construct the GetFeatureInfo URL 
function getFeatureInfoUrl(bbox, width, height, x, y) {
  return (
    `https://nrri-atlas2.d.umn.edu/geoserver/ows?` +
    `&REQUEST=GetFeatureInfo&SERVICE=WMS&SRS=EPSG:3857` + 
    `&STYLES=&VERSION=1.1.1&FORMAT=image/png&INFO_FORMAT=application/json` +
    `&BBOX=${bbox}&HEIGHT=${height}&WIDTH=${width}` +
    `&LAYERS=nra:dnr_chm_imagemosaic&QUERY_LAYERS=nra:dnr_chm_imagemosaic` +
    `&X=${x}&Y=${y}&FEATURE_COUNT=1`
  );
}

// Handle user clicks to get pixel value
view.on("click", function (event) {
  const { mapPoint } = event;

  // Use the map's extent in EPSG:3857 
  const extent = view.extent;

  // Get the bounding box in EPSG:3857 (Web Mercator)
  const bbox = `${extent.xmin},${extent.ymin},${extent.xmax},${extent.ymax}`;

  // Get the dimensions of the current view
  const width = view.width;
  const height = view.height;

  // Use event.screenPoint to get the pixel coordinates relative to the MapView container
  const x = event.screenPoint.x;
  const y = event.screenPoint.y;

  // Build the GetFeatureInfo URL
  const url = getFeatureInfoUrl(bbox, width, height, x, y);

  console.log("BBOX:", bbox);
  console.log("Width:", width, "Height:", height);
  console.log("X:", x, "Y:", y);
  console.log("GetFeatureInfo URL:", url);
  // Fetch pixel value from the WMS service
  fetch(url)
    .then((response) => response.json())
    .then((data) => {
      // Extract pixel value from the response
      const feature = data.features ? data.features[0] : null;
      const pixelValue = feature
        ? feature.properties.GRAY_INDEX
        : "No data";

      // Show the pixel value in a popup
      view.popup.open({
        title: "Pixel Value",
        content: `Pixel value at clicked location: ${pixelValue}`,
        location: mapPoint, // Show popup at the clicked location
      });
    })
    .catch((error) => {
      console.error("Error fetching pixel value:", error);
    });

Ignored attempt to cancel a touchend event with cancelable=false, for example because scrolling is in progress and cannot be interrupted

const Settings = {
  dots: false,
  arrows: false,
  infinite: false,
  speed: 500,
  slidesToShow: 1,
  slidesToScroll: 1,
  draggable: true,
  // swipe: false,
  currentSlide: activeLocation,
  afterChange: (newIndex: number) => {
    setActiveLocation(newIndex);
  },
};

const LocSettings = {
  dots: false,
  arrows: false,
  infinite: false,
  speed: 500,
  slidesToShow: 1.5,
  slidesToScroll: 1,
  draggable: true,
  swipe:true
}; 

In NextJS, if I want to use swipe then I am commenting it but its giving this error:

Ignored attempt to cancel a touchend event with cancelable=false, for example because scrolling is in progress and cannot be interrupted.

I want that swipe to be true. I can’t make it false. What is the solution for this?

How to hide Google Ads that appeared on our printed documents?

We have a website on Blogger to print legal documents but when printing we got a Google Adsense message in the top of the page as you can see in the document picture and same message appears in the footer of the website and it’s has this class .ipr-container and same with pop-up in bottom of the website that appears in the printed document and it has an ID #google-anno-sa and they are related to Google Ad intents and each document content exist inside this <div id="talabe-print">. I tried many CSS and Javascript solutions like this code to hide all classes and IDs but they don’t work at all. However when I use developers tools and delete the DIVs related to .ipr-container and #google-anno-sa everything works fine. How can I hide those two elements to have a normal printed page with a CSS or JavaScript code.

@media print {
  .ipr-container, #google-anno-sa {
    display: none;
  }
}

PRINTED DOCUMENT WITH MESSAGE

MESSSAGE

POP-UP

Project the shadow of a disk in 3D space onto a 2D plane

I want to project a disk and its shadow in a 3D space onto the 2D viewer plane. I’m working with Javascript and PIXI, but my problem mostly concerns the general geometrics of the problem. The projection of the disk itself works fine, but I have troubles with displaying the shadow correctly.

My approach for the disk is that I define the center c, two radii r1 and r2, and a normal vector to the disk plane. Then I find two vectors that are in the disk plane, viz. orthogonal to the defined normal vector, and orthogonal to each other. I move r1 steps from the center c in the direction of the first of these vectors to get a first point on the edge of the disk; then I move r2 steps in the direction of the second vector for a second point. Next, I project these two edge points and the center c onto the 2D viewer plane and compute the distance between the projected center and the projected edge point. Finally, my projected disk can be plotted as an ellipse around the projected center and radii according to the computed distances.

Now, my approach for the shadow which I cannot get to work is similar. Again, I compute two edge points of the original disk the same way as before, but now I protect these edge points and the center point onto the shadow plane. In the graphic below, you can see the center point projected on the shadow plane in green; the projected edge points in blue. Next, I again compute the distances between the edge points and center points of the shadow to get two radii for the shadow. Finally, for the projection of the shadow onto the viewer plane, I again use the same function as for the original disk.

In the figure below, the white lines are parallel lines orthogonal to the viewer. The two lines on the bottom are in the same plane that the shadows is projected on.

Example with light source, disk, points of shadow and wrong shadow

I’ve also added my code below. I excluded the function for projecting specifc points to the projection or shadow plane since nothing indicates a problem there.

// define position of light source and object
let light_vec = [768, 400, 600]
let obj_vec = [468, 472, 1000]

plotDisk(graphics, obj_vec, 50, 50, [0, 0, 1], color_str, 1.0)
plotShadow(graphics, obj_vec, 50, [0, 0, 1], light_vec, [0.0, 1.0 ,0.0], [0, 838, 0], color_str, 0.5)

// plot a 3d disk projected to the camera plane
function plotDisk(disk_obj, center_vec, rad1_fl, rad2_fl, norm1_vec, color_str, trans_fl) {

    // get non-colinear vector
    norm1_vec = normalize(norm1_vec)

    let nonCol_vec = [0.0, 0.0, 0.0]
    let eqZ_boo = true;
    let neqZ_boo = true;

    let i = 0;
    while (i < norm1_vec.length) {
        if (norm1_vec[i] !== 0 && eqZ_boo) {
            nonCol_vec[i] = - norm1_vec[i]  
            eqZ_boo = false
        } else if (norm1_vec[i] == 0 && neqZ_boo) {
            nonCol_vec[i] = 1.0 
            neqZ_boo = false;
        }
        i++;
    }

    // get second and third normal vector
    let norm2_vec = normalize(crossProduct(norm1_vec, normalize(nonCol_vec)))
    let norm3_vec = normalize(crossProduct(norm1_vec, norm2_vec))

    // construct points on disk line and project to plane
    let radPoint1_vec = projToPlane(addVec(center_vec, scalarMulti(norm2_vec, rad1_fl)), view_proj);
    let radPoint2_vec = projToPlane(addVec(center_vec, scalarMulti(norm3_vec, rad2_fl)), view_proj);
    let centerPro_vec = projToPlane(center_vec, view_proj) 

    // get radii of ellipse
    let radPro1_fl = Math.sqrt(Math.pow(centerPro_vec[0] - radPoint1_vec[0], 2) +  Math.pow(centerPro_vec[1] - radPoint1_vec[1], 2));
    let radPro2_fl = Math.sqrt(Math.pow(centerPro_vec[0] - radPoint2_vec[0], 2) +  Math.pow(centerPro_vec[1] - radPoint2_vec[1], 2));

    // plot actual ellipse
    disk_obj.beginFill(color_str, trans_fl);
    disk_obj.drawEllipse(centerPro_vec[0], centerPro_vec[1], radPro1_fl, radPro2_fl);
    disk_obj.endFill();
}

// plot the shadow of a disk
function plotShadow(disk_obj, center_vec, rad_fl, norm1_vec, light_vec, plane_normal, plane_point, shadow_color_str, trans_fl) {

    // get two orthonal vectors on the disk as before
    norm1_vec = normalize(norm1_vec);

    let nonCol_vec = [0.0, 0.0, 0.0];
    let eqZ_boo = true;
    let neqZ_boo = true;
    let i = 0;
    while (i < norm1_vec.length) {
        if (norm1_vec[i] !== 0 && eqZ_boo) {
            nonCol_vec[i] = -norm1_vec[i];
            eqZ_boo = false;
        } else if (norm1_vec[i] == 0 && neqZ_boo) {
            nonCol_vec[i] = 1.0;
            neqZ_boo = false;
        }
        i++;
    }

    let norm2_vec = normalize(crossProduct(norm1_vec, normalize(nonCol_vec)));
    let norm3_vec = normalize(crossProduct(norm1_vec, norm2_vec));

    // project points on the disk to the shadow plane
    let diskEdge1_vec = addVec(center_vec, scalarMulti(norm2_vec, rad_fl));
    let diskEdge2_vec = addVec(center_vec, scalarMulti(norm3_vec, rad_fl));

    // get shadow points on the plane
    let shadowEdge1_vec = projectToShadowPlane(diskEdge1_vec, light_vec, plane_normal, plane_point);
    let shadowEdge2_vec = projectToShadowPlane(diskEdge2_vec, light_vec, plane_normal, plane_point);
    let shadowCenter_vec = projectToShadowPlane(center_vec, light_vec, plane_normal, plane_point);

    // compute radius on shadow plane
    let planeRad1_fl = Math.sqrt(Math.pow(shadowCenter_vec[0] - shadowEdge1_vec[0], 2) + Math.pow(shadowCenter_vec[1] - shadowEdge1_vec[1], 2) + Math.pow(shadowCenter_vec[2] - shadowEdge1_vec[2], 2));
    let planeRad2_fl = Math.sqrt(Math.pow(shadowCenter_vec[0] - shadowEdge2_vec[0], 2) + Math.pow(shadowCenter_vec[1] - shadowEdge2_vec[1], 2) + Math.pow(shadowCenter_vec[2] - shadowEdge2_vec[2], 2));

    plotDisk(disk_obj, shadowCenter_vec, planeRad1_fl, planeRad2_fl, plane_normal, shadow_color_str, trans_fl)

    // plot the points of the shadow for debugging
    let shadowPoint1_proj = projToPlane(shadowEdge1_vec, view_proj);
    let shadowPoint2_proj = projToPlane(shadowEdge2_vec, view_proj);
    let shadowCenter_proj = projToPlane(shadowCenter_vec, view_proj);

    graphics.beginFill("blue");
    graphics.drawCircle(shadowPoint1_proj[0], shadowPoint1_proj[1], 5);
    graphics.drawCircle(shadowPoint2_proj[0], shadowPoint2_proj[1], 5);
    graphics.endFill();

    graphics.beginFill("green");
    graphics.drawCircle(shadowCenter_proj[0], shadowCenter_proj[1], 5);
    graphics.endFill();   
}

As you can see in the figure, the blue edge points of the shadow are not actually on the edge and the circle is too big and the proportions are not right. I looked into the computation of the radii for the shadow and tested that the the plotDisk function really works for an ellipse and not just for circles.

Auto capture documents from mobile camera using a react web-app

Context:
We have created a web application that is opened in mobile app’s WebView and capturing images using MediaStream APIs.

Could someone please suggest any npm packages or existing APIs that we can utilize for Auto detect and capture of document(any valid official or other document).

NOTE: we have opened camera and capturing images using MediaStream APIs(https://developer.mozilla.org/en-US/docs/Web/API/ImageCapture)

Thanks in advance!