I have a comments section on my website and I need a way to make it update live (or every 30 seconds or so) It gets the comments from a mysql database with PHP:
<?php
$link = mysql_connect('localhost', 'root', '');
if (!$link) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db('SJCE');
$qu1 = mysql_query("SELECT `ID`,`contence`,`from`,`time`,`subject` FROM `***` WHERE `where` = 1 ORDER BY `time` DESC LIMIT 0 , 30");
$numr1 = mysql_num_rows($qu1);
$i = 1;
while($row=mysql_fetch_array($qu1)) {
$i++;
echo '
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading panel-title h3">
<div class="row">
<div class="col-xs-4">
<i class="fa fa-clock-o"></i> '.$row['3'].'
</div>
<div class="col-xs-4 text-center">
'.$row['4'].'
</div>
<div class="col-xs-4 text-right">
<i class="fa fa-user"></i> '.$row['2'].'
</div>
</div>
</div>
<div class="panel-body">
'.$row['1'].'
</div>
</div>
</div>
</div>
';
}
?>
and at the moment I use a piece of JavaScript to refresh the page:
<script type="text/javascript">
timeout = setTimeout("location.reload(true);",5000);
function disable_ar(){
clearTimeout(timeout);
}
function enable_ar(){
timeout = setTimeout("location.reload(true);",5000);
}
</script>
This works but makes the page flash every 5 seconds and sometimes causes it not to load properly.
I need a way to make the comments update without refreshing the whole page.
Thank you.
P.S. I know little about javascript, ajax and jquery
Load the jquery library:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
Then use an ajax script like this (must be called after jquery is loaded).
And use interval, not timeout (which only runs once).
$(function(){
window.setInterval(function(){
loadLatestResults();
}, 5000);
function loadLatestResults(){
$.ajax({
url : '/load/from/this/url.php',
cache : false,
success : function(data){
$('#id-of-element-into-which-results-are-loaded').html(data);
}
});
}
});
Related
I'm making a live search function using ajax on laravel 7 and it works just fine for the most part. However, i have a button that disables the functions of the search output. When the page first loaded the functions are successfully disabled. But when i run the live search, the output's function is enabled again. I'm guessing its because the live search output is taken from a partial view/html which then loaded to the main view/html. The function run without any problem just after the page loads because the DOM already loaded it. When i append a new view/html, the DOM doesn't recognize it.
Here is the ajax code
function fetch_data(page, query){
$.ajax({
url:"/search?query="+query+"&page="+page,
success:function(data){
$('#product-container').html('');
$('#product-container').html(data);
}
});
}
$('#search').keyup(delay(function(){
var query = $('#search').val();
var page = $('#hidden_page').val();
fetch_data(page, query);
}, 400));
This is the partial view
<div class="row">
#if(count($products) < 1)
<div class="col-md-12 text-center">
<h5>No results</h5>
</div>
#endif
#foreach($products as $product)
<div class="col-md-3" id="item">
<div class="product__item p-2" style="background: #dce0e2;">
<div class="thumbnail">
<img src="{{ asset('img/products/'. $product->image) }}">
</div>
<div class="product__item__text">
<h6 style=" white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">{{ $product->name }}</h6>
<h5>{{ rupiah($product->price) }}</h5>
</div>
<a href="{{ route('kasir.add.item', ['product_id' => $product->id]) }}" class="add-btn" id="{{ $product->id }}">
<div class="btn-success text-center m-2 p-1">
Add +
</div>
</a>
</div>
</div>
#endforeach
</div>
{{ $products->links('partials.pagination') }}
This is the controller
public function search(Request $request){
if ($request->ajax()) {
$query = $request->get('query');
$query = str_replace(" ", "%", $query);
$products = Product::orderBy('name', 'ASC')->where('name', 'LIKE', '%'.$query."%")->paginate(8);
return view('kasir.product_data', compact('products'))->render();
}
}
My question is can the DOM load the partial view as if it loaded at the same time as the page so that the jquery functions can work on the new view/html?
This should be your partial (only works if you add it through ajax requests). It will add the listeners you want, even after the DOM is completely loaded the first time. Rerunning the same piece of jQuery will re-establish the listeners you are expecting.
<div class="row">
....
</div>
{{ $products->links('partials.pagination') }}
<script>
$('#search').keyup(delay(function(){
var query = $('#search').val();
var page = $('#hidden_page').val();
fetch_data(page, query);
}, 400));
</script>
in this issue, i use booster widgets tbcollapse to make some like a inbox in message menu, unread or new message is have status 0, so when i click the panel title in collapse widgets, it will open div with id #collapse, and change the status in database to be 1 (readed), its possible??? how?
<?php $collapse = $this->beginWidget('booster.widgets.TbCollapse');
<div class="panel-group" id="accordion">
<?php for ($a = 0; $a<count($pesan); $a++){ ; ?>
<div class="panel panel-warning">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapse<?php echo $a ;?>">
<?php echo $pesan[$a]["sender"] ;?>
</a>
</h4>
</div>
<div id="collapse<?php echo $a ;?>" class="panel-collapse collapse">
<div class="panel-body">
<?php echo $pesan[$a]["message"] ;?>
</div>
</div>
</div>
<?php }; ?>
</div>
Just use bootstrap's collapse events to trigger an ajax call, for what you want probably the best option is the shown.bs.collapse event, for example:
$('#myCollapsible').on('shown.bs.collapse', function () {
//Get the id of the message and use ajax to update the database
});
Edit #1
A little example:
First add a custom id to your widget
<?php $collapse = $this->beginWidget('booster.widgets.TbCollapse',
array('id'=>"myCollapsible")
);?>
At the end of your view add a script tag, or you can register a script with yii's CClientScript. For the sake of simplicity I will use script tags
<script>
$(function(){
$('#myCollapsible').on('shown.bs.collapse', function (e) {
var target=$(e.target);//get shown element
if(target.attr('id')===$(this).attr('id'))return;//Event is fired on page load, ignore event on main collapse
$.post('controllerUrl',{messageId:$(e.target).attr("id")},function(data){//call server to update
//do something if everything was ok or display error
});
});
});
</script>
In your controller just add a method to update the message status
public function actionUpdateMessage{
MessageModel::model()->updateByPK($_POST['messageId'],'viewed'=>'1');//update the model whose id was sent, provide some validation if needed
return;//end processing
}
Hope this helps
Edit #2
In case you need to put more metadata for the ajax call, I recommend to use data attributes in your elements, so for example you could add an Id based on your database
<div id="collapse<?php echo $a ;?>" class="panel-collapse collapse"
data-messageId="<?php echo $pesan[$a]["id"] ;?>">
<div class="panel-body">
<?php echo $pesan[$a]["message"] ;?>
</div>
</div>
And in the javascript code you can retrieve the info with data method like the following
<script>
$(function(){
$('#myCollapsible').on('shown.bs.collapse', function (e) {
var target=$(e.target);//get shown element
if(target.attr('id')===$(this).attr('id'))return;//Event is fired on page load, ignore event on main collapse
$.post('controllerUrl',{messageId:$(e.target).data("messageId")},function(data){//call server to update
//do something if everything was ok or display error
});
});
});
</script>
Edit #3
If retrieving data attributes using jquery data method doesn't work, you still can access these attributes using attr method
$.post('controllerUrl',{messageId:target.attr("data-messageId")},function(data){//call server to update
//do something if everything was ok or display error
});
If the data attributes aproach doesn't work, you can also try with hidden fields like this:
Firs, instead of setting data-messageId attribute, add inside your panel-collapse div an input hidden like the following:
<div id="collapse<?php echo $a ;?>" class="panel-collapse collapse">
<input type="hidden" value="<?php echo $pesan[$a]["id"] ;?>"/>
<div class="panel-body">
<?php echo $pesan[$a]["message"] ;?>
</div>
</div>
Then, change the following in the javascript:
$.post('controllerUrl',{messageId:target.find("input").val()},function(data){//call server to update
//do something if everything was ok or display error
});
I'm wrapping up results of ajax request on div and appending to main div in a page. SO if the array of results returned empty, I would like to alert user, saying that no result found and also provide a link for them to click on. When they click a pop up box carrying products by category would popup. Important thing to notice here is,the products are derived via php and ajax scripts.
So When I use onclick event or directly, nothing happens!!!. But if I call empty or HTML pop up it would work. Also the same php scripts contained pop up would work if I trigger it on page load or in the ajax success function. SO I dont understand why only with on click it doesn't work?
This is the pop up I want to trigger on 'click' event
<section id="browse-search-popup" class="mfp-hide white-popup">
<h1>Browse Courses</h1>
Can't find what you're looking for? Tell us here!
<h2>First, pick a learning Zone:</h2>
<div class="row">
<div class="small-12 medium-8 large-8 medium-centered large-centered columns">
<ul class="small-block-grid-2 medium-block-grid-2 large-block-grid-2">
<?php
$tutor = new register();
$data = $tutor->get_maincat();
$i=0;
foreach($data as $k=>$v)
{
$i++;
?>
<li><div class="mainCat_<?php echo $i;?>" id="<?php echo $v['main_cat_id'];?>"><?php echo $v['main_cat_name'];?></div></li>
<?php
}
?>
</ul>
</div>
</div>
<h2>Then, pick a field:</h2>
<div class="row">
<div class="small-12 medium-12 large-12 columns" id="cat">
</div>
</div>
<h2>Finally, choose your Course:</h2>
<div class="row">
<div class="small-12 medium-12 large-12 columns" class="choosen_subjects">
</div>
</div>
<div class="row">
<div class="small-12 medium-12 large-12 columns" id="sub">
</div>
</div>
<input type="submit" id="done" value="Done">
</section>
Ajax request
$("#search_tutor").submit(function() {
var data = {
"action": "test"
};
var subject = $("#subject").val();
data = $(this).serialize() + "&" + $.param(data);
$.ajax({
type: "POST",
dataType: "json",
url: "/fetch_tutor.php", //Relative or absolute path to response.php file
data: data,
success: function(data) {
$("#contents img.loading").remove();
var sizy = data.length;
if(sizy ==0) {
console.log("sorry, cannot locate");
$(".simply-popup-link").trigger("click");
$("#simply-popup").empty();
//This is where I want to trigger the on click
$("#simply-popup").append("Unable to locate the subject you entered, please <a href='#' onclick='browse("+sizy+")' class='yellow'>Browse</a>");
}
console.log("size= "+data.length);
var j=0;
for (i = 0; i < data.length; i++) {
........................
......................
The browse function:
function browse(param) {
//this would work
/* $(".simply-popup-link").trigger("click");
$("#simply-popup").empty();
$("#simply-popup").append("test only"); */
// but not this
$(".browse-search-popup-link").trigger("click");
}
I tried loading the page into the an empty popup box ($("#simply-popup")) like this but doesn't work either:
$("#simply-popup").load('search/browse.php');
Change
$("#simply-popup").append("Unable to locate the subject you entered, please <a href='#' onclick='browse("+sizy+")' class='yellow'>Browse</a>");
to
$("#simply-popup").append("Unable to locate the subject you entered, please <a href='#' class='yellow browse'>Browse</a>");
write a separate code for this
$('body').on('click', '.browse', function() {
$('.browse-search-popup-link').click();
});
Can't you just call that function after append:
$("#simply-popup").append("Unable to locate the subject.....");
browse(sizy);// call it here.
or when you append it in the element then you can call the click:
$("#simply-popup").append("Unable to locate the subject.....");
$("#simply-popup a").click();
$(document.body).append('browse value is 1');
$(document.body).find('a').click();
function browse(num){ $(document.body).find('p').html("<pre>"+num+"</pre>");}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
log out here:
<p></p>
I have a php script that loops over the results of a database query and prints them out. I am trying to load them into an Admin Interface Panel with AJAX, but to no avail. My job requires me to write mostly backend code, so I haven't gotten around to learning much JS/Jquery. Anyways, I have a page "insert.php" that has a button I want to click and have it call the results from the "posts.php" page. Here are my files
insert.php
Load Posts
</div>
</div>
<div class="row main">
<div class="small-8 columns" id="posts">
</div>
</div>
</div>
posts.php
<?php
require_once 'connect.php';
$user = 'admin';
$sql = "SELECT * FROM posts WHERE author = ?";
$stmt = $db->prepare($sql);
$stmt->bindParam(1, $user);
$stmt->execute();
$data = $stmt->fetchAll();
foreach ($data as $row)
{
$id = $row['id'];
$title = $row['title'];
$author = $row['author'];
$date = $row['date'];
$smalltext = $row['smalltext'];
$bodytext = $row['bodytext'];
$images = $row['images'];
$imagelist = split(' ', $images);
$shorttext = str_replace(
array("\r\n", "\n"),
array("</p><p>", "</p><p>"),
$smalltext);
echo
"
<div class='row main'>
<h1 class='padding-top-12 bottom-rule-green'>$title</h1>
<div class='small-2 columns'>
<p class='text-justify small-text'>
Post MetaData goes here
</p>
</div>
<div class='small-10 columns bottom-rule-red text-justify'>
<p>
$shorttext
";
foreach ($imagelist as $key => $value)
{
echo "<img src='users/$author/img/$value'>";
}
echo
"
</p>
</div>
</div>
<div class='row main small-text padding-top-1'>
<div class='small-2 small-oofset-2 columns'>
<a href='posts/$author/$id'>Edit Post</a>
</div>
<div class='small-4 columns'>
Timestamp: $date
</div>
<div class='small-4 columns'>
Author: <a href='users/$user'>$user</a>
</div>
</div>
";
}
?>
postAjax.js
$.ajaxSetup ({
cache: false
});
var loadUrl = "../../includes/posts.php";
$(function(){
$('#ajaxbtn').on('click', function(e){
e.preventDefault();
$('#ajaxbtn').fadeOut(300);
$.post(loadUrl, {language: "php", version: 5},
function(res){
$("posts").html(res)
}, "html");
});
});
This is the file that loads my scripts into the page
<!--Foundation Framework Necessities-->
<script type="text/javascript" src="../../assets/js/vendor/jquery.js"></script>
<script type="text/javascript" src="../../assets/js/foundation/foundation.min.js"></script>
<script type="text/javascript" src="../../assets/js/postAjax.js"></script>
<script type="text/javascript">
$(document).foundation();
</script>
When I click the #ajaxbtn button, it fades out so I know the JS is being called to that element onclick, but it doesn't post the results of posts.php. I think this may just be my misunderstanding of how Ajax works; if you would please tell me what I did wrong.
Try changing,
$("posts").html(res)
to
$("#posts").html(res)
Also I see some mistakes in your code in posts.php
You are not embedding php variables in strings properly.
I believe you need to use a delegated event. Change your code from:
$('#ajaxbtn').on('click', function(e)
to:
$('#ajaxbtn').on('click', 'a', function(e)
This way event handlers will fire as expected even if the contents of that parent element change. I had the same issue and this solved it. Good luck.
I'm new to jQuery and am having trouble figuring out the right way to loop a set of code for a basic carousel/banner rotator. I've tried a few versions of "for" statements and .each(), but I can't get it to work on my own so I'm reaching out for help.
Here's my code so far:
$('.next-1').click(function () {
$('.featured-1').fadeOut(500,function(){
$('.featured-2').fadeIn(500,function(){
$('.featured-2').toggleClass("hide");
});
});
});
$('.next-2').click(function () {
$('.featured-2').fadeOut(500,function(){
$('.featured-3').fadeIn(500,function(){
$('.featured-3').toggleClass("hide");
});
});
});
And then a similar code block for going back within the slider:
$('.prev-2').click(function () {
$('.featured-2').fadeOut(500,function(){
$('.featured-1').fadeIn(500,function(){
$('.featured-2').toggleClass("hide");
});
});
});
$('.prev-3').click(function () {
$('.featured-3').fadeOut(500,function(){
$('.featured-2').fadeIn(500,function(){
$('.featured-3').toggleClass("hide");
});
});
});
This code does work right now, I just don't want to have to output so many unnecessary lines of code when I know I could loop it. I'd like to be able to loop until there are no more "featured-n" divs to cycle through (being able to cycle around to the beginning would be great too!)
Here's the PHP/HTML I'm using to generate each "featured-n" div block:
function home_slider_loop() {
$count = 0;
query_posts ('tag=slider');
if (have_posts()) : while (have_posts()) : the_post();
$count++;
?>
<div class="featured-post featured-<?php echo $count; if ($count>1) { echo ' hide';}?>">
<div class="featured-header">
<h1 class="featured-title"><?php the_title(); ?></h1>
<p class="author">Written by Evan Luzi</p>
</div>
<div class="image-wrap">
<?php the_post_thumbnail('full', array('class' => 'slider-image')); ?>
<div class="slider-nav">
<div class="featured-prev prev-<?php echo $count; ?>"></div>
<div class="featured-next next-<?php echo $count; ?>"></div>
</div><!--End Navigation-->
</div><!--End Image <?php echo $count; ?>-->
<div class="featured-footer">
<?php the_excerpt(); ?>
<a class="more-link" href="<?php the_permalink(); ?>" alt="<?php the_title(); ?>" >Read more</a>
</div>
</div><!--End Featured <?php echo $count; ?>-->
<?php
endwhile;
endif;
}
Here's a sample of one of the static HTML outputs (just imagine this iterated several times with the "featured-n" classes incrementing:
<div class="featured-1">
<div class="featured-header">
<h1 class="featured-title">5 Useful Cinematography Apps for iOS You Should Download Today</h1>
<p class="author">Written by Evan Luzi</p>
</div>
<div class="image-wrap">
<img width="1018" height="416" src="http://www.tbabdev.com/wp-content/uploads/2013/07/cinematography-apps-8-hero.jpg" class="slider-image wp-post-image" alt="cinematography-apps-8-hero" />
<div class="slider-nav">
<div class="featured-prev prev-1"></div>
<div class="featured-next next-1"></div>
</div><!--End Navigation-->
</div><!--End Image 1-->
<div class="featured-footer">
<p>The devices we have in our pockets, the ones that can run these apps, these are the new leathermans. They have everything we need. They eliminate the need to carry paper manuals and enable us to do complex timelapse calculations in a fraction of the time as a paper and pen.</p>
<a class="more-link" href="http://www.tbabdev.com/?p=27" alt="5 Useful Cinematography Apps for iOS You Should Download Today" >Read more</a>
</div>
</div><!--End Featured 1-->
You can see the code in action at http://www.tbabdev.com/
Thank you in advance for your help and please be kind to a n00b :)
Use something like this :
$('.nav .prev').click(function(){
activeBlock = $('.featured.active');
prevBlock = activeBlock.prev('.featured');
activeBlock.fadeOut('slow',function(){
prevBlock.fadeIn().addClass('active');
}).removeClass('active');
});
$('.nav .next').click(function(){
activeBlock = $('.featured.active');
nextBlock = activeBlock.next('.featured');
activeBlock.fadeOut('slow',function(){
nextBlock.fadeIn().addClass('active');
}).removeClass('active');
});
Html
<div class="nav">
<div class="prev"> </div>
<div class="next"> </div>
</div>
<div class="featured-post featured <?php if($count>1) echo 'hide' ?>">
<div class="featured-header">
<h1 class="featured-title"><?php the_title(); ?></h1>
<p class="author">Written by Evan Luzi</p>
</div>
<div class="image-wrap">
<?php the_post_thumbnail('full', array('class' => 'slider-image')); ?>
</div>
<!--End Image <?php echo $count; ?>-->
<div class="featured-footer">
<?php the_excerpt(); ?>
<a class="more-link" href="<?php the_permalink(); ?>" alt="<?php the_title(); ?>" >Read more</a>
</div>
</div>
You could do it this way :
$('.featured-next, .featured-prev').click(function () {
//find out if the clicked element is a prev or next element, extract the last part, will be useful later
var direction = $(this).hasClass("featured-next") ? "next" : "prev";
//select the ".featured-n" block which is the super-parent of clicked element
var $fullBlock = $(this).closest('div[class^="featured-"]'); //or add a class here to make your life easier
//fade out full block
$fullBlock.fadeOut(500, function () {
//search for the next element and show it
//note that $fullBlock.next() => $fullBlock["next"]() => $fullBlock[direction]()
$fullBlock[direction]().fadeIn(500, function () {
//toggle the class "hide" of the element next to fullBlock
$(this).toggleClass("hide");
});
});
});
Explanation:
You can join up both prev and next events together.
Then, you have to check if its a next or a prev element. Set that to a variable called direction. We'll be using this to find out if we have to use prev() or next() when we're trying to fadeIn featured-n divs.
Find the parent with the class set to featured-n (in your case its the superparent). It might be better if you give a common class to all these elements so that we can stop using 'div[class^="featured-"]' selector, which is slightly inefficient.
Fade out the superparent.
In the callback, based on the direction variable, we'll have to decide if the carousel is gonna go to prev block or next block, something like this :
if(direction === "prev")
{
$fullBlock.prev().fadeIn(//your code)
}
else
{
$fullBlock.next().fadeIn(//your code)
}
You must also know that, in an object like this :
var data = {"name" : "Blah Blah"}
To get the "Blah Blah" out, we can say
data.name
or we could say :
data["name"]
So based on this, in our situation, instead of
$fullBlock.prev()
Or we could say
$fullBlock["prev"]()
Which is what direction variable contains. So finally, we could do this to select the next/prev element based on what was clicked :
$fullBlockdirection
Show the prev/next element.
Add/remove "hide" class.
Hope this helped!