Trying to create drag, resize and rotate feature in Angular 17. When I am trying to resize the element, it is not working as expected

I am trying to create a drag, resize and rotate feature in angular using custom javascript functions. My resize is not working as expected. When I am trying to resize the element from corners or from center dots, position of other corners is not fixed. Also when element is rotated to a particular deg let’s assume 20 degree and then trying to resize, then position is not stable.

Demo Url:
https://stackblitz.com/edit/angular-empty-project-emm12p?file=app%2Fapp.component.ts

Trying to create drag, resize and rotate feature in Angular 17. When I am trying to resize the element, it is not working as expected

I am trying to create a drag, resize and rotate feature in angular using custom javascript functions. My resize is not working as expected. When I am trying to resize the element from corners or from center dots, position of other corners is not fixed. Also when element is rotated to a particular deg let’s assume 20 degree and then trying to resize, then position is not stable.

Demo Url:
https://stackblitz.com/edit/angular-empty-project-emm12p?file=app%2Fapp.component.ts

How can I get the class index of a XML requested object more efficiently (as I am having problems with the current approach)?

The problem I have is a bit more complicated, so I have made a video that shows the behavior I am talking about.

Problem video

As you can see what I want to achieve is to open a photo on a larger size upon clicking on it. As you can see it works … well … kind of.
It behaves kind of weird because it seems to be lagging and not recording the onclick event very well. Sometimes it can record it faster sometimes slower, but not even once would it open the image on a single click as I would want it to. It takes at least two clicks. And I tried the code on a page that has no XML requests and it works on a single click (with a slight delay between the two console log calls though .. around 0.3 sec). And it also works on the chat page if I have a huge delay in refreshing the chat. But I would want to have it work with a single click on a refresh rate of 1 second.

The XML request is the following:

  
     table2 = function(url, callback) 
{
    var request = new XMLHttpRequest();
    request.onreadystatechange = function()
    {
        if (request.readyState == 4 && request.status == 200)
        {
            callback(request.responseText); 
             document.getElementById("scrollchat").innerHTML = this.responseText;
        }
    }; 
    request.open('GET', url);
    request.send();
    
    
}

function mycallback(data) {
   //alert(data);
}

table2('load_chat.php', mycallback);

setInterval(function(){
       table2('load_chat.php', mycallback);
      }, 1700);

The items within the XML request file load_chat.php look like this:

<img src="image1.jpg" class="responsive" onclick="fullimagetry()">
<img src="image2.jpg" class="responsive" onclick="fullimagetry()">
<img src="image3.jpg" class="responsive" onclick="fullimagetry()">
<!-- And the list goes on as more images are being loaded. -->

My JS function that handles this is the following:

function fullimagetry() {

    let photonameval = document.getElementsByClassName('responsive');   
    console.log("click");

document.querySelectorAll('.responsive').forEach((element, index) => {
  element.addEventListener('click', function(event) {
    console.log('Clicked element index:', index, 'Image path:',photonameval[index].src);
    
    const fullPage = document.querySelector('#fullpage');
    
fullPage.style.backgroundImage = 'url(' + photonameval[index].src + ')';
    fullPage.style.display = 'block';
    
  });
});
    

}

Is there a better way to handle this? Maybe modify the fullimagetry() function and make it more efficient, or change something in the XML request itself? As you can see the request is made at 1.7s which is already too slow, but it makes things work at least on a double click. And I would want it to load at 1 second so that the user won’t feel like the server is lagging. Looking forward to your response.

EDIT: I have to specify that I use XML for this because I don’t know any other way to load elements on page without refreshing it. If you could provide me with an alternate way that is more efficient, I am keen to try it. I am still learning, and I go by what I can find on Youtube or W3Schools. Also that 1.7 delay is just set to make the opening of the photo more likely, the lower the value is the more click it needs to open (I know it’s weird).

Fetching data simultaneously with Emscripten

I am trying to use Emscripten to fetch and process a set of images. The approach below works well with a single image file, but it fails when fetching multiple images simultaneously, resulting in various errors. I believe the asynchronous fetch operations are sharing resources, which leads to race conditions, data inconsistencies, and other issues. I am using Emscripten’s Fetch API to retrieve the images.

How can I solve this problem?

function read_object(object, url) {
    return new Promise((resolve, reject) => {
        try {
            Module.onFetchClosed = (succeeded) => {
                if (!succeeded) {
                    reject(new Error("Fetch failed"));
                    return;
                };
                resolve();
            };
            object.read_url(url);
        } catch(e) {
            reject(e);
        };
    });
};

var Module = { onRuntimeInitialized: function() {

    async function async_call(n) {
        try {
            var object = new Module.cpp_object();
            let url = await get_url(n);
            await read_object(object, url);
            ...
        } catch(e) {
            object.delete();
            console.error("Error:", e);
        };
    };

    let promises = [];
    for (let i = 0; i < NUM; i++) {
        let promise = async_call(i);
        promises.push(promise)
        console.log(i);
    };
    Promise.all(promises).then(() => {
        ...;
    }).catch((err) => {
        console.error("Something went wrong:", err);
    });
}};

I get these errors:

Uncaught RuntimeError: index out of bounds
Error: Object { name: "ExitStatus", message: "Program terminated with exit(1)", status: 1 }

I have tried another approach by modularizing the Emscripten code and giving a Module to each async_call. It works, therefore the C++ code should be okay. However, I don’t believe that giving a Module to each async_call is correct.

How do you change the icon of a Google maps cluster on click?

In an angular app I’ve inherited there’s a map of vehicle positions. What I’m to do is group them and make it possible to click and show which vehicles is in that group. When a group is clicked I need to change that icon, and that’s what I can’t seem to do.

When the vehicles are loaded this function is called to draw the markers:

  async addPoints(points: ILatLng[]) {
    this.clearMarkers();

    const { Marker, PinElement  } = (await google.maps.importLibrary("marker") as google.maps.MarkerLibrary);
    const markers = points.map(point => this.addImageMarker(point, Marker));
    
    const onClusterClick = (
      (event, cluster) => {
        // And then what
        event.stop();
      }
    ) as onClusterClickHandler;


    this.markerCluster = new MarkerClusterer({
      map: this.currentMap, 
      markers,
      renderer: await this.createRenderer(),
      onClusterClick
    }) as MarkerClustererWithPublicClusters;
    

    if (this.autoCenter)
      this.setCenter();
  }

And the renderer looks like this:

  async createRenderer() {      
    const { Marker, AdvancedMarkerElement, PinElement  } = (await google.maps.importLibrary("marker") as google.maps.MarkerLibrary);

    return {
      render: (cluster, stats) => {
        const marker = new Marker({
          label: { text: `${cluster.count}`, color, fontWeight: "bold", "className": "group-marker"},
          icon: {
            url: ClusterMarker.Default
            scaledSize: new google.maps.Size(28, 49, "px", "px"),
          },
          position: cluster.position,
          zIndex: Number(google.maps.Marker.MAX_ZINDEX) + cluster.count,
        });

        return marker;
      }
    } as Renderer;
  }

I’ve tried a lot of things too. I’ve tried storing the selected cluster both in window, and in the component itself. And using a isClusterSelected function defined in createRendere like:

  async createRenderer() {      
    const { Marker, AdvancedMarkerElement, PinElement  } = (await google.maps.importLibrary("marker") as google.maps.MarkerLibrary);

    const isClusterSelected = (cluster: Cluster) => {
      if (!(window as any & {cluster: Cluster}).cluster)
        return false;

      const selectedMarker = (window as any & {cluster: Cluster}).cluster.marker as ExtendedMarker;
      const currentMarker = cluster.marker as ExtendedMarker;

      if (!cluster.marker)
        return false;


      return selectedMarker.anchorPoint.x === currentMarker.anchorPoint.x && selectedMarker.anchorPoint.y === currentMarker.anchorPoint.y
    };

    return {
      render: (cluster, stats) => {
        const color = isClusterSelected(cluster) ? "#ff00ff" : "black";

        console.log("Rendering", color); // Always prints "Rendering black"

        const marker = new Marker({
          label: { text: `${cluster.count}`, color, fontWeight: "bold", "className": "group-marker"},
          icon: {
            url: isClusterSelected(cluster) ? ClusterMarker.Clicked : ClusterMarker.Default,
            scaledSize: new google.maps.Size(28, 49, "px", "px"),
          },
          position: cluster.position,
          zIndex: Number(google.maps.Marker.MAX_ZINDEX) + cluster.count,
        });

        return marker;
      }
    } as Renderer;
  }

There I’ve tried comparing both the clusters coordinates, and with === which doesn’t change anything. I’m not even sure how I get it to rerender the points except zooming in and out a bit. If I in onClusterClick loop through all clusters in this.markerCluster and set their icon to default, and set the icon in the cluster in onClusterClick to the other icon. The property seen in the picture below

Chromes console showing a console.log of the cluster in onClusterClick

it doesn’t change anything. I know I can call setIcon on the clusters marker in the onClusterClick function like so:

    const onClusterClick = (
      (event, cluster) => {
        for (const markerCluster of this.markerCluster.clusters.filter(m => m.count > 1))
          (markerCluster.marker as google.maps.Marker).setIcon(ClusterMarker.Default);

        (cluster.marker as google.maps.Marker).setIcon(ClusterMarker.Clicked);

        event.stop();
      }
    ) as onClusterClickHandler;

But the icon will reset as zoom as I zoom. So I don’t really know what to do here?

How to ensure QWebEngineScript is executed before any other JS script in HTML document?

I’m trying to add to a PyQt5 application a QtWebEngineView widget. This widget must load the following very simple SVG (which, by specs, I cannot modify):

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
    <circle cx="50" cy="100" r="50" fill="red" />
    <script type="text/javascript"><![CDATA[
        alert("tag")
        mynamespace.myfunction();
    ]]></script>
</svg>

But obviously, I need to define mynamespace beforehand, so I’m trying the following in my widget constructor:

class MyWebPageView(QtWebEngineView):

    def __init__(svg,*args,**kwargs):
        super().__init__(*args,**kwargs)

        js_script = QWebEngineScript()
        js_script.setSourceCode("""
            alert("qwebenginescript");
            const mynamespace = { myfunction: function() { alert("success");}};
            """)
        js_script.setInjectionPoint(QWebEngineScript.DocumentCreation)            
        self.page().scripts().insert(js_script)

        time.sleep(3) #to be sure this is not a timing issue
        
        self.load(QUrl("file:///path/to/svg.svg"))

I expect the QWebEngineScript to be executed before the SVG’s <script> code, but what I see is first the the “tag” alert, and only then the “qwebenginescript” alert. The red circle is properly drawn, but the “success” alert never shows, and I get the following error message:

js: Uncaught ReferenceError: mynamespace is not defined

How can I ensure the QWebEngineScript is really executed first?

(Note: this is a follow-up of this question: https://stackoverflow.com/posts/79059688)

using NATs how can I create a durable consumer that constantly listens for new messages

I have this function in javascript that given a durable consumer fetches messages and triggers a callback function:


export const consumeMessages = async (callback, consumer) => {
    const iter = await consumer.fetch({ max_messages: 1 });

    (async () => {
        for await (const m of iter) {
            await callback(m.subject, m.data);
            m.ack()
        }
    })();
    return iter
};

consumeMessages is triggered once on booting up of my app:

            await jsm.consumers.add(config.NATS_STREAM_NAME, {
                ack_policy: AckPolicy.Explicit,
                durable_name: sessionId,
                filter_subject: subject,
            });
            const consumer = await js.consumers.get(config.NATS_STREAM_NAME, sessionId);

            const iter = await consumeMessages(receiveMessages, consumer);
    

This works but only retrieves 1 message. I want to consumer to keep retrieving messages that come in.

I understand that this is happening because of this line await consumer.fetch({ max_messages: 1 });

But I cannot find another way to do this from the documentation. I do not want to hardcode a mac_messages value since I want consumer to keep fethching until it is deleted.

using NATs how can I create a durable consumer (in javascript) that constantly listens for new messages

I have this function in javascript that given a durable consumer fetches messages and triggers a callback function:


export const consumeMessages = async (callback, consumer) => {
    const iter = await consumer.fetch({ max_messages: 1 });

    (async () => {
        for await (const m of iter) {
            await callback(m.subject, m.data);
            m.ack()
        }
    })();
    return iter
};

consumeMessages is triggered once on booting up of my app:

            await jsm.consumers.add(config.NATS_STREAM_NAME, {
                ack_policy: AckPolicy.Explicit,
                durable_name: sessionId,
                filter_subject: subject,
            });
            const consumer = await js.consumers.get(config.NATS_STREAM_NAME, gameSession);

            const iter = await consumeMessages(receiveMessages, consumer);
    ```

This works but only retrieves 1 message. I want to consumer to keep retrieving messages that come in.

I understand that this is happening because of this line `await consumer.fetch({ max_messages: 1 });`

But I cannot find another way to do this from the documentation. I do not want to hardcode a `mac_messages` value since I want consumer to keep fethching until it is deleted.

Views counter randomly resets to 0 — What could be causing this issue?

I have a small news website with thousands of articles. I’m using NextJS (version 14 with pages directory) on the frontend and Strapi on the backend. Each article has “views” field in Strapi, which is 0 by default. Then I increment it like that:

export const Article = ({ data }) => {
    const [views, setViews] = useState()
    useEffect(() => {
        async function addViews() {
            setViews("loading")
            const article = await getArticle(data.id)
            if (article) {
                await updateArticle(data.id, article.views + 1)
                setViews(article.views + 1)
            }
        }
        addViews()
    }, [data])

    return <article>

        <h1>{data.title}</h1>
        
        {(views && views !== "loading") && <span>{views}</span>}

        <div dangerouslySetInnerHTML={{ __html: data.content }} />

    </article>

}

Everything works fine, but sometimes views counter of some articles just randomly starts from 0 again. I know the code is far from perfect, I’m actually very new in the coding. What should I look into to improve it?

Monitoring for input value change and altering HTML [closed]

tried a few previous examples from here (eg. how to monitor the HTML input value changed by javascript ) and not got anywhere so asking for help 🙂

Real world example at https://beijaflor.com.au/ – add something to cart, click the cart button (it’ll pop out), and on delivery tab I want to monitor for when a date is selected. This changes the value of the hidden input field with name=”attributes[Delivery Day ]” (that’s the only unique thing I can reference) from “value” to eg “value=”01/01/2025″”.

I can’t alter any of the code that makes these changes, so need to monitor for the change itself. I assume it’s changing via javascript but adding a get/set on it doesn’t seem to do anything.

On change, I want to display or hide the checkout button (I know that bit is just a style.display = “none”; type thing).

To complicate things, it needs to reset if it date back to blank. And do the same thing on the pickup tab but with both date and time needing to be selected. But I’d be happy to just get one bit working for now.

Any tips appreciated 🙂

How to have the image annotation on react native or pwa

I’m quiet a newbie in react-native mobile development. I’ve been struggling to find any solid resources or guidance on how to implement image annotations in either React Native or a React PWA. I’ve found some libraries, but they don’t seem to fully solve the problem:

  • react-image-annotation: Works only on desktop browsers and requires
    a mouse, which is not suitable for mobile or touch devices
  • react-native-image-annotation: This doesn’t seem to work for me at
    all, and there isn’t much documentation available.

What I’m trying to achieve is a simple image annotation tool, where users can draw or highlight areas on an image and save those annotations to a database. Ideally, the image should allow for further editing or additional annotations after saving.

A good example of what I want to build is something similar to the annotation functionality in the Avalla app but now in my case, I want to annotate an image and also attach other form details to the post request with the annotated image.In that sense,I need something that is lighter than avalla or heavy . Technically how react image annotation library works.

Key Requirements:

  • Image annotation should work across mobile and desktop devices.
  • Annotations should be saved in a way that they can be edited later
    (e.g., allowing users to add/remove annotations from an already
    annotated image).

Even if there’s no out-of-the-box package, I’d appreciate some guidance on the theory or approach to build such a tool from scratch.
Again , I tried converting the react-image-annotation library to react native but that is something that cannot work since one uses the dom and the other doesn’t.
I’ve also tried to make the use of gestures and the panresponder but realized on saving the image I cannot undo the gestures neither doesn’t come out as expected.
If anyone has experience with this or can point me in the right direction, I’d be very grateful!

How to Disable the Add Text Function in Excalidraw on Double Tap?

I’ve already posted this question on the GitHub discussion page for Excalidraw, but I haven’t received any responses yet, so I’m hoping someone here on StackOverflow can help.

By default, Excalidraw allows users to add text by double-clicking or double-tapping. I want to disable this behavior.

I added the following JavaScript code to disable double-click and double-tap, and here’s what the script looks like:


$(document).ready(function() {
    var checkExist = setInterval(function() {
        var lastTap = 0;
        
        if ($(".excalidraw__canvas").length) {
            // Disable double-click on desktop
            $(".excalidraw__canvas").dblclick(function(e) {
                console.log("Double-click detected on excalidraw__canvas");
                e.stopPropagation();
                
            });

            // Disable double-tap on mobile
            $(".excalidraw__canvas").on("touchstart", function(e) {
                var currentTime = new Date().getTime();
                var tapLength = currentTime - lastTap;

                if (tapLength < 300 && tapLength > 0) {
                    console.log("Double-tap detected on excalidraw__canvas");
                    e.stopPropagation();
                    return false;
                }

                lastTap = currentTime;
            });

            
            clearInterval(checkExist);
        }
    }, 100); 
});

Although the double-click functionality is successfully disabled, the double-tap still triggers the add text function when in mobile view.

My backend is in PHP, and I’m using the index.php file as a guide, which you can find in this GitHub discussion link.

how can I override or disbale the add text by using double tap?

How to dynamically add form values to a new row in an HTML table?

I’m trying to dynamically add the values from a form into an HTML table. Each time the user submits the form, the values should be added as a new row in the table. However, I’m unsure how to append the new values to a new row and ensure that subsequent form submissions go to the next row.

Here’s the structure of my HTML form:

<form id="schedule-form">
  <label for="Name">Name:</label>
  <input type="text" name="Name" id="name">
  
  <label for="program">Course:</label>
  <select id="program">
    <option value="BSIT">BSIT</option>
    <option value="BSHM">BSHM</option>
    <option value="BSCRIM">BSCRIM</option>
    <option value="BSED">BSED</option>
    <option value="BEED">BEED</option>
  </select>
  
  <label for="subjects">Subject:</label>
  <select id="subjects"></select>
  
  <label for="room">Room:</label>
  <select id="room">
    <option value="IT Room 1">IT Room 1</option>
    <option value="IT Lab 1">IT Lab 1</option>
    <option value="IT Lab 2">IT Lab 2</option>
    <option value="IT Lab 3">IT Lab 3</option>
  </select>
  
  <label for="day">Day:</label>
  <select id="day">
    <option value="MWF">MWF</option>
    <option value="TTH">TTH</option>
    <option value="Mon">Mon</option>
    <option value="Tue">Tue</option>
    <option value="Wed">Wed</option>
    <option value="Thu">Thu</option>
    <option value="Fri">Fri</option>
  </select>
  
  <label for="start-time">Start Time:</label>
  <input type="time" id="start-time">
  
  <label for="end-time">End Time:</label>
  <input type="time" id="end-time">
  
  <button type="submit">Schedule</button>
</form>

And here’s the table where I want to display the scheduled classes:

<h3>Scheduled Classes</h3>
<table>
  <thead>
    <th>Name</th>
    <th>Course</th>
    <th>Subject</th>
    <th>Room</th>
    <th>Day</th>
    <th>Time</th>
  </thead>
  <tbody id="schedule-table">
    
  </tbody>
</table>

Here’s my current JavaScript (which is not working):

document.getElementById('schedule-form').addEventListener('submit', function(e) {
  e.preventDefault();
  
  // Get form values
  let name = document.querySelector('[name="Name"]').value;
  let course = document.getElementById('program').value;
  let subject = document.getElementById('subjects').value;
  let room = document.getElementById('room').value;
  let day = document.getElementById('day').value;
  let startTime = document.getElementById('start-time').value;
  let endTime = document.getElementById('end-time').value;

  // I need help figuring out how to append these values to a new table row
  // and ensure that multiple submissions add to the next row

});

JavaScript equivalent of Python’s setdefault for dictionaries

Python has setdefault which lets you set a default value for a dictionary entry.

There’s a good example here which shows making the default an array so you can do

dict[id].append(elem)

without having to check if dict[id] exists.

In JavaScript I could do this

const dict = {};
(dict[id] = dict[id] ?? []).push(elem)

But I was wondering if I could somehow implement similar functionality to python’s setdefault

I tried this

function makeObjectWithDefault(defaultFactory) {
  const obj = {};

  const handler = {
    get(target, prop, receiver) {
      let v = target[prop];
      if (v === undefined) {
        v = defaultFactory();
        target[prop] = v;
      }
      return v;
    },
  }

  return new Proxy(obj, handler)
}

It partly worked

const dict = makeObjectWithDefault(() => []);
dict['abc'].push(123);
dict.def.push(456);

But then unfortunately it adds extra properties

console.log(JSON.stringify(dict, null, 2));

prints

{
  "abc": [
    123
  ],
  "def": [
    456
  ],
  "toJSON": []     // !!! <- because it looked for a `toJSON` function
}

Because JSON.stringify looked for toJSON function on the object it ended up adding an array for that entry.

Of course I could check if the prop equals toJSON but that’s not really valid since I should be able to do dict['toJSON'].push(789) if I wanted to. And, I’d have to figure out which other functions try to access various properties (eg, toString)

Is it possible to implement python’s setdefault for JavaScript objects?

Alternatives:

  1. a helper

    Of course I could write a helper

    function accessWithDefaultArray(dict, id) {
      return (dict[id] = dict[id] ?? []);
    }
    
    accessWithDefaultArray(dict, 'abc').push(123);
    accessWithDefaultArray(dict, 'def').push(456);
    

    But it’s not very pretty

  2. I could write a class but it would require not using standard syntax

  3. A Map might work as a substitute since it uses get and set and so won’t
    suffer from confusion between access of methods and access of elements.
    In that case a simple class would work

    class MapWithDefault extends Map {
      constructor(defaultFactory, iterable) {
        super(iterable);
        this.defaultFactory = defaultFactory;
      }
      get(key) {
        let v = super.get(key);
        if (!v) {
          v = this.defaultFactory();
          super.set(key, v);
        }
        return v;
      }
    }
    
    {
      const d = new MapWithDefault(() => []);
      d.get('abc').push(123);
      d.get('def').push(456);
      d.get('def').push(789);
      console.log(JSON.stringify(Object.fromEntries(d.entries()), null, 2));
    }
    

    It’s not as nice as d['abc'].push(123) and d.def.push(456) and it’s not as directly
    usable as Object in various places.