How to set time between reports of users? - javascript

Is it possible to add a timer between reports of a user?I want to add 5 minutes between the reports of a user, or to make disable the button for reports for 5 minutes, even if the user refresh the page.It is possible?
Here is my button for report
<li class="share-link" style="float: right;left: 20px"><a data-toggle="modal" data-target="#exampleModal" href="javascript:void(0)" ><i class="rounded-x icon-flag"></i></a></li>
and after that I have a modal which send the report.
Here is the controller
public function careerReportCareerSolution(requ $request)
{
$reportExists = \App\Reports::where('user_id', $request['user_id'])
->whereDate('created_at', '>', Carbon::now()->subMinutes(5)->toDateTimeString())
->exists();
if($reportExists) {
// report has been created within 5 minutes
return Redirect::back()->withErrors(['error', 'Report created within the last 5 minutes']);
}
$report = \App\Reports::create([
'user_id' => $request['user_id'],
'username' => $request['username'],
'user_id_posted' => $request['user_id_posted'],
'username_posted' => $request['username_posted'],
'career_solution_id' =>$request['career_solution_id'],
'subject' =>$request['subject'],
'why_reporting' =>$request['why_reporting'],
'why_reporting_message' =>$request['why_reporting_message'],
'additional_message' =>$request['additional_message'],
'comment' =>$request['comment'],
'comment_user' =>$request['comment_user'],
'comment_id' =>$request['comment_id'],
]);
$id = $request['career_solution_id']; // looks like this is the ID you ar looking for
$career = CareerSolution::findOrfail($id);
$career->active = $request['active'];
$career->save();
if($report != ""){
flash('Career solution report submited', 'success');
}else{
flash('Career solution report', 'warning');
}
return Redirect::back();
}
}
So, I to set a time between reports, 3-5 minutes a user shouldn't be able to make a report.

Untested, however assuming you are using timestamps (created_at, updated_at) on the Report table, you should be able to achieve this with the following logic:
$reportExists = \App\Report::where('user_id', $request['user_id'])
->whereDate('created_at', '>', now()->subMinutes(5)->toDateTimeString())
->exists();
if ($reportExists) {
// report has been created within 5 minutes
return Redirect::back()->withErrors(['error', 'Report created within the last 5 minutes');
}
...
This will check whether or not a report has been created for that user within the last 5 minutes using the ->whereDate() eloquent query method.
The ->exists() method is used to find out if there is at least one occurance of the report.
A check is made to see if $reportExists is true. If so, the application will redirect the user to the same page with an error message (fill the ->withErrors() method with the appropriate message).
This should be placed before all other controller logic.

Related

Symfony Forms - dynamically add/remove fields depending on choices

I'm trying to create a form that maps to an entity of the type "Participant". A participant is in a one-to-one relationship with a 'person'. Adding a participant, I want to first give the option to choose a person already in the database and if the right one doesn't exist, create that person with the participant form.
This works if I do it with two pages/forms. The first one trying to choose an existing person, otherwise open a new page with the different form.
First page:
$form->add('person', AjaxEntityType, [ // EntityType but with select2 ajax
'class' => Person::class,
'remote_route' => 'person_ajax_list'
]);
Second page:
$participant->setPerson(new Person());
$form->add('person', PersonType::class);
// adds PersonType fields to the Participant form
Well, that works, but it's terribly slow and unecessary. What I'd rather want is having BOTH of those shown, where the PersonType form fields (first name, last name, title, company, address, etc.) are automatically populated with the persons data, if one is selected. Otherwise, if no Person is selected and the form is submitted with data entered, a new Person should be created and persisted in the database.
It's sadly not possible to render the 'person' twice, once as a dropdown and once as a PersonType form. So how would I go about achieving what I want, without surreal amounts of JavaScript?
My current solution would be to manually create all the required fields with JavaScript and populate them with the person data I'd get with another Ajax request on a onchange event on the person dropdown, then in the PRE_SUBMIT event of the form, remove the 'person' field and add it again as a PersonType field, check if the entered data corresponds to an existing person or a new one and then act accordingly. There has to be a better solution, right?
Form events have sadly otherwise proven majorly pointless, as it's not possible to attach an event listener to a 'change' event on one of the fields.
Thanks.
Ended up solving it with an unmapped person choice field and javascript to automatically update the data (using ajax).
participant/add.twig:
{% block javascripts %}
<script type="text/javascript">
$(document).ready(function () {
function onTrainerChange() {
let trainerId = $('#participant_person_choose').val();
$.get(Routing.generate('person_data_ajax', { id: trainerId }), function (data) {
$('#participant_person_gender').val(data.gender);
$('#participant_person_title').val(data.title);
$('#participant_person_firstName').val(data.firstName);
$('#participant_person_lastName').val(data.lastName);
$('#participant_person_email').val(data.email);
$('#participant_person_telephone').val(data.telephone);
if (data.company) {
let company = $('#participant_person_company');
company.empty();
company.append(new Option(data.company.text, data.company.id));
company.val(data.company.id);
company.trigger('change');
// manipulate dom directly because of .select('data') bug with select2 >=4.0
}
});
};
let trainer = $('#participant_person_choose');
trainer.change(onTrainerChange);
});
</script>
{% endblock %}
ParticipantController add:
$participant = new Participant($seminar);
$person = $participant->getPerson() ?? new Person();
$participant->setPerson($person);
$form = $this->createParticipantForm($participant)
->add('person_choose', AjaxEntityType::class, [
'mapped' => false,
'class' => Person::class,
'remote_route' => 'person_select_ajax',
'placeholder' => 'form.personCreate',
'label' => 'form.person'
])
->add('person', PersonType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if ($form->get('reservation')->getData()) {
$participant->setInterested();
}
$personEntered = $form->get('person')->getData();
$personChosen = $form->get('person_choose')->getData();
if ($personChosen) {
$person = $personChosen;
$person->setGender($personEntered->getGender());
$person->setTitle($personEntered->getTitle());
$person->setFirstName($personEntered->getFirstName());
$person->setFirstName($personEntered->getLastName());
$person->setCompany($personEntered->getCompany());
$person->setEmail($personEntered->getEmail());
$person->setTelephone($personEntered->getTelephone());
$participant->setPerson($person);
}
$this->getDoctrine()->getManager()->persist($person);
$this->getDoctrine()->getManager()->persist($participant);
}
PersonController Ajax:
/**
* #Route("/{id}/data", name="person_data_ajax", methods={"GET"}, options={"expose": true})
*/
public function dataAjax(Person $person, PhoneNumberHelper $phonenumberHelper)
{
$arr = [
'id' => $person->id,
'gender' => $person->getGender(),
'title' => $person->getTitle(),
'firstName' => $person->getFirstName(),
'lastName' => $person->getLastName(),
'email' => $person->getEMail(),
'telephone' => $person->getTelephone() ? $phonenumberHelper->format($person->getTelephone(), PhoneNumberFormat::NATIONAL) : null,
'company' => $person->getCompany() ? [
'id' => $person->getCompany()->id,
'text' => $person->getCompany()->__toString()
] : null
];
return new JsonResponse($arr);
}
Hope this can help someone else. Really disappointed with how limited Symfonys Forms are.

Taking just a few elements in a JSON object

I'm using Laravel 5.5.* and jQuery (jquery-3.3.1.min.js).
I commercially develop mostly (like 95% of the time) in PHP, so using jQuery is really different for me, so I need help.
I am developing a blog's landing page and I must show just 3 posts in it. In it's bottom, I have a button <a> that is supposed to load 3 more posts and show it to the user. Everytime the user hits this button, 3 more posts must load in the page.
I have the following codes so far.
Posts controller
public function index() {
// this loads the landing page with 3 initial posts
// Working like a charm
$posts = Posts::with('categories', 'user', 'media')
->where('status', 1)
->orderBy('published', 'desc')
->limit(3)
->get();
$rank = self::blogPanel();
return view('portal.pages.blog',
compact(
'rank',
'posts'
)
);
}
I call this action from the route
Route::get('/', 'User\PostsController#index')->name('landingPage');
For the logic in which I load more posts, I have the following:
Posts Controller
public function loadMore() {
$posts = Post::with('categories', 'user', 'media')
->where('status', 1)
->orderBy('publicacao', 'desc')
// ->limit(3) I took this out because I was trying to set the limit in front-end
->get();
return json_decode($posts);
}
Which returns the following:
array:48 [▼
0 => {#257 ▼
+"id": 48
+"title": "Lorem ipsum"
+"summary": "Perferendis labore veritatis voluptas et vero libero fuga qui sapiente maiores animi laborum similique sunt magni voluptate et."
+"content": """
Really long text here, with line-breaks and all
"""
+"seo_id": null
+"url": "Sunt rerum nisi non dolores."
+"link_title": "dolor"
+"published": "2018-03-01 10:35:12"
+"scheduled": "2018-03-01 10:25:12"
+"user_id": 1
+"media_id": null
+"status": 1
+"created_at": "2018-03-01 10:25:12"
+"updated_at": "2018-03-01 10:25:12"
+"category_id": 3
+"slug": "cum-aut-officia-consequatur-dolor"
+"categories": []
+"user": {#313 ▼
+"id": 1
+"name": "Jonessy"
+"email": "jonessy#email.com"
+"status": 1
+"grupo_id": 1
+"created_at": null
+"updated_at": null
}
+"media": null
}
1 => {#341 ▶}
2 => {#254 ▶}
]
Please, note I'm using json_decode() because it looks easier to work with in front-end.
This is my blade file, where I should print my results
blogPost.blade.php
#foreach($posts as $post)
#php
$date = date_create($post->published);
#endphp
<div class="blog-post" id="blog-post">
<div class="blog-post__title" >
<h3 id="artTitle">
{{ $post->title }}
</h3>
#foreach($post->categories as $cat)
<span class="blog-post__category"> {{ $cat->name }} </span>
#endforeach
<span class="blog-post__date" id="artDate">
{{ date_format($date,"d/m/y - H") }}H
</span>
</div>
<div class="blog-post__image" id="artImage">
#if(isset($post->media_id))
<img src="{{ asset('img/post-img/' . $post->media->file) }}">
#else
<img src="{{asset('img/post-img/default-img-post.jpg')}}">
#endif
</div>
<div class="blog-post__resume">
<p id="artSumma">
{{ $post->summary }}
</p>
</div>
<div class="blog-post__link">
<a href="{{ route('blogPost', $post->slug) }}">
Read More
</a>
</div>
<div class="blog-post__social">
// Some social media links for sharing
</div>
</div>
#endforeach
I am calling the loadMore() method from PostsController using a GET route:
Route::get('/', 'User\PostsController#loadMore')->name('loadMore');
For jQuery, here is the code I got so far:
<script type="text/javascript">
// after importing jquery file...
$(document).on('click', '#loadingPosts', function(e) {
e.preventDefault();
var listing = {!! $posts !!};
console.log("list ", listing);
var lastId = listing[2].id;
console.log("id from pos 2, listing ", lastId);
var parts = $(listing).slice(lastId);
console.log("part ", parts);
// THIS DOESN'T WORK, BY THE WAY
// var lastId = listing[2].id;
// console.log("listing 2 id", lastId);
$('#loadingPosts').html("Loading More Posts");
$.ajax({
url: '{{ route('loadMore') }}',
method: 'GET',
// data: {
// 'id': lastId,
// I was trying to set up an ID here, but it didn't work as well
// },
// contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
// console.log("checking if data not null", data);
// this returns the expected $posts array
$('#blog-post').html(data);
// using .html() because .append() didn't work, which is weird, I guess
console.log("data depois do apend", data);
// This returns the same $posts array
lastId = data[2].id;
console.log("last id from data", lastId);
// I can retrieve the id from the given position from the array.
// I was trying to set up the id here so I could check, with jQuery, the last post iterated, so I could continue from that point forward
$('#loadingPosts').html("load More");
return data[2].id;
// A last minute despair
}
});
});
</script>
Well, it doesn't work (that's the reason I'm here). I really don't know what I am doing wrong, since the $posts array is passing...
I need help with this, please.
A few things worth saying:
Laravel comes with a default pagination, but it works "horizontally", and the projects asks for a "vertical" pagination.
The page must have a "load more" button because the footer has some much needed info, so the content can not load automatically
IF there is a way to make it work using vanilla JavaScript OR using Laravel's PHP methods (EXCEPT FOR THE PAGINATION METHOD, AS STATED BEFORE), I would be really happy
Thank you all in advance.
public function loadMore(Request $request) {
$posts = Post::with('categories', 'user', 'media')
->where('status', 1)
->orderBy('publicacao', 'desc')
->limit($request->input('limit'))
->skip($request->input('skip'))
->get();
return json_decode($posts);
}
But you can just use the next page from pagination()
So, after a little while I came up with a fix for my needs.
Turns out I didn't need to json_encode() or json_decode() anything.
First of all, I'll use a pseudo mark-up for everything inside blades. It'll be easy to understand, since what I am using is HTML. For jQuery, someone involved with the project came up with a pseudo-jQuery-like functions that emulate its syntax. It is a straight forward syntax, easy to understand, nothing out of the ordinary.
Then, here it is.
PostsController
public function loadMore(Request $request) {
$limit = $request->input('limit');
$skip = $request->input('skip');
// as #Dry7 suggested, I am taking a dynamic skip
$posts = Post::with('categories', 'user', 'media')
->where('status', 1)
->orderBy('published', 'desc')
->limit($limit)
->skip($skip)
->get();
return view(
'portal.pages.blogPost',
compact(
'posts'
)
)->render(); // here is the difference
}
So, what I did is pre-render the view where the posts will be printed WITHOUT loading a new page.
Before we continue, here is the structure of the blog.(Using pseudo-markup, as stated before)
main page
#extends('layouts.layout')
div class=container
div class=blog
h1
Page title
/h1
div class=blog-body
#include('portal.pages.blogPost')
a id=loadMorePosts class=none
Load More
/a
/div
div class=sidebar
#include('portal.components.panel')
/div
/div
/div
Then in my pages.blogPost I have the same code I posted in my question (The code is the one with the foreach loop).
After this, I came up with this pseudo-jQuery-like code.
// I'll start listening to any 'click' in the element I am passing the event
// then I'll increment the number of clicks in the element
var click = 0;
// this is the first skip number
var startCounting = 6;
// start a click event in the <a #loadMorePosts> element
$.event('#loadMorePosts','click',function () {
// increment the number of clicks
click++;
// set my skip that will be sent to server and
// applied in my PostsController
skip = startCounting * click;
// open an ajax request passing the route I set up
// that calls PostsController#loadMore method
HttpRequest.get('{{ route('loadPosts') }}?limit=6&skip=' + skip,function (res) {
// I am concatenating my skip var here, so It'll be sent to server
// checking if I have an empty data
if(res.data != "") {
// not empty, so I'll append it to my div with blog class
// first finding the element, searching for its class
// then passing the data to be appended
$.append('.blog',res.data);
} else {
// the data is empty, so first I'll search for
// the element with class=none
// clean up any innerHtml it has
// then set up a new innerHtml in it
$.replaceAll('.none',"No More Posts");
// to finish it all up, I style the same element with some suggesting colors and actions
$.css('.none', 'pointer-events: none; background-color: lightgrey;');
}
});
});
And its done. The posts are appended, the skip is working, so I don't take repeated posts, it works until all of my posts are loaded and when there are no more posts to show, the button is disabled, stopping any new request to be sent to server.
I hope that with these comments the process made to implement this functionality is clear and you can apply the same steps with whatever framework or library you are using.
Thank you all for reading and for taking time to answer my question.

Populate data from groovy controller in pop up

I have a gsp page with a delete button for each row of a table. On the button click I want a pop up which tells the consequences of the delete. These consequences depends on the data present in the row and a few other constraints known to the grails service which is called from the grails controller associated to the gsp page. If the user confirms these consequences the row should be deleted from the table, else the table remains unchanged.
How should i go about to achieve this behavior?
Currently, I have in my gsp
<tr>
<td>name</td>
<td>parentName</td>
<td>data</td>
<td>
<g:link action="deleteRow" params="${[name: row.name, parentName: row.parentName]}">
<button class="deleteSnapshot">Delete</button>
</g:link>
</td>
</tr>
and in my .js file
$(document).on('click', ':button', function (e) {
var btn = $(e.target);
btn.attr("disabled", "disabled"); // disable button
alert('getting deletion details');
//var deletionDetails -->not sure how to get these
//var deletionDetails will get data from controller action:"getDetails"
if (confirm('/*print deletion details and ask*/ Do you want to proceed?')) {
alert('will delete')
return true
}
else {
btn.removeAttr("disabled"); // enable button
return false
}
});
and in my controller
class DeleteController{
DeleteService deleteService
def index() {
[list:deleteService.getTableList()]
}
def getDeletionDetails(string name, String parentName){
return deleteService.getDetails(name,parentName)
}
def deleteRow(String name, String parentName){
service.deleteRow(name, parentName)
redirect controller:"DeleteController", action:"index"
}
}
I know the deletion works fine, because it works even with in the current state. Just that the confirmation box asks Do you want to proceed, without displaying the details.
Any help on how i could achieve what I am looking for will be appreciated.
P.S. I am new to stackoverflow, so if i missed out on certain convention do let me know.
Thanks in advance.
I can think of two ways of doing it:
The first one is using ajax to both get deletion details and delete the row
Assuming that deleteService.getDetails(name, parentName) returns a String,
first you need to change an getDeletionDetails action so it renders the response:
def getDeletionDetails(String name, String parentName){
render deleteService.getDetails(name, parentName)
}
and change g:link-s to buttons in gsp:
<button data-name="${row.name}" data-parent-name="${row.parentName}">
Delete
</button>
In your .js then put:
$(document).on('click', ':button', function (e) {
var btn = $(e.target);
btn.attr("disabled", "disabled"); // disable button
var name = btn.data('name');
var parentName = btn.data('parentName');
$.ajax({
url: "/delete/getDeletionDetails",
data: {
name: name,
parentName: parentName
},
success: function (data) {
if (confirm(data + '\nDo you want to proceed?')) {
$.ajax({
url: '/delete/deleteRow',
data: {
name: name,
parentName: parentName
},
success: function (d) {
console.log("Success: " + d);
}
});
} else {
btn.removeAttr("disabled"); // enable button
}
}
});
});
What this code does is it sends an ajax call to /delete/getDeletionDetails, then uses its response (rendered by getDeletionDetails action in DeleteController) to show a confirmation alert. If user confirms the question, another ajax call is sent - now to deleteRow action of DeleteController - with parameters taken from data attributes of clicked button. If user cancels - nothing happens, except for reenabling a button.
Your deleteRow should only change the return statement - it also must render the response:
def deleteRow(String name, String parentName){
service.deleteRow(name, parentName)
render "You deleted an item $name - $parentName."
}
You don't need redirect here, because - thanks to using ajax - user will never leave delete/index. You can just display some kind of confirmation on page after successful ajax call.
The second option is to put deletion details in hidden fields or data- attributes in each row and then just retrieve them in js:
You can create a method getDeletionDetails() in row's domain class (presumably Row) that returns the details (using services in domain classes is not perfect, but is should work ok if the service is not very complex). Then, in your .gsp place:
<td>
<g:link action="deleteRow" params="${[name: row.name, parentName: row.parentName]}">
<button class="deleteSnapshot" data-details="${row.deletionDetails}">Delete</button>
</g:link>
</td>
You should then be able to get details in .js like this:
var deletionDetails = btn.data('details');

AngularJS Voting System - Preventing Multi-Votes

I'm trying to create a voting system using AngularJS with the Ionic Framework. I'm using ng-repeat to loop over a series of user posts from a JSON array. Each post has an upvote and a downvote button. After one is selected, I have the button on that post disabled. The problem I'm currently experiencing is keeping that button disabled regardless if the user reopens the app. My goal is to prevent multi-voting. Currently, I'm using this method to disable the button after it's been clicked:
<button class="button button-small button-light" ng-click="upThread({{thread.id}})" ng-disabled="upDisabled[thread.id]">
<i class="icon ion-thumbsup"></i>
</button>
<button class="button button-small button-light" ng-click="downThread({{thread.id}})" ng-disabled="downDisabled[thread.id]">
<i class="icon ion-thumbsdown"></i>
</button>
$scope.upDisabled = {};
$scope.downDisabled = {};
$scope.upThread = function(id) {
...
$scope.upDisabled[id] = true;
$scope.downDisabled[id] = false;
}
$scope.downThread = function(id) {
...
$scope.downDisabled[id] = true;
$scope.upDisabled[id] = false;
}`
And this works great for disabling the buttons. Now, the problem is, I require Cache for the controller to be false, otherwise my new posts do not update in the view when added. This means, when reloading the app or switching between routes/views, the buttons become enabled again, which is not what I want. Additionally, setting cache to true doesn't keep the buttons disabled after the app has been reopened either.
I have tried using localstorage to store the $scope.upDisabled and $scope.downDisabled, but it ruins the JSON formatting. I have tried remote storage and received the same result. For example, the $scope.upDisabled and $scope.downDisabled store data like so:
{"2":true, "3":false, "4":true}
and so on. But because storing in localstorage or a database requires me to use JSON.stringify, you can guess that those quotes cause trouble and I end up with nested JSON as well. So, the data from localstorage does not return the correct format.
My known problems/options are twofold.
Is there a better solution to persistently disabling those
buttons?
How would I correctly format the JSON coming out of
localstorage?
Something else to note: Since this is a mobile/hybrid app using Ionic, I am not using cookies, but I did create a token system to act similarly.
Edit: Thanks to those who replied and your suggestions. I am currently using a MySQL database to keep track of the votes (May switch to SQLite later) #aorfevre: I've taken a look at the SQLite plugin before and will probably use it down the road. I finally got everything working how I want it to.
$scope.upDisabled = {};
$scope.downDisabled = {};
$scope.upCheck = {};
$scope.downCheck = {};
...Votes Loading function up here
...Thread loading Function up here
.finally(function(){
angular.forEach($scope.threads,function(value,index){
angular.forEach($scope.upCheck,function(value2,index){
if(value.id == value2.threadID)
{
$scope.upDisabled[value.id] = true;
$scope.downDisabled[value.id] = false;
}
})
})
angular.forEach($scope.threads,function(value,index){
angular.forEach($scope.downCheck,function(value2,index){
if(value.id == value2.threadID)
{
$scope.downDisabled[value.id] = true;
$scope.upDisabled[value.id] = false;
}
})
})
}
$scope.loadVotes();
$scope.loadThreads();
As for the server side (PHP with Laravel Framework):
public function upvoteThread($id, $token)
{
$thread = Thread::find($id);
$score = $thread->score;
$score = $score + 1;
$thread->score = $score;
$thread->save();
$voted = ThreadVote::where('threadID','=',$id)->where('token','=',$token)->get();
if($voted->isEmpty())
{
$upVote = new ThreadVote;
$upVote->threadID = $id;
$upVote->token = $token;
$upVote->upVote = 'true';
$upVote->downVote = 'false';
$upVote->save();
}
else
{
DB::table('thread_votes')
->where('threadID', '=', $id)
->where('token','=',$token)
->update(array('upVote' => 'true', 'downVote' => 'false')
);
}
return Response::json(array('status'=>1))->setCallback(Input::get('callback'));
}
public function getUpVotes($token)
{
$votes = ThreadVote::where('token','=',$token)
->where('upVote','=','true')
->select('threadID','upVote')
->get();
return Response::json($votes)->setCallback(Input::get('callback'));
}
...Similar downVote Function...
So as it stands. When the button is pushed, it saves the user's token, threadID, and vote to the database. When the view is loaded, that information, based on the token and threadID is loaded as a JSON array, associated with the Thread array and if a threadID and thread.id matches, it's pushed into the up/downdisabled scope as "threadID":bool ("1":true for example).
I'll recommand you to implement a DB if you manage huge volume of post.
I personnaly use localStorage for several preferences not for storing a db.
Therefore, if you target only for ios / android, I recommand you https://github.com/litehelpers/Cordova-sqlite-storage
If you target windows phone 8.1, the implementation is not trivial and I'm facing some issues regarding the structure of WindowsPhone & C++ compilation librairy ( more details here : https://issues.apache.org/jira/browse/CB-8866 )

Twitter like "x new tweets" with .arte or .ajax?

I've found this great example to implement a twitter like "x new tweets" http://blog.hycus.com/2011/03/14/realtime-updates-like-twitter-using-phpmysqljquery/
In this example the .arte jQuery plug-in is used. However I think it can be done just as the same with .ajax and I've coded as:
$.ajax({
url:'async.php? main='+$('.boxOfMainPage:first').attr('id'),
success:function(results)
{
if(results!='')
{
if(results.indexOf('boxOfMainPage')>=0)
$('#tweetEveryone').prepend(results);
else
$('#newTweet').html("<center><a href=''>I found "+results+" new tweets</a></center>").show();
}
}
});
This checks the results and loads the result to tweetEveryone. Async.php simply makes a mysql_query and brings the new results. I've actually done exactly the same with the example however when I click the 'new tweet's like it sometimes causes a postback. In the example I haven't experience it. Can it be because of the difference between .arte and .ajax ?
It's nothing about the differences between arte and ajax (in fact and in a short way, arte is ajax that is called with an interval, trying to do something like "long polling")
So, u have a link without href value, this must "reload" ur page, ie, it will perform a GET request to the actual URL in window.location. A postback performs a POST request, this is really happening?
--- edited ---
If you wanna to do the same effect from twitter, it's simple.. In async.php, instead u write an link element that shows how many tweets has after the old state, make this page write a JSON object with all tweets, then, ur ajax function must get this JSON and convert it into a JS object. With this object, u'll be able to count how many updates u have to show and exactly which are they.
So, ur function could be like this (assuming that "#boxOfMainPage" is ur tweets container):
$.ajax({
url : 'async.php?main='+$('.boxOfMainPage:first').attr('id'),
success : function (tweets) {
window.NEW_TWEETS = tweets;
if ( NEW_TWEETS && NEW_TWEETS.length ) {
$('#newTweet').html("<center><a href='#' onclick='showNewTweets()'>I found "+NEW_TWEETS.length+" new tweets</a></center>").show();
}
}
});
The showNewTweets functions will be:
function showNewTweets() {
if ( window.NEW_TWEETS && NEW_TWEETS.length ) {
$('#newTweet').hide().html("");
for ( tweet in NEW_TWEETS ) {
$("#boxOfMainPage").prepend(buildTweetHTML(tweet));
}
}
}
And buildTweetHTML:
function buildTweetHTML(tweet) {
var $tweetElm = $("<div class='tweet'>");
$tweetElm.append("<h2>"+tweet.user+" said:</h2>");
$tweetElm.append("<p>"+tweet.content+"</p>");
$tweetElm.append("<p class='time'>"+tweet.time+"</p>");
return $tweetElm;
}
Finally, async.php should write JSON object like this:
[
{ user : 'Rafael', content : 'The content from tweet', time : 'X time ago' },
{ user : 'George', content : 'The content from tweet', time : 'Y time ago' }
{ user : 'Jack', content : 'The content from tweet', time : 'H time ago' }
]

Categories

Resources