Background
I am using PHP to created a list of voting sections. Each section is the same except for a unique number, which increases by 1 each time the PHP loops.
I use the PHP variable $n as a counter, and place that in the id attributes in several places in each section.
Current PHP/HTML:
echo "<div id='votesection'>";
echo "<h3 id='rating " . $n . "' style='display:block;'>" .
echo "<h3 id='ratingup " . $n . "' style='display:none;'>" . $ratingup . "</h3>\r\n";
echo "<h3 id='ratingdown " . $n . "' style='display:none;'>" . $ratingdown . "</h3>\r\n";
echo "<div class='arrow-down' onclick='downvote($n)'></div>\r\n";
echo "<div class='arrow-up' onclick='upvote($n)'></div>";
echo "</div>";
Goal
When a user clicks on an arrow down or arrow up, certain divs are hidden or displayed. Example, when the up arrow in my second section is clicked, my <h3 id='ratingup2'></h3> would change to visible.
Current JS
function upvote() {
// Script to hide rating, and rating down and display:block ratingup
// Will also need to execture php sql query to increment event rating by one for event by one
}
function downvote(){
// Same script but to show rating down and decrement rating
}
Should I pass every rating id to the script or is there an easier way to do this that I'm missing?
Passing the ID is the easiest way to do it with plain Javascript.
function upvote(n) {
document.getElementById('ratingup ' + n).style.display="block";
document.getElementById('ratingdown ' + n).style.display="none";
}
function downvote(n) {
document.getElementById('ratingup ' + n).style.display="none";
document.getElementById('ratingdown ' + n).style.display="block";
}
A way to do it without passing the ID would be to put classes on the rating DIVs, and pass this instead.
HTML:
echo "<div id='votesection'>";
echo "<h3 id='rating " . $n . "' style='display:block;'>" .
echo "<h3 class='ratingup' style='display:none;'>" . $ratingup . "</h3>\r\n";
echo "<h3 class='ratingdown' style='display:none;'>" . $ratingdown . "</h3>\r\n";
echo "<div class='arrow-down' onclick='downvote(this)'></div>\r\n";
echo "<div class='arrow-up' onclick='upvote(this)'></div>";
JS:
function upvote(self) {
var parent = self.parentNode;
parent.querySelector(".ratingup").style.display = "block";
parent.querySelector(".ratingdown").style.display = "none";
}
function downvote(self) {
var parent = self.parentNode;
parent.querySelector(".ratingup").style.display = "none";
parent.querySelector(".ratingdown").style.display = "block";
}
You can create only one wrapper with the id votesection_id and then do everything else with js/ajax
echo "<div id='votesection_" . $n . "'>";
echo "<h3 id='rating' style='display:block;'>" .
echo "<h3 id='ratingup' style='display:none;'>" . $ratingup . "</h3>\r\n";
echo "<h3 id='ratingdown' style='display:none;'>" . $ratingdown . "</h3>\r\n";
echo "<div class='arrow-down' onclick='downvote($n)'></div>\r\n";
echo "<div class='arrow-up' onclick='upvote($n)'></div>";
echo "</div>";
<script>
function upvote(id){
// 1. Go To the server with ajax do your stuff 2. return the current upvotes 3.replace the upvotes h3 text
}
function downvote(id){
// 1. Go To the server with ajax do your stuff 2. return the current downvotes 3.replace the downvotes h3 text
}
</script>
As #idioteque says in their comment, spaces in element IDs are not allowed. The best way to get this information into the document is probably with data attributes.
Also, multiple elements with the same id are not allowed, what you probably need in this case are classes. (I'm assuming this chunk of HTML will be repeated multiple times per page.)
Borrowing #Barmar's idea of passing this into the event handler, here's how I'd change the server code:
echo "<div class='votesection' data-rating-id=" . $n . ">";
echo "<h3 class='rating' style='display:block;'>" .
echo "<h3 class='ratingup' style='display:none;'>" . $ratingup . "</h3>\r\n";
echo "<h3 class='ratingdown' style='display:none;'>" . $ratingdown . "</h3>\r\n";
echo "<div class='arrow-down' onclick='downvote(this)'></div>\r\n";
echo "<div class='arrow-up' onclick='upvote(this)'></div>";
echo "</div>";
And the JS:
function upvote(self) {
var parent = self.parentNode;
parent.querySelector(".ratingup").style.display = "block";
parent.querySelector(".ratingdown").style.display = "none";
var id = parent.dataset.ratingId;
// do your AJAX or whatever with id
}
function downvote(self) {
var parent = self.parentNode;
parent.querySelector(".ratingup").style.display = "none";
parent.querySelector(".ratingdown").style.display = "block";
var id = parent.dataset.ratingId;
// do your AJAX or whatever with id
}
Related
I am currently reading through a piece of code provided by my faculty and I am having troubles understanding how it works.
Specifically how the anchor is linked to the php without method="post" or method="get".
Kindly appreciate if anyone could explain or link me to relevant materials to do further readings. Much thanks.
if (!isset($_SESSION['cart'])){
$_SESSION['cart'] = array();
}
if (isset($_GET['buy'])) {
$_SESSION['cart'][] = $_GET['buy'];
header('location: ' . $_SERVER['PHP_SELF']. '?' . SID);
exit();
}
for ($i=0; $i<count($items); $i++){
echo "<tr>";
echo "<td>" .$items[$i]. "</td>";
echo "<td>$" .number_format($prices[$i], 2). "</td>";
echo "<td><a href='" .$_SERVER['PHP_SELF']. '?buy=' .$i. "'>Buy</a></td>";
echo "</tr>";
}
Cart for bought items indexes is created in session if it's not there yet.
if (!isset($_SESSION['cart'])){
$_SESSION['cart'] = array();
}
When link with buy query parameter is opened, buy value is added to session cart. After that page is redirected to location without buy parameter.
if (isset($_GET['buy'])) {
$_SESSION['cart'][] = $_GET['buy'];
header('location: ' . $_SERVER['PHP_SELF']. '?' . SID);
exit();
}
List of items to buy is printed on page (i quess code in question is not full).
for ($i=0; $i<count($items); $i++){
echo "<tr>";
echo "<td>" .$items[$i]. "</td>";
echo "<td>$" .number_format($prices[$i], 2). "</td>";
echo "<td><a href='" .$_SERVER['PHP_SELF']. '?buy=' .$i. "'>Buy</a></td>";
echo "</tr>";
}
Links open pages with GET method.
Link query parameters can be accessed by special $_GET variable
I have a php 'search' script that looks for the requested data in a MySQL database and prints a table. Each row of this table can be modified or deleted by clicking on an icon. When you click on one of these icons a javascript function that shows a display is called.
This is the piece of code:
while ($row = mysqli_fetch_row($result)) {
// Define $id
$id = $row[7];
// Sanitize output
$user = htmlentities($row[0]);
$name = htmlentities($row[1]);
$surnames = htmlentities($row[2]);
$email = htmlentities($row[3]);
$role = htmlentities($row[4]);
$access = htmlentities($row[5]);
$center = htmlentities($row[6]);
$message .= "<tr>
<td>" . $user . "</td>" .
"<td>" . $name . "</td>" .
"<td>" . $surnames . "</td>" .
"<td>" . $email . "</td>" .
"<td>" . $role . "</td>" .
"<td>" . $access . "</td>" .
"<td>" . $center . "</td>" .
"<td>" .
"<input type='image' src='../resources/edit.png' id='edit_" . $user . "' class='edit' onclick=edit_user(\"$user\",\"$name\",\"$surnames\",'$email','$role','$access',\"$center\",'$id') title='Editar'></button>" .
"</td>" .
"<td>" .
"<input type='image' src='../resources/delete.png' id='delete_" . $user . "' class='delete' onclick=delete_user(\"$user\",'$role') title='Eliminar'></button>" .
"</td>
</tr>";
}
This is just part of the table I generate. After all this, I encode the table with json_encode and echo it. The echo is captured by an ajax function that decodes it (JSON.parse) and puts it into a div.
The table is correctly rendered and everything works fine with normal characters, but I have detected I can have some problems if I have quotes, slashes and another meaningfull characters. The strings are showed correctly in the table, so there is no problem with php, but the generated javascript doesn't work with some strings.
For example, if I introduce:
</b>5'"
or:
<b>5'6"</b><br><div
as users, when I click on edit or delete icon I get some errors in javascript console:
Uncaught SyntaxError: Invalid regular expression: missing /
home.php:1 Uncaught SyntaxError: missing ) after argument list
Uncaught SyntaxError: missing ) after argument list
Uncaught SyntaxError: Unexpected token ILLEGAL
I have tried with several combination of addslash, replace, htmlentites, htmlspecialchars... but I can't get the right one.
What's the right way to work with this in order to avoid any problem?
Thank you.
EDIT:
I have probed this and it seems to work:
In php I use this function:
function javascript_escape($str) {
$new_str = '';
$str_len = strlen($str);
for($i = 0; $i < $str_len; $i++) {
$new_str .= '\\x' . dechex(ord(substr($str, $i, 1)));
}
return $new_str;
}
and then I use something like
$('<textarea />').html(user).text()
in javascript to decode the string.
Is this safe against XSS attacks?
First, create an HTML-safe JSON string of the array and modify your code to use a data attribute like so:
while ($row = mysqli_fetch_row($result)) {
// Define $id
$id = $row[7];
// Sanitize output
$user = htmlentities($row[0]);
$name = htmlentities($row[1]);
$surnames = htmlentities($row[2]);
$email = htmlentities($row[3]);
$role = htmlentities($row[4]);
$access = htmlentities($row[5]);
$center = htmlentities($row[6]);
$json_str_edit = htmlentities(json_encode(array($row[0], $row[1], $row[2], $row[3], $row[4], $row[5], $row[6], $id)));
$json_str_delete = htmlentities(json_encode(array($row[0], $row[4])));
$message .= "<tr>
<td>" . $user . "</td>" .
"<td>" . $name . "</td>" .
"<td>" . $surnames . "</td>" .
"<td>" . $email . "</td>" .
"<td>" . $role . "</td>" .
"<td>" . $access . "</td>" .
"<td>" . $center . "</td>" .
"<td>" .
"<input type=\"image\" src=\"../resources/edit.png\" id=\"edit_$user\" class=\"edit\" data-user=\"$json_str_edit\" title=\"Editar\"></button>" .
"</td>" .
"<td>" .
"<input type=\"image\" src=\"../resources/delete.png\" id=\"delete_$user\" class=\"delete\" data-user=\"$json_str_delete\" title=\"Eliminar\"></button>" .
"</td>
</tr>";
}
Then create an event listener to catch associated click events in JS like this:
function edit_user(user, name, surnames, email, role, access, center, id) {
// `this` will refer to the html element involved in the event
}
function delete_user(user, role) {
// `this` will refer to the html element involved in the event
}
document.addEventListener('click', function(event) {
if(event.target.hasAttribute('data-user')) {
switch(event.target.className) {
case 'edit':
edit_user.apply(event.target, JSON.parse(event.target.dataset.user));
break;
case 'delete':
delete_user.apply(event.target, JSON.parse(event.target.dataset.user));
break;
}
}
}, false);
Alternatively from the addEventListener method, you can simply add this onclick event listener directly to the element like so (I really don't think it matters in this case):
onclick="edit_user.apply(this, JSON.parse(this.dataset.user))"
FYI It's more common practice to use single quotes in scripts to avoid having to escape the double quote characters. Makes things both cleaner and more standardized.
My question, before I go further with how I did it, is: How can I make this work, and make it easier and better than what I have done?
I have a database with a lot of data, and I am viewing all these in a table. Each <td> has a <div title=""> included, so that all who mouseover each <td> can see more information about that data item. The trouble is, that it's only viewable as a table on mobile devices. To create a hyperlink for a new page is difficult, because that takes the user away from a <table> with comparrision to just that one data information. So I was thinking to use jQuery UI. And was reading a little over the "Basic Dialog" option. I tried to put that into my script, but I see I have way too much data. So I created a file called jq_scripts.php. In there I have a script to create dialog options. But first I include it like this in the header:
<script src=\"//code.jquery.com/jquery-1.10.2.js\"></script>
<script src=\"//code.jquery.com/ui/1.11.4/jquery-ui.js\"></script>
<script src=\"jq_scripts.php\" type=\"text/javascript\"></script>
Then in the script I have put this as a standard:
$(function() {
$( "#dialog" ).dialog({
autoOpen: false,
});
$( "#opener" ).click(function() {
$( "#dialog" ).dialog( "open" );
});
});
But since I have so many different dialogs, I need one #id to each button with unique information, so this is what I have as a script:
echo "\$(function() {\n";
$result = mysqli_query($con, "SELECT * FROM $database WHERE type = 1");
$num = mysqli_num_rows($result);
if(!$result) {
die('Invalid query: ' . mysqli_error($con));
}
while($row = mysqli_fetch_array($result)) {
$id = $row['id'];
foreach($abo as $abo_vis) {
$abo_vis = strtolower(str_replace(' ', '', $abo_vis));
echo " \$( \"#dialog_" . $abo_vis . "_" . $id . "\" ).dialog({\n";
echo " autoOpen: false,\n";
echo " });\n\n";
echo " \$( \"#opener_" . $abo_vis . "_" . $id . "\" ).click(function() {\n";
echo " \$( \"#dialog_" . $abo_vis . "_" . $id . "\" ).dialog( \"open\" );\n";
echo " });\n\n";
}
}
echo "});\n";
This creates a viewing file with 12583 lines!!!
In a <td> I have put this _DATA_ and in the bottom of the viewing file, I have created this:
echo "<div id=\"dialog_" . $abo_vis . "_" . $id . "\" title=\"" . $abo_vis . "\">\n";
echo "<p>" . $dialog_info[$id] . "</p></div>\n\n";
This creates this file to be a lot longer than needed. And on top of that, none of my <a href="#"> works. Actually, the <div id="dialog..."> actually shows, while on the demo it was hidden.
Maybe your problem is the way you are calling it, instead of using IDs use classes:
echo "<div class=\"dialog_" . $abo_vis . "_" . $id . "\" title=\"" . $abo_vis . "\">\n";
I have a php query like so:
<?php
$query = "SELECT * FROM " . $usertable . " ORDER BY fname;";
$result = mysql_query($query);
while($row = mysql_fetch_array($result)){
echo '<option value="' . $row['pkid'] . '">' . $row['fname'] . ' ' . $row['lname'] . '</option>';
}
?>
Within this same .php file I have some javascript. All I would like to do is return $row['fname'] as a a javascript variable.
Is this possible?
If you want to output the PHP variable in a JavaScript variable you could do something like this -
echo '<script>var name+' . $row['pkid'] . ' = ' .$row['fname'] . ';</script>';
This would give you a uniquely named variable for each row.
Right now I have a grid and each grid part/bit contains an image, the name of the item and different buttons that can delete the item from the mysql database and update the price. What I want to do know is that when a user say clicks on the image a window would pop up where extra information would be displayed. However it is not a pop up in a usual sense that it would create another window but rather a pop up within the current window/tab. E.g. When you press on a photo in Facebook it creates almost like a popup on which you can comment or change to the next photo. Does anyone have any idea on how to do this or at least what is the whole thing/process called?
Sorry if I can't give a proper name but I don't know it myself :/
Here is the code to what I have now. I would prefer an actual code solution but if you can lead me to where I should look for it I would also be happy. I tried looking online however everything I get is window pop ups.
<div class="boxes">
<?php
$ID = $_SESSION['SESS_MEMBER_ID'];
$con = mysql_connect("", "", "");
if (!$con){
die("Cannot connect: " . mysql_error());
}
mysql_select_db("test", $con);
$sql = "SELECT * FROM items WHERE member_id = $ID";
$myData = mysql_query($sql, $con);
$dir = 'Images';
$symbol = '\\';
$end = 'r.jpg';
$currency = '£';
while($record = mysql_fetch_array($myData)) {
$real_name = str_replace('_', ' ', $record['Name']);
$result = $dir . $symbol . $record['Name'] . $end;
$value = $currency . $record['price_now'];
$link = $record['url'];
echo "<div class = frame>";
echo "<div class = bit-3>";
echo "<div class = box>" . "<img src=" . $result . " alt=some_text>";
echo "<br />";
echo "<br />";
echo $real_name;
echo "<br />";
echo "<br />";
echo "Price now: " . $value;
echo "<form action = member-profile-page.php method = post>";
echo "Desired price: ";
echo "<td>" . "<input type = text name = desired_price value = " . $record['desired_price'] . " </td>";
echo "<td>" . "<input type = hidden name = hidden value = " . $record['Id'] . " </td>";
echo " ";
echo "<td>" . "<input type = submit name = update value = Update" . " </td>";
echo "<br />";
echo "<br />";
echo "<td>" . "<input type = submit name = delete value = Delete" . " </td>";
echo "<br />";
echo "<br />";
echo "<td>" . "<input type = submit name = buy value = Buy" . " </td>";
echo "</form>";
echo "</div>";
echo "</div>";
echo "</div>";
}
if (isset($_POST['buy'])){
$query = "select url from items where Id = '$_POST[hidden]'";
if ($result = mysql_query($query)) {
$row = mysql_fetch_assoc($result);
$code = $row['url'];
echo "$code";
header("Location: $code");
}
};
if (isset($_POST['update'])){
$UpdateQuery = "UPDATE items SET desired_price = '$_POST[desired_price]' WHERE Id = '$_POST[hidden]'";
mysql_query($UpdateQuery, $con);
};
if (isset($_POST['delete'])){
$DeleteQuery = "DELETE FROM items WHERE Id = '$_POST[hidden]'";
mysql_query($DeleteQuery, $con);
};
mysql_close($con);
?>
</div>
Sounds like you're looking for an overlay:
http://jquerytools.org/demos/overlay/index.html
or a modal:
https://jqueryui.com/dialog/
These are by no means the only examples; there are hundreds of such solutions. These will get you started, though. Good luck!
What you think about is just a layer in the current browser viewport, having some controls to let the user handle it like a "desktop window".
There are quite a lot of JS frameworks offering handy solutions for this, i.e. jQuery UI. Within there, look for "dialog"