How to hide content after click "more"? - javascript

My HTML Code is like this :
...
#foreach($hotel as $key=>$value)
...
<div class="iteration">
<input type='hidden' value='<?php echo $value['HCode'].'#'.$value['HName'].'#'.$value['CheckIn'].'#'.$value['CheckOut'] ?>' id='tes'>
...
...
{{ $value['HotelNo'] }}
{{ $value['HotelName'] }}
...
<button class="save">More</button>
<div class="loading"></div>
... </div>
#endforeach
...
My Javascript Code is like this :
$(function(){
$('.save').click(function () {
var $parent = $(this).closest('div.iteration');
var bla = $parent.find('.tes:first').val();
console.log(bla);
$parent.find('.loading').html('<img src="http://preloaderss.net/preloaders/287/Filling%20broken%20ring.gif"> loading...');
$.ajax({
type: "GET",
url: "hotel-detail",
success: function (response) {
var elem = $parent.find('.loading').empty(); //remove org content
for(var i=0; i<response.SearchAvailResponse.Hotel.length; i++){ //make sure to use var
elem.append("<p>" + response.SearchAvailResponse.Hotel[i].HotelNo + "</p>"); //add the new content
}
}
});
});
});
When click the "more" button, the system displays the content with the loading process. I want when click the "more" button again, the system hide the content. So when click "more" button, the system displays the contents of the loading process. When click "more" button again, the system hide the content. And so on
How hidden the content after click "more" button?
Any solution to solve my problem?
Thank you very much

You need somehow to remember the state of loading and that the content is shown. For instance you can add some class to the parent element $parent.addClass("is_loading") and then check if ($parent.hasClass("is_loading")) {...} else {...} or use data of element $parent.data("loading", true) and check if ($parent.data("loading")) {...} else {...}. One branch show content and make ajax request, another hide the content. And for example success callback later reset the state $parent.data("loading", false) or $parent.removeClass("is_loading").

Related

$(this).attr("data-id") returning undefined

I'm building a webshop and on every item there is a button to add that item to the shopping cart.
<?php
$i = 0;
$path = "../images/women/winter/winter1";
$lang = "description_".get_param();
if(!$result = $db->query("SELECT * FROM cloths;")){
die("There was an error running the query [".$db->error."]");
}
while($winter = $result->fetch_assoc()){
echo "<div class = \"boxsale $winter[image]\">
<img src = \"$path.jpg\"/>
<div class = \"test\"> $winter[$lang] </div>
<select>
<option>S</option>
<option>M</option>
<option>L</option>
<option>XL</option>
<option>XXL</option>
</select>
<button class = \"addToCart\" onclick = \"executeJS()\"> <i class = \"fa fa-shopping-cart\" data-id = \"$i\" aria-hidden=\"true\"></i></button>
</div>";
$i++;
}?>
</div>
when you click on the button the executeJS() in the last few lines gets called from a seperate file.
addToCart.js
function executeJS(){
var id = $(this).attr("data-id");
$.ajax( {
type: "GET",
url: "ajax.php?id=" + id + "&action=add"
})
.done(function(){
alert("Product has been added.");
});
}
i wanted to grab the data-id from the button that has been clicked, with
$(this).attr("data-id"); but all i get is a header that has undefined as data-id.
id=undefined&action=add
can anyone please point me in the right direction?
thanks
The problem is because $(this) is not correctly being applied to the element you're trying to access. When using a string based onclick handler (onclick="test()"), this refers to the window, and NOT the element you're trying to access.
function test() {
console.log(this.id);
}
Link
If you want to use the string based onclick notation, pass your element in explicitly, and do $(element).
<button class = \"addToCart\" onclick = \"executeJS(this)\" data-id = \"$i\" />
Javascript:
function executeJS(element){
var id = $(element).data('id');
...
Personally, skip the attr-id all together, and simply pass your id directly:
<button class = \"addToCart\" onclick = \"executeJS($id)\" />
It looks like this may be pointing to the window instead of the button.
You can fix this by manually looking for the button:
var id = $(".addToCart").attr("data-id");
This will only really work if you only have one button. What you should do is use jquery to attach the event to the button.
In your javascript:
$(".addToCart").click(function(e){
var id = $(e.target).attr("data-id");
$.ajax({
type: "GET",
url: "ajax.php?id=" + id + "&action=add"
})
.done(function(){
alert("Product has been added.");
});
})
The e.target refers to the button that is being clicked.
Use regular function (function(){}) instead of arrow function:
$(document).on("click",".deleteBtn",function(){
//Your Code
});
Since you're using jQuery, this is how you should be doing it. First, remove the inline event handler in your PHP (e.g. onclick = \"executeJS()\")
The other issue is that your buttons don't have a data attribute but their <i> children do.
Next, create your jQuery event handler, binding to the button. By doing this you can use $(this).find('i') to get the fontawesone <i> element and its data attribute, .attr("data-id"):
$('button.addToCart').click(function() {
var id = $(this).find('i').attr("data-id");
$.ajax({
type: "GET",
url: "ajax.php?id=" + id + "&action=add"
})
.done(function() {
alert("Product has been added.");
});
})
jsFiddle example

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);
}
});
}

Updating Like Button Without Page Refresh

I'm working on a Like button. It's working fine. After Like button completes it's functionality I'm trying to update the button text (Like to Liked) without refreshing the page, but problem is that It's updating the every single Like button on the webpage (until I refresh the page) not just the one I clicked on . . .
Here's that success function in AJAX call,
$('.like-click').click(function(e){
e.preventDefault();
var this_ = $(this);
var quesURL = this_.attr('like-href');
$.ajax({
url: quesURL,
method: 'GET',
data: {},
success: function (data) {
var like_text = $(data).find('.like-click').html();
$('.like-click').html(like_text);
}
})
});
Here's the HTML code,
{% for data in datas %}
...
<a class="like-click" like-href="...">{% if user in Likes %}Liked{% else %}Like{% endif %}</a>
...
{% endfor %}
How can I update the button I clicked, not all of them ?
You have saved your clicked element in var this_, so you have to just update that element text only via replacing $('.like-click').html(like_text); to $(this_).html(like_text);
So it will not update each button text.
that's happened because you firing all button with having 'like-click' class
$('.like-click').click(function(e){
e.preventDefault();
var this_ = $(this);
var quesURL = this_.attr('like-href');
$.ajax({
url: quesURL,
method: 'GET',
data: {},
success: function (data) {
if(this_.html()=='like'){
this_.html('liked');
}else{
this_.html('like');
}
}
})
});
Why you use AJAX for this? You are not pulling "Like" or "Liked" from database. Do it with simple handler:
$(function(){
$('button').click(
function(){
$(".button div").toggle();
}
)
});
<button type="button" class="button like-click">
<div>Like</div>
<div style="display: none">Liked</div>
</button>
And note, that selecting button / a element by class="like-click" is probably not what you need (it would affect all elements by that class), so better asing them ids that are unique and comes from your {% for data in datas %} loop
UPDATE:
Because you dont have a dislike, it could be done in same manner as in my above example:
<button type="button" class="button" id="btn">
<div class="like">Like</div>
<div style="display: none" class="like">Liked</div>
<div class="count" id="current"> 1 </div>
<div style="display: none" class="count" id="clicked"> </div>
</button>
$('#btn').click(function() {
$('#btn #clicked').html(parseInt($('#current').text()) + 1);
$('#btn .like').toggle();
$('#btn .count').toggle();
})

Update dynamically generated list item (generated using PHP) after ajax call

The following HTML code is being echoed using a while loop in PHP which is adding a list item after fetching data from database.
PHP:
echo '
<li>
<div class="collapsible-header">
<div class = "left">
<div class = "issueStatusIcon" style = "background-color:'.$smallCircleColor.';">'.$smallMsg.'</div>
<span class = "issueTitle" style = "font-family: robotoBold">'.$issueTitle.'</span>
</div>
<div class = "issueButtonsGroup">
<form id = "archiveIssueForm'.$i.'" issue-name = "'.$issueTitle.'" action = "archiveIssue.php">
<input type = "hidden" value = "'.$issueID.'" name = "issueID"/>
</form>
<a class = "right archiveIconButton" onclick = "ajaxIssueArchive('.$i.')" href = "#">
<i class="material-icons black-text issueOptions archiveIcon">archive</i>
</a>
<a class = "right"><i class="material-icons black-text issueOptions">edit</i></a>
</div>
</div>
</li>
';
This is the preview image of the generated list:
Notice the cursor over the archive button which archives the list item. The class for that button is archiveIconButton (you can find it in the above code). When the button is clicked, archiveIssueForm is submitted via AJAX (each form has a unique identifier variable $i appended to its id).
Following is the JQuery AJAX code:
JQuery:
<script>
function ajaxIssueArchive($num){
$.ajax({
type: "post",
url: "archiveIssue.php",
data: $('#archiveIssueForm' + $num).serialize(),
success: function(data){
$fetchIssueName = $('#archiveIssueForm' + $num).attr("issue-name");
$toastText = $fetchIssueName + " has been archived";
Materialize.toast($toastText, 3000);
$('#archiveIssueForm' + $num).html(data);
}
});
}
</script>
After archiving any list item, it gets deleted from the database. I want to update the ul element which contains these list items so that the list item which gets deleted doesn't gets displayed after the AJAX form submission.
Assume the id of ul to be issueListUL.
What i'm currently getting is the whole code of the html page displayed in the li item. I am certainly doing something wrong, any help would be appreciated!
After archiving a list item:
I was able to solve this issue in the following way, The JQuery script in the question should be changed like this:
JQuery:
<script>
function ajaxIssueArchive($num){
$.ajax({
type: "post",
url: "archiveIssue.php",
data: $('#archiveIssueForm' + $num).serialize(),
success: function(data){
//assigning the updated ul's html to a variable
$afterIssueArchival = $(data).find("#issueListContainer").html();
//toast
$fetchIssueName = $('#archiveIssueForm' + $num).attr("issue-name");
$toastText = $fetchIssueName + " has been archived";
Materialize.toast($toastText, 3000);
//updation of ul's html, ID of the ul which contains all the list items is assumed to be 'listContainer'
$("#issueListContainer").html($afterIssueArchival);
}
});
}
</script>
When updating an element's html, just extract the element's updated html code from data attribute in the ajax code (as show in the above code) and update the existing element's html with it!
Hope this helps people with the same problem as mine! :D

How can I make dynamic Ajax requests with Laravel

I'm creating a social network site using Laravel. I have a page that load all the posts created by users the currentUser follows. I have a comment section on each post. I want a user to be able to comment on any post without the page reloading so the user doesn't have to re-scroll through the page.
I have everything working fine without ajax (minus the reloading page). I'm able to post comments, the page reloads and the new comment is displayed. However, when I try to use Ajax I've been running into problems.
Here is my code.
Here is the view of the comment-box. It contains a section where I loop through each comment and display them. At the end is the type field so a user can post a new comment:
<div class="comment-box-container ajax-refresh">
<div class="comment-box">
#if ($type->comments)
#foreach ($type->comments as $comment)
<div class="user-comment-box">
<div class="user-comment">
<p class="comment">
<!-- starts off with users name in blue followed by their comment-->
<span class="tag-user">{{ $comment->owner->first_name }} {{ $comment->owner->last_name }} </span>{{ $comment->body }}
</p>
<!-- Show when the user posted comments-->
<div class="com-details">
<div class="com-time-container">
{{ $comment->created_at->diffForHumans() }} ยท
</div>
</div>
</div><!--user-comment end-->
</div><!--user-comment-box end-->
#endforeach
#endif
<!--type box-->
<div class="type-comment">
<div class="type-box">
{{ Form::open(['data-remote', 'route' => ['commentPost', $id], 'class' => 'comments_create-form']) }}
{{ Form::hidden('user_id', $currentUser->id) }}
{{ Form::hidden($idType, $id) }}
{{--{{ Form::hidden('user_id', $currentUser->id) }}--}}
{{ Form::textarea('body', null, ['class' =>'type-box d-light-solid-bg', 'placeholder' => 'Write a comment...', 'rows' => '1']) }}
{{ Form::close() }}
</div><!--type-box end-->
</div><!--type-comment-->
</div><!--comment-box end-->
The user submit the form for the comment type box by pressing the "enter/return" key. Here is the JS for that
<script>
$('.comments_create-form').on('keydown', function(e) {
if (e.keyCode == 13) {
e.preventDefault();
$(this).submit();
}
});
</script>
Here is my Ajax
(function(){
$('form[data-remote]').on('submit', function(e){
var form = $(this);
var method = form.find('input[name="_method"]').val() || 'POST';
var url = form.prop('action');
$.ajax({
type: method,
url: url,
data: form.serialize(),
success: function(data) {
var tmp = $('<div>');
tmp.html(data);
$('.ajax-refresh').html(tmp.find('.ajax-refresh').html());
$('.type-box').html(tmp.find('.type-box').html());
tmp.destroy();
}
});
e.preventDefault();
});
})();
I'm running into a few problems with this code. The comment gets displayed on ever single post until I manually refresh the page then it only shows on the correct post. I feel like every post's comment-box will need it's own unique ID to solve this, but I do not know how to do this with Laravel and make the JavaScript work.
also,
After I submit one comment I can no longer submit a second one because my "submit on enter/return key" functionally is no longer working. My cursor just moves to a new line, and I'm not able to post another comment.
Does anyone know a way to fix these problems?
EDIT
Here is my ajax so far
(function(){
$(document).on('submit', 'form[data-remote]', function(e){
e.preventDefault();
var form = $(this)
var target = form.closest('div.ajax-refresh');
var method = form.find('input[name="_method"]').val() || 'POST';
var url = form.prop('action');
$.ajax({
type: method,
url: url,
data: form.serialize(),
success: function(data) {
var tmp = $('<div>');
tmp.html(data);
target.html( tmp.find('.ajax-refresh').html() );
target.find('.type-box').html( tmp.find('.type-box').html() );
tmp.destroy();
}
});
});
})();
Please use the following to fix the issue:
$(document).on('submit', 'form[data-remote]', function(e){
e.preventDefault();
var form = $(this),
var target = form.closest('div.ajax-refresh');
var method = form.find('in......
......
.....
tmp.html(data);
target.html( tmp.find('.ajax-refresh').html() );
target.find('.type-box').html( tmp.find('.type-box').html() );
tmp.destroy();
}
});
});
The variable target will help you target just the right div to add the ajax response to.
Further, you would have to just reset the relevant form rather than replace the form markup. Otherwise each form will work only once.
UPDATE
The above code has been updated to use a delegated submit event -- $(document).on('submit', '.selector', ...) instead of $('.selector').on('submit', .....) since the form content is being replaced after each comment.
UPDATE 2
The following delegated keydown event should enable you to submit by pressing the enter key:
$(document).on('keydown', '.comments_create-form', function(e) {
if (e.keyCode == 13) {
e.preventDefault();
$(this).submit();
}
});

Categories