Door
Fabian W
op 07-03-2015 16:24
gewijzigd op 07-03-2015 16:25
4.489 views
Ik heb een database met allerlei hitlijst data over een nummer. Ik wil niet alle data in een tabel zetten, maar de meeste data pas ophalen als er op een bepaald nummer wordt geklikt (tabel row). In een div op de pagina moet dan meer data over dat bepaalde data verschijnen. Hieronder leg ik het met afbeeldingen nog een keer uit.
Kan iemand me hierbij helpen? Ik vind het behoorlijk lastig om dynamisch data uit de database te halen en dit met een javascript functie (waarschijnlijk) te linken aan de user-interface.
Ik heb een database die uit de volgende twee tabellen bestaat:
songs:
ID (PK, A_I)
Title
Artist
Image
pchart:
ID (PK, A_I)
Rank
Jaar
Week
ID_Songs (komt overeen met songs.ID bij een joint)
Dit is hoe ik nu gegevens uit de database haal, maar zoals gezegd wil ik dus niet alle data in een keer showen:
<?php
$sql = "SELECT c.songid, s.title, s.artist, s.image, c.rank this_week, COALESCE(p.rank, '---') last_week,
COUNT(g.rank) total_weeks, MIN(g.rank) peak_position, (41 * COUNT(g.rank)-SUM(g.rank)) points
FROM pchart c
JOIN songs s
ON c.songid = s.id
LEFT JOIN pchart p
ON c.songid = p.songid AND p.week=".$last_week." AND p.year=".$last_year."
LEFT JOIN pchart g
ON c.songid = g.songid
WHERE
c.week= ".$this_week." AND c.year= ".$this_year."
GROUP BY this_week, c.songid, s.title, s.artist, last_week
ORDER BY this_week";
Het is in wezen simpel:
Als je ergens overheen hovert (misschien met een bepaalde timeout) moet er extra informatie opgehaald worden. Dit kan JSON zijn, of HTML, of wat dan ook. Wat belangrijk is, is dat je op een of andere manier kunt bepalen *welke* informatie je precies op wilt halen.
Hierbij hoef je het wiel niet (helemaal) opnieuw uit te vinden. Je kunt bijvoorbeeld jQuery gebruiken om het volgende te maken: indien je over een (collectie van) element(en) hovert, pluk je informatie uit dit element (bijvoobeeld een song-id), en deze gebruik je om hier via een AJAX-call een scriptje aan te spreken dat je meer informatie teruggeeft over dit song-id. Vervolgens kun je deze informatie (zoals eerder aangegeven, dit kan van alles zijn) ergens neerplakken of tonen. Ik denk dat het meeste werk nog zit in de grafische afwerking van dit alles.
Het klinkt alleen niet alsof je al veel met jQuery gewerkt hebt.
Tweede stap die ik maak is het omzetten van php data naar javascript.
<script type="text/javascript">
var this_week = <?php echo json_encode($this_week) ?>;
var last_week = <?php echo json_encode($last_week) ?>;
var artist = <?php echo json_encode($artist) ?>;
var title = <?php echo json_encode($title) ?>;
var image = <?php echo json_encode($image) ?>;
var peak_position = <?php echo json_encode($peak_position) ?>;
var total_weeks = <?php echo json_encode($total_weeks) ?>;
var points = <?php echo json_encode($points) ?>;
alert(title[16]);
alert(this_week[16]);
</script>
In stap 2 zie ik meteen dat er een probleem opgetreden is al bij stap 1. Waar de title nog prima wordt opgeslagen, wordt this_week[16] opgeslagen als "1" ipv "16". 32 wordt bijvoorbeeld opgeslagen als 3. Wat is de oorzaak hiervan?
Dit gaat niet werken in combinatie met een AJAX-call denk ik. Wat je in je AJAX-call onder andere aangeeft is het type data wat je terugverwacht. Dit doe je met de dataType parameter, en kan bijvoorbeeld JSON zijn. Maar dan moet de "response" enkel JSON bevatten, en geen script-tags of wat dan ook.
Stel dat je via je AJAX call script.php aanroept (met een aantal parameters die aangeven welke informatie je nodig hebt uiteraard), dan moet je op de volgende manier je response opstellen:
<?php
// verzamel je data in $data (een array van arrays)
// ...
// verstuur je antwoord op de goede manier
header('Content-Type: application/json; charset=UTF-8');
echo json_encode($data);
?>
Wat je ook zou kunnen doen is de HTML-output rechtstreeks genereren als "response". In je dataType parameter vul je dan 'html' in. Dat lijkt mij in dit geval een stuk makkelijker? Anders moet je met die JSON via JavaScript allerlei HTML gaan opbouwen ofzo? Dat kan ook direct. En in je AJAX-call geef je vervolgens aan waar je de HTML moet neerploppen.
// Laat de browser netjes weten dat het JSON is
header('Content-Type: application/json');
// enige verplichte GET variabele is id.
if(isset($_GET['id']) === FALSE)
{
echo json_encode(array( 'status' => 'error',
'error' => 'Geen GET variabele met id gekregen.'));
exit;
}
Het plan is dat ik de main table met de hele top 40 en de sidebar met extra info over een nummer (row onclick) op dezelfde pagina wil weergeven, met het form ook ergens in een div.
Ik weet niet hoever we al in de richting komen, maar dit is zo'n beetje wat ik nu dan heb:
index.php:
<div id="content_changing_select_tag">
<form id="access_database" method="POST" action="artist-json.php">
<select id="week1" name="week1"><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option><option value="7">7</option><option value="8">8</option><option value="9">9</option><option value="10">10</option><option value="11">11</option><option value="12">12</option><option value="13">13</option><option value="14">14</option><option value="15">15</option><option value="16">16</option><option value="17">17</option><option value="18">18</option><option value="19">19</option><option value="20">20</option><option value="21">21</option><option value="22">22</option><option value="23">23</option><option value="24">24</option><option value="25">25</option><option value="26">26</option><option value="27">27</option><option value="28">28</option><option value="29">29</option><option value="30">30</option><option value="31">31</option><option value="32">32</option><option value="33">33</option><option value="34">34</option><option value="35">35</option><option value="36">36</option><option value="37">37</option><option value="38">38</option><option value="39">39</option><option value="40">40</option><option value="41">41</option><option value="42">42</option><option value="43">43</option><option value="44">44</option><option value="45">45</option><option value="46">46</option><option value="47">47</option><option value="48">48</option><option value="49">49</option><option value="50">50</option><option value="51">51</option><option value="52">52</option></select>
<select id="year1" name="year1"><option value="2015">2015</option><option value="2014">2014</option><option value="2013">2013</option></select>
<input id="go_button" name="formsubmit" type="submit" value="Go"/>
</form>
</div>
<div id="container">
<div id="chartlist"></div>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('#go_button').click(function(e) {
$.ajax({
'type': "GET",
'url': "artist-json.php",
'dataType': "json",
'error': function(xhr, status, error){ alert(error.message); },
'success': jsonParser1 // call function
}); // $.ajax
})
});
function jsonParser1(json)
{
HTML = "<table id='chart'> <thead> <tr id='row1'> <th id='vw'>dw</th> <th id='vw'>vw</th> <th id='pic'></th> <th id='song'>artiest</th> <th id='song'>titel</th> <th id='wk'>hp</th> <th id='wk'>wk</th> <th id='wk'>pts</th> </tr> </thead> <tbody>";
var x=json.list;
for (i=0;i<x.length;i++)
{
HTML += "<tr id='row1'><td id='vw'>";
HTML += x[i].this_week;
HTML += "</td><td id='vw'>";
HTML += x[i].last_name;
HTML += "</td><td id='pic'><img src='";
HTML += x[i].image;
HTML += "' width='50px' height='50px'></td><td id='song'>";
HTML += x[i].artist;
HTML += "</td><td id='song'>";
HTML += x[i].title;
HTML += "</td><td id='wk'>";
HTML += x[i].peak_position;
HTML += "</td><td id='wk'>";
HTML += x[i].total_weeks;
HTML += "</td><td id='wk'>";
HTML += x[i].points;
HTML += "</td></tr>";
}
HTML += "</tbody></table>";
document.getElementById("chartlist").innerHTML = HTML;
}
</script>
artist-json.php
<?php
// Laat de browser netjes weten dat het JSON is
header('Content-Type: application/json');
// if form is submitted
if($_POST['formsubmit'] == "Go") {
// form variables
$this_year = $_POST['year1'];
$this_week = $_POST['week1'];
if ($_POST['week1'] == 1) {
$last_year = $_POST['year1'] - 1;
$last_week = '(SELECT MAX(week) FROM pchart WHERE year = ' . $last_year . ')';
}
else {
$last_year = $_POST['year1'];
$last_week = $_POST['week1'] - 1;
}
// sql query
$sql = "SELECT c.songid, s.title, s.artist, s.image, c.rank this_week, COALESCE(p.rank, '---') last_week, COUNT(g.rank) total_weeks, MIN(g.rank) peak_position, (41 * COUNT(g.rank)-SUM(g.rank)) points
FROM pchart c
JOIN songs s
ON c.songid = s.id
LEFT JOIN pchart p
ON c.songid = p.songid AND p.week=".$last_week." AND p.year=".$last_year."
LEFT JOIN pchart g
ON c.songid = g.songid
WHERE
c.week= ".$this_week." AND c.year= ".$this_year."
GROUP BY this_week, c.songid, s.title, s.artist, last_week
ORDER BY this_week";
// save query in array 'data'
while($row = mysqli_fetch_array($mysqli)) {
$data[] = $row;
}
mysqli_close($con);
}
// Als er items in de array 'data' staan
if(count($data)){
$list = array(
'status' => 'ok',
'list' => $data
);
}
else {
$list = array(
'status' => 'error',
'error' => 'niets gevonden.'
);
}
// echo de json string
echo json_encode($list);
?>
Wat ik krijg te zien als ik op 'go' druk is het json file (ipv een html table) en daarvoor nog een alert met 'undefined'. Verder geeft de console aan dat hij een ander MIME type verwacht dan application/json.
Waar zit de fout?
Verder vind ik je korte stukje van het maken van de data array wel heel leuk eigenlijk. :-)