Sorting HTML divs - javascript

I have a database table with a list of images. Each image also has data attached, like a name and value. Using this table, I create HTML code with PHP to make a grid on the screen, each with an image/name/value from the table.
This is my PHP that generates the HTML:
//Makes a div for each item in table
Echo "<li id=div" . $i . ">";
//Content for single grid block
Echo '<center><h3 id="credits' . $i . '">' . $credit_value . " credits" . '</h3></center>';
Echo "<img id='item" . $i ."' src= '$new_link' title='$row[Item_Name]' class='clickableImage' alt='$just_name' data-creditvalue='" . $credit_value . "' data-imagenumber='" . $i . "'border=0 style='position: center; top: 0; left: 0;'/>";
Echo '<center><h3 id="quality">' . $quality . '</h3></center>';
Echo '</li>';
This makes each div named "div1", "div2" etc. In the //content section, printed with the image is data-imageName=$imageName and data-imageValue=$value, though I should be able to attach those to the divs holding the content as well.
What I want to do is add buttons at the top of my page which will sort the image grid by categories. It is currently loaded in order of the items in the database table, but for example, I would have a button that could be clicked after the grid is loaded, which changes the orders of all the divs, so they are in alphabetical order, or lowest->highest valule.
How can I do this?
EDIT: Here is an example of the html generated by the above code.
<li id="div2">
<center>
<h3 id="credits2">108 credits</h3>
</center>
<div style="position: relative; left: 0; top: 0;">
<img id="item2" src="http://steamcommunity-a.akamaihd.net/economy/image/fWFc82js0fmoRAP-qOIPu5THSWqfSmTELLqcUywGkijVjZYMUrsm1j-9xgEObwgfEh_nvjlWhNzZCveCDfIBj98xqodQ2CZknz56P7fiDz9-TQXJVfdSXfgF9gT5DBg-4cBrQJnv8eMDKgnutIGTZeEpYt8dH5LTU_ePNwj-uE9s1aZVepTb9Czu33zpJC5UDL2Z8FjG/155fx118f" title="AK-47 | Blue Laminate (Minimal Wear)" class="clickableImage" alt="AK-47 | Blue Laminate " data-creditvalue="108" data-imagenumber="2" border="0" style="position: center; top: 0; left: 0;">
<img src="images/tick.png" id="tick2" class="hidden" style="position: absolute; top: 0px; left: 70%;">
</div>
<center>
<h3 id="quality">Minimal Wear</h3>
</center>
</li>

It's pretty easy to sort nodes with jQuery (and in pure JS actually too). You need to use sort methods which delegates to Array.prototype.sort, just provide custom comparator functions.
In your case you want to be able to sort by string title as well as by number, so I would create two separate functions and use them depending on what button was clicked:
<button onclick="sort('title', 'string')">Sort by name</button>
<button onclick="sort('data-creditvalue', 'number')">Sort by value</button>
and sort function will be
var comparators = {
string: function(a, b) {
return a.localeCompare(b);
},
number: function(a, b) {
return Number(a) - Number(b);
}
};
function sort(attr, type) {
var $container = $('ul'),
$li = $container.find('li');
$li.sort(function(a, b) {
var aVal = $(a).find('img').attr(attr),
bVal = $(b).find('img').attr(attr);
console.log(aVal)
return comparators[type](aVal, bVal);
}).appendTo($container);
}
Demo: http://plnkr.co/edit/lLJ0AWlLvwDeInBEIYCb?p=info

Depends where you want to have the sorting done.
Do you want the sorting done on the server or on the client?
SERVER SIDE: Your column headers would need to link back to the server and pass a SQL parameter to update your SQL query. This wouldn't be the prefered way. It would refresh the page every time you sorted.
CLIENT SIDE: You could use a jQuery plugin, like DataTable, to do the sorting.
CLIENT SIDE (Ajax): Here is some good detail already published

Related

Best way to Programatically write HTML [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
What would be the best way to go about programatically writing many lines of HTML in the following format:
<div class="grid-item"> <img src="gifs/image-GLITCH.gif" alt="image-GLITCH"/> </div>
<div class="grid-item"> <img src="gifs/image.gif"
alt="image"/> </div>
<div class="grid-item"> <img src="gifs/image-GLITCH.gif"
alt="image-GLITCH"/> </div>
The end result is a grid of gifs where the center column contains a normal image, while the left and right columns contain "GLITCH" versions of the image.
Desired end result: many many rows of the following:
https://i.stack.imgur.com/nG08z.jpg
I've thought about using php like:
$images = glob("gifs/*.gif}");
foreach($images as $image) {
echo <div class="grid-item"> <img src=$image alt=""/> </div>
}
Please note that the above is not the exact php I would use, I don't know how to exclude search strings with glob (I believe you can't do that). But this question is meant to ask:
"What is the best way to programatically write html in order to create a grid of images like that contained in the attached image." [i.e this question is not about the actual code to write, but instead what method of writing code should be used: javascript? php?]
The best way to go about this would definitely be with PHP (or a different server-side language). And for that matter, you can completely take glob() out of the equation; you don't want to output based on how many images you have, you want to output a fixed number of images so that it results in the pattern you desire.
First, let's take a look at your raw HTML:
<div class="grid-item">
<img src="gifs/image-GLITCH.gif" alt="image-GLITCH" />
</div>
<div class="grid-item">
<img src="gifs/image.gif" alt="image" />
</div>
<div class="grid-item">
<img src="gifs/image-GLITCH.gif" alt="image-GLITCH" />
</div>
Every second row alternates. The only difference is the <img> src and alt.
Now let's say you have a total of 33 of these (start with a glitch and ending with a glitch), giving a 'nice' number. That's really easy to set up in a PHP loop, using modulo. All you need to do is check whether the variable in your loop divided by your desired 'glitch insertion' offset (every second image in my example) has a remainder or not:
<?php
$image_count = 33;
for ($i = 0; $i < $image_count; $i++) {
if ($i % 2 == 0) {
echo '<div class="grid-item"><img src="gifs/image-GLITCH.gif" alt="image-GLITCH"/></div>' . PHP_EOL;
} else {
echo '<div class="grid-item"><img src="gifs/image.gif" alt="image"/></div>' . PHP_EOL;
}
}
Now you have all of the images outputted correctly, just as with the HTML snippet above.
Also, don't forget your quotation marks around your string!
This can be seen working here:
<div class="grid-item"><img src="gifs/image-GLITCH.gif" alt="image-GLITCH"/></div>
<div class="grid-item"><img src="gifs/image.gif" alt="image"/></div>
<div class="grid-item"><img src="gifs/image-GLITCH.gif" alt="image-GLITCH"/></div>
...
Are you after a javascript solution for this?
(function($) {
var imageUrl = "gifs/image.gif";
var markup = glitichify(imageUrl);
$(markup).appendTo($elementToAppendThisTo);
function glitichify(imageUrl) {
var imageUrlParts = imageUrl.split(".");
var glitchImageUrl = imageUrlParts[0] + "-GLITCH" + imageUrlParts[1];
var imageUrls = [glitchImageUrl, imageUrl, glitchImageUrl];
var imageMarkup = imageUrls.map(function(imageUrl, index) {
return '<div class="grid-item"> <img src="' + imageUrl + '" alt="image"/> </div>';
});
return imageMarkup.join("");
}
})(jQuery);
If you dont use an UI framework like React or Vue and no html engine like pug to generate img tags out of a loop you could do it with js. At least the place where you get your images counts. If you want to include your images dynamically from your local folder you should write a server side script to get an array of your images and then you could pass it to js or use it with your server side lang like php.
var data = ['https://picsum.photos/300?random', 'https://picsum.photos/300?random', 'https://picsum.photos/300?random'],
section = document.querySelector('section');
for (var i = 0; i < data.length; i++) {
var img = document.createElement('img');
img.src = data[i];
section.appendChild(img);
}
section {
border: 1px solid #000;
min-width: 50px;
min-height: 50px;
}
<section></section>

PHP- Assigning DIV an ID from databse to display appropriate data

Im new to PHP and have set up a connection to my server with Queries that retrieve data from my database.
One of the Columns im getting is 'NoteID', this also has a 'NoteName' column and a 'Note' column.
I currently have it so for every row of data that is in the Notes table it pulls through as a separate DIV. If you would like to see this please see this page
<!-- Main Body Area -->
<div class="main-container-notes">
<div id="left-box">
<?php
echo "<div style='width: 100%;'>";
while( $noteName = sqlsrv_fetch_array( $resultNotes, SQLSRV_FETCH_ASSOC))
{
echo "<div class='hvr-bounce-to-right1 hover-cursor' style='width: 100%; border-right: 5px solid #00AA88; height: 50px;'>" . $noteName['NoteName'] . "</div>";
}
echo "</div>";
?>
</div>
<div id="right-box">
<!-- This will display the Note Text in the 'Note' column -->
</div>
</div>
<!-- End Main Body Area -->
Above is the HTML/PHP
$getNotes = "SELECT NoteID, NoteName, Note FROM Notes";
Above being my Query
Say on the Notes table i have the following:
NoteID | NoteName | Note
1 | Test Note | This is some text associated with that name
How do i make it so when a user clicks on 'Test Note' it displays 'This is some text associated with that name' in the DIV to the right of it
So i essentially need to give the DIV a 'NoteID' of '1' so it can pull through the Note associated to that ID.
I hope i have explained this correctly. Any help is much appreciated.
Thanks,

PHP/jQuery: Randomly display single div from loop

I have a loop that contains dynamic and multiple divs. I only need to display single div randomly and when refreshing the page it should change the div dynamically
Like for example PHP
for($i= 1; $i<=5; $i++){
echo'<div class="">
this is div '.$i.'
</div>';
}
Output will be
1
2
3
4
5
But i want to only display single div. Other should hide using jquery or php, so whenever i refresh the page it should display any number in the loop randomly
//output-->
//this is div 2
First need to calculate the length of div. Then we hide all other elements and show just the randomly chosen one.
$('.random').hide().eq(Math.floor(Math.random()*$('.random').length)).show();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="random">1</div>
<div class="random">2</div>
<div class="random">3</div>
<div class="random">4</div>
<div class="random">5</div>
You can accomplish this only with PHP.
$array = array("PHP", "CSS", "JavaScript", "jQuery");
$randomItem = $array[array_rand($array)];
<div><?php echo $randomItem ?></div>
You can use both css and php
CSS
.Hide_Divs{display: none;}
PHP
$random = rand(1, 5); // random number between 1 to 5
for($i= 1; $i<=5; $i++){
$ran = ($i !== $random)? 'Hide_Divs' ? '';
echo'<div class="'.$ran.'">
this is div '.$i.'
</div>';
}

Bug with draggable/sortable options

Background: I am working with an e-learning platform that asks students a series of questions with 4 options to determine what career path would suit them best. We recently decided to move towards a configuration where, instead of putting them through the difficult decision of choosing just one #1 option, we would allow them to sort a drag-and-drop list to order the 4 options in their order of preference.
The catch is, the system is designed to still only care about whatever they placed first. Call it reverse psychology, if you will. Each option has a weight of 1-4 - and they don't always show up in that order - so you reorder them, it adds the weight to your running total score, and later on there's ranges of scores that determine where you fit.
The system works great, even if my methods of handling the data are unorthodox (keeping a running total and feeding it back into the URL to be carried along - I'm not worried about tampering because the accuracy of the numbers is for the student's benefit. If they want to tinker with it, they can blame themselves for false results :D)
Here's the bug: If the student does not touch the sorted list - i.e. decides that they like the order of the options as they loaded on the page - the line to update the running total score doesn't run. It only runs if they move something around. Even if the #1 option stays in place but other stuff is moved around, it still works fine - but if they just do not touch it at all, it keeps the value from the previous question, effectively adding "0" to their score and this does affect results.
Code after the jump, but first I figured I would cite specifically the line that updates the total:
.done(function(data) {
var runningTotalNew = parseInt(runningTotalCurrent) + parseInt(data);
document.getElementById("runningTotal").value = parseInt(runningTotalNew);
});
To be completely honest, I jerry-rigged it so bad that I don't even really fully understand how "data" knows what the first option is, but that's where the action happens and it resets a hidden input (that's later passed into the URL) with the new score. It's fairly near the top of the full code:
<script type="text/javascript">
$(document).ready(function(){
$(function() {
$("#qoptions ul").sortable({ opacity: 0.8, cursor: 'move', update: function() {
var order = $(this).sortable("serialize");
var runningTotalCurrent = "<?php echo $_GET['rt']; ?>";
$.get("/logic_getTopRankedItem.php", { rand: Math.random(), sortableData: encodeURIComponent(order) })
.done(function(data) {
var runningTotalNew = parseInt(runningTotalCurrent) + parseInt(data);
document.getElementById("runningTotal").value = parseInt(runningTotalNew);
});
}
});
});
});
</script>
<script type="text/javascript">
function nextQuestion() {
// Some info to figure this out
var totalQuestions = 15;
var currentQuestion = <?php echo $_GET['page']; ?>;
var thisPage = "/questionnaires/skills/";
var completePage = "/questionnaires/skills/complete/";
var userSalt = <?php echo $_GET['salt']; ?>;
// The logic
if(currentQuestion <= totalQuestions) {
var nextQuestion = currentQuestion + 1;
if(nextQuestion <= totalQuestions) {
window.location = thisPage + userSalt + "/" + nextQuestion + "/" + parseInt(document.getElementById("runningTotal").value);
}
if(nextQuestion > totalQuestions) {
window.location = completePage + parseInt(document.getElementById("runningTotal").value);
}
}
if(currentQuestion > totalQuestions) {
// Not possible, 404 it out
window.location = "/404";
}
}
</script>
<?php
// Only show "let's get started" if they're on the first question.
if($_GET['page'] == "1")
{
echo "<div align=\"center\">\r\n";
echo "<h1>let's get started.</h1>\r\n";
echo "</div>\r\n";
}
// Load question/weight data from data file
include($_SERVER['DOCUMENT_ROOT']."/data/questionnaire_skills.php");
// Determine current question from page number
$currentQ = $_GET['page'];
// Determine current running total, which the website sets to 0 at survey start
$runningTotal = $_GET['rt'];
?>
<div style="padding-top: 15px;"></div>
<div style="width: 610px; margin: auto;">
<p style="font-size: 16px;" align="center">
For each option set, <strong>rank the options from <i>most</i> preferred to <i>least</i> preferred</strong> to indicate the skill you'd like to use most in your next career move.
</p>
</div>
<table border="0" align="center" width="625" height="175">
<tr>
<td style="width: 75px; background: url('/images/pref_spec.png') no-repeat;" valign="top"><!-- Preference Spectrum --></td>
<td style="width: 550px;">
<!-- Begin options drag n drop -->
<div id="qoptions">
<ul>
<li id="option_<?php echo $weight[$currentQ][1]; ?>"><?php echo $option[$currentQ][1]; ?>
<div class="clear"></div>
</li>
<li id="option_<?php echo $weight[$currentQ][2]; ?>"><?php echo $option[$currentQ][2]; ?>
<div class="clear"></div>
</li>
<li id="option_<?php echo $weight[$currentQ][3]; ?>"><?php echo $option[$currentQ][3]; ?>
<div class="clear"></div>
</li>
<li id="option_<?php echo $weight[$currentQ][4]; ?>"><?php echo $option[$currentQ][4]; ?>
<div class="clear"></div>
</li>
</ul>
</div>
<!-- End options drag n drop -->
<!-- Start options form handler -->
<form name="optionsHandler">
<input type="hidden" name="runningTotal" id="runningTotal" value="<?php echo $runningTotal; ?>" />
</form>
<!-- End options form handler -->
<!-- Button to push all this data into the next question in an informal cookie -->
<p align="center">
continue ยป
</p>
</td>
</tr>
</table>
Don't worry about the PHP file that it references in /data/ - that's just containing the weights and options and it's just a bunch of arrays. I think this is an issue with the jQuery handling of the sortable data. FWIW, this uses Bootstrap and it's my first foray into both Bootstrap and an application so dense into data processing.

JQuery click slidetoggle only working for the first DIV of PHP repeated DIVS

I have DIVs which are repeated for records in a database via PHP, and I have jquery script which on click should expand a div bellow out.
This is the simple code for the slide, generic stuff:
<script src =
"http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>
<script>
$(document).ready(function(){ // Line A
$("#flip").click(function(){ // Line B
$("#panel").slideToggle("slow"); // Line C
});
});
</script>
<body>
<div style="background:red" id="flip">Click to slide the panel down or up</div>
<div style="background:green" id="panel">Oh Hello There</div>
#panel {
display:none;
}
Fiddle: http://jsfiddle.net/hpvgp/3/
However when I try and apply this to my code where I have the divs looped out, it only works for the first div.
Current code:
<?php
$webserver = 'localhost';
$administrator = 'root';
$password = '';
$db_name = 'cdb';
$db = mysqli_connect($webserver, $administrator, $password, $db_name)
or die('Error connecting');
if( isset($_REQUEST['page'])) {
$_SESSION['page'] = $_REQUEST['page'];
}else{
$_SESSION['page'] = 1;
}
$records_per_page = 8;
$query = "SELECT * FROM cars";
$result = mysqli_query($db, $query)
or die("Error in query: '$query'");
$row = mysqli_fetch_assoc($result);
$i = 0;
$start = ($_SESSION['page'] - 1) * $records_per_page;
$end = ($_SESSION['page']) * $records_per_page;
while($row = mysqli_fetch_assoc($result) and $i < $end) {
$i++;
if( $i > $start )
{;
echo'
<div><br><br>
<div id="flip" class="navbar navbar-inverse" style ="margin-top:-40px; height:128px">
<div style="float:left; height:100px; width:200px">
<img src="'.$row['logo'].'" style="margin:10px; float:left" height="100"/></div>
<div style="float:left"><h2>'.$row['make'].' '.$row['model'].'</h2></div>
</div>
</div>
<div><img id="panel" style="padding-bottom: 100px" src="images/cars/'.$row['carIndex'].'.jpg" height="300"/><div> ';
}
}
I'm currently using Bootstrap, not sure if that would matter.
I find it really strange that this would work for the first DIV but not any of the following ones. Do I perhaps need to place the script somewhere else? I'm really lost on this.
Any help appreciated -Tom
IDs are expected to be unique. Never use the same id more than once in a document. Change your code to:
while($row = mysqli_fetch_assoc($result) and $i < $end) {
$i++;
if( $i > $start )
{
echo'
<div><br><br>
<div class="flip navbar navbar-inverse" data-panel="panel_' + $i . '" style ="margin-top:-40px; height:128px">
<div style="float:left; height:100px; width:200px">
<img src="'.$row['logo'].'" style="margin:10px; float:left" height="100"/></div>
<div style="float:left"><h2>'.$row['make'].' '.$row['model'].'</h2></div>
</div>
</div>
<div><img id="panel_' . $i . '" style="padding-bottom: 100px" src="images/cars/'.$row['carIndex'].'.jpg" height="300"/><div> ';
}
}
And now chang your javascript to:
<script>
$(document).ready(function(){
$(".flip").click(function(){
var panelId = $(this).attr('data-panel');
$('#' + panelId).slideToggle("slow")
});
});
</script>
This way your IDs are unique, and each panel is related to its 'flip' div via a custom attribute (data-panel) that contains the panel's ID.
You're assigning the same ID to multiple divs. An ID is, by definition, unique. If you set the same ID on more than one element then your HTML will be invalid and all bets are off. jQuery will use GetElementByID () to select which element to grab when you pass it an ID, and the behaviour of GetElementByID when there's more than one element with the same ID is undefined. It could in theory do anything (throw an exception, return the first matching element, select the last matching element, select a single matching element at random, make demons fly out of your nose, etc).
As you want your code to affect more than one element, then all those elements have something in common. Therefore they all belong to the same class of elements, and you should use class="someclass" to indicate which elements belong to that class. HTML like:
<div class="flip navbar navbar-inverse" style ="margin-top:-40px; height:128px">
JS like:
$(".flip").click(function(){ // Line B
As an advice that works at least for me, when I'm using classes for bind functions, I like to difference that class to the others, so I add the prefix "js-" to the class. That way I'll know that it's not a design class, that an event is bind to that class and that class should not be removed. So I'll use "js-flip" instead "flip". But it is just and advice as good practises and some people cannot be agree with me, but it has been quite useful in projects where more than one person were touching the same code. Also I will not add css styles to that class because the porpoise of it is only programmatic, so it will be transparent for the designers.

Categories

Resources