I have this levelselector.php page, where players can pick one of the levels. This works fine, but I want to add an extra thing. The table of the levels shows the level name, the difficulty, the count of completers (solved), and if the actual player has completed it.
This is the table with the levels
Here's what I want to do with AJAX: If I move the mouse over the CELL which shows how many players have completed the map, I want a little DIV that follows the mouse to show who the completers are. I already have the div which only appeares when the player moves over the "Solved" CELL, but I want to fill this "div" with the completers of the actual map. These completers are stored in a database, in which all the levels are stored with all their parameters, in another file, it doesn't matter.
This is the div which I want to fill with the actual level's completers
I was thinking this way: with Javascript I get the name of the Level name by getting the first "TD"-s innerHTML, and if I could give this name to PHP it would fill the DIV with the completers of the level the mouse over on is.
Here is my script.js code:
function delegate(parent, selector, type, fn) {
function delegatedFunction(event) {
let handler = this;
let target = event.target;
const closest = target.closest(selector);
if (handler.contains(closest)) {
fn.call(closest, event);
}
}
parent.addEventListener(type, delegatedFunction);
}
delegate($("table"), "td[id=completed]", "mouseover", showCompleters);
delegate($("table"), "td[id=completed]", "mouseout", hideCompleters);
async function showCompleters() {
var cursorsdiv = document.getElementById("completers");
cursorsdiv.style.visibility = "visible";
var levelname = this.closest("tr").firstElementChild.innerHTML;
const formData = new FormData();
formData.set("name", levelname);
const response = await fetch('levelselector.php', {
method: "POST",
body: formData
});
const data = await response;
document.addEventListener('mousemove', function(e){
var x = e.clientX;
var y = e.clientY;
cursorsdiv.style.left = x + 20 + 'px';
cursorsdiv.style.top = y + 10 + "px";
} )
}
function hideCompleters() {
var cursorsdiv = document.getElementById("completers");
cursorsdiv.style.visibility = "hidden";
}
(I used this delegate function to add each lines of the table mouseover events)
And here is the levelselector.php's html table part:
<table id="levelsTable">
<tr>
<th>Level</th>
<th>Difficulty</th>
<th>Solved</th>
<th>Completed by me</th>
</tr>
<?php foreach($levels as $level): ?>
<tr id="level">
<td id="levelname"><?= $level['level'] ?></td>
<td><?= $level['difficulty'] ?></td>
<td id="completed"><?= count($level['completed_by']) ?></td>
<td><?php if(in_array($_SESSION['username'],$level['completed_by'])) {
echo "Yes";
} else {
echo "No";
} ?></td>
</tr>
<?php endforeach; ?>
</table>
<div id="completers"><?= CONTENT WITH THE ACTUAL LEVEL'S COMPLETERS ?></div>
<script src="./levels/script.js" type="text/javascript" charset="utf-8"></script>
This DIV with the "completers" id would be the div which displays the completers, according to which level you move the mouse over.
Aaand here is what I could figure out in the PHP part:
<?php
$levels = load_file("levels.json");
if($_POST) {
$levelname = $_POST['name'];
}else {
$levelname = "";
}
?>
But sadly I don't understand how this AJAX works.
The question: How do you properly use AJAX in this case to fill the DIV with different content each line of the table if the mouse is moved over?
Hope you understood my english, thanks for all your help, appreciate it!!!
Peter
Related
Videos come from a folder and are automatically displayed on my website. But I am having a problem at implementing share feature. All I want to do is when share button is pressed, video's whole path like https:\\example.com\vid.mp4 should show up. I tried but it just shows the location of very last video on my page.
My php:
$exten = '.mp4';
$dir = __DIR__ . DIRECTORY_SEPARATOR . "gallery" . DIRECTORY_SEPARATOR;
$videos = glob("$dir*.{mp4}", GLOB_BRACE);
$alt = glob("$dir*.{webm,mp4,ogg}", GLOB_BRACE);
if (count($videos) > 0) { foreach ($videos as $vid) {
$base = basename($vid,'.mp4');
printf("<div class='vi'><video src='gallery/%s' id='basename($vid,'.mp4')' loop='loop'></video>", rawurlencode(basename($vid)));
echo '<div class="sh"><button class="share" onclick="phprun()">SHARE</button></div>' ;
echo "<div class='title'>".basename($vid,'.mp4')."</div></div>";
}}
?>
My js:
var result ="<?php echo('http://victure.freecluster.eu/gallery/'.basename($vid)); ?>"
const copy = document.getElementById("copy");
const h1 = document.getElementById("h1");
const h2 = document.getElementById("h2");
function phprun(){
if (copy.style.display === "none") {
copy.style.display = "block";
} else {
copy.style.display = "none";
}
h1.innerHTML="SHARE: "+"<?php echo(basename($vid,'.mp4')); ?>";
h2.innerHTML=result;
// alert(result)
}
It makes a div appear with video's path but it is showing the path of only one video.
Note:
Keep in mind it is automated.
In short:
How to display path of each video?
You can see working problem here:
Problem
Thanks in advance:)
What you need is to get the onclick target (like explained here) in order to make your content dynamic.
1. 'onclick' event: pass the 'this' parameter to your function phprun(). For an event, 'this' as a parameter refers to the target of the event (the div on which the event has been fired).
<div class="vi">
<video src="..." id="..." loop="..."></video>
<div class="sh">
<button class="share" onclick="phprun(this)"> // <-----(GET THE EVENT TARGET)
<svg class="..."></svg>
</button></div>
<div class="title">Demo from ShazamBolt8</div>
</div>
2. In your function: inject the event target ( phprun(target){...} ) then use it in your logic. Example of code for your function:
function phprun(target) { // <-----( INJECT THE EVENT TARGET)
// get the video element from the target
let videoEl = target.parentNode.parentNode.childNodes[0];
// retrieve the data you want (eg. the video url and title)
let videoUrl = videoEl.getAttribute('src');
let videoTitle = videoEl.documentQuerySelector('.title');
// inject it into the desired containers
h1.innerHTML = 'Share:' + videoTitle;
h2.innerHTML = videoUrl;
// do more stuff...
if (copy.style.display === "none") {
copy.style.display = "block";
} else {
copy.style.display = "none";
}
}
This question already has answers here:
How do I attach events to dynamic HTML elements with jQuery? [duplicate]
(8 answers)
Closed 4 years ago.
I have a school project of making some page, which have to add, remove, modify and sort data from mysql. And i need, to refresh section 3 called "jezdci" or just the table in it. I using load() for that. But its loads only once, when i click on that a second time, nothing happend. Then i have to again refresh the page. And i need to load it again and again. Do someone know, where is a mistake?
You can see it at http://188.75.190.236/host/xhrazd7/www/ZP%20Hrazdira/index1.php
HTML:
<section>
<?php include "vypis.php"; ?>
</section>
JS:
$(document).ready(function(){
$(".serad > td").click(function(){
y = $(this).index();
$("section:eq(2)").load("vypis.php",{
serad:y
},);
alert("Loaded index of td on click with value: "+y);
});
});
PHP:
<?php
include "conn.php";
if(!empty($_POST["serad"])){
$serad = $_POST["serad"];
echo "<script>alert(\"variable succefully sended to PHP with value of \"+$serad);</script>";
}else{
$serad=8;
}
if($serad==0) $SQLprikaz = "SELECT * FROM ZP ORDER BY ID";
if($serad==1) $SQLprikaz = "SELECT * FROM ZP ORDER BY jmeno";
if($serad==2) $SQLprikaz = "SELECT * FROM ZP ORDER BY prijmeni";
if($serad==3) $SQLprikaz = "SELECT * FROM ZP ORDER BY vek";
if($serad==4) $SQLprikaz = "SELECT * FROM ZP ORDER BY bydliste";
if($serad==5) $SQLprikaz = "SELECT * FROM ZP ORDER BY ulice";
if($serad==6) $SQLprikaz = "SELECT * FROM ZP ORDER BY kategorie";
if($serad==7) $SQLprikaz = "SELECT * FROM ZP ORDER BY zaplaceno";
if($serad==8) $SQLprikaz = "SELECT * FROM ZP";
$result = $conn->query("$SQLprikaz");
echo "<table>";
echo"<tr class=\"serad\"> <td><p>Pořadí</p></td> <td><p>Jméno</p></td> <td><p>Příjmení</p></td> <td><p>Věk</p></td> <td><p>Bydliště</p></td> <td><p>Ulice</p></td> <td><p>Kategorie</p></td> <td><p>Zaplaceno</p></td> </tr>";
while($zaznam=$result->fetch_array(MYSQLI_NUM)){
echo"<tr> <td>$zaznam[0]</td> <td>$zaznam[1]</td> <td>$zaznam[2]</td> <td>$zaznam[3]</td> <td>$zaznam[4]</td> <td>$zaznam[5]</td> <td>$zaznam[6]</td> <td>$zaznam[7]</td> </tr>";
}
echo "</table>";
?>
And sorry for my poor english :D
PS: Když by se tu našel někdo hodný z Česka nebo Slovenska a měl chvíli času, budu rád, když mě zkontaktujete. Dík < some boring notes in my native language
and Thanks a lot!
As haï_uit mentioned it's because there's no event attached to the next table. You can get around this by targeting an element that will always be in the page and using the on Method like so:
$(document).ready(function(){
$("body").on("click", ".serad > td", function(){
y = $(this).index();
$("section:eq(2)").load("vypis.php",{
serad:y
},);
alert("Loaded index of td on click with value: "+y);
});
});
The problem is here :
$(document).ready(function(){
$(".serad > td").click(function(){
y = $(this).index();
$("section:eq(2)").load("vypis.php",{
serad:y
},);
alert("Loaded index of td on click with value: "+y);
});
});
After your ajax load successfully, your old table which has "td" attached to click event is replaced by new table which doesn't have "td" with click event. So in your ajax load function, you must add click event for your table again after it load successfully. Another solution is just replace the data rows, not the whole table.
First option, you can add the click event again :
$(document).ready(function(){
var tabs = $('.serad > td');
tabs.click(changeTabs);
function changeTabs() {
y = $(this).index();
$('section:eq(2)').load('vypis.php',{
serad:y
}, function () {
tabs = $('.serad > td');
tabs.click(changeTabs);
});
}
}
Second option, only load table content:
Change your html file to this :
<section>
<table>
<tbody id="tabs">
<tr class="serad">
<td>
<p>Pořadí</p>
</td>
<td>
<p>...</p>
</td>
</tr>
</tbody>
<tbody id="content">
<?php include "vypis.php"; ?>
</tbody>
</table>
</section>
in php file, only echo the rows :
while($zaznam=$result->fetch_array(MYSQLI_NUM)){
echo"<tr> <td>$zaznam[0]</td> <td>$zaznam[1]</td> <td>$zaznam[2]</td> <td>$zaznam[3]</td> <td>$zaznam[4]</td> <td>$zaznam[5]</td> <td>$zaznam[6]</td> <td>$zaznam[7]</td> </tr>";
}
and finally, in your script :
$(document).ready(function() {
$('.serad > td').click(function () {
y = $(this).index();
$.post('vypis.php', { serad: y }, function (response) {
$('#content').html(response);
});
});
});
I am using js and php to build an app. I've used a foreach loop in php to create buttons for each row fetched from mysql table. Each button has a unique value (row id).
If someone clicks on of the buttons (each with unique id), there will be a total likes count that holds how many times a button is clicked.
If we have three buttons, and button 1 is clicked, then total likes will be increase by 1. if the same button is clicked again, then the value would decrease by 1.
However, if two buttons of different values are clicked, the total likes add.
When using js, I cant get each button id to pass to the js function loaded from the foreach loop. only the last button value loads to the js function.
Here is what i've tried. the js works but it doesnt apply to each button of the foreach loop.
My Code
<?php foreach($values as $value){
$value['button_id'];
<!-- button --->
<button id="button"
class="button-<?= $value['button_id']; ?>"
value="<?= $value['button_id']; ?>"
onclick="showUser(this.value)" >LIKE
</button>
<!-- button --->
} ?>
<script>
var i = parseInt(document.getElementById('button').value, 10);
var x = i;
function showUser(this.value) {
/// changing value //
if (x == i){
i++;
document.getElementById('button').value = i;
}
else {
i = x;
document.getElementById('button').value = i;
}
}
</script>
Here is an illustration explaining what I mean
Thanks in advance
<script>
var likes = new Array();
function calc(value) {
if(likes[value] == 0 || !likes[value]) {
likes[value]=1;
} else {
likes[value]=0;
}
var sum=0;
for(i=0; i<likes.length; i++) {
if(likes[i]==1){ sum ++ }
}
document.getElementById("total").innerHTML = sum;
}
</script>
<div id=total>0 </div>
<?php
$values = [1,2,3]; //here you can generate values
foreach($values as $value){
?>
<button id="button"
class="button-<?php echo $value; ?>"
value="<?php echo $value; ?>"
onclick="calc(<?php echo $value; ?>)" >LIKE
</button>
<?php
} ?>
<script>
var i = parseInt(document.getElementById('button').value, 10);
var x = i;
function showUser(this.value) {
/// changing value //
if (x == i){
i++;
document.getElementById('button').value = i;
}
else {
i = x;
document.getElementById('button').value = i;
}
}
</script>
I am trying to show child nodes(If option selected is 'Yes') based on the indent value. indent0-> parent node , indent1 - child node.
Sort-order is the order in which nodes are placed in DB.
$( "body" ).on( "click", ".js-show-aspects", function(event) {
var displayLabel = $(this).data('meta-value');
var sort_order = $('.js-data-selector.active:first').data('sort-order');
var indent = $('.js-data-selector.active:first').data('indent');
var rowCount = $('#show_aspects td').length;
for (var i=0;i<rowCount;i++)
{
var hasindent0 =$(this).next().hasClass("indent0");
if((displayLabel=='Yes') && (hasindent0== false)) {
child1 = $("table tr td").filter(function() {
return $(this).prop("class").match(/indent/)});
child = child1.addClass(function (index){ return "sort-order"+(sort_order+1)});
}
}
});
HTML
In the below html, $aspects gets all the nodes from DB,
<tbody>
<? foreach($aspects as $a) { ?>
<tr id="show_aspects" class="js-data-selector
<?=($a['active'] == 0) ? "text-warning" :""; ?> "
data-sort-order="<?= $a['sort_order'] ?>"
data-indent="<?= $a['indent']?>" align="left"
data-taxonomy-id="<?=$a['taxonomy_id']?>">
<td class="indent<?=$a['indent']?>
sort-order<?=$a['sort_order']?>"
data-indent="<?= $a['indent']?>">
<? if($a['active'] == 0) {
echo '<strong class="pull-right text-warning">Inactive</strong>';
} ?>
<?=$a['aspect_label']?> :
<span class="aspect-data" data-taxonomy-id="<?=$a['taxonomy_id']?>"></span>
</td>
</tr>
<?}?>
</tbody>
But I am unable to get the child nodes displayed. Any idea how to sort this out?
Edited the question with the HTML content..
It is difficult to understand exactly what you are trying to do with the question in its current form, but if you want to hide or show child nodes with jQuery, it can be done with $("#id").children().hide(); and $("#id").children().show();.
(Where "#id" is the ID of the parent DOM node.)
children() also takes a selector as an argument in case you only want specific children hidden/shown: http://api.jquery.com/children/
(If you clear up your question a bit, it would be possible to give a more appropriate answer)
I have this problem. I can't figure what's wrong with my code. All i need to do is to hide the inline edit image button whenever the $principal_amt==$balance_amt but my code does nothing. Here's my code:
// Edit image button:
<td <?php echo $rowclass; ?>>
<?php echo $html->linkWithImage('Edit','cashadvance/update/' . $cashadvance["id"], array(), 'editicon.png', array('class' => 'try')); ?>
</td>
//JS:
$("#principal_amt").change(function(){
var principal = $("#principal_amt").val();
$("#balance_amt").val(principal);
if("#balance_amt" == "#principal"){
$('.try').show(true);
}
else{
$('.try').hide(true);}
});
you are comparing with the the ID's not there values in if("#balance_amt" == "#principal")
that should be :
$("#principal_amt").change(function(){
var principal = $("#principal_amt").val();
$("#balance_amt").val(principal);
if($("#balance_amt").val() == principal){
$('.try').show(true);
}
else{
$('.try').hide(true);}
});
you compare two different string:
if("#balance_amt" == "#principal"){
This means: if the string #balance_amt = #principal then.. but this is always false.
If I understand well your problem try to change to this your code:
$("#principal_amt").change(function(){
var principal = $("#principal_amt").val();
$("#balance_amt").val(principal);
if($("#balance_amt").val() == principal){
$('.try').show(true);
}
else{
$('.try').hide(true);
}
});
In this case is always true...