how to get the newest variable when using react event bind

I am using this event bind to listening the window tab switch:

const handleVisibilityChange = () => {
    if (!wsSocketIOProvider) {
      console.warn("provider is null");
      return;
    }
    let connected = wsSocketIOProvider?.ws?.connected;
    if (connected) {
      console.log("connected is ok");
    } else {
      console.error("disconnected......");
      window.location.href = "/doc/tab";
    }
  };

  React.useEffect(() => {
    document.addEventListener("visibilitychange", handleVisibilityChange);

    return () => {
      document.removeEventListener("visibilitychange", handleVisibilityChange);
    };
  }, []);

now I facing when trigger the handleVisibilityChange, the variable wsSocketIOProvider always null even though the wsSocketIOProvider changed. why did this happen? What should I do to tracing the lastest variable of wsSocketIOProvider?

MapTiler SDK markers move across the map when scrolling

I’m trying to create markers using the MapTiler SDK. I have a map component that displays a MapTiler map, and in its TypeScript file, I’m adding markers like this:

 const marker = new maptilersdk.Marker({ anchor: 'bottom' })
            .setLngLat([105.8509611111111,21.03162777777778,])
            .addTo(this.map);
          console.log('Marker position:', marker.getLngLat());

The coordinates are pointing to Hanoi, and logging the marker’s coordinates shows the correct longitude and latitude. However, when zoomed out, the marker appears somewhere in the ocean. As I zoom in, the marker smoothly moves straight toward the intended position in Hanoi. When fully zoomed in, the marker reaches the correct location and stays there until I zoom out again.enter image description hereenter image description here

(intended)End location at max zoom:enter image description here

Markers are made after map has been loaded

import { Component, OnInit, ViewChild, ElementRef, AfterViewInit, OnDestroy } from '@angular/core';
import { Map, MapStyle, config } from '@maptiler/sdk';
import * as maptilersdk from '@maptiler/sdk';
import ExifReader from 'exifreader';

 ngAfterViewInit() {
    const initialState = { lng: 106.6000, lat: 17.4833, zoom: 5 };

    this.map = new Map({
      container: this.mapContainer.nativeElement,
      style: MapStyle.STREETS,
      center: [initialState.lng, initialState.lat],
      zoom: initialState.zoom
    });
    this.map.on('load', () => {
      const marker = new maptilersdk.Marker({ anchor: 'bottom' })
            .setLngLat([105.8509611111111,21.03162777777778,])
            .addTo(this.map!);
          console.log('Marker position:', marker.getLngLat());
    });
  }

Here are my .HTML and .scss if of any use. Thank you for any help!

<div class="map-wrap">
  <div #map class="map"></div>
</div>

<img id="img1" src="/IMG_1100.jpg" alt="Testbild" crossorigin="anonymous" />

.map-wrap {
  width: 100vw;      /* 100% der Viewport-Breite */
  height: 95vh;      /* 95% der Viewport-Höhe, z.B. fast voll */
  margin: 0 auto;    /* zentriert horizontal, meist redundant bei 100% Breite */
  border: 1px solid #000;
}

.map {
  width: 100%;
  height: 100%;
}

#img1 {
  display: none;
}

How to open dropdown menu from other class

I have something like this and i want to open menu using not only .dropdown-btn but also when somebody click ‘a’ class in menu. It is some easy way to change it ?

JS:

 //Submenu Dropdown Toggle
  if ($(".main-header li.menu-item-has-children ul").length) {
    $(".main-header .navigation li.menu-item-has-children > a").append(
      '<div class="dropdown-btn"><span class="fa fa-angle-right"></span></div>'
    );
  }

  //Mobile Nav Hide Show
  if ($(".side-menu__block").length) {
    var mobileMenuContent = $(".main-header .nav-outer .main-menu").html();
    var mobileNavContainer = $(".mobile-nav__container");
    mobileNavContainer.append(mobileMenuContent);

    //Dropdown Button
    mobileNavContainer
      .find("li.menu-item-has-children .dropdown-btn")
      .on("click", function (e) {
        e.preventDefault();
        $(this).toggleClass("open");
        $(this).parent("a").parent("li").children("ul").slideToggle(500);
      });
    
      
    //Menu Toggle Btn
    $(".mobile-nav-toggler").on("click", function () {
      $(".side-menu__block").addClass("active");
    });

    $(".side-menu__block-overlay,.side-menu__toggler, .scrollToLink > a ").on(
      "click",
      function (e) {
        $(".side-menu__block").removeClass("active");
        e.preventDefault();
      }
    );
  }

i try to change JS and still the same problem

How to Replace a Box Player Entity with a GLB Model in Noa.js + Babylon.js Game

I’m currently working on a game built using Noa.js and Babylon.js. In the existing entity.js file from the project template, the player is created using a simple box mesh.

I’m trying to replace this box with a .glb model to serve as the main player character. I’ve successfully loaded the GLB model into the scene, but it spawns separately and doesn’t inherit the behavior or properties of the existing player (like movement, controls, or collision handling).

What’s the correct way to replace the current box mesh used for the player entity with a GLB model, while ensuring it functions as the main player (movement, collision detection, and controls) within the Noa.js engine?

I’ll attach my current implementation for reference in the comments — would really appreciate if someone could review it and help me identify where I’m going wrong.

Thanks in advance!

Here is my code:

import * as BABYLON from '@babylonjs/core';
import '@babylonjs/loaders';

import { noa } from './engine';
import { setMeshShadows } from './shadows';
import { blockIDs } from './registration';
import blastImg from './assets/blast.png';

let sheepMesh = null;
let gameActive = true;
let explosionSound = new Audio('./assets/explosion.mp3');

const npcSheepEntities = [];

/**
 * Convert 3D mesh position to 2D screen coordinates.
 */
function toScreenPosition(mesh, scene) {
  if (!mesh || !scene || !scene.activeCamera) {
    return { x: window.innerWidth / 2, y: window.innerHeight / 2 };
  }

  const worldMatrix = mesh.getWorldMatrix();
  const transformMatrix = scene.getTransformMatrix();
  const camera = scene.activeCamera;

  const engine = scene.getEngine();
  const viewport = camera.viewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());

  const projected = BABYLON.Vector3.Project(
    mesh.position,
    worldMatrix,
    transformMatrix,
    viewport
  );

  return { x: projected.x, y: projected.y };
}

/**
 * Display a blast effect at given screen position.
 */
function showBlastEffect(screenX = window.innerWidth / 2, screenY = window.innerHeight / 2) {
  return new Promise((resolve) => {
    const blastElement = document.createElement('img');
    blastElement.src = blastImg;
    blastElement.style.position = 'fixed';
    blastElement.style.top = `${screenY}px`;
    blastElement.style.left = `${screenX}px`;
    blastElement.style.transform = 'translate(-50%, -50%)';
    blastElement.style.pointerEvents = 'none';
    blastElement.style.zIndex = '9999';
    blastElement.style.width = '300px';
    blastElement.style.height = '300px';
    blastElement.style.opacity = '1';
    blastElement.style.transition = 'opacity 1s ease-out';

    document.body.appendChild(blastElement);

    setTimeout(() => { blastElement.style.opacity = '0'; }, 300);
    setTimeout(() => {
      document.body.removeChild(blastElement);
      resolve();
    }, 1100);
  });
}

/**
 * Load a GLB model and attach it to a given entity.
 * Mesh follows entity position in game loop.
 */
async function loadAndAttachGLBToEntity(entityId, modelPath, modelFilename, options = {}) {
  const scene = noa.rendering.getScene();
  const dat = noa.entities.getPositionData(entityId);
  const { width: w, height: h, position: pos } = dat;

  const {
    scaleMultiplier = 1,
    yOffset = 0
  } = options;

  return new Promise((resolve, reject) => {
    BABYLON.SceneLoader.ImportMesh(
      null,
      modelPath,
      modelFilename,
      scene,
      (meshes) => {
        const visualMesh = meshes.find(m => m.getTotalVertices && m.getTotalVertices() > 0) || meshes[0];
        if (!visualMesh) return reject(new Error('No visible mesh found in GLB model.'));

        visualMesh.position.set(pos[0], pos[1] + h / 2 + yOffset, pos[2]);
        visualMesh.scaling = new BABYLON.Vector3(w, h, w).scale(scaleMultiplier);
        visualMesh.material = noa.rendering.makeStandardMaterial();
        visualMesh.visibility = 1;

        noa.entities.addComponent(entityId, noa.entities.names.mesh, {
          mesh: visualMesh,
          offset: [0, h / 2 + yOffset, 0],
        });

        setMeshShadows(visualMesh, true);

        if (entityId === noa.playerEntity) {
          sheepMesh = visualMesh;
        }

        noa.on('beforeRender', () => {
          if (!gameActive) return;
          const data = noa.entities.getPositionData(entityId);
          if (!data) return;
          visualMesh.position.set(
            data.position[0],
            data.position[1] + yOffset,
            data.position[2]
          );
          if (entityId === noa.playerEntity) {
            checkFenceCollision(data.position[0], data.position[1], data.position[2]);
          }
        });

        resolve(visualMesh);
      },
      null,
      (scene, message, exception) => {
        console.error('Error loading GLB model:', message, exception);
        reject(exception);
      }
    );
  });
}

/**
 * Collision detection between player and fence blocks.
 */
function checkFenceCollision(x, y, z) {
  if (!gameActive) return;
  const blockBelow = noa.getBlock(x, y, z);
  const blockAtFeet = noa.getBlock(x, y + 0.5, z);
  if (blockBelow === blockIDs.fence || blockAtFeet === blockIDs.fence) {
    endGame();
  }
}

/**
 * Update sheep counter in UI.
 */
function updateSheepCount() {
  const sheepCountElement = document.querySelector('#sheep-counter .counter-value');
  if (sheepCountElement) {
    sheepCountElement.textContent = npcSheepEntities.length.toString();
  }
}

/**
 * End the game — hide sheep mesh, play sound and show blast.
 */
async function endGame() {
  if (!gameActive) return;
  gameActive = false;

  const scene = noa.rendering.getScene();
  let screenPos = { x: window.innerWidth / 2, y: window.innerHeight / 2 };
  if (sheepMesh) {
    screenPos = toScreenPosition(sheepMesh, scene);
    sheepMesh.setEnabled(false);
  }

  explosionSound.play();
  await showBlastEffect(screenPos.x, screenPos.y);

  document.getElementById('end-game-screen').style.display = 'flex';
  document.getElementById('game-ui').style.display = 'none';
}

/**
 * Spawn a single NPC sheep entity.
 */
async function spawnNPCSheep(startX, startY, startZ) {
  const eid = noa.entities.add([startX, startY, startZ], 0.5, 1.2);
  npcSheepEntities.push(eid);

  await loadAndAttachGLBToEntity(eid, '/castle/', 'sheep.glb', {
    scaleMultiplier: 0.4,
    yOffset: 0,
  });

  updateSheepCount();

  // Give sheep circular wandering movement
  const centerX = startX + (Math.random() - 0.5) * 100;
  const centerZ = startZ + (Math.random() - 0.5) * 100;
  const radius = 5 + Math.random() * 15;
  const angularSpeed = 0.0005 + Math.random() * 0.001;
  const angleOffset = Math.random() * 2 * Math.PI;

  noa.on('beforeRender', () => {
    if (!gameActive) return;
    const time = performance.now();
    const angle = angleOffset + angularSpeed * time;
    const x = centerX + Math.cos(angle) * radius;
    const z = centerZ + Math.sin(angle) * radius;
    const currentY = noa.entities.getPosition(eid)[1];
    noa.entities.setPosition(eid, [x, currentY, z]);
  });
}

/**
 * Spawn a herd of NPC sheeps around player.
 */
async function spawnNPCSheepHerd(centerX, centerY, centerZ) {
  for (let i = 0; i < 5; i++) {
    const randX = centerX + (Math.random() - 0.5) * 160;
    const randZ = centerZ + (Math.random() - 0.5) * 160;
    await spawnNPCSheep(randX, centerY, randZ);
  }
}

/**
 * Initialize player entity and NPC herd after game tick.
 */
noa.once('tick', async () => {
  try {
    const eid = noa.playerEntity;
    if (!eid) throw new Error('Player entity not found');

    // Replace box mesh with GLB model for player
    await loadAndAttachGLBToEntity(eid, '/castle/', 'sheep.glb', {
      scaleMultiplier: 0.4,
      yOffset: 0
    });

    // Adjust camera follow position for player sheep
    const sheepHeight = noa.ents.getPositionData(eid).height;
    const eyeOffset = 0.8 * sheepHeight;

    noa.ents.removeComponent(noa.camera.cameraTarget, 'followsEntity');
    noa.ents.addComponent(noa.camera.cameraTarget, 'followsEntity', {
      entity: eid,
      offset: [0, eyeOffset, 0],
    });

    // Spawn NPC herd
    const pos = noa.entities.getPosition(eid);
    await spawnNPCSheepHerd(pos[0], pos[1], pos[2]);

    console.log('Player sheep loaded and NPC herd spawned.');
  } catch (error) {
    console.error('Failed to initialize game:', error);
  }
});

https://github.com/fenomas/noa-examples

I clone the code from here

Is it possible to config our SCSS class like the ones in tailwind css especially for media query. ‘lg:items-center’ like this way

/* Width in percentage properties */
$opacityPercentages:
  10 10%,
  20 20%,
  33 33%,
  50 50%,
  55 55%,
  60 60%,
  70 70%,
  80 80%,
  85 85%,
  100 100%;

@each $opacityName, $opacityValue in $opacityPercentages {
  .opacity-#{$opacityName} {
    opacity: #{$opacityValue};
  }
}

/* Position relative properties */
$position: relative, absolute, fixed, sticky;

@each $positionName in $position {
  .position-#{$positionName} {
    position: $positionName !important;
  }
}

is it possible to write our own media query class just like tailwind. This particular field has not yet been configured in my project. Help me to achieve it

Open for your answers

coreUI : CSidebar under CHeader

Using the latest version of coreUI, CSidebar takes up 100% height of the webpage while the CHeader, CContent, and CFooter take up the space the right.

https://coreui.io/demos/react/5.3/free/?theme=light#/dashboard

However, I am after a layout where the CHeader takes up the whole width of the top while the CSidebar, CContent, and CFooter take up the space below it:

Is this possible?

https://codesandbox.io/p/sandbox/coreui-admin-v3-ndlzq5

enter image description here

Argument of type ‘string’ is not assignable to parameter of type ‘linkType’

I am trying to map through my data but in my onChange function I keep getting the error below, can anyone help?

Argument of type ‘string’ is not assignable to parameter of type ‘linkType’

Component:

  type linkType = 'breakdown' | 'insurance' | 'lite';

  {data &&
    data.accountCoverTypes?.map((button, index) => (
      <>
        {index === data.accountCoverTypes.length - 1 ? (
          <Divider
            ...
          />
        ) : null}
        <HighlightButton
          key={index}
          ...
          onPress={() => onChange(button.link, index)}
          ...
        />
      </>
    ))}

Data:

export const data = {
  title: 'What type of cover do you have?',
  accountCoverTypes: [
    { link: 'breakdown', title: 'Breakdown' },
    { link: 'insurance', title: 'Car insurance' },
    { link: 'lite', title: "I don't have any RAC cover" },
  ],
};

Openlayer clustered feature style not being updated

I implemented cluster in my openlayer map.
Everything work as it should, (the way it work without cluster) except for selection.
The issue here is that the clustering breaks the selected style from my single selected feature. The selection is good, but the style is like desync when it get updated.

Every X seconds, I update my featur on my map :

   let newPoint = new Point([trackable.lon, trackable.lat]).transform('EPSG:4326', 'EPSG:3857')
     if (this.trackingConfigParams?.ui_map_clustering_enabled) {
    layer?.getSource()?.getFeatures()?.forEach((featureCluster)=> {
      if (feature) {
        return
      }
      feature = featureCluster?.get('features')?.find((f)=> {
        return f.get('tracking_id') === trackable.tracking_id
      })
    })
  }
     feature.setGeometry(newPoint)
     feature.setProperties({ x: value })

When I check the function call stack in the code without the cluster strategy, the “setGeometry” function seems to calls the style function located in the select function from openlayer, which allow to keep the selected style applied on the element

createSelectInteraction(trackingConfig) {
    const self = this
    let features = null
    this.selectInteraction = new Select({
      style: this.selectedFeatureStyle.bind(this)
    // ...etc

But whener I switch to the cluster strategy, this function is not automatically called anymore. I suspect the feature inside feature to cause the issue, breaking the reactivity, but I have no idea how to fix this.

The behaviour is the following :

  • I select my cluster feature (only for single feature cluster, with non cluster style) on map, it changes the style to the selected style.
  • My feature get updated, a new feature is created with new coordinates
  • my selected feature is still displayed, but has not moved, therefore, I have 2 duplicated feature, one selected who has not been updated (old coordinates) with selected style, and the other new one which has not selected style but has updated coordinates

Note that my selection are on special layer

 const overlay = new VectorLayer({
      style: null,
      source: new VectorSource({
        features: this?.selectInteraction?.getFeatures()
      }),
      zIndex: 5000
    })

I tried to changes the features from my selection layer, but did not help
I have no idea how i could fix this ATM

Any help welcome

Why is my Spring Boot POST controller returning HTTP 400 when sending data via Ajax?

I’m having trouble posting a JSON array to a Spring Boot @RequestMapping controller. Get 400 Bad Request. Any suggestions how to correct?

html code

  console.log("send:", JSON.stringify(resultList));
  $.ajax({
    url : '/oper_list', 
    type : 'post', 
    data : JSON.stringify(resultList), 
    contentType : "application/json; charset=utf-8",
    // headers: {"Accept": "application/json"},  
    // xhrFields: { withCredentials: true },
    success: (data) => alert(data),
    error: (xhr) => {
      console.error("error:", xhr.responseText)
      // console.log(xhr)
    }
  });

@controller
controller

@PostMapping("/oper_list")
@ResponseBody
public String insertOperTimeList(
    @RequestBody List<BusinessDateVO> operList
        /*, @AuthenticationPrincipal CustomManager manager*/
) {
        System.out.println("ajax to controller");
        /*if (manager == null || manager.getManager() == null) {
                return "no account";
        }*/
        if (operList == null || operList.isEmpty()) {
                return "no operList";
        }
        System.out.println("opertimelist: " + operList);
        

        //int rtNum = manager.getManager().getRm_rt_num();
        int rtNum = 1;
        int result = 0;
        for (BusinessDateVO oper : operList) {
                oper.setBd_rt_num(rtNum); 
                if (oper.getBd_date() == null || oper.getBd_open() == null || oper.getBd_close() == null) {
                        continue; 
                }

                managerService.makeOperTime(oper); // insert
                result++;
        }

        return "completed" + result + "counts";
}

configurations

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = "root") 
public class WebMvcConfig implements WebMvcConfigurer{

    @Value("${root}")
    String uploadPath;

    public void addResourceHandlers(ResourceHandlerRegistry registry){
        registry.addResourceHandler("/file/**").addResourceLocations("file:///"+uploadPath);
        registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/");
    }

    @Override
    public void addCorsMappings(org.springframework.web.servlet.config.annotation.CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:8080") 
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowCredentials(true); 
    }
    @Override
    public Validator getValidator() {
            return new LocalValidatorFactoryBean();
    }

/////////////////////////////////////////////////////////////////////////////////////

@Configuration
@EnableWebSecurity
public class SecurityConfig{

  @Autowired
  private ManagerDetailService managerDetailService;

  @Value("${root}")
  private String rememberMeKey;

  @Bean
    @Order(1)
    public SecurityFilterChain managerSecurityFilterChain(HttpSecurity http) throws Exception {
      http
      .securityMatcher("/manager/**", "/schedule/**")
      .csrf(csrf ->csrf.disable())
      .authorizeHttpRequests(auth -> auth
          .requestMatchers("/manager/signup", "/manager/register").permitAll()
          .anyRequest().authenticated()
      )
      .formLogin(form -> form
          .loginPage("/manager/login")
          .loginProcessingUrl("/manager/login")
          .defaultSuccessUrl("/manager/")
          .permitAll()
      )
      .userDetailsService(managerDetailService)
      .rememberMe(rm-> rm
        .userDetailsService(managerDetailService)
        .key(rememberMeKey)/
        .rememberMeCookieName("LC_manager")
        .tokenValiditySeconds(60 * 60 * 24 * 100)
      )

      .logout(logout -> logout
          .logoutUrl("/manager/logout")
          .logoutSuccessUrl("/manager/")
          .clearAuthentication(true)
          .invalidateHttpSession(true)
          .permitAll());
  
      return http.build();
    }

error code

The request fails with a 400 Bad Request, but the error is swallowed silently in the backend cosole logs.

make_opertime:208 error: {"timestamp":1747989098092,"status":400,"error":"Bad Request","path":"/manager/make_opertime_list"}
error   @   make_opertime:208
c   @   jquery-3.7.1.min.js:2
fireWith    @   jquery-3.7.1.min.js:2
l   @   jquery-3.7.1.min.js:2
(anonymous) @   jquery-3.7.1.min.js:2
XMLHttpRequest.send     
send    @   jquery-3.7.1.min.js:2
ajax    @   jquery-3.7.1.min.js:2
(anonymous) @   make_opertime:199
dispatch    @   jquery-3.7.1.min.js:2
v.handle    @   jquery-3.7.1.min.js:2

//////////////////////////////////////////////////////////////////////

and

@Data
public class BusinessDateVO {

    private int bd_num;

    private String bd_date;
    private int bd_rt_num;
    private boolean bd_off;

    // @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
    private String  bd_open;

    // @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
    private String  bd_close;

    // @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
    private String  bd_brstart;

    // @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
    private String  bd_brend;

    // @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
    private String  bd_loam;

    // @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
    private String  bd_lopm;
    

        // @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
    @JsonIgnore
    private Timestamp  bd_open_ts;

    // @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
    @JsonIgnore
    private Timestamp  bd_close_ts;

    // @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
    @JsonIgnore
    private Timestamp  bd_brstart_ts;

    // @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
    @JsonIgnore
    private Timestamp  bd_brend_ts;

    // @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
    @JsonIgnore
    private Timestamp  bd_loam_ts;

    // @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
    @JsonIgnore
    private Timestamp  bd_lopm_ts;



/////////////////////////////////////////////

    @JsonIgnore
    private String  bd_local_date;

    
    // public String getBd_date(){
    //  SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
    //  return format.format(bd_open);
    // }

    
}

Google Maps API MarkerClusterer is not defined

I have a working map with AdvancedMarkerElements, but it’s completely killing the browser as soon as there are a few hundred markers. So I’m trying to add MarkerClusterer, but I just won’t get it to work whatever I try – feel quite stupid now.

I’ve tried to add MarkerClusterer Library from several sources with different methods and looked at tons of examples, but I always end up with an error saying “MarkerClusterer is not defined” or similiar.

<script src="https://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/src/markerclusterer_compiled.js"></script>
<div id="map"></div>
<script type="text/javascript">
  (g => {
    var h, a, k, p = "The Google Maps JavaScript API",
      c = "google",
      l = "importLibrary",
      q = "__ib__",
      m = document,
      b = window;
    b = b[c] || (b[c] = {});
    var d = b.maps || (b.maps = {}),
      r = new Set,
      e = new URLSearchParams,
      u = () => h || (h = new Promise(async (f, n) => {
        await (a = m.createElement("script"));
        e.set("libraries", [...r] + "");
        for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]);
        e.set("callback", c + ".maps." + q);
        a.src = `https://maps.${c}apis.com/maps/api/js?` + e;
        d[q] = f;
        a.onerror = () => h = n(Error(p + " could not load."));
        a.nonce = m.querySelector("script[nonce]")?.nonce || "";
        m.head.append(a)
      }));
    d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n))
  })
  ({
    key: "",
    v: "weekly"
  });

  async function initMap() {
    const {
      Map
    } = await google.maps.importLibrary("maps");
    const {
      AdvancedMarkerElement
    } = await google.maps.importLibrary("marker");
    const center = {
      lat: 50.5459719,
      lng: 10.0703129
    };
    const map = new Map(document.getElementById("map"), {
      zoom: 6.6,
      center,
      mapId: "4504f8b37365c3d0",
    });
    geocoder = new google.maps.Geocoder();
    markers = [];
    for (const property of properties) {
      if (property.lat != '' && property.lng != '') {
        var marker = new google.maps.marker.AdvancedMarkerElement({
          map: map,
          content: buildContent(property),
          position: new google.maps.LatLng(property.lat, property.lng),
          title: property.name,
        });
        marker.addListener("gmp-click", () => {
          toggleHighlight(marker, property);
        });
        markers.push(marker);
      }
    }
    var mc = new MarkerClusterer(map, markers)
  }

  function toggleHighlight(markerView, property) {
    if (markerView.content.classList.contains("highlight")) {
      markerView.content.classList.remove("highlight");
      markerView.zIndex = null;
    } else {
      markerView.content.classList.add("highlight");
      markerView.zIndex = 1;
    }
  }

  function buildContent(property) {
    const content = document.createElement("div");

    content.classList.add("property");
    content.innerHTML = `
    <div class="icon user" id="wb${property.id}">
        <i aria-hidden="true" class="fa fa-icon fa-user" title="${property.name} (${property.type})"></i>
        <span class="fa-sr-only">${property.name} (${property.type})</span>
    </div>
    <div class="details">
        <div class="name">${property.name}</div>
        <div class="address">${property.address}</div>
        <div class="mail"><a href="mailto:${property.mail}">${property.mail}</a></div>
        <div class="phone"><a href="tel:${property.phone}">${property.phone}</a></div>
        <div class="features">
        </div>
    </div>
    `;
    return content;
  }
</script>

Please help this requirement via SAP Adobe Form [closed]

I have designed a dynamic table in an SAP Adobe Form (XFA-based). The table displays line items with multiple columns such as PRODUCT NO., DESCRIPTION, BATCH NO., QUANTITY, UNIT PRICE, DISCOUNT, VAT, and TOTAL.

These lines are coming from a repeating structure (DATA[*]) in the context.

Requirement:

  • If the PRODUCT NO. (Material Number) is the same across consecutive
    rows, I want to visually suppress those rows, i.e.:

  • Hide the row borders (top and bottom) between the repeated rows.

  • Only the last row with that material number should display the bottom
    border to “close” the section visually.

  • The column lines (left and right borders) should remain visible so
    that the table maintains structure.

I attempted the following approaches:

Hiding all borders using:

this.border.edge.presence = "hidden";

Trying to selectively show the bottom line for the last row using:

this.border.edge[2].color.value = "0,0,0"; // bottom

result :
enter image description here

expected result :
enter image description here

There are two cases:

  • If the material is the same but the batch is different, then the row
    borders should be hidden.

  • If the material is different, then the table should display normally
    with all row borders.

How can I scale my HTML and CSS to suit for different resolution devices?

How can I make my web content scale to different device sizes?

I do not know specific phone scales, and what I can really do about this. I’m looking forward to scale my code to be able to work on different devices with the same layout shown and nothing moved around. It uses JavaScript code to move stuff around, but that only toggles display:none and display:block. Do I change the JavaScript to flex, or other stuff?
If you need to know more about my code, I’ll try to provide more of it.
<iframe id="IPTV" src="nosignal.html" width="460" height="259" allowfullscreen frameborder='0' style="width: 100%; height: 100%;"></iframe>
That is an example of my iframe which uses a scale format, and I don’t know if it is device friendly.

Calculate payload size for a context.sync() in Excel JS API

tl;dr: is there some way to detect if an Excel context is getting “full”, instead of randomly guessing how often to sync?

I’m writing an add-in using the Excel JavaScript API. For web-based Excel, the following (simplified) code throws an error on the await context.sync() at the end:

async function setAndFormat(address, values, formats) {
   await Excel.run(async (context) => {
      const sheet = context.workbook.worksheets.getItem("foo")
      const range = sheet.getRange(address)

      // Set the values
      range.values = values
      // await context.sync()

      // Reset formatting
      range.format.fill.clear()
      range.format.font.bold = false
      range.format.font.color = "#000000"
      // await context.sync()

      for (const format of formats) {
         // Creates a new range and sets various formatting attributes on it
         applyFormat(sheet, format)
         // await context.sync()
      }

      try {
         await context.sync()
      } catch (e) {
         showError(e)
      }      
   })
}

/*
RichApi.Error: The request payload size has exceeded the limit.
Please refer to the documentation:
"https://docs.microsoft.com/office/dev/add-ins/concepts/resource-limits-and-performance-optimization#excel-add-ins".
*/

The above works fine for small amounts of changes. However, when values is 40,000 numbers, and formats causes 10,000+ ranges comprising 20,000+ cells to change their formatting, the RichApi.Error is thrown.

Per the documentation there is a:

“payload size limit for requests and responses of 5MB”

However, I don’t know how to calculate (or even estimate) this. If I uncomment the first two context.sync() calls in the code above I avoid the error 50% of the time. If I uncomment the last call—synchronizing after EVERY format change—the error is never raised…but performance is abysmal.

My current hack is something like this:

let cellsAffected = 0
for (const format of formats) {
   cellsAffected += applyFormat(sheet, format)
   if (cellsAffected > 2000) {
      // apply the cached changes so far
      await context.sync()
      cellsAffected = 0
   }
}
if (cellsAffected) await context.sync()

…but I have only trial-and-error to guide whether the best value is 500 or 2000 or 5000…and it probably depends on how many formats are changed for each cell range, and possibly the values set for each!

I’d like to create something like this:

// Flush the cache, by default if the payload is > 4.5MiB
async function flushContextIfOverLimit(context, limit = 4.5 * 2**20) {   
   if (calculatePayloadSizeForContext(context) > limit) {
      return await context.sync()
   }
}

…but I’m uncertain how to write calculatePayloadSizeForContext(). I’ve tried to trace down where the size of the body is calculated in the library that raises the error, but failed to find it so far.