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.
Related
I successfully implemented a Masonry-Gallery for a WordPress website by using Bootstrap 5 in combination with 'Masonry-Layout'.
It works all fine except in Safari, where the layout usually breaks, a known problem and the solution is supposed to be 'imagesLoaded'.
I tried a lot, but I just don't manage to add the needed classes at the right place(s).
The code as far as I got, see below. Anybody who can help?
<div class="row grid" id="gallery-masonry" data-masonry='{"percentPosition": true }'>
<?php
$images = get_field('gallery');
$size = 'large';
if( $images ): ?>
<?php foreach( $images as $image_id ): ?>
<div class="col-md-6 mb-3">
<div id="post-<?php the_ID(); ?>" class="card rounded-0" >
<?php echo wp_get_attachment_image( $image_id, $size, "", ["class" => "card-img-top rounded-0","alt"=>""]); ?>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<!--Masonry-Layout-->
<script src="https://cdn.jsdelivr.net/npm/masonry-layout#4.2.2/dist/masonry.pkgd.min.js" integrity="sha384-GNFwBvfVxBkLMJpYMOABq3c+d3KnQxudP/mGPkzpZSTYykLBNsZEnG2D9G/X/+7D" crossorigin="anonymous" async></script>
<!--ImagesLoaded-->
<script src="https://unpkg.com/imagesloaded#5/imagesloaded.pkgd.min.js"></script>
<!--Script ImagesLoaded-->
<script>
var $grid = $('.grid').imagesLoaded( function() {
// init Masonry after all images have loaded
$grid.masonry({
// options...
});
});
</script>
Please check my post regarding adding a Masonry to a Wordpress Site.
https://www.customfitwebdesign.com/how-to-add-masonry-layout-in-wordpress/
Note: Masonry is actually built into the core of WordPress ( wp-includes/js/masonry.min.js ). This WordPress version of Masonry also includes ImagesLoaded (imagesloaded.min.js).
I'm bringing articles from a database with ORDER BY RAND() with a PHP foreach cycle:
<?php foreach($posts as $post): ?>
<div class="post" id="post">
<article>
<div class="post-head">
<a href="<?php echo ROUTE; ?>/profile.php/<?php echo $post['user_id']; ?>">
<img class="post-pfp" src="<?php echo ROUTE; ?>/users_pics/<?php echo ($post['profile_pic']); ?>">
</a>
<h1>
<a class="links-3" href="<?php echo ROUTE; ?>/profile.php?user=<?php echo $post['user_id']; ?>"><?php echo $post['post_by']; ?></a>
</h1>
<p class="post-date"><?php echo get_date($post['date']); ?></p>
<div class="x_hover" onclick="hide_post()">
<img src="<?php echo ROUTE; ?>/icons/cross.svg">
</div>
<hr id="post-hr">
<br>
<a href="<?php echo ROUTE; ?>/post.php?p=<?php echo $post['ID']; ?>">
<p class="post-content"><?php echo $post['content']; ?></p>
</a>
</div>
</article>
</div>
<?php endforeach; ?>
As you can see, the div with the class x_hover has an onclick attribute:
<div class="x_hover" onclick="hide_post()">
<img src="<?php echo ROUTE; ?>/icons/cross.svg">
</div>
What the hide_post() function does is this:
var post = document.getElementsByClassName("post");
function hide_post(){
if (post[0].style.display = "block") {
post[0].style.display = "none"
}
}
I'm new to JS so I have some issues as well.
We are declaring that var post is equal to all the elements with the class name "post", such as the HTML code I added at the beginning, has the class post:
<div class="post" id="post">
This div has the display: block; attribute. However, when I run all this code, It only turns into display: none the first element that brings us from the database, it doesn't works with the rest of them...
Why is this happening?
IDs must be unique and since you have named all of the post only the first one will ever been "seen". Make the IDs unique, change your hide_post function to accept a ID name to hide, and add the unique ID to your onclick calls.
Change
<div class="post" id="post">
to something like
<div class="post" id="post<?php echo $post['ID']; ?>">
Then change
<div class="x_hover" onclick="hide_post()">
to
<div class="x_hover" onclick="hide_post('post<?php echo $post['ID']; ?>')">
Finally, modify your hide_post function to accept the name of the ID to show or hide.
function hide_post(idToHide){
if (idToHide.style.display = "block") {
idToHide.style.display = "none"
}
}
When you use getElementsByClassName it returns an HTMLCollection. You should iterate elements and hide all of them if it's what you intent to. Right now you are just hiding 0th element of this collection.
var posts = document.getElementsByClassName("post");
for (let post of posts) {
if (post.style.display = "block") {
post.style.display = "none"
}
}
If you intent to hide a single post you give unique ids to divs, and call hide_post with id of that post. Also you should use getElementById for that. Notice that it's not plural. Function should be like this:
function hide_post(postId){
var post = document.getElementById(postId);
if (post.style.display = "block") {
post.style.display = "none"
}
}
A more cleaner way of doing this would be.
function hide_post() {
document.querySelectorAll('.post').forEach(v => {
if(v.style.display == block) v.style.display = none; }); }
I want a box with a welcome message etc to appear after a user registrers on my website. But instead of making it appear from just clicking on a button, i want it to happend when the email,password,username etc gets sendt to the database. So, instead of doing this :
<button onclick="document.getElementById('id01').style.display='block'" style="width:auto;">Login</button>
Is there any ways i can do this programmatically? I have also tried :
<script>
self = function(id01)
</script>
but it wont work. Any tips on what i should try/ do?
This is how i send the info to my database :
//if no errors have been created carry on
if(!isset($error)){
$hashedpassword = $user->password_hash($_POST['password'], PASSWORD_BCRYPT);
$activasion = md5(uniqid(rand(),true));
try {
$stmt = $db->prepare('INSERT INTO members (username,password,email,active) VALUES (:username, :password, :email, :active)');
$stmt->execute(array(
':username' => $_POST['username'],
':password' => $hashedpassword,
':email' => $_POST['email'],
':active' => $activasion
));
$id = $db->lastInsertId('memberID');
//send email
$to = $_POST['email'];
$subject = "Registration Confirmation";
$body = "<p>Thank you for registering at Game World.</p>
<p>To activate your account, please click on this link: <a href='".DIR."activate.php?x=$id&y=$activasion'>".DIR."activate.php?x=$id&y=$activasion</a></p>
<p>Regards Site Admin</p>";
$mail = new Mail();
$mail->setFrom(SITEEMAIL);
$mail->addAddress($to);
$mail->subject($subject);
$mail->body($body);
$mail->send();
//redirect to index page
header('Location: index.php?action=joined');
?>
well you can achieve what the results you want in many ways, js alerts, jquery pop up. bootstrap modals.
Option 1 :
using jquery and jquery ui
<!-- latest stable jquery -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<!-- latest stable jquery ui -->
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>
<?php
if(isset($_GET['action']) && !empty($_GET['action'])){
$action = $_GET['action'];
if($action == "joined"){?>
<div id="modal" style="display: none;">
This is pop up, add message.
</div>
<script type="text/javascript">
$(document).ready(function () {
$("#modal").dialog();
});
</script>
<?php
}else{
//action != joined do something
}
}else{
//$GET NOT set do something
}
Option 2 :
Using Bootstrap
<!-- latest stable jquery -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<!-- Bootstrap links -->
<?php
if(isset($_GET['action']) && !empty($_GET['action'])){
$action = $_GET['action'];
if($action == "joined"){?>
<div class="modal fade" id="success">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div class="alert alert-block alert-success">
<h4>Welcome</h4>
<p>Add Message</p>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$('document').ready(function(){
$('#success').modal('toggle'); });
</script>
<?php
}else{
//action != joined do something
}
}else{
//$GET NOT set do something
}
Option 3
Js alert
<?php
if(isset($_GET['action']) && !empty($_GET['action'])){
$action = $_GET['action'];
if($action == "joined"){?>
<script type="text/javascript">
alert('welcome');
</script>
<?php
}else{
//action != joined do something
}
}else{
//$GET NOT set do something
}
The first option, you will need to style the pop/div according to your design needs.
as you can see u need to first check if the action in the url is joined, meaning they have successfully signed up, then show the popup
You can do this using server side language PHP using $_GET['action'] or $_REQUEST['action'] on a proper return of your header - index.php?action=joined
Create logic on your DB insert page that checks to see if your query was successful. On success, it routes you to the header redirect, else returns an error message and exits the script.
Something like this:
$query = 'INSERT INTO members (username,password,email,active) VALUES (:username, :password, :email, :active)';
$stmt = $db->prepare($query);
$stmt->execute(array(
':username' => $_POST['username'],
':password' => $hashedpassword,
':email' => $_POST['email'],
':active' => $activasion
));
//Check to see if your $stmt is set, will return true if successful else it will return false
if($stmt){
$id = $db->lastInsertId('memberID');
//send email
$to = $_POST['email'];
$subject = "Registration Confirmation";
$body = "<p>Thank you for registering at Game World.</p>
<p>To activate your account, please click on this link: <a href='".DIR."activate.php?x=$id&y=$activasion'>".DIR."activate.php?x=$id&y=$activasion</a></p>
<p>Regards Site Admin</p>";
$mail = new Mail();
$mail->setFrom(SITEEMAIL);
$mail->addAddress($to);
$mail->subject($subject);
$mail->body($body);
$mail->send();
//redirect to index page
header('Location: index.php?action=joined');
}else{
echo 'Sorry but there was an issue with the INSERT.';
exit();
}
On index.php use an if/else statement or switch to check if $_GET['action'] (isset) and see if it is == to your value 'joined'. Then create a variable to hold your welcome message and display it else declare the variable null or post an alternate message perhaps.
Top of your index.php page:
$message = "";
if(isset($GET['action']) && $GET['action']=="joined"){
//place your Welcome message here
$message .= "<h2>Welcome and thank you for signing up!</h2>";
}else{
$message .= "<h2>Some other message</h2>";
//Or you could go with empty quotes or declare $message NULL
}
Then in your HTML call on your variable $message with something like:
<?=$message?> or <?php echo $message; ?>
<body>
<div id='wrapper'>
<header>Some header</header>
<nav id='nav'>
<ul>
<li class="nav-item">
BUTTON 1
</li>
<li class="nav-item">
BUTTON 2
</li>
</ul>
</nav>
<div id="content">
<?=$message?>
<div id="heading">Some Page Heading</div>
<div id="">
<p>
Some page content.
</p>
</div>
</div>
</div>
</body>
I am not the most proficient in PHP but this is probably how I would handle a server side request like this.
*** Keep in mind that you are requesting an update to your page on the update of your server, not a client side action like pressing the button.
Hope this helps.
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 have an area on my Wordpress theme where I am showing info about a random taxonomy. Basically, the taxonomy is "playwrights" and I am featuring a random one on the home page. Here is the HTML:
<div id="home-top-right">
<?php
$allpw = get_terms( 'playwrights', 'hide_empty=0' );
$randpw = $allpw[ array_rand( $allpw ) ];
$randpw = get_term($randpw->term_id, 'playwrights');
$pwlink = get_term_link($randpw->term_id, 'playwrights');
?>
<div class="title">
Playwright Spotlight
<li class="fa fa-refresh refresh"></li>
</div>
<div class="content" id="p-spotlight">
<?php if (get_field('image', 'playwrights_'.$randpw->term_id)) { ?>
<div class="thumb">
<?php $imageid = get_field('image', 'playwrights_'.$randpw->term_id); ?>
<a href="<?php echo $pwlink; ?>">
<?php echo wp_get_attachment_image($imageid, 'pwthumb'); ?>
</a>
</div>
<?php } ?>
<div class="text">
<div class="sub-title">
<?php echo $randpw->name; ?>
</div>
<?php echo print_excerpt('', '200'); ?>
</div>
</div>
</div>
I want to be able to click a button (in the code, it is the <i> tag) and reload just that section (not the whole page) with a new random taxonomy term (playwright). I'm not great at JS/jquery and I'm not able to find a tutorial online that gets me where I need to go, especially considering the exchange between post data and the js function.
How should I go about this?
By default, WordPress has an admin-ajax.php file which you can send AJAX calls to. You can create a hook that is linked to your own custom function in which you can do the stuff you want, like getting the random term and send it back to the client.
Then you can pass a value to your AJAX call, called 'action'. When admin-ajax.php is getting a POST request with the action you 'hooked', your custom function is being executed.
Have a look at the links below for a more detailed explanation:
http://premium.wpmudev.org/blog/how-to-use-ajax-with-php-on-your-wp-site-without-a-plugin/
http://codex.wordpress.org/AJAX_in_Plugins