Getting logic error using JavaScript on creating like/dislike counter - javascript

I've fixed the bug. I'm documenting my code for future reference.
I'm creating a like/dislike counter and getting a logic error.
My script works such that on clicking on either button I can like/dislike or undo that action. I've tried creating logic such that when I dislike after liking the post, or vice versa, the dislike decrements and the like counter increments . The problem where I'm stuck at is after successively clicking both buttons, either one of the counter resets to zero.
<script type="text/javascript">
var dislike_b = like_b = false;
var num1 = 0;
var like = parseInt("{{post.like_votes}}");
var num2 = 0;
var dislike = parseInt("{{post.dislike_votes}}");
function likeHandler() {
const xhr = new XMLHttpRequest();
if (dislike_b == true){
dislikeHandler();
//dislike_b = false ;
}
// like iterator
like = like + (-1)**num1 ;
num1 = (num1 + 1)%2;
document.getElementById("like").innerHTML = like;
like_b = !like_b;
console.log( like , num1);
//var catid;
//catid = $(this).attr("data-catid");
$.ajax(
{
type: "POST",
url: "/likepost/",
data: {
//post_id: catid ,
votes : like ,
csrfmiddlewaretoken: '{{ csrf_token }}'
},
success: function (data) {
//$('#like' + catid).remove();
$('#message').text(data);
}
})
}
function dislikeHandler() {
const xhr2 = new XMLHttpRequest();
if (like_b == true){
likeHandler();
}
// like iterator
dislike = dislike + (-1)**num2 ;
num2 = (num2 + 1)%2;
document.getElementById("dislike").innerHTML = dislike;
dislike_b = !dislike_b;
console.log( dislike , num1);
$.ajax(
{
type: "POST",
url: "/dislikepost/",
data: {
votes : dislike ,
csrfmiddlewaretoken: '{{ csrf_token }}'
},
success: function (data) {
$('#message').text(data);
}
})
}
</script>

Have you tried preventDefault()?

You could try simplifying it a little like this by putting the ajax request in its own function. What else needs to happen when clicking the buttons? Just comment and I'll update.
// Variables
let likes = 0
let dislikes = 0
// Like
function like() {
const likeDOMText = document.querySelector('.like span')
likes++
likeDOMText.innerText = likes
// Calling the ajax request
initRequest({
likes: likes,
dislikes: dislikes,
// And whatever else
})
}
// Dislike
function dislike() {
const dislikeDOMText = document.querySelector('.dislike span')
dislikes++
dislikeDOMText.innerText = dislikes
// Calling the ajax request
initRequest({
likes: likes,
dislikes: dislikes,
// And whatever else
})
}
// Ajax request to server
function initRequest(data) {
// $.ajax({
// ...
//data: JSON.parse(data)
//})
}
<button class="like" onclick="like()">Like <span>0</span></button>
<button class="dislike" onclick="dislike()">Dislike <span>0</span></button>

Related

Ajax if more then one #mention

I am trying to make a facebook and twitter style mention system using jquery ajax php but i have a problem if i try to #mention more then one user. For example if i start to type something like the follow:
Hi #stack how are you.
The results showing #stack but if i try to mention another user like this:
Hi #stack how are you. i am #azzo
Then the results are nothing. What i am missing my ajax code anyone can help me please ?
I think there is a regex problem for search user_name. When i write some username after first one like #stack then the ajax request posting this:
f : smen
menFriend : #stack
posti : 102
But if i want to tag my other friend in the same text like this:
Hi #stack how are you. I am #a then ajax request looks like this:
f : smen
menFriend : #stack, #a
posti : 102
So what I'm saying is that apparently, ajax interrogates all the words that begin with #. It needs to do is interrogate the last #mention from database.
var timer = null;
var tagstart = /#/gi;
var tagword = /#(\w+)/gi;
$("body").delegate(".addComment", "keyup", function(e) {
var value = e.target.value;
var ID = e.target.id;
clearTimeout(timer);
timer = setTimeout(function() {
var contents = value;
var goWord = contents.match(tagstart);
var goname = contents.match(tagword);
var type = 'smen';
var data = 'f=' +type+ '&menFriend=' +goname +'&posti='+ID;
if (goWord.length > 0) {
if (goname.length > 0) {
$.ajax({
type: "POST",
url: requestUrl + "searchuser",
data: data,
cache: false,
beforeSend: function() {
// Do Something
},
success: function(response) {
if(response){
$(".menlist"+ID).show().html(response);
}else{
$(".menlist"+ID).hide().empty();
}
}
});
}
}
}, 500);
});
Also here is a php section for searching user from database:
$searchmUser = mysqli_real_escape_string($this->db,$searchmUser);
$searchmUser=str_replace("#","",$searchmUser);
$searchmUser=str_replace(" ","%",$searchmUser);
$sql_res=mysqli_query($this->db,"SELECT
user_name, user_id
FROM users WHERE
(user_name like '%$searchmUser%'
or user_fullname like '%$searchmUser%') ORDER BY user_id LIMIT 5") or die(mysqli_error($this->db));
while($row=mysqli_fetch_array($sql_res,MYSQLI_ASSOC)) {
// Store the result into array
$data[]=$row;
}
if(!empty($data)) {
// Store the result into array
return $data;
}
Looks like you're sending an array which is result of match you in AJAX request.
Though I cannot test it but you can use a lookahead in your regex and use 1st element from resulting array. Negative lookahead (?!.*#\w) is used to make sure we match last element only.
var timer = null;
var tagword = /#(\w+)(?!.*#\w)/;
$("body").delegate(".addComment", "keyup", function(e) {
var value = e.target.value;
var ID = e.target.id;
clearTimeout(timer);
timer = setTimeout(function() {
var contents = value;
var type = 'smen';
var goname = contents.match(tagword);
if (goname != undefined) {
var data = 'f=' +type+ '&menFriend=' +goname[1] +'&posti='+ID;
$.ajax({
type: "POST",
url: requestUrl + "searchuser",
data: data,
cache: false,
beforeSend: function() {
// Do Something
},
success: function(response) {
if(response){
$(".menlist"+ID).show().html(response);
} else {
$(".menlist"+ID).hide().empty();
}
}
});
}
}, 500);
});

Ajax passing value to PHP

I would like to pass multiple values to php via ajax (on same page), here's my code:
HTML (user_list.php):
<button type="submit" class="button button-block savebutton" name="save_changes"/>
Save changes</button>
Javascript (user_list.php):
$(".savebutton").on("click", function (event) {
event.preventDefault();
var js = [];
var i = 0;
$('select').each(function () {
var a = {"id": "", "permission": ""}
a.id = $(this).val();
a.permission = $(this).children(":selected").text();
js.push(a);
alert(js[i].permission + " - "+js[i].id);
i++;
});
$.ajax({
type: "POST",
url: "user_list.php",
data: {result: JSON.stringify(js)}
});
return false;
});
PHP (user_list.php):
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (isset($_POST['delete_selected'])) { // Button to delete selected user(s)
if (!empty($_POST['check_list'])) {
foreach ($_POST['check_list'] as $id) {
$sql = "DELETE FROM users WHERE id=$id";
$mysqli->query($sql);
header("Refresh:0"); //Refresh page
}
}
}
// Other if above works fine
elseif (isset($_POST['result'])){
// I want to get the js array with the values here after ajax
}
else {
// But I get here, and I don't get the js array
}
}
So I have 2 problems, the first is that I pass the elseif, and the second is that I dont get the array. I think the problem is with ajax, since filling the array works properly
EDIT: I moved the php to a different page, now it's working.
Though your Ajax request is initiated, a "normal" submit request is also started, when you press the button. To prevent the second request (thus keeping only the Ajax request), you have to return false; at the end of your onclick callback.
Solution #1:
$(".savebutton").on("click", function () {
var js = [];
var i = 0;
$('select').each(function () {
var a = {"id": "", "permission": ""}
a.id = $(this).val();
a.permission = $(this).children(":selected").text();
js.push(a);
alert(js[i].permission + " - "+js[i].id);
i++;
});
$.ajax({
type: "POST",
url: "user_list.php",
data: {result: JSON.stringify(js)}
});
return false;
});
Solution #2 (as also suggested by #charlietfl):
$(".savebutton").on("click", function (event) {
event.preventDefault();
var js = [];
var i = 0;
$('select').each(function () {
var a = {"id": "", "permission": ""}
a.id = $(this).val();
a.permission = $(this).children(":selected").text();
js.push(a);
alert(js[i].permission + " - "+js[i].id);
i++;
});
$.ajax({
type: "POST",
url: "user_list.php",
data: {result: JSON.stringify(js)}
});
});
It seems that when you're submitting the POST request, the data is coming as their own POST fields. Simply check for the values of what you submitted. For example, if you had done the same, but put foo as bar and hello as world, you could check for foo and hello with something like this:
elseif (isset($_POST['foo'], $_POST['hello']) {
# your code
}
$('.savebutton').click(function (e) {
e.preventDefault()
var js = []
var i = 0
$('select').each(function (i) {
var a = {}
a.id = $(this).val()
a.permission = $(this).children(':selected').text()
js.push(a)
alert(js[i].permission + ' - ' + js[i].id)
})
js = JSON.stringify(js)
$.post('user_list.php', {result: js}
})
Try with this
<button type="submit" class="button button-block savebutton" name="save_changes[]"/>Save changes</button>

How to wait for AJAX calls in an each loop to complete before moving on without ASYNC: FALSE

I currently have setup a AJAX to PHP set of functions that processes a number of items on a page. Basically the code inserts a series of tasks into the database, then inserts supplies into the database based on those newly created task ID's. However it works 90% of the time. Sometimes it seems as though the Task ID's are not created first which doesn't allow the supplies to use those ID's for inserting into the database. Is there a way to make sure that the task is inserted, then all supplies are inserted for that ID, then move onto the next one. At the end when all is complete I would like to redirect to a new page, again I put this in the last success call on the supplies portion, but it would redirect on the first loop. This process usually generates around 5 tasks, with 12 supplies per each task. I was reading about a $.when loop but could not get it to work. NOTE: after testing the ajax calls are submitting correctly, it was that one field on some of them was null, and the DB was having an issue. So the counter method below works.
$(document).on("click", "#submitTasks", function(e) {
e.preventDefault();
var tasks = $('#tasks').find('.box');
var project_id = $('#project_id').val();
tasks.each(function() {
var trs = $(this).find('.reqTables').find('.table').find('tbody').find('tr');
var task_definition_id = $(this).find('.task_definition_id').val();
var labor_type_id = $(this).find('.laborAmount').children('option:selected').val();
var task_status_id = 1;
var qty_labor = $(this).find('.laborQty').val();
var amount_labor = $(this).find('.laborTotal').val();
var amount_materials = $(this).find('.matTotal').val();
var amount_gst = $(this).find('.gstTotal').val();
amount_materials = +amount_materials + +amount_gst;
amount_materials = amount_materials.toFixed(2);
var active = 1;
//console.log(div)
var task = {
project_id : project_id,
task_definition_id : task_definition_id,
labor_type_id : labor_type_id,
task_status_id : task_status_id,
qty_labor : qty_labor,
amount_labor : amount_labor,
amount_materials : amount_materials,
active : active
};
saveTasks(task, trs, project_id);
});
});
function saveTasks(task, trs, project_id) {
$.ajax({
type : "POST",
url : "<?php echo base_url(); ?>" + "mgmt/project/saveTasks",
data : task,
dataType : "json",
cache : "false",
success : function(data) {
trs.each(function() {
var total = $(this).find('input[name="calculatedCost"]').val();
if (total != 'n/a') {
var task_id = data;
var supply_id = $(this).find('.suppliesPicker').children('option:selected').val();
var task_requirement_id = $(this).find('td:first-child').data('id');
var qty = $(this).find('input[name="calculatedQty"]').val();
var cost_per = $(this).find('.costPicker').val();
var delivery_cost = $(this).find('input[name="transport"]').val();
var notes = '';
var qty_actual = '';
var active = 1;
var taskSupply = {
task_id : task_id,
supply_id : supply_id,
task_requirement_id : task_requirement_id,
qty : qty,
cost_per : cost_per,
delivery_cost : delivery_cost,
total : total,
notes : notes,
qty_actual : qty_actual,
active : active
};
saveTaskSupplies(taskSupply);
console.log(taskSupply);
}
});
}
});
}
function saveTaskSupplies(taskSupply) {
$.ajax({
type : "POST",
url : "<?php echo base_url(); ?>" + "mgmt/project/saveTaskSupplies",
data : taskSupply,
dataType : "json",
cache : "false",
success : function(data) {
***** I WANT TO REDIRECT TO A NEW PAGE WHEN THE LAST ONE OF THESE COMPLETES ******
}
});
}
This code will wait for nested loop ajax function calls to finish their promises, then proceed..
var allPromises;
$(document).on("click", "#submitTasks", function(e) {
//...
var tasks = $('#tasks').find('.box');
allPromises = [];
tasks.each(function() {
//.. somehow getTask
var req = saveTasks(task, trs, project_id);
allPromises.push(req);
});
$.when.apply(null, allPromises).done(function(){
// Do your things here,
// All save functions have done.
});
});
function saveTasks(task, trs, project_id) {
return $.ajax({
// ,,, your codes
success : function(data) {
// ...
trs.each(function() {
// ... Somehow get taskSupply
var req = saveTaskSupplies(taskSupply);
allPromises.push(req);
}
}
});
}
function saveTaskSupplies(taskSupply) {
return $.ajax({
// ... bla bla bla
success : function(data) {
// Whatever..
}
});
}
Here is a direct solution using the code you provided. The basic concept is to increment a counter as supplies are processed. Once the counter reaches the total number of supplies, a procedure is run. See comments throughout.
var totalTaskSupplies = 0;
var processedTaskSupplies = 0;
$(document).on("click", "#submitTasks", function(e) {
e.preventDefault();
var tasks = $('#tasks').find('.box');
var project_id = $('#project_id').val();
tasks.each(function() {
var trs = $(this).find('.reqTables').find('.table').find('tbody').find('tr');
var task_definition_id = $(this).find('.task_definition_id').val();
var labor_type_id = $(this).find('.laborAmount').children('option:selected').val();
var task_status_id = 1;
var qty_labor = $(this).find('.laborQty').val();
var amount_labor = $(this).find('.laborTotal').val();
var amount_materials = $(this).find('.matTotal').val();
var amount_gst = $(this).find('.gstTotal').val();
// Add number of supplies for current task to total task supplies
totalTaskSupplies += trs.length;
amount_materials = +amount_materials + +amount_gst;
amount_materials = amount_materials.toFixed(2);
var active = 1;
//console.log(div)
var task = {
project_id : project_id,
task_definition_id : task_definition_id,
labor_type_id : labor_type_id,
task_status_id : task_status_id,
qty_labor : qty_labor,
amount_labor : amount_labor,
amount_materials : amount_materials,
active : active
};
saveTasks(task, trs, project_id);
});
});
function saveTasks(task, trs, project_id) {
$.ajax({
type : "POST",
url : "<?php echo base_url(); ?>" + "mgmt/project/saveTasks",
data : task,
dataType : "json",
cache : "false",
success : function(data) {
trs.each(function() {
var total = $(this).find('input[name="calculatedCost"]').val();
if (total != 'n/a') {
var task_id = data;
var supply_id = $(this).find('.suppliesPicker').children('option:selected').val();
var task_requirement_id = $(this).find('td:first-child').data('id');
var qty = $(this).find('input[name="calculatedQty"]').val();
var cost_per = $(this).find('.costPicker').val();
var delivery_cost = $(this).find('input[name="transport"]').val();
var notes = '';
var qty_actual = '';
var active = 1;
var taskSupply = {
task_id : task_id,
supply_id : supply_id,
task_requirement_id : task_requirement_id,
qty : qty,
cost_per : cost_per,
delivery_cost : delivery_cost,
total : total,
notes : notes,
qty_actual : qty_actual,
active : active
};
saveTaskSupplies(taskSupply);
console.log(taskSupply);
}
});
}
});
}
function saveTaskSupplies(taskSupply) {
$.ajax({
type : "POST",
url : "<?php echo base_url(); ?>" + "mgmt/project/saveTaskSupplies",
data : taskSupply,
dataType : "json",
cache : "false",
success : function(data) {
++processedTaskSupplies;
// All supplies have been processed
if (processedTaskSupplies == totalTaskSupplies) {
// Do something
}
}
});
}
Regarding the first question, by studying your code I couldn't see the reason of it. You only execute the saveTaskSupplies() when saveTasks() has executed successfully, so the task_id should already be created.
However, I would think of another possible problem from your backend, in your Ajax success function in saveTasks(), You assume the PHP script always execute successfully and return the task_id. Would it be possible that your PHP script has some problem and the task_id is not created in some instance?
For the second question, there are a few approaches, as #Seth suggest you can use jQuery.when, or you can create a global counter to keep track of whether the saveTaskSupplies() is the last one. Note that you should calculate the total length of trs before firing the Ajax request, otherwise, you may have a chance of having a not well-calculated total and redirecting before all tasks are done. If it is the last one it will redirect after successful Ajax call.
// create a global counter
var counter = 0,
trl = 0;
$(document).on("click", "#submitTasks", function(e) {
...
var trList = [];
tasks.each(function() {
// calculate the length of total task before actually firing the Ajax Request
var trs = $(this).find('.reqTables').find('.table').find('tbody').find('tr');
// keep a copy of the trs so the next each loop does not have to find it again
trList.push(trs);
trl += trs.length;
});
tasks.each(function() {
// get the trs of current iteration we have found in last loop
var trs = trList.shift();
...
saveTasks(task, trs, project_id);
});
});
function saveTasks(task, trs, project_id) {
$.ajax({
...
success : function(data) {
trs.each(function() {
...
saveTaskSupplies(taskSupply);
}
}
});
}
function saveTaskSupplies(taskSupply) {
$.ajax({
...
success : function(data) {
// check if the counter exceed the length of trs
if (++counter == trl) {
location.href = 'place you want to go';
}
}
});
}
On the other hand, for your task I would also suggest shifting the responsibility of data insertion to PHP backend, so all you need to do is to pass the task information and the task supplies at once to a single PHP script. This approach allows the use of Transaction to make sure all data insertion is success or otherwise all should fail.

Setting something in DB only once

I'm using a setInterval to detect a value I get from my PLC(Programmable logic controller) When it is 1 it executes a PHP page that inserts data in my MYSQL database.
So when I'm holding my button down for longer than 1 second, it sets the DB values multiple times in it.
Below you can find my code:
var Axo800RstBtn;
setInterval(function()
{
Axo800RstBtn = document.getElementById('Axo800BtnStatus').innerHTML;
var BatchUnits1 = document.getElementById('Axo800BatchProduction').innerHTML;
if(Axo800RstBtn == 1)
{
$.ajax({
method: "POST",
url: "SetBatchProductionInDB.php",
data: {
machineNumber: 1,
actualProduction: BatchUnits1
}
})
.done(function(msg)
{
console.log("Bericht: " + msg);
})
}
},1250);
Is there a way to tell my page it can only execute once per 1 minute? some kind of block. Or maybe a block on the execute query?
This could do the trick:
var Axo800RstBtn;
var hasBeenSet = false;
setInterval(function()
{
Axo800RstBtn = document.getElementById('Axo800BtnStatus').innerHTML;
var BatchUnits1 = document.getElementById('Axo800BatchProduction').innerHTML;
if(Axo800RstBtn == 1 && !hasBeenSet)
{
hasBeenSet = true;
$.ajax({
method: "POST",
url: "SetBatchProductionInDB.php",
data: {
machineNumber: 1,
actualProduction: BatchUnits1
}
})
.done(function(msg)
{
console.log("Bericht: " + msg);
})
}
},1250);
Although I would strongly advise that you also do this control server-side. I.E. you could keep track of the script being called by setting up a session var in PHP.
This code will prevent the request from being sent as soon as the request has been sent once. If you want to enable it after 60 seconds you could add after hasBeenSet = true;
hasBeenSet = true;
setTimeout(function(){ hasBeenSet = false}, 60000);

ASP.net 3.5 WebMethod Strange Behavior, jQuery AJAX receives strange data

I've ran into this strange JSON behavior.. I just cant figure out what the hell is going on..
I've got a WebMethod in my asp.net page.. It repetitively calls as page loads through jQuery AJAX.. Everything goes pretty smooth but what strange thing happens is that the data I sens to my jQuery ajax is not the SAME I just sent.. :S
here is not code of page method
[WebMethod()]
public static List<Unister.UnisterCore.Core.Domain.Comment> LoadComments(long objID, int sysID)
{
if (objID == 0)
return null;
UnisterWeb.UserControls.Presenter.CommentsPresenter _presneter;
_presneter = new UnisterWeb.UserControls.Presenter.CommentsPresenter();
List<Unister.UnisterCore.Core.Domain.Comment> comments = new List<Unister.UnisterCore.Core.Domain.Comment>();
comments = _presneter.LoadComments(sysID, objID);
if (comments.Count == 0)
return null;
return comments;
}
Here returning list is what I got from my presenter layer but when I receive that in my js method, its either null or previous value.
Here is my jQuery method..
function LoadComments(SysID, ObjID) {
if (parseInt(SysID) == 0 || parseInt(ObjID) == 0)
return;
var args = 'objID:' + ObjID + ',sysID:' + SysID;
$.ajax({
type: "POST",
url: "/dashboard/default.aspx/LoadComments",
cache: false,
data: '{' + args + '}',
contentType: "application/json",
dataType: "json",
success: function(result) {
if (result.d != null) {
comments = new Array();
$.each(result.d, function(key, val) {
data = new Object();
data.CommentID = val.CommentID;
data.Body = val.Body;
codate = new Date(parseInt(val.CreateDate.replace("/Date(", "").replace(")/", ""), 10));
var fdate = dateFormat(codate, "isoUtcDateTime");
ldate = $.timeago(fdate);
data.CreateDate = ldate;
data.CommentByAccountID = val.CommentByAccountID;
comments.push(data);
});
var boxid = "#commentBox_" + ObjID;
$(boxid).setTemplateURL("../Templates/comments.htm");
$(boxid).processTemplate(comments);
}
}
});
}
Please help me..
I found the solution... :)
First thing we could do is make our request async: false (BUT it'll impact our performance).. Instead, Im sending an ID (in my case SysID) and also bind it with my DIV id like the code below..
<div id ="comment_<%= SysID %>"></div>
In my jQuery function I use
var ID = "#comment_" + val.SysteID;
$(ID).setTemplateURL("../Templates/comments.htm");
$(ID).processTemplate(comments);
Hope it helps you guys too ... :)

Categories

Resources