Skip to content
Advertisement

Why can I not overwrite the innerHTML after I once clicked into it

My Code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Real Time Texteditor</title>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap');

        body{
            background-color: white; 
            margin: 25px;
        }

        h1{
            margin-bottom: 0px;
            color: black; 
            align-content: center; 
            font-family: 'Roboto Mono', monospace;
        }

        #ErrorParag{
            margin-top: 0px;
            font-family: 'Roboto Mono', monospace;
        }

        #textarea{
            width: 100%; 
            height: 90vh; 
            color: black; 
            font-size:20px; 

            border: 5px solid;
            border-radius: 5px;
        } 
    </style>
    <script>
        const params = new Proxy(new URLSearchParams(window.location.search), {
            get: (searchParams, prop) => searchParams.get(prop),
        })
        const ID = params.id
        const NAME = params.name
        //console.log(String(ID)+" "+String(NAME))

        const xhr =  new XMLHttpRequest();

        last_input = ""
        

        window.onload = function(){
            xhr.open('POST', '/api/retrieve', false);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.send(JSON.stringify({"id":ID, "name":NAME}));
            response = JSON.parse(xhr.responseText);
            //console.log(response);
            if(response.status==="error"){
                document.getElementById("ErrorParag").innerHTML = response.error
                document.getElementById("ErrorParag").style.color = "#ff0000";
            } else if(response.status==="success"){
                document.getElementById("textarea").innerHTML = response.data
            }
        }

        function compareString(x, y){ //x = originally, y = new => 
            if(x.length>y.length){ //smaller String => char was deleted x>y
                for(let i = 0; i<x.length; i++){
                    //console.log(String(x)+" "+String(y[i])+" --- "+String(x.length)+" "+String(i)) //kleiner Bug bei der Darstellung wird der gesamte Text angezeigt
                    if(x[i]!==y[i]){
                        return {"pos":String(i),"change":String(-1),"char":String(x[i])}
                    }
                    else if(i===x.length-1){
                        return {"pos":String(i+1),"change":String(-1),"char":String(x[x.length])}
                    }
                }
                
            }
            else if(x.length<y.length){ //bigger String => char was added x<y
                for(let i = 0; i<y.length; i++){
                    //console.log(String(x[i])+" "+String(y[i])+" --- "+String(y.length)+" "+String(i))
                    if(x[i]!==y[i]){
                        return {"pos":String(i),"change":String(1),"char":String(y[i])}
                    }
                    else if(i===y.length-1){
                        return {"pos":String(i+1),"change":String(1),"char":String(y[y.length])}
                    }
                }
            }
            return {"Error":"Something went completely wrong"} 
        }

        function onTextUpdate(e){
            let results = compareString(last_input, e.value)
            //console.log(results)
            globalThis.last_input = e.value;

            send_data = JSON.stringify({"update":results, "id":ID, "name":NAME}) // {"update":{"pos": ..., "change": ..., "char": ...}, "id": ... , "name": ... }
            //console.log("Data which is gonna be send:")
            console.log(send_data)
            
            //post the results to back end
            xhr.open('POST', '/api/update', false);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.send(send_data);
            response = JSON.parse(xhr.responseText);
            console.log(response);
            if(response.status==="failure"){
                document.getElementById("ErrorParag").innerHTML = response.error
                document.getElementById("ErrorParag").style.color = "#ff0000";
            } else if(response.status==="success"){
                document.getElementById("ErrorParag").innerHTML = "success"
                document.getElementById("ErrorParag").style.color = "#00ff00";
            }
        }
        
        const loadData = function(){
            console.log("get data from server")
            xhr.open('POST', '/api/retrieve', false);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.send(JSON.stringify({"id":ID, "name":NAME}));
            response = JSON.parse(xhr.responseText);
            console.log(response.data);
            
            if(response.status==="error"){
                document.getElementById("ErrorParag").innerHTML = response.error
                document.getElementById("ErrorParag").style.color = "#ff0000";
            } else if(response.status==="success"){
                console.log("success!")
                document.getElementById("textarea").innerHTML = response.data
            }
        }

        const load_data = setInterval(loadData, 1000)
    
    </script>
</head>
<body>
    <h1>Real Time Texteditor</h1>
    <p id="ErrorParag"></p>
    <textarea id="textarea" placeholder="Just write ..." oninput="onTextUpdate(this)"></textarea>
</body>
</html>

As you probably read, the code is for a Real-Time Texteditor Project I’m working on with a friend. But I don’t understand why everything works well until I click on the text field and wanna write something. The server gets everything and the other instance also. The only problem is, that the second instance doesn’t overwrite the innerHTML of the text field. If I reload the second instance everything appears in the text field. I’m confused. Does anyone know why this is happening?

Advertisement

Answer

First of all, you shouldn’t set an Interval to load data every second, as in a normal text editor, you load data every time the textarea’s value is changed. When setting an Interval to load data every second you’re essentially spamming the user and the server for no reason.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Real Time Texteditor</title>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap');

        body{
            background-color: white; 
            margin: 25px;
        }

        h1{
            margin-bottom: 0px;
            color: black; 
            align-content: center; 
            font-family: 'Roboto Mono', monospace;
        }

        #ErrorParag{
            margin-top: 0px;
            font-family: 'Roboto Mono', monospace;
        }

        #textarea{
            width: 100%; 
            height: 90vh; 
            color: black; 
            font-size:20px; 

            border: 5px solid;
            border-radius: 5px;
        } 
    </style>
    <script>
        const params = new Proxy(new URLSearchParams(window.location.search), {
            get: (searchParams, prop) => searchParams.get(prop),
        })
        const ID = params.id
        const NAME = params.name
        //console.log(String(ID)+" "+String(NAME))

        const xhr =  new XMLHttpRequest();

        last_input = ""
        

        window.onload = function(){
            xhr.open('POST', '/api/retrieve', false);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.send(JSON.stringify({"id":ID, "name":NAME}));
            response = JSON.parse(xhr.responseText);
            //console.log(response);
            if(response.status==="error"){
                document.getElementById("ErrorParag").innerHTML = response.error
                document.getElementById("ErrorParag").style.color = "#ff0000";
            } else if(response.status==="success"){
                document.getElementById("textarea").innerHTML = response.data
            }
        }

        function compareString(x, y){ //x = originally, y = new => 
            if(x.length>y.length){ //smaller String => char was deleted x>y
                for(let i = 0; i<x.length; i++){
                    //console.log(String(x)+" "+String(y[i])+" --- "+String(x.length)+" "+String(i)) //kleiner Bug bei der Darstellung wird der gesamte Text angezeigt
                    if(x[i]!==y[i]){
                        return {"pos":String(i),"change":String(-1),"char":String(x[i])}
                    }
                    else if(i===x.length-1){
                        return {"pos":String(i+1),"change":String(-1),"char":String(x[x.length])}
                    }
                }
                
            }
            else if(x.length<y.length){ //bigger String => char was added x<y
                for(let i = 0; i<y.length; i++){
                    //console.log(String(x[i])+" "+String(y[i])+" --- "+String(y.length)+" "+String(i))
                    if(x[i]!==y[i]){
                        return {"pos":String(i),"change":String(1),"char":String(y[i])}
                    }
                    else if(i===y.length-1){
                        return {"pos":String(i+1),"change":String(1),"char":String(y[y.length])}
                    }
                }
            }
            return {"Error":"Something went completely wrong"} 
        }

        function onTextUpdate(e){
            let results = compareString(last_input, e.value)
            //console.log(results)
            globalThis.last_input = e.value;

            send_data = JSON.stringify({"update":results, "id":ID, "name":NAME}) // {"update":{"pos": ..., "change": ..., "char": ...}, "id": ... , "name": ... }
            //console.log("Data which is gonna be send:")
            console.log(send_data)
            
            //post the results to back end
            xhr.open('POST', '/api/update', false);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.send(send_data);
            response = JSON.parse(xhr.responseText);
            console.log(response);
            if(response.status==="failure"){
                document.getElementById("ErrorParag").innerHTML = response.error
                document.getElementById("ErrorParag").style.color = "#ff0000";
            } else if(response.status==="success"){
                document.getElementById("ErrorParag").innerHTML = "success"
                document.getElementById("ErrorParag").style.color = "#00ff00";
            }
            console.log("get data from server")
            xhr.open('POST', '/api/retrieve', false);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.send(JSON.stringify({"id":ID, "name":NAME}));
            response = JSON.parse(xhr.responseText);
            console.log(response.data);
            
            if(response.status==="error"){
                document.getElementById("ErrorParag").innerHTML = response.error
                document.getElementById("ErrorParag").style.color = "#ff0000";
            } else if(response.status==="success"){
                console.log("success!")
                document.getElementById("textarea").value = response.data
            }
        }

        
    
    </script>
</head>
<body>
    <h1>Real Time Texteditor</h1>
    <p id="ErrorParag"></p>
    <textarea id="textarea" placeholder="Just write ..." oninput="onTextUpdate(this)"></textarea>
</body>
</html>

All I changed was combining the load_data function with the onTextUpdate function, and changing document.getElementById("textarea").innerHTML = response.data to document.getElementById("textarea").value = response.data, since as Teemu explained well in the comments: textarea can’t contain HTML, it contains plain text only. Use value instead of innerHTML.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement