Reading a lot about sessions and how to add and remove items. I see there are a lot of different way's to get this done. I'm having the same problem.
I hope someone here could help me out with this one. I've come along way from nothing to where I am now with the help of this community (thanks!).
This is my problem, I hope I can explain it so you can understand.
Let say I have a shop that sells t-shirts and pants. When I save a t-hirt item to my cart it display's it like it should. But I'm not able to remove the item. If I then filter my page for pans (this triggers an AJAX event) and try to remove the t-shirt, the item is removed. But ALL items are removed not just the one I clicked on to remove.
Here is my HTML to add a product:
<button type="submit"
class="btn btn-primary text-right add-product showtoast"
data-target="post-<?php the_ID(); ?>"
data-attribute="<?php the_title(); ?>"
data-product="<?php the_title(); ?>">
Add to cart
</button>
And this is the HTML to remove an item:
<div class="echo-product">
<?php echo htmlspecialchars($product); ?>
<input type="submit" class="delete-product" value="Remove">
</div>
These are my Javascripts to add and remove items:
$('.add-product').click(function() {
var productName = $(this).data('product');
$.post('http://example.com/reload.php?addparam',
{productName: productName}, function(data) {
$('.txtHint').html(data);
})
});
$('.delete-product').click(function() {
var productName = $(this).data('product');
$.post('http://examples.com/reload.php?delparam',
{productName: productName}, function(data) {
$('.txtHint').html(data);
})
});
And last but not least, my reload.php script:
<?php
session_start();
if (!array_key_exists('products', $_SESSION) || !is_array($_SESSION['products'])) {
$_SESSION['products'] = [];
}
$productName = array_key_exists('productName', $_POST) ? (string) $_POST['productName'] : '';
if(isset($_GET['delparam'])){
unset($_SESSION['products'][$productName]);
}
if(isset($_GET['addparam'])){
$_SESSION['products'][] = $productName;
}
?>
<?php foreach ($_SESSION['products'] as $product): ?>
<div class="echo-product">
<i style="color:#F60;padding-right:20px;" class="fa fa-anchor" aria-hidden="true"></i>
<?php echo htmlspecialchars($product); ?>
<input type="submit" class="delete-product" value="Remove">
</div>
<?php endforeach;?>
Is there anyone that could help me understand why (it looks like) an AJAX event has to take place before I'm able to remove items. And why it removes ALL the items when I just click on one item?
Thanks!
Compare how products are added vs. how they are deleted
if(isset($_GET['delparam'])){
unset($_SESSION['products'][$productName]);
}
if(isset($_GET['addparam'])){
$_SESSION['products'][] = $productName;
}
When adding a product, you just append the productName to an array. The entry receives an numeric index.
When deleting a product you look for the productName as index - but that does not exist!
I'm sure it doesn't answer why all products are removed, but it might help to do things right.
Related
This is the div that i am updating
but i want to add a active class to the (li) item
every time the div refreshes the active class goes away
so i don`t want to refresh all the data in the (ul) but
only add (li) if there is a new data in the database,
with out refreshing the previous (li) items
<div id="contacts">
<ul id="rooms" class="rooms">
<!-- This is where the data get inserted -->
<!-- the ajax call and this -->
<li class='contact' data-val='<?php echo $room['id']; ?>'>
<div class='wrap'>
<div class='meta'>
<p class='name'><?php echo $room['sender']; ?></p>
<p class='preview'><?php echo $room['senderemail']; ?></p>
</div>
</div>
</li>
</ul>
</div>
this is my ajax call
$(document).ready(function() {
var interval = setInterval(function(){
$.ajax({
url: 'rooms.php',
success: function(data){
$('#rooms').html(data);
}
});
}, 1000);
});
in the room php
$rooms = get_rooms();
foreach($rooms as $room){
?>
<li class='contact' data-val='<?php echo $room['id']; ?>'>
<div class='wrap'>
<div class='meta'>
<p class='name'><?php echo $room['sender']; ?></p>
<p class='preview'><?php echo $room['senderemail']; ?></p>
</div>
</div>
</li>
<?php
}
the get_rooms() function
function get_rooms() {
$sql = "SELECT id, sender, senderemail FROM chatroom ";
$result = mysqli_query($GLOBALS['dbh'], $sql);
$rooms = array();
while($room = mysqli_fetch_assoc($result)){
$rooms[] = array('id'=>$room['id'], 'sender'=>$room['sender'],
'senderemail'=>$room['senderemail']);
}
return $rooms;
}
You Just need to push new data to the div as below just replace your line with:
$('#rooms').append(data);
this will add new <li> in your existing <div> after the last <li>
jquery append()
To get the id of the last <li>
var lastId = $( "#rooms li" ).last().attr('id');
Once you get the last id then pass it in your ajax call.
If I understand you correctly, your problem is that you lose the active class (which you clicked on the li container) when there is new data.
This has to do with the fact that you exchange all of the content.
There are now three options. Either
You give the rooms.php the id of the currently active li-container
and this script sets the active class for the affected container.
You transfer all the chatrooms (ids) already shown to rooms.php and only
load the new ones (this means effort later with sorting).
You save the active li class and re set it after content changed (this is the fastest)
f.e: in your Ajax succes functions:
let id=0;
let active_li = $('li.active');
if (active_li.length>0) id=active_li.data('val');
$('#rooms').html(data);
if (id!=0) $('li[data-val="'+id+'"]').addClass ('active');
A few other thoughts:
Note the interval of 1000ms. Possible it makes Problems if the request lasts longer than 1000ms. This may still work well in your tests, but maybe not anymore if there are a hundred or 1000 users in your application.
Doesn't it make sense to tell the server when you click the active room and save it in a session so that the server knows which room is active in the client?
You need to simply update your JS code like:
$(document).ready(function() {
var active_list = '';
var interval = setInterval(function(){
$.ajax({
url: 'rooms.php',
beforeSend: function(){
active_list = $('#rooms').find('li.contact.active').attr('data-val');
}
success: function(data){
$('#rooms').html(data);
$(data).find('li[data-val="' + active_list +'"]').addClass('active');
}
});
}, 1000);
});
This should solve your problem and Let me know if you still face any issue.
I have successfully built a shopping cart and everything works fine.
Here is what i want to accomplish:
if a user clicks on the add to cart button, it should add to the cart and refreshe the same page with the added item update.
If a user clicks on the image or View button, it displays the image of the item.
my problem is as follows:
1. IF a user clicks on the add to cart button, it adds but redirects to the cart.php file (Which is not what i want, I want the page to reload with the added item update)
2. I tried using:
$head = $_SERVER['HTTP_REFERER'];
echo '<script>location.href="'.$head.'"</script>';
exit();
It seems to work well, when a user clicks add to cart button, but when a user clicks on image or click on view button, it refrehes the same page without allowing the user to view the image.
Below is my code.
//My custom shopping cart script
if (isset($_GET['pid'])) {
$pid = $_GET['pid'];
$wasFound = false;
$i = 0;
// If the cart session variable is not set or cart array is empty
if (!isset($_SESSION["cart_array"]) || count($_SESSION["cart_array"]) < 1) {
// RUN IF THE CART IS EMPTY OR NOT SET
$_SESSION["cart_array"] = array(0 => array("item_id" => $pid, "quantity" => 1));
} else {
// RUN IF THE CART HAS AT LEAST ONE ITEM IN IT
foreach ($_SESSION["cart_array"] as $each_item) {
$i++;
while (list($key, $value) = each($each_item)) {
if ($key == "item_id" && $value == $pid) {
// That item is in cart already so let's adjust its quantity using array_splice()
array_splice($_SESSION["cart_array"], $i-1, 1, array(array("item_id" => $pid, "quantity" => $each_item['quantity'] + 1)));
$wasFound = true;
} // close if condition
} // close while loop
} // close foreach loop
if ($wasFound == false) {
array_push($_SESSION["cart_array"], array("item_id" => $pid, "quantity" => 1));
}
}
$head = $_SERVER['HTTP_REFERER'];
//header("location: $head");
echo '<script>location.href="'.$head.'"</script>';
exit();
}?>
<!--My Products item Display-->
<div class="col-md-4">
<div class="product-img product-img-brd">
<img class="full-width img-responsive" src="../../backend/'.$product_img.'" alt="'.$product_name.'">
<a class="product-review" href="pro_single.php?pid='.$id.'">Quick review</a>
<a class="add-to-cart" href="cart.php?pid='.$id.'" ><i class="fa fa-shopping-cart"></i> Add to cart </a>
<div class="product-price">
<span class="title-price">$'.$price.'</span>
</div>
</div>
Instead of making it a link (with an anchor tag <a>), you'll want to write some JavaScript that will use one of the many different ways to call it with AJAX.
A simple version might look like this:
// update <a> in HTML
<a onclick="addToCart(' . $id . ')">Add to Cart</a>
// JavaScript
const addToCart = id => fetch('cart.php?pid=' + id).then(response => { /* do something with response here */ });
This is a simple version, but it gives you an idea. There are tons of guides for AJAX with all the different methods (I prefer the newer fetch(), but there is jQuery.ajax() and pure XMLHttpRequest too, amongst others).
When you use an anchor with a link, it's saying "go to this place", which isn't what you want. Using AJAX, you can pull down data without affecting the flow of the page itself.
Side note: ideally, change your <a> to a <button> as well. This will make it more semantic, since a button is a thing to click to do thing and an anchor is a link to another page.
I'm trying to manage a dynamic menu based on results from tables in my database.
Code below is so far i have come.. But i can't get it to display as i want to.
i have 3 tables in my database looking like this.
ws_categories
id
maincat (name of main-category)
ws_subcategories
id
subcat (Name of sub-category)
parentcat (id of main-category)
ws_subsubs
id
subsub (Name of 2nd-sub-category)
parentsub (id of sub-category)
What i want to achieve?
Having a simple vertical menu, that outputs main categories, and onclick, submenue alternatives related to that main category will show, if a sub category has a 3rd submenu/submenues, they will show under..
Code below is so far i have come.. But i don't seem to understand why it output main category several times and not just once..
To be clear, i do not understand how i should use join to achieve this. I want to be able to echo all main categories once, and subcategories once, and if there is one or more 2nd sub categories i want them to echo too.. How do i achieve this with join? is it even possible or am i looking the wrong way?
Thanks in advance.
PHP
<?php
echo '<div class="dl_parent">';
$results = mysqli_query($link, "SELECT * FROM `ws_categories` INNER JOIN `ws_subcategories` ON `ws_categories`.`id` = `ws_subcategories`.`parentcat`;") or die (mysqli_error($link));
while($row = mysqli_fetch_array($results)){
echo '
<div class="dl_parent">
<div class="dl_link">'.$row['maincat'].'</div>
<div class="dl_sub_dd">
<ul>
<li>'.$row['subcat'].'</li>
</ul>
</div>
</div>
';
}
?>
Javascript
$(window).on('load',function(){
//CLICK-HANDLERS=============================
$('.dl_link').click(function(){
var submenu = $(this).parent().children('.dl_sub_dd');
if (submenu.css('display') == 'none') {
$('.dl_sub_dd').hide(); //first hide any previously showing submenu's
submenu.show(); //then show the current submenu
} else {
submenu.hide(); //hide the current submenu again
}
});
});
CSS
/*LINK------------------------*/
.dl_link {
cursor:pointer;
}
/*DROPMENU--------------------*/
.dl_sub_dd {
display:none;
}
Your SQL request will give you for each main category as many rows as it has sub categories:
row 1: maincat1 | subcat1
row 2: maincat1 | subcat2
etc...
You could make a request to select all maincats, and for each maincat, make another request to select all its subcats. Something like this:
PHP
<?php
$results = mysqli_query($link, "SELECT * FROM `ws_categories`;") or die (mysqli_error($link));
while($row = mysqli_fetch_array($results)){
echo '
<div class="dl_parent">
<div class="dl_link">'.$row['maincat'].'</div>
<div class="dl_sub_dd">
<ul>';
$query = mysqli_query($link, "SELECT * FROM `ws_categories` INNER JOIN `ws_subcategories` ON `ws_categories`.`id` = `ws_subcategories`.`parentcat` WHERE `ws_categories`.`id` = " . $row['id'] . ";") or die (mysqli_error($link));
while($row2 = mysqli_fetch_array($query)) {
echo '<li>'.$row2['subcat'].'</li>';
}
echo '</ul>
</div>
</div>
';
}
?>
i am using ul li to display menus, menus fetched from database
$Features = $session->get('Features');
foreach ($Features as $menuItems) {
$order_priority = $menuItems->order_priority;
$name = $menuItems->name;
$path = $menuItems->path;
}
here below the menu listed ,
<li>
<a href="<?php echo Url::to($path);?>">
<?php echo $menuItems->name; ?>
</a>
</li>
my question is i want to display the menu SORT with order_priority [1,2,3,4]?
If your order_priority attribute doesn't repeats. You can try this:
$menu = [];
foreach ($session->get('Features') as $menuItems) {
$menu[$menuItems->order_priority] = Html::a($menuItems->name, $menuItems->path);
}
ksort($menu);
And for generate the list, you can do like this:
echo Html::ul($menu)
But if it does repeat, you could sort the items in your db query like #ustmaestro said in the comments.
I have three db tables.
-Paid
-Partially Paid
-Owes
When someone registers for an account I send their user_id, name, etc to my 'Owes' db table and then output their name into a drag and drop table I have in the 'Owes' column. As of now if I move anyone's name to any other category (Paid/Partially paid) I am not sure how to delete that record from the Owes db and insert the name into the new db table so the changes are permanent.
What's really throwing me off is how to do it with the drag and drop table. I'm not sure how to apply the logic that when something is dropped into that column that the past record is deleted and a new one is added to that specific table or how to make the changes without a submit button or page reload.
What is a way I can do this and how could I structure it?
PHP
<?php
//Payment Section
$con = mysqli_connect("localhost", "root", "", "db");
$paid_run = mysqli_query($con,"SELECT * FROM paid ORDER BY id DESC");
$partially_paid_run = mysqli_query($con,"SELECT * FROM partial_payment ORDER BY id DESC");
$owes_run = mysqli_query($con,"SELECT * FROM owes ORDER BY id DESC");
$paid_numrows = mysqli_num_rows($paid_run);
$partially_paid_numrows = mysqli_num_rows($partially_paid_run);
$owes_numrows = mysqli_num_rows($owes_run);
if($paid_numrows > 0){
while($row = mysqli_fetch_assoc($paid_run)){
$paid_id = $row['user_id'];
$paid_name = $row['name'];
}
}
if($partially_paid_numrows > 0){
while($row = mysqli_fetch_assoc($partially_paid_run)){
$partially_paid_id = $row['user_id'];
$partially_paid_name = $row['name'];
$partially_paid_amount = $row['payment'];
}
}
if($owes_numrows > 0){
while($row = mysqli_fetch_assoc($owes_run)){
$owes_id = $row['user_id'];
$owes_name = $row['name'];
}
}
?>
$(function() {
$( "#paid, #partially_paid, #owes" ).sortable({
connectWith: ".tdPayment",
remove: function(e, ui) {
var $this = $(this);
var childs = $this.find('div');
if (childs.length === 0) {
$this.text("Nothing");
}
},
receive: function(e, ui) {
$(this).contents().filter(function() {
return this.nodeType == 3; //Node.TEXT_NODE
}).remove();
},
}).disableSelection();
});
Table
<table class="paymentTable" id="dragTable">
<tr>
<th class="thPayment">Paid</th>
<th class="thPayment">Partially Paid</th>
<th class="thPayment">Owes</th>
</tr>
<tr>
<td class="tdPayment" id="paid">
<div>
<?php
if ($paid_name == true) {
echo $paid_name;
} else {
echo "No one has paid";
}
?>
</div>
</td>
<td class="tdPayment" id="partially_paid">
<div>
<?php
if ($partially_paid__name == true) {
echo $partially_paid__name . " - " . $partially_paid_amount;
} else {
echo "No one has made a partial payment";
}
?>
</div>
</td>
<td class="tdPayment" id="owes">
<div>
<?php
if ($owes_name == true) {
echo $owes_name;
} else {
echo "Everyone has paid something";
}
?>
</div>
</td>
</tr>
</table>
Here's a rough outline on how to do it. I would recommend using jQuery, a JavaScript library that has a lot of useful stuff for this.
Implement the drag and drop part using jQuery draggable and droppable. A nice guide can be found here.
Write a PHP page that updates the database the way you want it.
Use jQuery to call that page when something is dropped. This can be done using Ajax.
Clarification of part 3
I recommend looking at the photo manager in the droppable documentation to get a full working example of something similar.
For this to work, you need to set up the HTML so it has some class names and some data attributes:
<h1>Owes</h1>
<div class="bin" data-bin-id="1">
<div class="user" data-user-id="5">Eva</a>
<div class="user" data-user-id="8">Anna</a>
</div>
<h1>Partially paid</h1>
<div class="bin" data-bin-id="2">
<div class="user" data-user-id="2">Tom</a>
...
</div>
...
Then we need to implement some javascript that takes care of calling the PHP when the user drops something:
jQuery(".bin").droppable({
accept: ".user",
drop: function( event, ui ) {
//Get the ID of the bin the user was dropped into.
var intBinID = jQuery(this).attr("data-bin-id");
//Get the ID of the user that was dropped.
var intUserID = ui.droppable.attr("data-user-id");
//Make an ajax call to the PHP page.
jQuery.ajax("update.php?binid=" + intBinID + "&userid=" + intUserID);
}
});
In addition you might want update.php to return something to let the JavaScript know if it worked or not, and if it failed abort the drop.
Disclaimar: Since I don't have all the parts of this project set up, I have not tested this code.
An easier way to do this, is by creating an independent User table where you keep all the users. Then, in a separate table like the ones you have already, you just keep the Id of that user (and maybe some information related to how much he owes or has already payed).
This way, when you have to insert or to update any information about the state of the user, you just have to insert/delete the Id of the User from these tables.
The information about the user will always be safe and kept in it's own table.