Load GLTF model from binary data, not URL

I’m using drei usegltf to load a glTF asset:

export default function GLTFModel(props: GLTFModelProps) {
  const gltf = useGLTF(props.model);
  return <primitive object={gltf.scene} />;
}
<Canvas>
 <Suspense fallback={null}>
    <GLTFModel model={glbUrl}/>
 </Suspense>
</Canvas>

While this works well for glTF assets available from a local or remote URL, I’m attempting to render a glTF asset I have available as a binary blob

  1. API returns GLB as application/octet-stream
const response = await fetch(apiUrl, {});
const data = await response.blob();
  1. Want to render the binary data
const gltf = useGLTF(data);

Is there a way to work this out without API uploading the GLB to a URL?

Recursive function to add path to nested object using parent object values

I’m trying to add a “path” to all nested objects using their ancestor’s attributes. Essentially I want to represent a “path” of the hierarchical structure to a nested object using a concatenation of its parent object’s attribute values instead of using keys (like I could with dot notation, lodash, etc).

What I’ve tried:

interface SimpleObject {
    name : string
    slug : string
    slug_path? : string
    fields? : SimpleObject[]
}


const addNestedObjSlug = (data:SimpleObject[], parents:SimpleObject[] = []) => {

    data.map((obj) => {
        obj.slug_path = parents.length > 0 ? `${parents.map(({slug}) => slug).join('.')}.${obj.slug}` : obj.slug
        if(obj.fields && obj.fields.length > 0) {
            parents.push(obj)

            // I think the issue is here, that I probably need to set parents to an empty array at some point
            return addNestedObjSlug(obj.fields, parents)
        }
    })

    return data
}

const desiredResult = addNestedObjSlug([
    {
        name : 'Item 1',
        slug : 'i1',
        fields : [
            {
                name : 'Item 1 - 1',
                slug : 'i1-1'
            },
            {
                name : 'Item 1 - 2',
                slug : 'i1-2'
            },
            {
                name : 'Item 1 - 3',
                slug : 'i1-3'
            }
        ]
    },
    {
        name : 'Item 2',
        slug : 'i2',
        fields : [
            {
                name : 'Item 2 - 1',
                slug : 'i2-1',
                fields : [
                    {
                        name : 'Item 2 - 1 - 1',
                        slug : 'i2-1-1'
                    }
                ]
            }
        ]
    }
])

My expected result is:

[
    {
        "name": "Item 1",
        "slug": "i1",
        "fields": [
            {
                "name": "Item 1 - 1",
                "slug": "i1-1",
                "slug_path": "i1.i1-1"
            },
            {
                "name": "Item 1 - 2",
                "slug": "i1-2",
                "slug_path": "i1.i1-2"
            },
            {
                "name": "Item 1 - 3",
                "slug": "i1-3",
                "slug_path": "i1.i1-3"
            }
        ],
        "slug_path": "i1"
    },
    {
        "name": "Item 2",
        "slug": "i2",
        "fields": [
            {
                "name": "Item 2 - 1",
                "slug": "i2-1",
                "fields": [
                    {
                        "name": "Item 2 - 1 - 1",
                        "slug": "i2-1-1",
                        "slug_path": "i2.i2-1.i2-1-1"
                    }
                ],
                "slug_path": "i2.i2-1"
            }
        ],
        "slug_path": "i2"
    }
]

But instead I get the following, where the original nested object’s slug is part of the new slug_path attribute of objects which are not ancestors.

[
    {
        "name": "Item 1",
        "slug": "i1",
        "fields": [
            {
                "name": "Item 1 - 1",
                "slug": "i1-1",
                "slug_path": "i1.i1-1" // correct
            },
            {
                "name": "Item 1 - 2",
                "slug": "i1-2",
                "slug_path": "i1.i1-2" // correct
            },
            {
                "name": "Item 1 - 3",
                "slug": "i1-3",
                "slug_path": "i1.i1-3" // correct
            }
        ],
        "slug_path": "i1" // correct
    },
    {
        "name": "Item 2",
        "slug": "i2",
        "fields": [
            {
                "name": "Item 2 - 1",
                "slug": "i2-1",
                "fields": [
                    {
                        "name": "Item 2 - 1 - 1",
                        "slug": "i2-1-1",
                        "slug_path": "i1.i2.i2-1.i2-1-1" // incorrect
                    }
                ],
                "slug_path": "i1.i2.i2-1" // incorrect
            }
        ],
        "slug_path": "i1.i2" // incorrect
    }
]

Angular 8 – click event not firing inside ngFor when it is calling a service method

I have a ngFor loop that is calling a service to get the current list of items to be displayed.

Click events are not handled anywhere inside of this loop, but work normally outside of it.

The click events will fire inside the loop, if I replace the service method call (that returns an array of objects to display) with an inline number array:

Not working:

<ng-container *ngFor="let variable of designerService.getVariables();" >
     <div (click)="onClick()">doesn't work</div>
</ng-container>

Working:

<ng-container *ngFor="let index of [0,1,2,3,4,5]" >
     <div (click)="onClick()">works</div>
</ng-container>

Can anyone explain to me what the issue is?

How to remove scroll from tooltip plugin Tooltipster?

Good time of day, friends.

There is such a project: jsfiddle.net/tek0gy57/5/

I am using Tooltipster plugin for tooltips.

I don’t understand for what reason, I get a vertical scroll when hovering over the first and second links.
But if you remove the cursor and hover again – it is displayed normally. What’s the magic?

I realized that the reason is in the images (icons) that I use, because there is no such strange effect on the 3rd link.

Please tell me how to make it so that the vertical scroll does not appear when hovering over links 1 and 2. Thank you.

Quicksort visualization in ReactJS, state change don’t update DOM

I was given the task to visualize Quicksort at university. I wrote the partition of the algorithm very small-stepped, so that I can visualize every single step well.

My array looks like this:

 const [arr, setArr] = useState([
        {number: 1, isSelectedFromLeftArrow: false, isSelectedFromRightArrow: false, isPivot: false, isSorted: false},
        {number: 5, isSelectedFromLeftArrow: false, isSelectedFromRightArrow: false, isPivot: false, isSorted: false},
        {number: 3, isSelectedFromLeftArrow: false, isSelectedFromRightArrow: false, isPivot: false, isSorted: false},
        {number: 4, isSelectedFromLeftArrow: false, isSelectedFromRightArrow: false, isPivot: false, isSorted: false},
        {number: 2, isSelectedFromLeftArrow: false, isSelectedFromRightArrow: false, isPivot: false, isSorted: false},
        {number: 7, isSelectedFromLeftArrow: false, isSelectedFromRightArrow: false, isPivot: false, isSorted: false},
        {number: 6, isSelectedFromLeftArrow: false, isSelectedFromRightArrow: false, isPivot: false, isSorted: false},
    ])

I added several attributes to each number to be able to see what is happening with the element later when I display it, so that I can color it afterwards.

My problem is now the following. The algorithm itself works and gives me the correct result in the console. However, the display of the bars does not change. Only when I go into the IDE, make a small change and the display changes to the finished result.

In the first step only the sorted element should be colored.

Here is the actual quicksort process:

const newTryQuickSort = async () => {

        let stack = []

        // Zu Beginn nur ein großes Array, welches sortiert werden soll. Von index 0 bis zum letzten Element
        stack.push(0)
        stack.push(arr.length - 1)

        // while(stack[stack.length - 1] >= 0) {

        for (let i = 0; i <= 3; i++) {
            // Erste Element ist die linke Grenze und das zweite Element ist die rechte Grenze
            let rightEnd = stack.pop()
            let leftStart = stack.pop()

            // Sortiere die erste Partition
            const pivotIndex = await newPartition(leftStart, rightEnd)

            console.log("Result from Partition: " + pivotIndex)

            if (pivotIndex - 1 > leftStart) {
                stack.push(leftStart)
                stack.push(pivotIndex - 1)
            }

            if (pivotIndex + 1 < rightEnd) {
                stack.push(pivotIndex + 1)
                stack.push(rightEnd)
            }

            console.log('Stack: ')
            console.log(stack)

            console.log('______________________________________________________')
        }

Here is the partitioning:

const newPartition = async (leftStart, rightEnd) => {

        const pivotValue = arr[rightEnd].number
        const pivotIndex = rightEnd

        const left = leftStart
        // Das pivot element ist das letzt Element, daher muss die Grenze bis eins vorher gehen
        const right = rightEnd - 1

        let pivotIsSorted = false

        while (!pivotIsSorted) {
            // Lass den Linken pfeil laufen
            const leftArrowIndex = await checkFromLeft(left, right, pivotValue, pivotIndex)

            console.log('leftArrowIndex: ' + leftArrowIndex)

            // Wenn null rauskommt, gab es nur ein Element, welches dann sortiert ist.
            if (leftArrowIndex === null) {
                pivotIsSorted = true
                return leftArrowIndex
            }

            // Überprüfen, ob null zurückkommt, da dann das Array bereits sortiert ist

            //Lass den rechten Pfeil laufen
            const rightArrowIndex = await checkFromRight(left, right, pivotValue, leftArrowIndex)

            console.log('rightArrowIndex: ' + rightArrowIndex)

            // Wenn beide ein Element gefunden haben, welches nicht passt und sie sich nicht getroffen haben,
            // dann tausche sie, setzte leftStart und rightStart neu und beginne von vorne
            if (leftArrowIndex !== rightArrowIndex) {
                await swap(leftArrowIndex, rightArrowIndex, false)
                leftStart = leftArrowIndex
                rightEnd = rightArrowIndex
            }

            // Beide pfeile haben sich getroffen (indexLeft === indexRight)
            // Tausche die stelle, wo sich die Pfeile getroffen haben mit dem pivot und gebe das/die neue/neuen subarray/s zurück
            if (leftArrowIndex === rightArrowIndex) {
                await swap(leftArrowIndex, pivotIndex, true)
                pivotIsSorted = true

                // Das Pivot element liegt nach dem swapt an der Stelle von leftArrowIndex
                return leftArrowIndex

            }
        }

    }

const checkFromLeft = async (start, end, pivot, pivotIndex) => {

        console.log('checkFromLeft: start, end, pivot')
        console.log(start, end, pivot)

        // Wenn das subarray, welches sortiert werden soll nur 1 Element groß ist, ist es fertig sortiert
        if (start === end) {
            // Vertausche die beiden an der gleichen Stelle, um es als sortiert zu setzten
            console.log('Im hear')
            await swap(start, end, true)

            // Gebe 'null' zurück, um zu sagen, dass das subarray nur ein element groß ist
            return null
        }


        // Ansonsten gehe von links nach rechts alle Elemente durch und suche nach einem Element, welches größer ist als das pivot
        for (let i = start; i <= pivotIndex; i++) {

            if (arr[i].number >= pivot) return i

            // Trifft auf den rechten pfeil, welcher noch nicht losgelaufen ist - VORHER
            // Trifft auf das Pivot, somit steht es an der richtigen stelle - NACHHER
            if (i === pivotIndex) return i

        }


    }

const checkFromRight = (start, end, pivot, positionOfLeftArrow) => {


        for (let i = end; i >= start; i--) {

            // Wenn er an der gleichen Stelle ankommt oder der linke schon am Pivot ist, wie der linke Pfeil, gibt er nicht seine, sondern die
            // Position des Linken pfeils zurück (da der linke Pfeil ja auch schon weiter sein kann, als der Rechte)
            if (i <= positionOfLeftArrow) {
                return positionOfLeftArrow
            }

            // Wenn er ein Element gefunden hat, was kleiner als das pivot ist, gibt er es zurück
            if (arr[i].number <= pivot) {
                return i
            }


        }

    }

Here is the swapping of the two elements:

const swap = async (left, rightOrPivot, isPivot = false) => {

        setArr((prevArr) => {

            // Tausche beide Werte aus
            const oldLeft = prevArr[left]
            prevArr[left] = prevArr[rightOrPivot]
            prevArr[rightOrPivot] = oldLeft

            console.log('NewArray after swap: ')
            console.log(prevArr)

            // Wenn das Pivot verschoben wurde, so ist es nun an seiner Finalen Position
            if (isPivot) {
                prevArr[left].isPivot = false
                prevArr[left].isSorted = true
            }

            return prevArr
        })
        
        await sleep(1000)
        
        return true

    }


    const sleep = (ms) => {
        return new Promise(resolve => setTimeout(resolve, ms))
    }

I use a useEffect to output the array whenever it changes. It is also strange that the array is already sorted at the first output.

 useEffect(() => {
        console.log("Arr: ")
        console.log(arr)
    }, [arr])

Here is a screenshot of the console:
Image of the visualization and console

I hope you can help me there.

JS: using object from parent class

I am having two classes and want to have an Object with values that are available for both classes. This is my sample code:

class Class1 {
  
  constructor() {
   this.things = [];
   this.testValue = "one two three";
  }
  
  doThings() {
  
        for(let i = 0; i < 10; i++) {
            this.things[i] = "test "+i;
        }
    
    console.log("Class 1 doThings(): ", this.things);
  
  }
  
  getContent() {
      console.log("getContent Class1: ", this.things);
  }
  
}

class Class2 extends Class1 {

  constructor(elmnt){
    super();
  }
  
  getContent() {
      console.log("Class 2 getContent(): ", this.things);
  }
  
  getValue() {
    
    console.log("Value: ", this.testValue)
    
  }

}

let handle1 = new Class1();
let handle2 = new Class2();

handle1.getContent(); // empty because this.things() did not run
handle1.doThings(); // create things...
handle1.getContent(); // this shows the things

handle2.getContent(); // this is empty even is doThings() is called before to produce things...

handle2.getValue();

Why is handle2.getContent() not showing the Things-Array? And (more important) what would be right?

i think the super() overrides the this.things… Is that true? how could i prevent this?

Javascript RegExp should check four-digit input for plausibility

I want to program a JavaScript code which checks the input into an input field if it is a double two-digit HEX value. The input must contain exactly 4 digits and letters between a to f and/or 0 to 9. The following code leads to an error with a four digit input.

function check() {
var input = (document.getElementById("textField").value);


if (input.length == 4 && input.match([A-Fa-f0-9])) { alert("the input matches the requirements");}
          else {alert("input is invalid");}
}
<input type="text" id="textField">
<button type="button" onclick="check()">check!</button> 

Is there any way to change the data.js file in local machine with user input?

I have data.js file and addPet.js file.

data.js file has objects in dataObject which is the list of the animals.

addPet.js file accepts user input from index.html.

In this case if I put infos in form input and submit it, then the data.js file has that input infos as last object in dataObject in data.js file?

The end goal is rendering the dataObject in the website(which exist as script.js)

const dataObject = {
  1: {
    name: "Fido",
    type: "dog",
    nature: "playful",
    status: "available",
  },
  2: {
    name: "Benson",
    type: "cat",
    nature: "jittery",
    status: "homed",
  },
  3: {
    name: "Esio",
    type: "tortoise",
    nature: "excitable",
    status: "available",
  },
  4: {
    name: "Turbo",
    type: "tortoise",
    nature: "relaxed",
    status: "available",
  },
  5: {
    name: "Ron Possible",
    type: "hamster",
    nature: "playful",
    status: "available",
  },
};

React and CSS – prevent Checkbox from unchecking

Is there any way to stop my checkbox from unchecking on refresh?

I have a checkbox with :checked property on SCSS and I don’t want to on Refreshing the page for it to automatically uncheck.

Is there any way? Or is there any way to target the :checked with react? for example className={ todo.isComplete ? "completed-checkbox:checked" : "completed-checkbox"}

This wont target the :checked obviously

CKeditor create editor not during build

I created a custom build of CKEditor which works fine.

ClassicEditor
    .create(document.querySelector('#editor'), {
        plugins: [Essentials, Autosave, Paragraph, Bold, Subscript, Superscript, Strikethrough, PasteFromOffice, Table, TableToolbar, TableProperties, TableCellProperties, TableCaption, List, Link, Image, ImageToolbar, ImageCaption, ImageStyle, ImageResize, LinkImage, Heading, ImageUpload, FontColor, BlockQuote, Italic, Alignment, SourceEditing, Underline, Undo, SimpleUploadAdapter],
        toolbar: ['bold', 'italic', 'underline', 'strikethrough', 'subscript', 'superscript', 'BlockQuote', 'fontcolor', 'spoiler', 'insertTable', 'List', 'Link', 'ImageUpload', 'Image', 'ImageToolbar'],
    })
    .then(editor => {
        console.log('Editor was initialized', editor);
    })
    .catch(error => {
        console.error(error.stack);
    });

This made a bundle.js which works fine. But it’s locked onto a single selector loaded at runtime?

How do I call the editor and set it to work on other selectors in my app afterwards instead of build time?

Where is the documentation on how to create/destroy the editor onto different inputs, I can’t find that anywhere.