How can I improve my Ajax? - javascript

I'm trying to figure out if what I'm doing is the right way. I have a comment form and when it gets clicked I'm appending the comment into a div element through Ajax. When the page is refreshed then of course that would disappear and instead of it I have a foreach loop that runs and echos the comments. Since they both have the same CSS attributes they look the same to the user. The reason I'm doing it this way is because the foreach loop gets updated only after a refresh. Is there a better way? Can I update the page directly from the database without refresh? I basically need that every time a user clicks on the comment button that the foreach loop will run again but I couldn't find how to do it. I feel like I'm covering a gun shot with bandage the way I do it at the moment.
Loop:
#foreach($comment as $comments)
#if($comments->image_id == $image->id)
<div id="{{$comments->id}}" class="col-md-5 ajaxrules">
<div class="deletecomment">
<i class="fa fa-trash-o"></i>
</div>
<div class="col-md-2">
<img src="{{$comments->user_avatar}}" class="img-circle buddy">
</div>
<div class="hello col-md-10">
<h4>{!! $image->user_name !!}</h4>
<p class="left">{!!$comments->body!!} </p>
</div>
</div>
#endif
#endforeach
//Where I append the comments through Ajax until the refresh that replaces it with the loop
<div class="man">
</div>
Ajax:
<script>
$(document).ready(function(){
$('.send-form').click(function(e){
e.preventDefault();
var username = "{{ $username }}";
var one = $('textarea[id="{{$image->id}}"]').val();
var value = "{{$image->id}}";
var begin = '<div class="col-md-5 addavatar">'+'<div class="deletecomment">'+'<i class="fa fa-trash-o">'+'</i>'+'</div>'+'<div class="col-md-2">'+'<img src="{{$profile}}" class="img-circle">'+'</div>'+'<div class="hello col-md-10">'+'<h4>' + username +'</h4>'+'<p>'+one+'</p>'+'</div>'+'</div>';
if(one.length > 0){
console.log(username);
$('textarea[id="{{$image->id}}"]').val('');
$.ajax({
url: 'comment',
type: "post",
beforeSend: function (xhr) {
var token = $('meta[name="csrf_token"]').attr('content');
if (token) {
return xhr.setRequestHeader('X-CSRF-TOKEN', token);
}
},
data: {'id': value, 'comment': one},
success:function(data){
$( ".man" ).append([begin]);
},error:function(){
console.log("error!!!!");
}
});
}
});
});
</script>

You are killing yourself.
Manipulate the DOM via javascript code like you do it's really hard work!
You are not suppose to write html inside javascript strings, there must be another way!
And there is... Welcome to AngularJS!
In angular you can write your html and assign a javascript controller to it, perform ajax request and after the ajax complete you can bind the returned data to the html automatically! That means the angular refresh your html and do all the work for you. Even perform loop of let's say, row in a table, etc...

Related

FLASK - AJAX GET data from database

I am making a "write anything here" webpage where users can write anything in a textbox then post it and it is visible to everyone. It worked fine till I found out that when any user writes and submits, all the others have to refresh the page so as to get the new data from database. So a solution to this was to call ajax continuously in some intervals. This would check if there are new entries in the table. If yes, then it would render it to the html without refreshing the whole page. Now I am pure ajax noob and after hours of research I am unable to find out how to do it.
Here is the html code
<div id="textArea">
<form action="http://127.0.0.1:3000" method="POST">
<br>
<textarea minlength="3" name="comment" placeholder="Enter Text Here.." required></textarea>
<input id="postButton" type="submit" name="" value="POST">
</form>
</div>
</div>
<div class="show">
{% for item in data %}
<div id="auto" class="disPost">{{item[0]}}</div>
{% endfor %}
</div>
Here the textarea is in a form and it submits the text to database via flask server.
Also, all the comments that users wrote are shown in "div.show"
Now the flask code is like this
#app.route('/', methods = ['POST', 'GET'])
def home():
if request.method == 'POST':
post = request.form["comment"]
myquery = "select p_id from posts order by p_id desc limit 1"
mycursor.execute(myquery)
new_p_id = mycursor.fetchone()[0] + 1
myquery = "select exists(select * from posts where p_des=%s)"
rec_tup = (post,)
mycursor.execute(myquery, rec_tup)
if mycursor.fetchone()[0]==0:
myquery = "insert into posts values(%s, %s)"
rec_tup = (new_p_id, post)
mycursor.execute(myquery, rec_tup)
mydb.commit()
mycursor.execute("select distinct p_des from posts order by p_id desc")
data = mycursor.fetchall()
return render_template("homepage.html", data=data)
"mydb" is the connector & "mycursor" is the connector's cursor
Now I am stuck somewhere in how to call AJAX function. I am not able to write beyond this ..
$(document).ready(function() {
setInterval(function() {
$.ajax({
url: '',
type: 'GET',
data: //something must be here,
success: function(data) {
//here "div" must be added to the "show" class - that is comment of other users
}
})
}, 3000);
});
I know that I have to do something like this but am literally not able to solve it.
I know this is not good question and I must look at tutorials first. But believe me I had it all. I am not able to solve this problem at all.
Thank you for seeing this :)
I did this on my latest project, you can try it too. But make sure to refresh only div element you want the data show, not all the page.
$(document).ready(function() {
function getData(){
$.ajax({
url: '',
type: 'GET',
data: //something must be here,
success: function(data) {
//here "div" must be added to the "show" class - that is comment of other users
}
});
}
getData();
setInterval(function() {getData()},2000);
});

How to receive AJAX (json) response in a divs with same class name individually?

I've been getting crazier day after day with this, I can't find an answer, I've spent like 100h+ with this... I hope someone could help me out!
UPDATE:
So to make myself more clear on this issue and be able to get help from others, I basically have 3 containers named "main-container" they all have 3 containers as childs all with the same class name, and when I submit the button, I trigger an ajax function to load the JSON strings comming from php into the child divs, the problem is that I get the 3 "main_containers" to load the ajax at the same time, I only want to load the ajax if I press the button of each "main_container" individually.
I've been using jquery and vanilla JS as well but seems I just can't get it done!
This is how I currently trigger the button with jquery:
$('.trigger_button_inside_divs').click(my_ajax_function);
And this is how my ajax looks like:
function my_ajax_function(){
$.ajax({
dataType: "JSON",
type: 'POST',
url: test.php,
success: function(data) {
$('.div_to_render_JSON_1').html(data.PHP_JSON_1_RECEIVED);
$('.div_to_render_JSON_2').html(data.PHP_JSON_2_RECEIVED);
$('.div_to_render_JSON_3').html(data.PHP_JSON_3_RECEIVED);
}
});
}
HTML looks like this:
<div class="main_container">
<div class="my_div">
//div_to_render_JSON_1
</div>
<div class="my_div">
//div_to_render_JSON_2
</div>
<div class="my_div">
//div_to_render_JSON_3
</div>
<button class="trigger_ajax_function_btn">Click to load ajax</button> //this btn loads ajax into the div class "my_div"
</div>
<div class="main_container">
<div class="my_div">
//div_to_render_JSON_1
</div>
<div class="my_div">
//div_to_render_JSON_2
</div>
<div class="my_div">
//div_to_render_JSON_3
</div>
<button class="trigger_ajax_function_btn">Click to load ajax</button> //this btn loads ajax into the div class "my_div"
</div>
<div class="main_container">
<div class="my_div">
//div_to_render_JSON_1
</div>
<div class="my_div">
//div_to_render_JSON_2
</div>
<div class="my_div">
//div_to_render_JSON_3
</div>
<button class="trigger_ajax_function_btn">Click to load ajax</button> //this btn loads ajax into the div class "my_div"
</div>
So in conclusion, each of those 6 "divs" has a button that triggers an function containing my ajax to render inside that particular div. But what I get is that every time I click that triggering button, I get the ajax to render in all of the 6 divs, instead of render on each particular div only when I click its particular button.
Thanks a lot people, I really hope to get this done!
Cheers.
PD:
This is something a programmer did to achieve what I'm trying to achieve but I just can't figure out what in this code is that is making possible clicking 1 button and affect THAT html element , even though they all have the same class.
(function(){
$("form input[type=submit]").click(function() {
$("input[type=submit]", $(this).parents("form")).removeAttr("clicked");
$(this).attr("clicked", "true");
});
var xhr = new XMLHttpRequest();
var el;
function SetDataInTheForm()
{
var resp = JSON.parse(xhr.response)
var pt=0
var ct=0
var gt=0
Array.prototype.forEach.call(el.querySelectorAll(".test"),function(e,i){
e.innerHTML=resp[i].name
})
Array.prototype.forEach.call(el.querySelectorAll(".p"),function(e,i){
e.innerHTML=parseFloat(resp[i].p).toFixed(0)
pt+=parseFloat(resp[i].p)
})
Array.prototype.forEach.call(el.querySelectorAll(".c"),function(e,i){
e.innerHTML=parseFloat(resp[i].c).toFixed(0)
ct+=parseFloat(resp[i].c)
})
Array.prototype.forEach.call(el.querySelectorAll(".g"),function(e,i){
e.innerHTML=parseFloat(resp[i].g).toFixed(0)
gt+=parseFloat(resp[i].g)
})
el.querySelector(".wtp").innerHTML=parseFloat(resp[0].total).toFixed(0)+" "+resp[0].unit
el.querySelector(".wtc").innerHTML=parseFloat(resp[1].total).toFixed(0)+" "+resp[1].unit
el.querySelector(".wtg").innerHTML=parseFloat(resp[2].total).toFixed(0)+" "+resp[2].unit
el.querySelector(".pt").innerHTML=pt.toFixed(0)
el.querySelector(".ct").innerHTML=ct.toFixed(0)
el.querySelector(".gt").innerHTML=gt.toFixed(0)
}
function HandleSubmit(e)
{
el=e.currentTarget
e.preventDefault();
xhr.open("POST","/url_here.php",true)
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded")
xhr.onload=SetDataInTheForm
var button=e.currentTarget.querySelector("input[type=submit][clicked=true]")
button.removeAttribute("clicked")
xhr.send($("#"+e.currentTarget.id).serialize()+"&"+button.getAttribute("name")+"=on")
}
[].forEach.call(document.querySelectorAll("._form_"),function(form){
form.addEventListener("submit",HandleSubmit,false);
})
})()
Remember that $('.div_container_to_render_JSON') is a new selector that selects all elements with a class div_container_to_render_JSON. What you want to happen is figuring out where that click came from, and find the corresponding div_container_to_render_JSON.
Luckily for you, a jQuery click handler sets the this keyword to the HTMLElement where the click was captured. You can use this to get the parent element.
$('.your-button').on('click', function () {
const myButton = $(this);
$.ajax({
// ...
success (data) {
myButton.parent().html(data.PHP_JSON_RECEIVED);
// or if you need to find a parent further up in the chain
// myButton.parents('.div_container_to_render_JSON').html(data.PHP_JSON_RECEIVED);
}
});
});
The problem is that your class selector is indeed selecting all your divs at the same time.
Solution, set identifiers for your divs as such:
<div class="my_div" id="my_div_1">
and then you can use those id's to fill in the data:
$('#my_div_1').html(data.PHP_JSON_1_RECEIVED);
and repeat for your 6 divs (notice the change from class selector '.' to identifier selector '#')
Thanks for the replies people. I finally figured it out after days of hard work, it was something really simple.. here's the answer:
$('.trigger_button_inside_divs').click(my_ajax_function);
var thisButton = $(this);
var thisDiv = thisButton.closest(".main_container");
function my_ajax_function(){
$.ajax({
dataType: "JSON",
type: 'POST',
url: test.php,
success: function(data) {
thisDiv.find('.div_to_render_JSON_1').html(data.PHP_JSON_1_RECEIVED);
thisDiv.find('.div_to_render_JSON_2').html(data.PHP_JSON_2_RECEIVED);
thisDiv.find('.div_to_render_JSON_3').html(data.PHP_JSON_3_RECEIVED);
}
});
}

How to sort data with javascript each()

I have html code with data from database. I need to update this data via AJAX, so users get the new currency rates without page refresh. Here's Laravel blade template:
#foreach ($currencies as $currency)
<div class="currency-{{ $currency->id }}">
<div class="cur-id">{{ $currency->id }}</div>
<div class="cur-name">{{ $currency->cur_name }}</div>
<div class="cur-sell">{{ $currency->cur_sell + 0 }}</div>
<div class="cur-buy">{{ $currency->cur_buy + 0 }}</div>
</div>
#endforeach
Once the page is loaded - it has actual data, but after 1 minute this data being refreshed, so i am firing an AJAX request every minute:
$.ajax({
type: 'GET',
url: '/ajax-currencies',
dataType: 'json',
success: function (data) {
$.each(data, function(index, element) {
$('.currency-+element.id+.cur-sell').text(element.cur_sell);
});
}
});
"/ajax-currencies" responses with json objects. How can i put each object with its values in to correct div - currency-1 (has own values), currency-2 (has own values) etc, so it looks like this:
<div class="currency-1">
<div class="cur-id">1</div>
<div class="cur-name">Bitcoin</div>
</div>
<div class="currency-2">
<div class="cur-id">2</div>
<div class="cur-name">Ethereum</div>
</div>
I don't know why you need any kind of sorting. If your divs have special classes, then you can find divs by these classes and insert data directly in these divs. You're already trying to do this, but incorrect. Your each callback should be:
function(index, element) {
$('.currency-' + element.id + ' .cur-sell').text(element.cur_sell);
// alternative version
//$('.currency-' + element.id).find('.cur-sell').text(element.cur_sell);
}
See, I moved element.id out of quoted string, as javascript cannot parse variables inside quoted strings.
I also added a space between classes in selector, because selector like .class1.class2 will try to find item with both classes applied, which you don't want.
Also, I added alternative selector using find() method. Just for example.
Now the selector should select correct div.

$('#notificationClick').click not working

so I'm trying to make this works here is the jquery+php.
When I try to trigle the click in jquery it doesnt even does the "alert()".
PHP(Updated):
$MSG_Notification_sql = mysqli_query($Connection, "SELECT * FROM notifications WHERE user_id='".$bzInfo['id']."'");
while ($MSG_Notification_row = mysqli_fetch_array($MSG_Notification_sql)){
$MSG_Notification_rows[] = $MSG_Notification_row;
}
foreach ($MSG_Notification_rows as $MSG_Notification_row){
$bzWhen = date('d-m-Y H:m:i', strtotime($MSG_Notification_row['when']));
echo '<form method="POST">
<div class="notificationClick notification-messages info">
<div class="user-profile">
<img src="assets/img/profiles/d.jpg" alt="" data-src="assets/img/profiles/d.jpg" data-src-retina="assets/img/profiles/d2x.jpg" width="35" height="35">
</div>
<div class="message-wrapper">
<div class="heading"> '.$MSG_Notification_row['title'].'</div>
<div class="description"> '.$MSG_Notification_row['description'].' </div>
<div class="date pull-left"> '.$bzWhen.'</div>
</div>
<input name="notificationID" value="'.$MSG_Notification_row['id'].'" style="display: none" />
<div class="clearfix"></div>
</div>
</form>';
}
Javascript(Updated):
$(document).ready(function(){
$('.notificationClick').click(function(event){
alert('Ok');
// get the form data
// there are many ways to get this data using jQuery (you can use the class or id also)
var formData = $('#notificationClick').serialize();
// process the form
$.ajax({
type : 'POST', // define the type of HTTP verb we want to use (POST for our form)
url : '../../class/notifications/msgs_del.php', // the url where we want to POST
data : formData, // our data object
dataType : 'json' // what type of data do we expect back from the server
})
// using the done promise callback
.done(function(data) {
// log data to the console so we can see
console.log(data);
window.location = '/?page=messages&sub=inbox&bx=preview&id='+ data.notificationID +'';
});
event.preventDefault();
});
});
Can anybody help me please? I'm trying to complete this but nothing :(
First as the others say, ids need to be singular. So use the class you already have. Now inside, you need to use the current form that you clicked on, not all the forms.
$('.notification-messages').click(function(event){ //<-- change to class
var formData = $(this).closest("form").serialize(); //change to this
...
If you are loading these dynamically, you need to use event delegation
$(document).on("click", '.notification-messages', function(event){
var formData = $(this).closest("form").serialize();
...
You can concatenate the timestamp to your id to make it unique (separated by an _ if you like) and change your selector for the click event to $('[id*="notificationClick_"]')
On the other hand, you might want to use a class instead, that's what it's there for:
$(".notification-messages")
You're using ID, you can only bind click to 1 id not multiple ids.
You should use the class to bind the .click function.

Only slideUp the deleted message

I'm using a PM system and added the delete-message feature. I've got a form which checks for the message_id and message_title. The form posts to delete_message.php page which contains the query to delete the message. This has been done via Javascript as I dont want the page to refresh.
I've got two functions for this:
function deleteMessage() {
$.ajax({
url: "message/delete_message.php",
type: "POST",
data: $("#delMsgForm").serialize(),
success: function(data,textStatus,jqXHR){ finishDeleteMessage(data,textStatus,jqXHR); }
});
}
function finishDeleteMessage( data , textStatus ,jqXHR ) {
$(".inboxMessage").slideUp('slow');
}
Currently when I click on the delete button (image of a trashcan) it deletes the message without reloading the page, as a finishing touch, it slidesUp the divclass (inboxMessage) the message is in. Since I tell it to slide up this class, it slides up every message. This is my piece of code containing the classes and the form:
<div class="inboxMessage">
<div class="inboxMessageImg NoNewMsg"></div>
<div class="inboxMessageHeader">
<a id="ajax" class="inboxMessageLink" onclick="showMessage('.$row['message_id'].')">'.$row['message_title'].'</a>
<p class="inboxMessageStatus Read">'.$inboxMessageStatus_Read.'</p>
</div>
<div class="inboxMessageDescription">'.$inboxMessageDescription.'</div>
<div class="inboxMessageActions">
<form id="delMsgForm" name="delMsgForm" action="message/delete_message.php" method="post">
<input type="hidden" id="msgTitle" value="'.$row['message_title'].'" name="message_title">
<input type="hidden" id="msgID" value="'.$row['message_id'].'" name="message_id">
</form>
<input type="submit" id="ajax" value="" name="deleteMessageButton" class="deleteMessageIcon" onclick="deleteMessage()">
</div>
</div>
What I want it to do is to slideUp only the message which has just been deleted by the user. I know this has to be done by telling javascript to only slideUp the deleted message which contains the message_id and/or message_title.
I've tried several things, but no love whatsoever. I'm also not that familiar with javascript/ajax. Any help would be highly appreciate.
Cheers :)
where do you call deleteMessage from? indirect the function call through another function which knows the parent of your "trash can", and can call slide up on that specific one.
function deleteMessage (element) {
//element will be clicked button
var container = $(element).closest("div.inboxMessage"),
//container div including the trashcan
$.ajax({
url: "message/delete_message.php",
type: "POST",
data: $("#delMsgForm").serialize(),
success: function(data,textStatus,jqXHR){
finishDeleteMessage(container);
}
});
});
and this will be your button
<input type="submit" id="ajax" value="" name="deleteMessageButton" class="deleteMessageIcon" onclick="deleteMessage(this)">
Apparently, you've got more divs with class inboxMessage. Since you're adding this code:
$(".inboxMessage").slideUp('slow');
.. all divs with that class will remove. If you want just one div to remove, give it a unique ID or data-attribute and hide it that way.
For example: add the message-id to the div..
<div class="inboxMessage" id="(message_id)">
..and use..
$(".inboxMessage#message_id").slideUp('slow');
.. to slide up the right div.
Edit:
Add your message ID to the div and to the function deleteMessage(), so it will be deleteMessage(message_id).
function deleteMessage(message_id) {
$.ajax({
url: "message/delete_message.php",
type: "POST",
data: $("#delMsgForm").serialize(),
success: function(){ finishDeleteMessage(message_id); }
});
}
function finishDeleteMessage(message_id) {
$(".inboxMessage#"+message_id).slideUp('slow');
}

Categories