PHP CSS HTML. Huge amount of data, dynamic columns and boxes - php

I have a huge list of data I want to display, 10,000's, with filters hopefully just a few thousand at a time.
Languages: HTML, PHP, CSS
I was thinking of the best way to display this data and thought of an idea I like. I would like to have a box (say a div) with a fixed height (90% or 100% of the screen/browser resolution). No horizontal scrolling. Data would display visually in columns, filling the first column, then the second, third, forth, etc.. as many as required. The boxes would house the columns and increase in number as required downwards (for vertical scrolling). This will need to be dynamic as I will not know what data will be displayed (based on filter), I will not know the users browser size etc..
Made a paint image if that helps more:
http://postimage.org/image/630pxp3sx/
If the box thing is not possible, could you at least tell me how to achieve the coloumn effect.
Hope that makes sense.
Ideally I think I want to achieve this with CSS?
Thanks

The closest you can get with pure CSS is with the columns property, but it won't fill exactly the way you want. The elements will fill from top to bottom, left to right, and divided equally so that all of the columns are as close to the same height as possible.
ul {
columns: 5em; /* some browsers require prefixes (eg. -moz-columns, etc.) */
}
http://jsfiddle.net/VQXH3/
Flexbox could do what you're asking for, but support for it is poor at the moment (IE10+, Opera, Chrome; Firefox is adding support for the new spec soon).
http://jsfiddle.net/VQXH3/1/ (try in Opera, didn't add prefixes to the demo)

If you want the columns to be as even as possible, simply figure out how many results are being displayed beforehand. Then, decide how many columns you want to display them. Say you had 100 results, and wanted to divide them among 5 columns, that would be 20 results for each column. You could do something like this in PHP/MySQL:
<?php
$con = mysql_connect('localhost', 'user', 'pass');
$db = mysql_select_db('data');
$get = mysql_query("SELECT * FROM table");
$columns = 5; // number of columns you want to have
$total = mysql_num_rows($get);
$perCol = ceil($total/$columns);
$counter = 0; // start counter at 0 and increment it as the loop progresses
$data = "<div class=\"column\">\n"; // create blank string for storing results
$counterTotal = 0; // keep track of total results
while($a = mysql_fetch_array($get)) {
$counter++;
$counterTotal++;
if ($counter == 1 ) { // no <br /> tag necessary
$data .= " " . $a['data'];
} else {
if ( $perCol == $counter ) {
$data .= "<br />\n " . $a['data'] . "\n</div>\n<div class=\"column\">\n";
$counter = 0; // reset counter for new column
} else {
$data .= "<br />\n " . $a['data'];
}
}
}
$data .= "\n</div>\n";
echo $data;
mysql_close($con);
?>
If you were wondering why I added all the new lines (\n) and whitespace in the code, it's just to make the source code look nice and pretty. :) Feel free to take that out if you wish, but I like my source code to look nice and readable, even when it's being dynamically generated.
Then if you want the columns to fill the whole width of the screen, you can just inject PHP into the <style> tag in the header, like this: (assuming it's on the same page as the code above so you can still access the $columns variable)
<style type="text/css">
.column {
float: left;
width: <?= floor(100/$columns); ?>%;
margin: 0px;
padding: 0px;
}
</style>
Of course this would only work if there is no remainder in the division, but it should come close even if it isn't a perfect division. Here is the code from a sample page I made to do this:
<?php
$con = #mysql_connect("localhost", "user", "pass");
$db = #mysql_select_db("sampleDB", $con);
$get = mysql_query("SELECT * FROM dataTable");
$columns = 5; // number of columns you want to have
$total = mysql_num_rows($get);
$perCol = ceil($total/$columns);
$counter = 0; // start counter at 0 and increment it as the loop progresses
$data = "<div class=\"column\">\n"; // create blank string for storing results
$counterTotal = 0; // keep track of total results
while($a = mysql_fetch_array($get)) {
$counter++;
$counterTotal++;
if ($counter == 1 ) { // no <br /> tag necessary
$data .= " " . $a['data'];
} else {
if ( $perCol == $counter ) {
$data .= "<br />\n " . $a['data'] . "\n</div>\n<div class=\"column\">\n";
$counter = 0; // reset counter for new column
} else {
$data .= "<br />\n " . $a['data'];
}
}
}
$data .= "\n</div>\n";
#mysql_close($con);
?>
<html>
<head>
<title>Data In Columns</title>
<style type="text/css">
.column {
float: left;
width: <?= floor(100/$columns); ?>%;
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<?= $data; ?>
</body>
</html>
If you'd like to see the results of this code, you can check out the sample that I made here: http://mdl.fm/sample.php
UPDATE: If you'd like to fit the content to the height of the screen and determine the number of columns needed, you would need to manually dictate how many items go in each column, so you would make the following replacements:
// replace this
$perCol = ceil($total/$columns);
// with this
$perCol = 20;
$columns = ceil($total/$perCol);
// the line above will just override the manual declaration of $columns
However, PHP cannot detect the browser's dimensions, so if you want to do that, you can forward to the PHP page again via Javascript with the dimensions included. Here is a piece of sample code you could use, put this in the tag of your page:
<script type="text/javascript">
function getDims() {
var myWidth = 0, myHeight = 0;
if( typeof( window.innerWidth ) == 'number' ) {
//Non-IE
myWidth = window.innerWidth;
myHeight = window.innerHeight;
} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
//IE 6+ in 'standards compliant mode'
myWidth = document.documentElement.clientWidth;
myHeight = document.documentElement.clientHeight;
} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
//IE 4 compatible
myWidth = document.body.clientWidth;
myHeight = document.body.clientHeight;
}
return {
'width' : myWidth,
'height' : myHeight
};
}
function loadDims() {
if ( document.URL.indexOf("?w=") < 0 ) {
var dims = getDims();
window.location.href = '/sample.php?w=' + dims.width + '&h=' + dims.height;
}
}
</script>
Then update your with an onload like this:
<body onload="loadDims();">
At this point, you will know the browser dimensions inside the PHP code, so you can divide the given height by the text-size and see how many items can be contained in one column without the need for scrolling. Again, I have updated my page with this code, so just check it out if you want these complete snippets. Also, if you have any questions implementing them, just contact me through my website (http://mdl.fm) and I'd be glad to help.

Related

How to create two dynamic text columns that run down a page inline with one another

What I'm looking for is a way to print two complete form elements next to each other as they go down a php page. Essentially two columns of repeating elements.
I have a "div" loop that creates multiple elements on my page using the same div I guess? I'm using two variables to set their location on the page as it goes down, ex. ($down += 200, $left += 200) and it works pretty well. The problem I'm facing is that I have to put an excessive amount of space between each element because some parts are 20px tall and some are 50px tall. With the div loop it looks like they're not aware of each other as far as I can tell meaning all the smaller ones cause the next larger element not to move far enough down the page making them overlap. It'd rather not account for each individual one to only have it do extra space on the smaller ones. I feel like there should be a better option for this. I would also like to avoid a table unless someone can show me a table without the table portion and just the formatting.
while ($results = mysqli_fetch_assoc($towerquery))
{
if ($number % 2 == 0 && $number !== 0 ){ $left = 200; $down += 320; }
print '<span style="display:block;position:relative;left:'.$left.'px;top:'.$down.'px;font-family:tahoma;font-size:13px;margin:40px;">';
$down -= 300;
$left += 500;
}
You can always use Flexbox to create equal height divs:
.paddingBlock {
padding: 20px 0;
}
.eqDisplay {
display: flex;
}
.equal {
padding: 10px;
}
.equal:nth-of-type(odd) {
background: darkgreen;
}
.equal:nth-of-type(even) {
background: black;
}
.eqHW {
flex: 1;
}
.eqHWrap {
justify-content: space-between;
color: #eee;
}
<div class="paddingBlock">
<h1>Equal Column Height</h1>
<div class="eqHWrap eqDisplay">
<div class="eqHW equal">
<p>Using</p>
<p>flex</p>
</div>
<div class="eqHW equal">
<p>works</p>
<p>well</p>
<p>despite</p>
<p>content</p>
<p>length</p>
</div>
</div>
</div>
Using that in php you could echo the results:
<?php
$yourVariable = array(1,9,5,12,73);
echo '<div class="paddingBlock"><div class="eqHWrap eqDisplay">';
while (x === x) {
echo '<div class="eqHW equal">' . $yourVariable . '</div>';
}
echo '</div></div>';
?>
The answer above definitely what lead me down the path to victory and dominance of my webpage, but I had to add a separate part to make it work for me which I have posted below
$number = 0;
if ($number % 2 == 0 || $number == 0 ) { print '<div class="eqHWrap eqDisplay">'; }
print '<div class="eqHW equal">';
print '<p>';
//multiple if statements, span elements, line breaks, returns
print '</p>';
if ($number % 2 !== 0 && $number !== 0 ) { print '</div>'; }
print '</div>';
$number++;
This extra code allowed me to only use one div and have it execute as two, because I'm pulling from an array of IPs and I can't get current and get next at the same time due to the coding disasters I kept running into. I assume other people run into the same problem when creating a loop to pull from an array as you can typically only do one at a time in sequence. My code is now successfully working though as seen below in the link!

Even/Odd to determine CSS class

I've read a lot of information about the determination of a even/odd number and using it to change the class of a div.
In my case I want to switch the position of divs called MessagePicture and MessageText every new message posted.
Picture left, Text right
Picture right, Text left
Picture left, Text right
ect.
This is the code I am using to display the messages, I also included one of my tries to get the even/odd code to work.
Can anyone tell me what I should change to get it to work?
<?PHP
$Query =
"
SELECT
ID,
NameBox,
MessageBox,
Code
FROM
messages
ORDER BY
ID
DESC LIMIT 10
";
$Result = mysql_query($Query);
if(!$Result)
{
echo 'ERROR: '.mysql_error();
}
else
{
if(mysql_num_rows($Result) == 0)
{
echo 'No results';
}
else
{
$i = 0;
$class = (++$i % 2) ? 'even' : 'odd';
while
($Row = mysql_fetch_assoc($Result))
echo '
<div id="MessageWrapper">
<div id="MessagePicture" class="'.$class.'">
<style>
#MessagePicture {
background-image: url(../../../Images/'.stripslashes($Row['Code']).'.png);
background-repeat: no-repeat;
background-position: center
</style>
</div>
<div id="MessageText" class="'.$class.'">
<div id="MessageTitle">
<h1>'.$Row['NameBox'].'</h1>
</div>
<div id="MessageContent">
<p>'.nl2br($Row['MessageBox']).'</p>
</div>
</div>
</div>
';}}}?>
Your $i always stays 0. Add $i++ in the while loop to increment it.
You can do that in one line:
$class = ($i++ % 2 == 0) ? 'even' : 'odd';
Full Example:
$i = 0;
while ($Row = mysql_fetch_assoc($Result)) {
$class = ($i++ % 2 == 0) ? 'even' : 'odd';
//echo ...
}
This may not be an answer to your exact problem, but since any markup already carries information on which of child element rows are even and which are odd, and since CSS is able to differentiate between these, you can achieve this using pure CSS, which is what I boldly offer here.
Use CSS selectors :nth-child(even) and :nth-child(odd) to select even and odd children, respectively. That way you also don't have to change or tag your markup. An example:
<ul>
<li>Apples</li>
<li>Oranges</li>
<li>Bananas</li>
<li>Pears</li>
<li>Pineapples</li>
</ul>
li:nth-child(even)
{
background-color: silver;
}
li:nth-child(odd) /* or leave this one out altogether */
{
background-color: white;
}
Check the following, rather authoritative page for more details and usage (like nth-child(5n+3)):
http://www.w3.org/Style/Examples/007/evenodd.en.html

PHP/CSS how to keep my checkboxs from going past my border

Basically I am createing a unknown size of checkboxs that is dependent on the row that is chosen from a table in my database. The reason I dont know the size is that the user chooses which row they will use with some rows containing what will become 10 checkboxs adn others containing as many as 75. So the problem is that if the user selects a row with a large amount of options it goes through the border of my div and then forces me to scroll the page down what I am looking for is a way to say >
if(number of checkboxs is >25 )
create a new column on my page
I dont know whether the right way to go about this is to use php or javascript or possibly do it using css I am new to all of these languages so any help no matter how trivial will greatly appreciated.
<div id="major1">
<?php
$courses=mysql_query("SELECT * FROM MAJORS_CHECKLIST WHERE MAJOR='$major'");
$courses_row=mysql_fetch_row($courses);
$count = 0;
echo "$courses_row[0] <br/>";
$checkit = 0;
$sidebyside = 0;
foreach($courses_row as $i=>$courses_row){
if($courses_row['$count'] == NULL)
{
break;//if we run out of courses stop printing them
}
if($courses_row[$count] == $courses_row[0] && $checkit == 0 )
{
$checkit = $checkit + 1;
}
else
{
echo "<input type='checkbox' value='$courses_row' name='majorCourses[]' /> ";//answer-$i
echo "$courses_row<br /> ";
}
$count = $count + 1;
/*$sidebyside++;
if($sidebyside == 2)//tried using this to put 2 checkboxes side by side that ened up just messing everything up
{
echo "<br/>";
$sidebyside = 0;
}*/
}
?>
here is my css:
#major1{
color: white;
/*border: 1px solid black;*/
padding: 5px;
float: left;
height:500px;
width:150px;
}
Producing a bunch of checkboxes in the div can be controlled using CSS. Should set the parent div of the checkboxes to the following rules: width:auto; height:auto; padding:10px 10px; position:relative; This is all assuming that the parent div of the checkboxes is a child of another div to control the preferred dimensions
edit: if you do not want to want to use css with the methods above, you can control the "X" amount of checkboxes per row. You can create a counter to count how many are being displayed and do a if($counter % X == 0) echo "</div><div>"; This is all assuming you have a starting div at the beginning of your code and an ending div at the end of the code.

Split Data into 3 columns

I have a MySQL table that contains people's names.
Using PHP, what's the best way of dividing these names up and displaying them in 3 columns.
This could be achieved using an HTML table, but would it be possible to do this using only <div>'s?
I heard that this can be done using the % operator. Would this be the best way, and how would this be done?
You could do this using the modulus operator, however it's actually possible with just CSS.
Using display: inline-block, you can get a good column effect. Take a look at this JSFiddle here. I'm only using JavaScript because I'm lazy; the <div> list would be generated by PHP in your case. If you want to confine them to a certain width, just put them in a container <div> with a fixed width.
I've come up with a solution using tables, which is really what you should be doing (you haven't given any special use cases). The code is below, as well as a working demo here.
$columns = 4; // The number of columns you want.
echo "<table>"; // Open the table
// Main printing loop. change `30` to however many pieces of data you have
for($i = 0; $i < 30; $i++)
{
// If we've reached the end of a row, close it and start another
if(!($i % $columns))
{
if($i > 0)
{
echo "</tr>"; // Close the row above this if it's not the first row
}
echo "<tr>"; // Start a new row
}
echo "<td>Cell</td>"; // Add a cell and your content
}
// Close the last row, and the table
echo "</tr>
</table>";
And to finish off, we have our column-centric layout, this time going back to divs. There's some CSS here; this should be put in a separate file, not left inline.
<?php
$rows = 10; // The number of columns you want.
$numItems = 30; // Number of rows in each column
// Open the first div. PLEASE put the CSS in a .css file; inline used for brevity
echo "<div style=\"width: 150px; display: inline-block\">";
// Main printing loop.
for($i = 0; $i < $numItems; $i++)
{
// If we've reached our last row, move over to a new div
if(!($i % $rows) && $i > 0)
{
echo "</div><div style=\"width: 150px; display: inline-block\">";
}
echo "<div>Cell $i</div>"; // Add a cell and your content
}
// Close the last div
echo "</div>";
?>

php recursive list help

I am trying to display a recursive list in PHP for a site I am working on.
I am really having trouble trying to get the second level to display. I have a function that displays the contents to the page as follows.
function get_menu_entries($content,$which=0)
{
global $tbl_prefix, $sys_explorer_vars, $sys_config_vars;
// INIT LIBRARIES
$db = new DB_Tpl();
$curr_time = time();
$db->query("SELECT * FROM ".$tbl_prefix."sys_explorer WHERE preid = '".$which."' && config_id = '".$sys_explorer_vars['config_id']."' && blocked = '0' && startdate < '".$curr_time."' && (enddate > '".$curr_time."' || enddate = '') ORDER BY preid,sorting");
while($db->next_record()){
$indent = $db->f("level") * 10 - 10;
$sitemap_vars['break'] = "";
$sitemap_vars['bold'] = "";
if($db->f("level") == 2) {
$sitemap_vars['ul_start'] = "";
$sitemap_vars['bold'] = "class='bold'";
$sitemap_vars['ul_end'] = "";
}
switch($db->f("link_type"))
{
case '1': // External Url
$sitemap_vars['hyperlink'] = $db->f("link_url");
$sitemap_vars['target'] = "";
if($db->f("link_target") != "") {
$sitemap_vars['target'] = "target=\"".$db->f("link_target")."\"";
}
break;
case '2': // Shortcut
$sitemap_vars['hyperlink'] = create_url($db->f("link_eid"),$db->f("name"),$sys_config_vars['mod_rewrite']);
$sitemap_vars['target'] = "";
break;
default:
$sitemap_vars['hyperlink'] = create_url($db->f("eid"),$db->f("name"),$sys_config_vars['mod_rewrite']);
$sitemap_vars['target'] = "";
break;
}
if($db->f("level") > 1) {
$content .= "<div style=\"text-indent: ".$indent."px;\" ".$sitemap_vars['bold'].">".$db->f("name")."</div>\n";
}
$content = get_menu_entries($content,$db->f("eid"));
}
return(''.$content.'');
}
At the moment the content displays properly, however I want to turn this function into a DHTML dropdown menu.
At present what happens with the level 2 elements is that using CSS the contents are indented using CSS. What I need to happen is to place the UL tag at the beginning and /UL tag at the end of the level 2 elements.
I hope this makes sense. Any help would be greatly appreciated.
Instead of using <div> tags with indentation, use an unordered list for each level, including the first one. Have your function output <ul> at the start and </ul> at the end, and change <div style="text-indent: ..."> to a simple <li>. Give the first level an ID so you can hook onto it. Then you can use CSS to remove bullet points and change the indentation, etc. You don't need to calculate the indentation or whether to bold the text in PHP—instead, use selectors and allow the browser to figure it out:
ul#menu { margin: 0; padding: 0; }
ul#menu > li { margin: 0; padding: 0; }
ul#menu > li > ul { margin-left: 10px; font-weight: bold; }
All this will allow you to use one standard algorithm for generating your list, instead of branching based on the level, as well as making the menu look like a menu to web crawlers, search engines and those with CSS-less browsers.
By the way, you should really be htmlspecialchars-ing all that dynamic text. You don't want a stray < to mess up your markup.
Correct me if I'm wrong, but it seems that your issue is not that you don't know when to print the first set of <ul> tags, but that you are trying to print the second set (for level 2) in every function call, and thus ending up with too many open/close tags.
I think what you should try to do is sort your array by level, first (see uasort() and then you can output your opening <ul> tag on the first loop of the second level (use a counter to keep track of which loop you're on and then do something like if ($i == 0) or if ($i == (count($array) - 1)). This will work no matter how many nested levels you have.

Categories