0

Below code works on localhost, but not on live server.

MAIN EDIT:

Only 1 thing remains which is not working:

On AJAX success this will being executed:

$(".FixedDiv").addClass("panel-danger");
setTimeout(close, 500);
$("#label_" + res[2]).html(data.score_result);
$("#monitoring_score").html(data.calculated_score);

How ever, the label(for example) is not being updated. The label needs to be updated by the score which is given (data.score_result).

Ajax code:

$('.rating').on('rating.change', function () {
  var rating_id = $(this).attr('id');
  var res = rating_id.split("_");

  var comment = $("#comments_" + res[2]).val();
  var score = $("#item_score_" + res[2]).val();

  var post = 'controller=QualityMonitoring&task=setScore&monitor_id='
    + <?php echo $query['monitor_id']; ?>
    + '&q=' + res[2] + '&item_score=' + score + '&comment=' + comment;

  $.ajax({
    url: "controller.php",
    type: "POST",
    data: post,
    cache: false,
    dataType: "json",
    beforeSend: function () {
      saveScore();
    },
    success: function (data) {
      $(".FixedDiv").addClass("panel-danger");
      setTimeout(close, 500);
      $("#label_" + res[2]).html(data.score_result);
      $("#monitoring_score").html(data.calculated_score);
    }
  });
});

When I put alert('test'); above the $.ajax({ code it shows 'test'. When I put the alert INSIDE (just below) the $.ajax({ code, it does not show the alert.

saveScore function:

function saveScore() {
  var docHeight = $(document).height();

  $("body").append("<div id='overlay'></div>");

  $("#overlay")
    .height(docHeight)
    .css({
      'opacity': 0.4,
      'position': 'absolute',
      'top': 0,
      'left': 0,
      'background-color': 'black',
      'width': '100%',
      'z-index': 5000
    });
}

Results/info:

  1. alert(post); gives me the correct data result.
  2. saveScore is executed, but won't close afterwards (setTimeout).
  3. #label and #monitoring_score are not being updated like it has to do.
  4. using jquery-3.1.1.

I'm distraught on how to solve this. Anyone has an idea on how to fix?

Extra:

@Teemu:

Add an error handler to the AJAX call too, most likely it's the server-side which passes an error instead of data. Or open Network tab from the DevTools, and see if you're actually getting 200 OK message and the data.

Edit 1: (Whole javascript code):

<script>
    $(document).ready(function () {
        $(".nav-tabs a").click(function () {
            $(this).tab('show');
        });
    });

    $(document).ready(function () {
        $('.summernote').summernote({
            height: 450,   //set editable area's height
            toolbar: [
                ['view', ['fullscreen']],
                ['help', ['help']]
            ],
            codemirror: { // codemirror options
                theme: 'monokai'
            }

        });
    });

    jQuery(document).ready(function () {

        $('.nvt').on('click', function () {
            // get the id:
            var id = $(this).attr('id');
            var res = id.split("_");

            // Reset rating:
            var rating_input = "item_score_" + res[1];
            $('#' + rating_input).rating('update', 0);

            var comment = $("#comments_" + res[1]).val();
            var score = 0;

            var post = 'controller=QualityMonitoring&task=setScore&monitor_id=' + <?php echo $query['monitor_id']; ?> +'&q=' + res[1] + '&item_score=' + score + '&comment=' + comment;

            $.ajax({
                url: "controller.php",
                type: "POST",
                data: post,
                cache: false,
                dataType: "json",
                beforeSend: function () {
                    saveScore();
                },
                success: function (data) {
                    $(".FixedDiv").addClass("panel-danger");
                    setTimeout(closediv, 500);
                    $("#label_" + res[1]).html(data.score_result);
                    $("#monitoring_score").html(data.calculated_score);
                },
                error: function (data) {
                    $(".FixedDiv").addClass("panel-danger");
                    setTimeout(closediv, 500);
                    $("#label_" + res[1]).html(data.score_result);
                    $("#monitoring_score").html(data.calculated_score);
                }
            });

        });

        $('.rating').on('rating.change', function () {
            var rating_id = $(this).attr('id');
            var res = rating_id.split("_");

            var comment = $("#comments_" + res[2]).val();
            var score = $("#item_score_" + res[2]).val();

            var post = 'controller=QualityMonitoring&task=setScore&monitor_id=' + <?php echo $query['monitor_id']; ?> +'&q=' + res[2] + '&item_score=' + score + '&comment=' + comment;

            $.ajax({
                url: "controller.php",
                type: "POST",
                data: post,
                cache: false,
                dataType: 'json',
                beforeSend: function (data) {
                    saveScore();
                },
                success: function (data) {
                    $(".FixedDiv").addClass("panel-danger");
                    setTimeout(closediv, 500);
                    $("#label_" + res[2]).html(data.score_result);
                    $("#monitoring_score").html(data.calculated_score);
                },
                error: function(data) {
                    console.log("ERROR: ", data);
                }
            });

        });

        $('.savecomment').on('blur', function () {
            var comment_id = $(this).attr('id');
            var res = comment_id.split("_");

            var commentraw = $("#comments_" + res[1]).val();
            var comment = encodeURIComponent(commentraw);

            var post = 'controller=QualityMonitoring&task=setComment&monitor_id=' + <?php echo $query['monitor_id']; ?> +'&q=' + res[1] + '&comment=' + comment;

            $.ajax({
                url: "controller.php",
                type: "POST",
                data: post,
                cache: false,
                dataType: "json",
                success: function (data) {
                    if (data.result == 666) {
                        $("#comments_" + res[1]).css("background-color", "#ffcccc");
                    }
                }
            });

        });
    });

    $(document).on('change', '.btn-file :file', function () {
        var input = $(this),
                numFiles = input.get(0).files ? input.get(0).files.length : 1,
                label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
        input.trigger('fileselect', [numFiles, label]);
    });

    $(document).ready(function () {
        $('.btn-file :file').on('fileselect', function (event, numFiles, label) {

            var input = $(this).parents('.input-group').find(':text'),
                    log = numFiles > 1 ? numFiles + ' files selected' : label;

            if (input.length) {
                input.val(log);
            } else {
                if (log) alert(log);
            }

        });
    });

    function closediv() {
        $(document).unbind("keyup");
        $("#overlay").fadeOut("slow", function () {
            $("#overlay").remove();
            $(".FixedDiv").removeClass("panel-danger");
        });

    }

    function saveScore() {
        var docHeight = $(document).height();

        $("body").append("<div id='overlay'></div>");

        $("#overlay")
                .height(docHeight)
                .css({
                    'opacity': 0.4,
                    'position': 'absolute',
                    'top': 0,
                    'left': 0,
                    'background-color': 'black',
                    'width': '100%',
                    'z-index': 5000
                });
    }

    $(document).ready(function () {
        var $sidebar = $(".FixedDiv"),
                $window = $(window),
                offset = $sidebar.offset(),
                topPadding = 55;

        $window.scroll(function () {
            if ($window.scrollTop() > offset.top) {
                $sidebar.stop().animate({
                    marginTop: $window.scrollTop() - offset.top + topPadding
                });
            } else {
                $sidebar.stop().animate({
                    marginTop: 24
                });
            }
        });
    });
</script>
Ronnie Oosting
  • 1,252
  • 2
  • 14
  • 35
  • 6
    don't use alert, check the console – Temani Afif Feb 08 '18 at 09:34
  • 1
    Will do, one sec. Do you want me to `console.log(data);` ? – Ronnie Oosting Feb 08 '18 at 09:34
  • 1
    Alert! It was 2018... Trivial to figure out the problem once you open devtools and check network tab. – dfsq Feb 08 '18 at 09:35
  • Are you able to `console.log(data)` on success function? – Eddie Feb 08 '18 at 09:35
  • no, i want you to check if there is error inside the console – Temani Afif Feb 08 '18 at 09:36
  • @TemaniAfif, no error. – Ronnie Oosting Feb 08 '18 at 09:37
  • you uploaded all the files, cleared all your cache, the structure is similar to localhost, no server issue, etc ? – Temani Afif Feb 08 '18 at 09:38
  • your code is missing the error block to detect the issue, see this: https://stackoverflow.com/questions/377644/jquery-ajax-error-handling-show-custom-exception-messages – Ricardo Pontual Feb 08 '18 at 09:39
  • @Eddie, console.log(data); inside the $.ajax doesn't give result in the console. It seems the $.ajax is not being executed. Outside the $.ajax i receive results in the console. – Ronnie Oosting Feb 08 '18 at 09:41
  • Just so that you don't catch yourself saying one day "I don't use alert just because a guy on SO told me not to": using `alert` is a bad idea because if you ever forget one alert from dev to prod it's going to impact your program and user experience since an ugly message will appear for no reason, `console.log` won't. – Adrien Brunelat Feb 08 '18 at 09:42
  • 1
    Add an error handler to the AJAX call too, most likely it's the server-side which passes an error instead of data. Or open Network tab from the DevTools, and see if you're actually getting 200 OK message and the data. – Teemu Feb 08 '18 at 09:44
  • @AdrienBrunelat, thanks I will edit my question with your information. But the alert was just to see if the script actually executes the function. From now on I'll use console.log ;-)! – Ronnie Oosting Feb 08 '18 at 09:45
  • @RicardoPontual, added error. But the `#label` and `#monitoring_score` are not being executed. And it seems error is being executed instead of success. – Ronnie Oosting Feb 08 '18 at 09:46
  • @Teemu See comment above ^ – Ronnie Oosting Feb 08 '18 at 09:46
  • Network errors are not logged to the console, you need to take a look at the Network tab. – Teemu Feb 08 '18 at 09:47
  • @Teemu, Console network gives me this: name = link to current page, status = 200, type = document, initator = other. All other requests are status 200 as well. First time im using network, so if you need anything just ask. – Ronnie Oosting Feb 08 '18 at 09:49
  • It seems 50% is solved. The layer from `saveScore` is being updated. Only thing left is to have the `#label` and `#monitoring_score` being edited. `saveScore` is fixed by adding error. – Ronnie Oosting Feb 08 '18 at 09:55
  • 1
    it can be a CORS problem . check your console for errors – Yassine CHABLI Feb 08 '18 at 10:00
  • @MOHAMMEDYASSINEChabli no error is shown. Meawhile: just `#label` and `#monitoring_score` is not being edited. – Ronnie Oosting Feb 08 '18 at 10:02
  • @Teemu `console.log(ajaxOptions);` gives me this: SyntaxError: Unexpected token < in JSON at position 0 at parse () at Nb (jquery-3.1.1.min.js:4) at A (jquery-3.1.1.min.js:4) at XMLHttpRequest. (jquery-3.1.1.min.js:4) – Ronnie Oosting Feb 08 '18 at 10:19
  • 1
    It looks like your server sends HTML instead of JSON then, or the JSON is malformed. Apart from that, [`close`](https://developer.mozilla.org/en-US/docs/Web/API/Window/close) is a native DOM method, you should not override it, use another name for the function, especially, if it is a global function. – Teemu Feb 08 '18 at 10:20
  • @Teemu Thank for all your help man, i really appreciate it. I've changed the `dataType` to 'text'. Now it seems `success` is being executed instead of `error`. I also changed 'close' to 'closediv'. Just this part does not work: `$("#label_" + res[1]).html(data.score_result);` and `$("#monitoring_score").html(data.calculated_score);` Do you have an idea? I will keep searching meanwhile on the internet for sure – Ronnie Oosting Feb 08 '18 at 10:26
  • Please check the data you're getting from the server. Obviously you need JSON to be send, that's why those parts are not working. When you set datatype to text, you'll receive a string, and naturally that won't have the properties you're retrieving from the send data. – Teemu Feb 08 '18 at 10:30
  • @Teemu Check! This is what I receive from the server: `{"calculated_score":7.7,"score_result":"1.17 pts"}`. This is what 'data' in ajax contains. – Ronnie Oosting Feb 08 '18 at 10:46
  • Now I'm dropping off the wagon ... That looks valid JSON, and everything should be OK. I can't understand, how jQuery found `<` from the response ..? – Teemu Feb 08 '18 at 10:50
  • It's maybe rather a hack, but you could parse the string to JSON with `JSON.parse()` and then use the created object as data ... – Teemu Feb 08 '18 at 11:01
  • Unfortunately I've got to go. I'll test your 'hack' tomorrow and I wil let you know the results! Thanks for your time thus far. – Ronnie Oosting Feb 08 '18 at 11:04
  • @Teemu ajax says its not a json format... This is my controller who creates the json with data: `public function setScore() { $data['calculated_score'] = 'some calculation'; $data['score_result'] = 'some calculation'; echo json_encode($data); exit(); }` – Ronnie Oosting Feb 09 '18 at 09:03
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/164814/discussion-between-ronnie-oosting-and-teemu). – Ronnie Oosting Feb 09 '18 at 10:03
  • Please join this [chat](https://chat.stackoverflow.com/rooms/167740/discussion-ajax-works-on-localhost-but-doesnt-on-live-server) room – Tarun Lalwani Mar 28 '18 at 14:22
  • What kind of servers do you use for localhost and live? Are they different types? – Jannes Botis Mar 28 '18 at 14:40
  • i just read the last part of the discussion and i'm curious about : `statically test the controller output` , how are you testing it exactly ? like .. an url ? an app like `postman` ? – Taki Mar 28 '18 at 16:57
  • This is a duplicate of any of the other hundreds of ajax questions with an error callback being called with a parseerror. Your server isn't returning valid json. **Make it return valid json**. The localhost vs live server is irrelevant to the ajax, if you want to figure out how to fix that, ask a different question with the required information to debug that particular problem. the client-side code isn't related to that problem. – Kevin B Mar 28 '18 at 22:03
  • use developer tools -> Network to trace the error. post it here. – Wils Mar 29 '18 at 03:13
  • Only 2 things can cause "#Label_" not to update. Check if res[2] is undefined, or a not expected value. check that data.score_result has a value. – Jorge Zuverza Mar 29 '18 at 14:11
  • @RonnieOosting is the local a linux server and the live a windows? what kind of operating systems do they use? How do you upload the code, ftp? – Jannes Botis Mar 29 '18 at 16:39
  • Where is your `close` function calling from here `setTimeout(close, 500);` ? – Niklesh Raut Apr 03 '18 at 06:39
  • @JannesBotis live is linux, local is windows. Upload to ftp through bitbucket – Ronnie Oosting Apr 03 '18 at 07:04

6 Answers6

1
  1. after function saveScore() add: var close = function() { $('#overlay').remove(); };

  2. after success: function (data) {} remove last comma

1

I think a few of the other posters are on to something about the invalid JSON,

I would add however, this is something I like to do for JSON

<?php
   ob_start(); //turn on output buffering

   //...other code


$debug = ob_get_clean();
$response['debug'] = $debug; //comment this when live in production

header('Content-type: application/json');

echo json_encode($response);

What this does is turn on output buffering. Which traps any output and buffers it. This includes warnings, notices, echo, and print stuff. Then it stuffs it into the response as debug and forwards it to the client.

Obviously you would not want to do this on live production server, but you can easily comment it out. It can be a security issue to include some errors and stack trace information to the client. But for debugging purposes it works great.

The problem with JSON is if you are checking the value of something somewhere (printing it) or have any notices it will muck up your JSON. For example

 printed content
 {"foo":"bar"}

So this takes away that problem entirely (assuming you output buffer before printing anything) like so:

 {"foo":"bar", "debug":"printed content"}

And now you have valid JSON, and as a side bonus you can print out your debug info by simply doing

 $.ajax({
     url: "controller.php",
     type: "POST",
     data: post,
     cache: false,
     dataType: "json",
     beforeSend: function () {
       saveScore();
     },
     success: function (data) {
          if(data.debug) console.log(data.debug);
     }
 });

It's simple and effective.

Hope it helps.

ArtisticPhoenix
  • 21,464
  • 2
  • 24
  • 38
1

Is your PHP code valid and not throwing extra code which is messing up your JSON object. When there is a notice the JSON object becomes a string instead of a JSON string and then javascript can't parse it anymore.

Please make a new clean controller without any other code, post the data again and then check what is happening. Never return data but echo data with an exit.

Javascript and Code looks valid but somewhere else in your MVC may throw HTML code in the exit statement or generating it before you enter the controller which is required to return the data.

Robert Dam
  • 199
  • 1
  • 2
  • 12
  • Thanks Robert. I've edited the code and posted it into a new clean controller. It seems it's working now. Thanks a lot. I've been searching for like two weeks for a fix. It seems the current controller is to big and somewhere it corrupts the output. I'll mark your answer as the correct one. – Ronnie Oosting Apr 03 '18 at 12:46
0

Try adding an error handler to your Ajax function and see what it returns:

$.ajax({
    url: "controller.php",
    type: "POST",
    data: post,
    cache: false,
    dataType: "json",
    beforeSend: function () {
      saveScore();
    },
    success: function (data) {
      $(".FixedDiv").addClass("panel-danger");
      setTimeout(close, 500);
      $("#label_" + res[2]).html(data.score_result);
      $("#monitoring_score").html(data.calculated_score);
    },
    error: function(data) {
      console.log("ERROR: ", data);
    }
  });

Share the result with us so we can trouble shoot your issue and help you.

Mario Andrade
  • 505
  • 3
  • 21
  • ERROR: {readyState: 4, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …} abort : ƒ (a) always : ƒ () catch : ƒ (a) done : ƒ () fail : ƒ () getAllResponseHeaders : ƒ () getResponseHeader : ƒ (a) overrideMimeType : ƒ (a) pipe : ƒ () progress : ƒ () promise : ƒ (a) readyState : 4 responseText : " LOTS OF HTML CODE – Ronnie Oosting Mar 29 '18 at 07:44
  • I'll take the long answer to anyone looking at this answer can understand what is happening. The readyState 4 and status 200 mean the HTTP request was successful but the data parsing probably had an error. Now we troube shoot again. On your Ajax function change your datatype to jsonp instead of json and test it again to see if it throws an error or not. – Mario Andrade Mar 29 '18 at 09:22
  • Thanks Mario. Do you have any idea what to do? – Ronnie Oosting Mar 29 '18 at 09:23
  • @RonnieOosting sorry, the first answer was incomplete. check the comment before yours I've updated it with more information. – Mario Andrade Mar 29 '18 at 10:03
  • {readyState: 4, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …} abort : ƒ (a) always : ƒ () catch : ƒ (a) done : ƒ () fail : ƒ () getAllResponseHeaders : ƒ () getResponseHeader : ƒ (a) overrideMimeType : ƒ (a) pipe : ƒ () progress : ƒ () promise : ƒ (a) readyState : 4 responseText : " LOTS OF HTML CODE – Ronnie Oosting Mar 29 '18 at 10:09
  • and: `VM3580:1 Uncaught SyntaxError: Unexpected token < at p (jquery-3.1.1.min.js:2) at Function.globalEval (jquery-3.1.1.min.js:2) at text script (jquery-3.1.1.min.js:4) at Nb (jquery-3.1.1.min.js:4) at A (jquery-3.1.1.min.js:4) at XMLHttpRequest. (jquery-3.1.1.min.js:4)` – Ronnie Oosting Mar 29 '18 at 10:10
  • want to chat here?: https://chat.stackoverflow.com/rooms/167740/discussion-ajax-works-on-localhost-but-doesnt-on-live-server that might be easier. – Ronnie Oosting Mar 29 '18 at 10:11
0

Are you wrapping your js code in $(document).ready() ?

A page can't be manipulated safely until the document is "ready." jQuery detects this state of readiness for you. Code included inside $( document ).ready() will only run once the page Document Object Model (DOM) is ready for JavaScript code to execute.

Try enclosing everything in

$(function(){
//your code here
})

Like this:

$(function(){
$('.rating').on('rating.change', function () {
  var rating_id = $(this).attr('id');
  var res = rating_id.split("_");

  var comment = $("#comments_" + res[2]).val();
  var score = $("#item_score_" + res[2]).val();

  var post = 'controller=QualityMonitoring&task=setScore&monitor_id='
    + <?php echo $query['monitor_id']; ?>
    + '&q=' + res[2] + '&item_score=' + score + '&comment=' + comment;

  $.ajax({
    url: "controller.php",
    type: "POST",
    data: post,
    cache: false,
    dataType: "json",
    beforeSend: function () {
      saveScore();
    },
    success: function (data) {
      $(".FixedDiv").addClass("panel-danger");
      setTimeout(close, 500);
      $("#label_" + res[2]).html(data.score_result);
      $("#monitoring_score").html(data.calculated_score);
    }
  });
});

function saveScore() {
  var docHeight = $(document).height();

  $("body").append("<div id='overlay'></div>");

  $("#overlay")
    .height(docHeight)
    .css({
      'opacity': 0.4,
      'position': 'absolute',
      'top': 0,
      'left': 0,
      'background-color': 'black',
      'width': '100%',
      'z-index': 5000
    });
}

});
Jorge Zuverza
  • 885
  • 8
  • 26
0

From the code you posted, the comments below and the discussion ( actually was very helpful to jump to this conclusion ) .. i can point a couple of things, but first :

adding error_reporting(0); in the begining of the controller right after <?php should solve your problem. ( if my guess is correct and it's just a notice, not an actual error)

i'm guessing that you already have this in your localhost 's php.ini and on the live server you have the default error_reporting = E_ALL, due to two different installations of php.

there's probably somewhere in the controller a notice of an undefined index or something, and php is trying to let you know by outputting this :

<br />
<b>Notice</b>:  Undefined index: ...
{"calculated_score":10,"score_result":"1.75 pts"}

it starts with a < and that's where this comes from

SyntaxError: Unexpected token < in JSON at position 0 

the $.ajax is unable to parse this because you have dataType="json" and this means that it is expecting a valid json back from the server, so you get the 200 status because the request was successful with no errors and console.log(data) will be empty because it was unable to parse it.

a simple way to reproduce this is creating a test php file and send the request to it instead of controller.php like :

<?php
    error_reporting(0); // try with and without this line.

    $data = [
        'city' => 'Montreal',
        'Country' => 'Canada'
    ];

    echo $_GET['something']; // this will trigger a notice of undefined index something

    echo json_encode($data);
?>

you can remove dataType:"json" and put console.log(data) in the success function and look in the console to see what the server is really telling you.

but here's something that bugs me ..

var post = 'controller=QualityMonitoring&task=setScore&monitor_id='

this looks like a query string you use for GET requests but you have type:"POST" in your ajax request ..

i don't know how you're handling this in the controller but it should be type:"GET" to send data like this, but if you want to send the data with POST then var post should be an object, ( this could be the problem as it defaults to GET when not set and in the controller there's a $_GET['task'] instead of $_POST['task'] or vise-versa ) so here's a snippet to convert the query string to a json :

function QueryStringToJSON(str) {
 var pairs = str.split('&');
 var result = {};
 pairs.forEach(function (pair) {
  pair = pair.split('=');
  var name = pair[0]
  var value = pair[1]
  if (name.length)
   if (result[name] !== undefined) {
    if (!result[name].push) {
     result[name] = [result[name]];
    }
    result[name].push(value || '');
   } else {
    result[name] = value || '';
   }
 });
 return (result);
}

var string = 'controller=QualityMonitoring&task=setScore&monitor_id=5&q=blah&item_score=99&comment=hello';
var obj = QueryStringToJSON(string);

console.log(obj);

i hope this helps or at least gives you an idea, and Good Luck.

Taki
  • 17,320
  • 4
  • 26
  • 47
  • Hi Taki, thank you for your time. `var post = 'controller=QualityMonitoring&task=setScore&monitor_id='` receives a json format. – Ronnie Oosting Mar 29 '18 at 08:16
  • There is only 1 problem left... The data is being saved, just the success part in the ajax needs to be executed. The div's need to be changed with new content. For example: `$("#label_" + res[2]).html(data.score_result);` inside the `$('.rating').on('rating.change', function () {` function. – Ronnie Oosting Mar 29 '18 at 08:22
  • if your controller is working fine then removing `dataType="json"` should get the `success` function to work because it won't have to parse the data it got from the server, but you won't have `data.score_result` , if adding`error_reporting(0);` to your controller didn't do the trick then post a screenshot of the `LOTS OF HTML CODE` you're having in the response. – Taki Mar 29 '18 at 15:45