I'm trying to learn php, mysql and javascript/jquery by building a live bidding system. I want to refresh the value of a bid button and dropdown automatically, but only if the value has changed. I've made a bidbuttons.php that outputs the buttons after querying the db for the current values, and I load and reload the page with this jquery I found elsewhere. I have tried several different methods of refreshing the div, and the best I came up with unfortunately closed the dropdown on the timer. This current version was described as exactly what I need but doesn't seem to work, in fact it logs me out. would prefer the div to refresh and the dropdown to close ONLY if the bidbuttons.php is updated. This is my first post, I hope I did this right.
<div id="bidbuttons"></div>
<script type="text/javascript">
var loadUrl = "includes/bidbuttons.php?id='.$item->id.'";
$("#bidbuttons").load(loadUrl).fadeIn("slow");
var auto_refresh = setInterval(function () {
$.get(loadUrl, function(data) {
if (data.changed) {
$("#bidbuttons").load(loadUrl).fadeIn("slow");
}
});
}, 10000);
</script>
and my bidbuttons.php
<?php
include_once 'db_connect.php';
include_once 'functions.php';
sec_session_start();
if (login_check($mysqli) == true) {
$getid = (int)$_GET['id'];
// get current price
$result = $mysqli->query("SELECT ammount, bidder_id FROM bids WHERE ammount=(SELECT MAX(ammount)) && item_id like $getid order by ammount desc");
while($row = $result->fetch_assoc()) {
$bidder_id = $row["bidder_id"];
$current = $row['ammount'];
echo ($mysqli->error);
$result->free();
}
//get item info
$results = $mysqli->query("SELECT * FROM items WHERE id like $getid ");
while($row = $results->fetch_assoc()) {
if (empty ($current)) { $current = $row["start"];}
$title = $row["title"];
$item->thenext = ($current + $row["raise"]);
$buyout = $row["buyout"];
$raise = $row["raise"];
$sold = $row["sold"];
}
$results->free();
echo ('<div id="buttons">
<a class="btn btn-primary btn-lg" style="margin-bottom: 10px; margin-top: 10px; width: 80%;" href="includes\placebid.php?itemid=' . $getid . '&ammount=' . $item->thenext .'">Bid $' . $item->thenext . '</a>
');
if ($buyout){echo ('
<a class="btn btn-success btn-lg" style="margin-bottom: 10px; width: 80%;" href="includes\placebid.php?itemid='.$getid.'&ammount='.$buyout.'">Buyout $'.$buyout.'</a>
');}
echo '</div><!-- buttons -->';
echo ('
<div class="dropdown">
<button style="margin-bottom: 10px; width: 80%;" type="button" class="btn btn-info btn-lg dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Custom Bid<span class="caret"></span></button>
<ul class="dropdown-menu">
');
// build the custom bid dropdown
if (!$buyout) { $maxcust = $item->thenext*25;
for ($cust = $item->thenext; $cust <= $maxcust; $cust = $cust + $raise) {
echo ('<li>' .$cust. '</li>');
}
}
if ($buyout) {
for ($cust = $item->thenext; $cust <= $buyout; $cust = $cust + $raise) {
echo ('<li>' .$cust. '</li>');
}
}
echo ('
</ul>
</div><!-- dropdown -->
');
}
mysqli_close($mysqli);
?>
I think the problem may be in that your PHP file is generating HTML which is continually replacing elements on your page due to them being loaded via AJAX.
Just an idea but you could make your PHP output a JSON instead that contains the database results, then have jQuery read the output. Your code would then process that JSON file and create or update the HTML elements accordingly (rather than replace them).
This way you have more fine grained control in the JavaScript for when your dropdown should close.
See this answer if you'd like to output from MySQLi to JSON.
Related
I have two php pages, first page is where I display the data from a MySQL database using Ajax that refreshes every 1 second, the second page contains the php code to fetch the data from the database wherein I have a bootstrap modal that shows the other information of every record.
First php page:
<div class = "container">
<div id = "show_MySql_table_data"></div>
</div>
<script>
//Ajax script for displaying the record every 1 second
var interval = 1000;
function displayData() {
$.ajax ({
url: "details_info.php",
type: "POST",
data: {},
dataType: "html",
success: function(data) {
$("#show_MySql_table_data").html(data);
},
complete: function (data) {
setTimeout(displayData, interval);
}
});
}
setTimeout(displayData, interval);
</script>
Second php page:
<?php
$cn = mysqli_connect("localhost","root","","testdb");
$sql = "SELECT * FROM tblsample";
$result = mysqli_query($cn,$sql);
if (mysqli_num_rows($result) > 0 ) {
while($rows = mysqli_fetch_array($result)) {
$name = $rows['Name'];
$address = $rows['Address'];
echo "<tr>";
echo "<td>" . $name . "</td>";
echo "<td>" . $address . "</td>";
echo "<td><button class = 'toggleDetailsModal btn btn-info'>More Info</button></td>";
echo "</tr>";
}
}
?>
<!-- Modal -->
<div class = "modal" id = "detailsModal">
<div class = "modal-dialog">
<div class = "modal-content">
<div class = "modal-header">
<h5 class = "modal-title">Details</h5>
<button class = "close" data-dismiss = "modal">×</button>
</div>
<div class = "modal-body">
More Information here....
</div>
<div class = "modal-footer">
<button class = "btn btn-danger btn-sm" data-dismiss = "modal">Close</button>
</div>
</div>
</div>
<script> //this is included in the second php page
$(".toggleDetailsModal").on("click", function(e) {
e.preventDefault();
$("#detailsModal").modal('show');
});
</script>
What's happening is when I click More Info button, the modal automatically close and my screen was grayed out.
How can I stop the automatic refreshing of the page (every 1 second) when I click the More Info button and if the Modal is active or in show mode?
Thank you in advance.
There are various ways to determine whether the modal is open or closed, one option is to hook into the bootstrap modal's events:
https://getbootstrap.com/docs/4.0/components/modal/#events
show.bs.modal
This event fires immediately when the show instance method is called. If caused by a click, the clicked element is available as the relatedTarget property of the event.
hide.bs.modal
This event is fired immediately when the hide instance method has been called.
Adding to your existing code:
var modalActive = false;
$("#detailsModal").on("show.bs.modal", function() {
modalActive = true;
});
$("#detailsModal").on("hide.bs.modal", function() {
modalActive = false;
});
function displayData() {
if (!modalActive) {
$.ajax ...
} else {
setTimeout(displayData, interval);
}
}
I'm trying to develop a notification system using jQuery and PHP. So I've created a new table in the database where I'm going to store all the new notifications. Using jQuery I've been able to show an alert (bubble icon) showing the number of new lines added to the database, but I'm now stuck because I don't really know how to update the database (fire update.php file) when I click the icon (.icon-bell) which does activate a drop-down menu.
This is the jQuery script I've added to the index page
<script type="text/javascript">
$(document).ready(function(){
$("#datacount").load("select.php");
setInterval(function(){
$("#datacount").load('select.php')
}, 20000);
});
</script>
This is the HTML code in the index page
<li class="dropdown dropdown-extended dropdown-notification dropdown-dark" id="header_notification_bar">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" data-hover="dropdown" data-close-others="true">
<i class="icon-bell">
</i>
<span class="badge badge-success"><div id="datacount">
</div>
</span>
</a>
<ul class="dropdown-menu" >
<li class="external">
<h3>
<span class="bold">12 pending</span>
notifications
</h3>
view all
</li>
<li>
<ul class="dropdown-menu-list scroller" style="height: 250px;" data-handle-color="#637283">
<li>
<a href="javascript:;">
<span class="time">just now</span>
<span class="details">
<span class="label label-sm label-icon label-success">
<i class="fa fa-plus">
</i>
</span> New user registered. </span>
</a>
</li>
</ul>
</li>
</ul>
</li>
This is the select.php file
<?php
$sql = "SELECT * from tbl_noti where status = 'unread'";
$result = $conn->query($sql);
$row = $result->fetch_assoc();
$count = $result->num_rows;
echo $count;
$conn->close();
?>
This is the update.php file
<?php
$sql = "update tbl_noti set status = 'read'";
$result = $conn->query($sql);
$row = $result->fetch_assoc();
$count = $result->num_rows;
echo $count;
$conn->close();
?>
You can use PHP + Ajax to accomplish this task. I have created a simple notification system and you can easily clone it from GitHub(https://github.com/shahroznawaz/php-notifications).
let's create an index.php file and put the following code. it will create a form. all the data will get by ajax call and updated in the view.
<!DOCTYPE html>
<html>
<head>
<title>Notification using PHP Ajax Bootstrap</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<br /><br />
<div class="container">
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">PHP Notification Tutorial</a>
</div>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<span class="label label-pill label-danger count" style="border-radius:10px;"></span> <span class="glyphicon glyphicon-bell" style="font-size:18px;"></span>
<ul class="dropdown-menu"></ul>
</li>
</ul>
</div>
</nav>
<br />
<form method="post" id="comment_form">
<div class="form-group">
<label>Enter Subject</label>
<input type="text" name="subject" id="subject" class="form-control">
</div>
<div class="form-group">
<label>Enter Comment</label>
<textarea name="comment" id="comment" class="form-control" rows="5"></textarea>
</div>
<div class="form-group">
<input type="submit" name="post" id="post" class="btn btn-info" value="Post" />
</div>
</form>
</div>
</body>
</html>
Now create ajax calls like this:
<script>
$(document).ready(function(){
// updating the view with notifications using ajax
function load_unseen_notification(view = '')
{
$.ajax({
url:"fetch.php",
method:"POST",
data:{view:view},
dataType:"json",
success:function(data)
{
$('.dropdown-menu').html(data.notification);
if(data.unseen_notification > 0)
{
$('.count').html(data.unseen_notification);
}
}
});
}
load_unseen_notification();
// submit form and get new records
$('#comment_form').on('submit', function(event){
event.preventDefault();
if($('#subject').val() != '' && $('#comment').val() != '')
{
var form_data = $(this).serialize();
$.ajax({
url:"insert.php",
method:"POST",
data:form_data,
success:function(data)
{
$('#comment_form')[0].reset();
load_unseen_notification();
}
});
}
else
{
alert("Both Fields are Required");
}
});
// load new notifications
$(document).on('click', '.dropdown-toggle', function(){
$('.count').html('');
load_unseen_notification('yes');
});
setInterval(function(){
load_unseen_notification();;
}, 5000);
});
</script>
You also need to fetch all the records from database and update the status for the notification viewd. create fetch.php file and add the following code:
<?php
include('connect.php');
if(isset($_POST['view'])){
// $con = mysqli_connect("localhost", "root", "", "notif");
if($_POST["view"] != '')
{
$update_query = "UPDATE comments SET comment_status = 1 WHERE comment_status=0";
mysqli_query($con, $update_query);
}
$query = "SELECT * FROM comments ORDER BY comment_id DESC LIMIT 5";
$result = mysqli_query($con, $query);
$output = '';
if(mysqli_num_rows($result) > 0)
{
while($row = mysqli_fetch_array($result))
{
$output .= '
<li>
<a href="#">
<strong>'.$row["comment_subject"].'</strong><br />
<small><em>'.$row["comment_text"].'</em></small>
</a>
</li>
';
}
}
else{
$output .= '<li>No Noti Found</li>';
}
$status_query = "SELECT * FROM comments WHERE comment_status=0";
$result_query = mysqli_query($con, $status_query);
$count = mysqli_num_rows($result_query);
$data = array(
'notification' => $output,
'unseen_notification' => $count
);
echo json_encode($data);
}
?>
Now you will be able to see the notification in navigation bar like this:
when you click the dropdown the status of views notification will update and count will disappear.
To execute PHP asynchronously, you need to use AJAX. jQuery has a few functions for this purpose.
$.ajax: Fully customizable asynchronous request, including error handling, headers, etc.
$.post: AJAX restricted to POST.
$.get: AJAX restricted to GET.
Both $.post and $.get can be accomplished with $.ajax, however they are, in most situations, easier to work with. You most likely will only need $.get in this case, since no additional data is being passed in the request.
Example code:
$.get(
"update.php",
function(result) {
console.log(result)
}
);
Here, result is the data outputted from update.php.
Use ajax to execute the PHP queries so they can execute in real time without page reload.
I have a MySQL database of a bible that I query via php. Right now i'm in the testing phase. Below is my test file where I display a specific Chapter of a Book in a modal. The problem is that I have no idea how to essentially 'display the next chapter (or previous chapter)' when a user clicks the left or right arrow buttons on the footer of the modal.
Currently the test file shows "Genesis 12". How can I allow the user to see Genesis 13 (inside the same modal) when the user clicks the right arrow button (at the bottom)?
<!DOCTYPE html>
<html>
<head>
<?php require "config.php"; ?>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<link rel='stylesheet' type='text/css' href='http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.1.0/css/font-awesome.min.css'/>
<script>
$(document).ready(function() {
$('.btn').click(function() {
$("#myModal").modal('show');
});
});
</script>
<style>
p, span, div { font-family:"Helvetica Neue",Verdana,Helvetica,Arial,sans-serif;font-size:1.3rem;line-height:1.8;}
.selverse { border-bottom:1px dotted blue;}
</style>
</head>
<body>
<button type='button' class='btn btn-success'>Click</button>
<div id="myModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<?php
$book = "Genesis";
$chapter = "12";
$verse = "5";
$v_under = "<span style='text-decoration:underline;'>";
$v_end = "</span>";
echo "<h4 class='modal-title'>".$book." ".$chapter."</h4>";
echo "</div><div class='modal-body'>";
$result = $db->prepare("SELECT * FROM `asv` WHERE Book = :book AND Chapter = :chapter");
$result->BindParam(':book',$book);
$result->BindParam(':chapter',$chapter);
$result->execute();
$y = 0;
while ($row = $result->fetch(PDO::FETCH_ASSOC)){
$bookx = $row['Book'];
$chapterx = $row['Chapter'];
$versex = $row['Verse'];
$versetext=$row["VerseText"];
if ($versex == $verse) {
echo "<span style='color:rgb(57, 128, 57);font-weight:bold;'><sup style='padding-left:0.5em;'>".$versex."</sup></span><span class='selverse' id='v".$versex."'>".$versetext."</span>";
} else {
echo "<span style='color:rgb(57, 128, 57);font-weight:bold;'><sup style='padding-left:0.5em;'>".$versex."</sup></span><span id='v".$versex."'>".$versetext."</span>";
}
}
?>
</div>
<div class="modal-footer" style='text-align:center;'>
<a href='javascript:;'><i style='float:left;margin-left:1em;' class='fa fa-angle-left fa-2x'></i></a>
<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
<a href='javascript:;'><i style='float:right;margin-right:1em;' class='fa fa-angle-right fa-2x'></i></a>
</div>
</div>
</div>
</div>
</body>
</html>
.. Any help will be greatly appreciated!!
You should look into AJAX to do something like that properly, what AJAX basically does is load content after the page has finished loading. So you can get rows out of your database without reloading the page. A very basic approach would be:
Change the href of the arrows to call the JavaScript function loadNew();
<div class="modal-footer" style='text-align:center;'>
<a href='javascript:loadNew('previous');'><i style='float:left;margin-left:1em;' class='fa fa-angle-left fa-2x'></i></a>
<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
<a href='javascript:loadNew('next');'><i style='float:right;margin-right:1em;' class='fa fa-angle-right fa-2x'></i></a>
</div>
Add the loadNew function to your script tag:
<script>
$(document).ready(function() {
$('.btn').click(function() {
$("#myModal").modal('show');
});
});
function loadNew(type){
//We pass the type (previous or next row) and the current ID of the row as GET variables to the fetch.php script
$.get("http://yoursiteurl.com/fetch.php?type="+type, function(data){
$(".modal-header").html(data);
});
}
</script>
Now all that's left is to create the PHP file (fetch.php), that would be something like:
<?php
session_start();
if(!isset($_SESSION['book'])){
$_SESSION['book'] = "Genesis";
$_SESSION['chapter'] = 12;
$_SESSION['verse'] = 5;
}
if($_GET['type'] == 'next'){
//Select the next verse, you are probably going to want to add a check to see if the chapter is available, if not go to the first chapter or something like that
$_SESSION['chapter'] = $_SESSION['chapter'] + 1;
} else{
$_SESSION['chapter'] = $_SESSION['chapter'] - 1;
}
$book = $_SESSION['book'];
$chapter = $_SESSION['chapter'];
$verse = $_SESSION['verse'];
$v_under = "<span style='text-decoration:underline;'>";
$v_end = "</span>";
echo "<h4 class='modal-title'>".$book." ".$chapter."</h4>";
echo "</div><div class='modal-body'>";
$result = $db->prepare("SELECT * FROM `asv` WHERE Book = :book AND Chapter = :chapter");
$result->BindParam(':book',$book);
$result->BindParam(':chapter',$chapter);
$result->execute();
$y = 0;
while ($row = $result->fetch(PDO::FETCH_ASSOC)){
$bookx = $row['Book'];
$chapterx = $row['Chapter'];
$versex = $row['Verse'];
$versetext=$row["VerseText"];
if ($versex == $verse) {
echo "<span style='color:rgb(57, 128, 57);font-weight:bold;'><sup style='padding-left:0.5em;'>".$versex."</sup></span><span class='selverse' id='v".$versex."'>".$versetext."</span>";
} else {
echo "<span style='color:rgb(57, 128, 57);font-weight:bold;'><sup style='padding-left:0.5em;'>".$versex."</sup></span><span id='v".$versex."'>".$versetext."</span>";
}
}
?>
Then save the file and edit the path http://yoursiteurl.com/fetch.php to the correct one.
I have a PHP page that lists a bunch of words that it grabs from a MySQL database table. It displays the words in different sizes based on a count in the table:
<?php
$selectStr = "select * from test";
if ($results = MySQL($dbName, $selectStr))
{
$rowCount = MySQL_NUMROWS($results);
}
$i = 0;
while ($i < $rowCount)
{
echo '<div style="float: left; font-size:' . (MySQL_RESULT($results,$i,'count') * 5) . 'px;">' . MySQL_RESULT($results,$i,'word') . '</div>';
$i++;
}
?>
The trick is that I want the content to display dynamically. So if a user is sitting on the page, and one of the word counts goes up, I want the word to change size without the user refreshing the page.
I am a novice with jQuery. I have used it a bit before, but only using examples. Can someone steer me in a good direction to have my page dynamically change the content without refreshing?
You can auto refresh your page body like this ... give body id='body'
<html>
<head>
<script type="text/javascript">
var auto_refresh = setInterval(
function ()
{
$('#body').load('wordscount.php').fadeIn("slow");
}, 10000); // refresh every 10000 milliseconds
</script>
</head>
<body>
<div id='content'></div>
</body>
Dont forget to include jquery inside your head tag
It calls the file rowfunctie.php every 30000ms and fills the topbar diff with with the result of the getRows function.
<div id="center-rows">
<div id="links">Nu </div>
<div id="rows">
<div id="topbar"></div>
</div>
<div id="rechts"> aantal rijen</div>
</div>
<script type="text/javascript">
function doRequest() {
jQuery("#topbar").fadeOut('slow', function() {
jQuery.ajax({
type: "GET",
url: "rowfunctie.php",
cache: false,
success: function(html){
jQuery("#topbar").html(html);
jQuery("#topbar").fadeIn('slow',function() {
setTimeout('doRequest()',30000);
});
}
});
});
}
doRequest();
</script>
rowfunctie.php should look like this beneath:
<?php
$selectStr = "select * from test";
if ($results = MySQL($dbName, $selectStr))
{
$rowCount = MySQL_NUMROWS($results);
}
$i = 0;
while ($i < $rowCount)
{
echo '<div style="float: left; font-size:' . (MySQL_RESULT($results,$i,'count') * 5) . 'px;">' . MySQL_RESULT($results,$i,'word') . '</div>';
$i++;
}
?>
I have a PHP script to selected records for comments from a database, and then print them onto the page. What I'd like to happen is that if a user is on a page, and another user comments on an item on said page, it automatically appends the new comment to the bottom. The problem I'm having is that I don't know how to differentiate between all of the statuses.
My code for generating the comments on a status is:
<?php
$rt = ("SELECT * FROM (SELECT comment as comment, byuid as byuid, comuid as comuid, likes as likes, dislikes as dislikes, UNIX_TIMESTAMP(timestamp) as timestamp FROM mingle_comments WHERE onuid = '$sid' AND type = 'status' ORDER BY timestamp DESC LIMIT 2) mingle_comments ORDER BY timestamp ASC"); //query
$result = mysql_query($rt) or die (mysql_error());
if(mysql_num_rows($result) >= 2) {
?>
<div id="sa" style="background:#E0E0E0; padding:5px 5px 5px 5px;">
View all comments...
</div>
<?php
}
while($st = mysql_fetch_assoc($result)) {
$comment = nl2br($st['comment']);
$by = $st['byuid'];
$comuid = $st['comuid'];
$time = $st['timestamp'];
$l = $st['likes'];
$d = $st['dislikes'];
$bq = "SELECT * FROM users WHERE uid = '$by' LIMIT 1";
$bqq = mysql_query($bq) or die (mysql_error());
while($bqr = mysql_fetch_assoc($bqq)) {
$dp = $bqr['dp'];
$fbq = $bqr['fname'];
$sbq = $bqr['sname'];
}
?>
<div id="commentbox" class="<?php echo $comuid; ?>" style="padding:5px 5px 5px 5px;">
<div id="cbi" style=" display:inline; position:relative; ">
<img src="<?php if ($dp == null) { echo 'img/unknown_user.jpg'; } else { echo "pf/" . $by . "/" . $dp; } ?>" width="36px" style=" display:inline; position:relative;"/>
</div>
<div id="cbt" style="position:relative; margin-left:32px; margin-top:-35px;">
<?php echo $fbq . " " . $sbq; ?>
<p class="<?php echo $comuid; ?>" style="position:relative; margin-left:5px;"><?php echo $comment; ?></p>
</div>
<div id="clb" style="background:#E0E0E0; padding-left:5px;">
Like<?php echo time_since($time); ?>
</div>
</div>
<?php
}
?>
TL:DR; How can I automatically fetch new comments and append them to the comments generated in the above script without page refresh.
JQUERY
$(document).ready(function(){
var lastcheck='';
setInterval(function() {
$.ajax({
url: 'URL_TO_PHP_SCRIPT',
type: 'POST',
data: {'lastcheck':lastcheck},
success: function(result){
if (result!='nothing_new'){
lastcheck=result.lastcheck /*Update lastcheck*/
var data=result.data;
$.each(data, function(i,val){
//Foreach comment you do what you need, like append, prepend, etc. data[i]."key" to get the value.
});
}
}
});
}, 15000 /* This will check each 15 seconds, you can change it */);
});
PHP SIDE
$lastcheck=$_POST['lastcheck'];
/*
You should add a date field to each new created comment,then filter by "orderby date > $lastcheck" so you get comments since your last check
You get the new comments here
...
...
..
*/
if (!empty($arrayofnewcomments)){
/*The output*/
echo json_encode(array('lastcheck'=>date('Y-m-d H:i:s'),'data'=>$arrayofnewcomments));
}else{/*No new comments*/
echo 'nothing_new';
}
This is some code I came up with, it's a general Idea but it works. It will check each 15 seconds for new comments.