0

I recently live hosted my website and got this error. Uncaught TypeError: Cannot set properties of null (setting 'innerHTML') at response (home:2593) at XMLHttpRequest. (home:2560)

This error did not occur on the local server but it occurred on a public server. I saw a few threads regarding this error and I heard that you should use addEventListener instead of onclick in your code. However, I'm not sure how to implement it into my code so it would be great if you could help me.

This is the line where the error occurred:

info_element.innerHTML = obj.info;

This is the JS:

<script type="text/javascript">
        function ajax_send(data, element) {

            var ajax = new XMLHttpRequest();

            ajax.addEventListener('readystatechange', function() {

                if (ajax.readyState == 4 && ajax.status == 200) {

                    response(ajax.responseText, element);
                }

            });

            data = JSON.stringify(data);

            ajax.open("post", "<?= ROOT ?>ajax.php", true);
            ajax.send(data);

        }

        function response(result, element) {

            if (result != "") {

                var obj = JSON.parse(result);
                if (typeof obj.action != 'undefined') {

                    if (obj.action == 'like_post') {

                        var likes = "";

                        if (typeof obj.likes != 'undefined') {
                            likes =
                                (parseInt(obj.likes) > 0) ?
                                '<svg fill="#1877f2" width="22" height="22" viewBox="0 0 24 24"><path d="M21.216 8h-2.216v-1.75l1-3.095v-3.155h-5.246c-2.158 6.369-4.252 9.992-6.754 10v-1h-8v13h8v-1h2l2.507 2h8.461l3.032-2.926v-10.261l-2.784-1.813zm.784 11.225l-1.839 1.775h-6.954l-2.507-2h-2.7v-7c3.781 0 6.727-5.674 8.189-10h1.811v.791l-1 3.095v4.114h3.623l1.377.897v8.328z"/></svg>' :
                                '<svg fill="#626a70cf" width="22" height="22" viewBox="0 0 24 24"><path d="M21.216 8h-2.216v-1.75l1-3.095v-3.155h-5.246c-2.158 6.369-4.252 9.992-6.754 10v-1h-8v13h8v-1h2l2.507 2h8.461l3.032-2.926v-10.261l-2.784-1.813zm.784 11.225l-1.839 1.775h-6.954l-2.507-2h-2.7v-7c3.781 0 6.727-5.674 8.189-10h1.811v.791l-1 3.095v4.114h3.623l1.377.897v8.328z"/></svg>';
                            element.innerHTML = likes;
                        }

                        if (typeof obj.info != 'undefined') {
                            var info_element = document.getElementById(obj.id);
                            info_element.innerHTML = obj.info;
                        }
                    }
                }
            }
        }

        function like_post(e) {

            e.preventDefault();
            var link = e.currentTarget.href;

            var data = {};
            data.link = link;
            data.action = "like_post";
            ajax_send(data, e.currentTarget);
        }
    </script>

This is where I implemented like_post in my HTML:

<a onclick="like_post(event)" href="<?= ROOT ?>like/post/<?php echo $ROW['postid'] ?>" style="text-decoration:none;float:left;position:relative;top:2px;">
                <svg id="icon_like" fill="<?= $Like_color ?>" width="22" height="22" viewBox="0 0 24 24">
                    <path d="M21.216 8h-2.216v-1.75l1-3.095v-3.155h-5.246c-2.158 6.369-4.252 9.992-6.754 10v-1h-8v13h8v-1h2l2.507 2h8.461l3.032-2.926v-10.261l-2.784-1.813zm.784 11.225l-1.839 1.775h-6.954l-2.507-2h-2.7v-7c3.781 0 6.727-5.674 8.189-10h1.811v.791l-1 3.095v4.114h3.623l1.377.897v8.328z" />
                </svg>
            </a>

I also did some debugging using console.log. This is what I received when I console.log(obj.id):

info_

It's supposed to return some values after info_ eg.143884

This is the code in ajax.php:

<?php

include("classes/autoload.php");

$data = file_get_contents("php://input");
if($data != ""){
  $data = json_decode($data);
}

if(isset($data->action) && $data->action == "like_post"){

  include("ajax/like.ajax.php");
}

This is the code in like.ajax.php:

<?php

if(!empty($data->link)){
    $URL = split_url_from_string($data->link);
}

$_GET['type'] = isset($URL[5]) ? $URL[5] : '';
$_GET['id'] = isset($URL[6]) ? $URL[6] : '';

$_id = $_GET['id'] ? htmlspecialchars( $_GET['id'], ENT_QUOTES) : '';
$_type = $_GET['type'] ? htmlspecialchars( $_GET['type'], ENT_QUOTES) : '';

$_SESSION['mybook_userid'] = isset($_SESSION['mybook_userid']) ? $_SESSION['mybook_userid'] : 0;
$login = new Login;
$user_data = $login->check_login($_SESSION['mybook_userid'],false);

//check if not logged in
if($_SESSION['mybook_userid'] == 0){

        $obj = (object)[];
        $obj->action = "like_post";

        echo json_encode($obj);
        die;
}

/*
 $query_string = explode("?", $data->link);
 $query_string = end($query_string);

$str = explode("&", $query_string);

foreach ($str as $value) {
    # code...
    $value = explode("=", $value);
    $_GET[$value[0]] = $value[1];
}
*/

$_id = addslashes($_id);
$_GET['type'] = addslashes($_GET['type']);

    if(isset($_GET['type']) && isset($_id)){

        $post = new Post();

        if(is_numeric($_id)){

            $allowed = array('post', 'user', 'comment');

            if(in_array($_GET['type'], $allowed)){


                $user_class = new User();
                $post->like_post($_id,$_GET['type'],$_SESSION['mybook_userid']);

                if($_GET['type'] == "user"){
                    $user_class->follow_user($_id,$_GET['type'],$_SESSION['mybook_userid']);

                }

            }

        }

        //read likes
        $likes = $post->get_likes($_id,$_GET['type']);

        //create info
        /////////////////
        $likes = array();
        $info = "";

                $i_liked = false;
                if(isset($_SESSION['mybook_userid'])){

                    $DB = new Database();

                    $sql = "select likes from likes where type='post' && contentid = '$_id' limit 1";
                    $result = $DB->read($sql);
                    if(is_array($result)){

                        $likes = json_decode($result[0]['likes'],true);

                        $user_ids = array_column($likes, "userid");

                        if(in_array($_SESSION['mybook_userid'], $user_ids)){
                            $i_liked = true;
                        }
                    }

                }

                $like_count = count($likes);

                if($like_count > 0){

                    $info .= "<br/>";

                    if($like_count == 1){

                        if($i_liked){
                            $info .= "<div style='text-align:left;'>You liked this post </div>";
                        }else{
                            $info .= "<div style='text-align:left;'> 1 person liked this post </div>";
                        }
                    }else{

                        if($i_liked){

                            $text = "others";
                            if($like_count - 1 == 1){
                                $text = "other";
                            }
                            $info .= "<div style='text-align:left;'> You and " . ($like_count - 1) . " $text liked this post </div>";
                        }else{
                            $info .= "<div style='text-align:left;'>" . $like_count . " others liked this post </div>";
                        }
                    }


                }

        /////////////////////////
        $obj = (object)[];
        $obj->likes = count($likes);
        $obj->action = "like_post";
        $obj->info = $info;
        //$obj->id = "info_$_GET[id]";
        $obj->id = 'info_'.$_id;
        
        echo json_encode($obj);


    }
rustyrice23
  • 9
  • 1
  • 3
  • 3
    `var info_element = document.getElementById(obj.id);` is null, that means its not able to find this element in dom. Are you sure there is an element with this ID? – ahsan Nov 01 '21 at 07:39
  • seems like your ajax request isn't working properly check if your path to the request is correct – Anil Parshi Nov 01 '21 at 07:57
  • I'm not too sure where the error is. Can you have a look at my ajax code? I've updated it on the main thread. – rustyrice23 Nov 01 '21 at 08:02
  • Below `$obj = (object)[];` `$obj->id = "info_".$_GET[id];` Update this line and check – Anil Parshi Nov 01 '21 at 08:05
  • It still receives the same error. – rustyrice23 Nov 01 '21 at 08:14
  • @rustyrice23 Your added code line does not answer the question from AhsanKhan – Reporter Nov 01 '21 at 08:28
  • Do you get a complete repsponse? `console.log(obj);` You might also try to check if the element id exists by adding this condition `if(info_element){info_element.innerHTML = obj.info}` Maybe the id is missing only sometimes. – herrstrietzel Nov 01 '21 at 23:53
  • @herrstrietzel this is what I received after console.log(obj); `{likes: 0, action: 'like_post', info: '', id: 'info_'}` – rustyrice23 Nov 02 '21 at 07:57
  • I received nothing in the console when checking if there is an info_element – rustyrice23 Nov 02 '21 at 08:00

1 Answers1

0

Probably it's related to a syntax error in your $_GET['id'] variable.
That's why console.log(obj) returned an empty id.

<?php echo $_GET[id]; // id is not enclosed by quotes ?>

Won't work on most servers running php7.x.
Make sure to always enclose your variable name in quotes (most of the time you did this, anyway).

<?php echo $_GET['id']; ?>

To simplify escaping, save your $_GET['id'] to a variable and sanitize it before you pass it to a sql query.
Try this:

Setting $_GET['id']
Replace null with '' – this way you save a lot of additional isset() checking e.g.

$_GET['id'] = isset($URL[6]) ? $URL[6] : '';
$_GET['type'] = isset($URL[5]) ? $URL[5] : '';

Saving to a sanitized variable:
You can now operate with this sanitized $_id variable instead of $_GET['id'].

$_id = $_GET['id'] ? htmlspecialchars( $_GET['id'], ENT_QUOTES) : '';
$_type = $_GET['type'] ? htmlspecialchars( $_GET['type'], ENT_QUOTES) : '';

Don't sanitize $_GET/$_POST (and other superglobals) variables by redefining them. Better leave them as the are but sanitize variables before any further usage (like echoeing, returning, passing to other functions etc.)

See also this thread: Sanitizing user's data in GET by PHP

DB query (the previous code also contained the enclosing issue):

$sql = "select likes from likes where type='post' && contentid = '$_id' limit 1";

Create your object data

$obj->id = 'info_'.$_id;

Code simplification and tweaks
As our ids and type variables are always defined (but maybe empty), you can focus on checking the values.

if( $_id && $_type ){ }

instead of

if(isset($_GET['type']) && isset($_GET['id'])){

The 'allowed array' might also cause some php warnings (depending on your php version etc.) – since you add array items to an array that hasn't been defined before. Better write it like this:

$allowed = array('post', 'user', 'comment');

JS part

if(info_element){
    info_element.innerHTML = obj.info
}

You should keep this condition as it just prevents the 'Cannot set properties of null' console.error.

The main problem should be solved by the aforementioned php fixes.

herrstrietzel
  • 11,541
  • 2
  • 12
  • 34
  • Thanks for the detailed explanation. However, after trying out your solution it's still not working. My updated code is on the thread. – rustyrice23 Nov 06 '21 at 02:22
  • Please, provide more debugging info. Do you get at least a proper object containing any Ids. If you still get something like ` id: 'info_ ` instead of ` id: 'info_ 123 ` then at some point, you still don't get/return the id. Most certainly you will have some error logfile on your server environment. Usually you can configure the settings in your hosting providers admin area. In these error log files you'd most certainly see php errors/notices giving you invaluable hints at which line of your code something breaks. – herrstrietzel Nov 07 '21 at 19:49
  • I'm still getting `id: 'info_ ` in my console log. You mentioned about the error logfile on the server environment. How do I check that? Also, I'm not too sure how to configure the settings in 000webhost. I only know how to change the php options. – rustyrice23 Nov 08 '21 at 02:03
  • if 000webhost provides any support this would be the best option. Usually you'd have some php.ini option. Since everthing was fine on your loacal machine, you might install an updated local server (like xampp etc) and test your current code. Most likely your previously used local server environment is rather outdated (something like php 5.6x) and forgiving/tolerant towards malformed code whereas your live server is probably using php 7.4. You could easily check the differnt versions by phpinfo(). BTW - is ROOT a previously defined constant – otherwise it might be $ROOT? – herrstrietzel Nov 08 '21 at 02:32
  • Sure I'll contact 000webhost. ROOT is already a defined constant. – rustyrice23 Nov 08 '21 at 03:01
  • You might also check your id right at the beginning. `echo $URL[6]` Maybe you need to decrease the array index since your locahost url might have an additional url part e.g `http://localhost/yourproject/thistype/123` whereas your public urls might be `https://yourproject.com/thistype/123` – herrstrietzel Nov 08 '21 at 17:09
  • You solved it! I forgot to change the URL as it doesn't correspond to the url address shown in the public server. Thank you so much for the help! Does that mean I have to change all the values or do I just change the values in like.ajax.php? – rustyrice23 Nov 09 '21 at 08:34
  • If I got you right you don't need to save the complete url (only id and type) – but it depends on your application. You can also add a check if you're on localhost or on the puplic server [How can I detect if the user is on localhost in PHP?](https://stackoverflow.com/questions/2053245/how-can-i-detect-if-the-user-is-on-localhost-in-php) so you'll retrieve e.g $URL[6] on localhost but $URL[5] online – herrstrietzel Nov 09 '21 at 15:42
  • Thanks for the link. I'll look into it. Appreciate the help! – rustyrice23 Nov 10 '21 at 02:13