datagrid Archives | phpGrid - PHP Datagrid Create PHP grids in minutes, not hours. Mon, 18 Nov 2024 06:36:12 +0000 en-US hourly 1 CodeProjecthttps://wordpress.org/?v=7.0.3 129966043 Transform HTML Table into Card View Using Nothing But CSS https://phpgrid.com/blog/transform-html-table-into-card-view-using-nothing-but-css/ Fri, 25 Oct 2024 00:26:37 +0000 https://phpgrid.com/?p=10187

I’d like share a recent experiment that explores how to transform a plain, old-fashioned HTML table into a dynamic card view, going beyond the traditional rows and columns. Start With a Simple HTML Table Let’s begin with a simple HTML table such as the following. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051<table>   <thead>     <tr>       <th>Company</th> […]

The post Transform HTML Table into Card View Using Nothing But CSS appeared first on phpGrid - PHP Datagrid.

]]>

I’d like share a recent experiment that explores how to transform a plain, old-fashioned HTML table into a dynamic card view, going beyond the traditional rows and columns.

Start With a Simple HTML Table

Let’s begin with a simple HTML table such as the following.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<table>
  <thead>
    <tr>
      <th>Company</th>
      <th>Contact</th>
      <th>Country</th>
    </tr>
  </thead>
  <tbody>
  <tr>
    <td>Alfreds Futterkiste</td>
    <td>Maria Anders</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Centro Moctezuma</td>
    <td>Francisco Chang</td>
    <td>Mexico</td>
  </tr>  
  <tr>
    <td>Alfreds </td>
    <td>Maria </td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Centro  </td>
    <td>Francisco Chang</td>
    <td>Mexico</td>
  </tr>
  <tr>
    <td>Alfreds </td>
    <td>Maria </td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Centro comercial </td>
    <td>Francisco </td>
    <td>Mexico</td>
  </tr>
  <tr>
    <td>Alfreds </td>
    <td>Maria Anders</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Centro comercial </td>
    <td>Francisco </td>
    <td>Mexico</td>
  </tr>
  </tbody>
</table>

It looks like this when rendered in browser.

plain table

Just another html table with rows and columns. Nothing fancy.

So how can we transform the traditional rows and columns layout into something more dynamic?

Discover the Power of CSS Grid

Tables don’t have to be boring. With a few simple CSS tricks, you can easily transform a traditional HTML table into a sleek list or card view.

The best part? No JavaScript, just pure CSS!

CSS grid has been an W3C Candidate Recommendation Draft since 2007, however, it has been adopted by the recent versions of all current major browsers.

CSS grid is designed for both rows and columns, making it ideal for complex layouts such as table. It allows you to manage both horizontal and vertical alignments simultaneously, which gives you much more control than Flexbox, which is primarily one-dimensional (row or column).

CSS Grid Properties to Use

  1. Use CSS grid layout for <thead> and <tbody>.
  2. Use CSS display property and set all <td> to be block elements
1
2
3
4
5
6
table tbody, table thead {
  display: grid;
}
table td {
  display: block;
}

With the CSS above, our plain HTML table already magically transforms into a responsive list view, displaying each record neatly in a single column.

table single column

It’s looking good but a bit chaotic! Let’s sprinkle on some CSS borders to give each row in our list a little breathing room.

1
2
3
table, th, tr {
  border: 1px solid black;
}

There you go. Not too shabby for a list view created without a single line of JavaScript!

table singl column with border

Now we got a nice list made from an old-fashioned html table, how do we turn that nice list into a card view?

Spoiler alert: just sprinkle on a few more lines of CSS!

Transform List into Card View

Our final card trick to transform table into cards is to use CSS grid property grid-template-columns:

1
2
3
4
table tbody {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}

grid-template-columns is a CSS property used in the CSS Grid layout to define the structure of the grid’s columns. It specifies the number of columns, their widths, and how the space within the grid is divided.

With the repeat() function, the first parameter lets us decide how many columns we want—let’s say 4. The second parameter tells those columns how big to be—1fr, or one fraction of the available space. It’s like telling your columns to all get an equal slice of the space pie.

Our final card view

final card view

Take a moment to explore the code and see the results for yourself over on CodePen. It’s the perfect place to experiment and play around with CSS grid transformations.

Keep in mind that CSS Grid is also responsive, providing developers with enhanced control over how layouts adjust and reflow across various screen sizes and devices.

Optional: Adding data-label to card view

While the card view is visually appealing, it lacks the clarity of column information, leaving users to guess the data represented in each card.

By incorporating a touch of JavaScript, we can seamlessly add data labels for each column, enhancing the association between the labels and their corresponding cells.

1
2
3
4
5
6
7
8
9
10
11
12
// Store each column header to array
var labels = [];
$('table').find('thead th').each(function() {
    labels.push($(this).text());
});

// Add data-label attribute to each cell
$('table).find('tbody tr').each(function() {
    $(this).find('
td').each(function(column) {
        $(this).attr('
data-label', labels[column]);
    });
});

The same code above using ES6 vanilla javascript without jQuery

1
2
3
4
5
6
7
8
9
10
11
12
// Store each column header to array
const labels = [];
document.querySelectorAll('table thead th').forEach(th => {
    labels.push(th.textContent);
});

// Add data-label attribute to each cell
document.querySelectorAll('table tbody tr').forEach(tr => {
    tr.querySelectorAll('td').forEach((td, column) => {
        td.setAttribute('data-label', labels[column]);
    });
});

Here’s card view new look with data label:

card view enhanced

Demo

It’s nothing like the html table that we started with. With CSS Grid, the layout options are endless because it allows for full control over both rows and columns in a two-dimensional space.

Final thought…

This tutorial only scratches the surface of the iceberg. You can easily create more responsive layouts, overlap elements, span items across multiple rows or columns, and adjust grid areas dynamically, making it highly versatile for various layout needs.

Happy gridding!

Richard

The post Transform HTML Table into Card View Using Nothing But CSS appeared first on phpGrid - PHP Datagrid.

]]>
10187
Clone CoinMarketCap.com Cryptocurrency Price Table with WebSockets https://phpgrid.com/example/clone-coinmarketcap-com-cryptocurrency-price-table-with-websockets/ Wed, 26 Jan 2022 18:50:27 +0000 https://phpgrid.com/?p=9876

Coinmarketcap.com is without a doubt the most popular cryptocurrency price tracking website. I’ve often wondered if its elegant bitcoin prices table could be reproduced with phpGrid. That is exactly what we are about to do today! The table includes crypto pricing statistics as well as sparkline chart based on real-time data from the backend server. […]

The post Clone CoinMarketCap.com Cryptocurrency Price Table with WebSockets appeared first on phpGrid - PHP Datagrid.

]]>

Coinmarketcap.com is without a doubt the most popular cryptocurrency price tracking website. I’ve often wondered if its elegant bitcoin prices table could be reproduced with phpGrid. That is exactly what we are about to do today!

The table includes crypto pricing statistics as well as sparkline chart based on real-time data from the backend server. It’s a proof of concept to show how far phpGrid can be pushed before I have to resort to other tools and frameworks.

Setup

Acquire the full version of phpGrid. The free Lite version is not compatible with this tutorial.

Follow these steps to install:

  1. Extract download file,
  2. Upload the phpGrid folder to web server,
  3. Complete the installation by configuring conf.php file.

For demo purpose, conf.php, set all database values to blank since our project doesn’t require a database.

1
2
3
4
5
6
7
// set all to blank
define(‘PHPGRID_DB_HOSTNAME’, ‘’);
define(‘PHPGRID_DB_USERNAME’, ‘’);
define(‘PHPGRID_DB_PASSWORD’, ‘’);
define(‘PHPGRID_DB_NAME’, ‘’);
define(‘PHPGRID_DB_TYPE’, ‘’);
define(‘PHPGRID_DB_CHARSET’,’’);

Sample JSON

The first step is to obtain a crypto data feed. Though it may be automatically retrieved from places like Binance or FTX.US, I decided to start with a local JSON data source for simplicity’s sake.

JSON sample

We’ll use this top 10 crypto sample to populate our CoinMarketCap clone.

Index.php

Let’s create index.php with the following:

1
2
3
4
5
6
7
require_once("phpGrid/conf.php");

$url = "data/coinmarket_top10.json";
$data = file_get_contents($url);
$json_output = json_decode($data, true);
$dg = new C_DataGrid($json_output, "id", "CoinMarket");
$dg -> display();

$json_output is the sample JSON data source save in data folder. It is passed to C_DataGrid as the first parameter. It should display a very rudimentary grid similar to the following.

 

JSON as data source is covered in this tutorial.

I’ll confess, this is still a long way from what I’d like to accomplish. Let’s make some changes to the user interface.

Update User Interface

First by adding descriptive column title,

1
2
3
4
5
6
$dg->set_col_title(<strong>Percentage24H</strong>, ‘24h %);
$dg->set_col_title(<strong>Percentage7D</strong>, ‘7d %);
$dg->set_col_title(<strong>MarketCap</strong>, ‘Market Cap’);
$dg->set_col_title(<strong>Volume24H</strong>, ‘Volume(24h));
$dg->set_col_title(<strong>CirculatingSupply</strong>, ‘Circulating Supply’);
$dg->set_col_title(<strong>Last7Days</strong>, ‘Last 7 Days’);

Hide non-display columns,

1
2
$dg->set_col_hidden("Coin”);
$dg->set_col_hidden("
MaxSupply”);

Fix text alignment,

1
2
3
4
5
6
$dg->set_col_align(‘Price’, ‘right’);
$dg->set_col_align(‘Percentage24H’, ‘right’);
$dg->set_col_align(‘Percentage7D’, ‘right’);
$dg->set_col_align(‘MarketCap’, ‘right’);
$dg->set_col_align(‘Volume24H’, ‘right’);
$dg->set_col_align(‘CirculatingSupply’, ‘right’);

Update money format

1
2
3
4
$dg->set_col_currency('Price', '$');
$dg->set_col_currency('MarketCap', '$');
$dg->set_col_currency('Volume24H', '$');
$dg->set_col_currency('CirculatingSupply', '');

Add row color and hover effect

1
$dg -> set_row_color(‘white’, ‘white’, ‘white’);

Fix column sort

1
2
3
4
$dg->set_col_property("Price”, array("sorttype”=>"currency"));
$dg->set_col_property("MarketCap”, array("sorttype”=>"currency"));
$dg->set_col_property("Volume24H”, array("sorttype”=>"currency"));
$dg->set_col_property("CirculatingSupply”, array("sorttype”=>"integer"));

Add responsive width to screen size

1
$dg-> enable_autowidth(true);

Finally some misc. style tweaks

1
2
3
$dg->set_caption(false);
$dg->set_col_property(‘Coin’, array(‘classes’=>‘coin’));
$dg->set_col_property(‘Name’, array(‘classes’=>‘name’));

Already look better! But it’s still not quite what I was looking for.

Adding Cascading Style Sheets (app.css)

I use a Chrome extension “What Font” to find out the font it used on CoinMarketCap. It is a free font from Google Fonts called “Inter”. Here are the embed links:

1
2
3
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600&amp;display=swap" rel="stylesheet">

Then I made a few adjustments with some additional custom styles so I could “perfectly” match the look (almost)

It looked better but still with a few issues:

  1. Missing the coin icons and tick symbols
  2. The prices are static and do not updates automatically like CMC does.

Let’s fix those.

Icons and Tickers

CoinMarketCap has the format: Icon Name Ticker as illustrated below.

 

I found a free library of all the major crypto icons on http://cryptoicons.co/ and downloaded them to “images/icons” folder.

Next, we need to use phpGrid custom formatter.

phpGrid Custom formatter

This is section is the most crucial. It’s what really makes our cloned table “shine”. Custom formatter in phpGrid is a super powerful and versatile function for manipulating, modifying, or even adding additional information in a single column in grid. You can learn more about it on custom formatter online documentation.

I’m adding custom formatter to the followings:

  • Name (with icon & ticker)
  • Price
  • 24h change (%)
  • 7day change (%)
  • Volume with dollar amount
  • Circulating supply with % bar

PHP

1
2
3
4
5
$dg->set_col_property('Name', array('formatter'=>'###nameFormatter###')); // must have ###
$dg->set_col_property('Volume24H', array('formatter'=>'###volumeFormatter###')); // must have ###
$dg->set_col_property('CirculatingSupply', array('formatter'=>'###circulatingSupplyFormatter###')); // must have ###
$dg->set_col_property('Percentage24H', array('formatter'=>'###percentageChangeFormatter###')); // must have ###
$dg->set_col_property('Percentage7D', array('formatter'=>'###percentageChangeFormatter###')); // must have ###

Javascript (app.js)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function percentageChangeFormatter (cellValue, options, rowData) {
 if (cellValue==0) return 'N/A';

  return (cellValue.indexOf('-') >= 0) ? `<span style="color:red">${cellValue}</span&>`: `<span style="color:green">${cellValue}</span>`;
}

function volumeFormatter (cellValue, options, rowData){
  if (cellValue==0) return 'N/A';

  let volume24hTotalCoin = parseInt(rowData['Volume24H']/rowData['Price']);

  return `${rowData['Volume24H'].toLocaleString(undefined,{})} <span class="volume24hTotalCoin">${volume24hTotalCoin.toLocaleString(undefined,{})} ${rowData['Coin']}</span>`;
  }

function circulatingSupplyFormatter (cellValue, options, rowData){
  if (cellValue==0) return 'N/A';

  let volume24hTotalCoin = parseInt(rowData['Volume24H']/rowData['Price']);

  if (!!rowData['MaxSupply']) {
    const percentageOfMaxSupply = parseInt((cellValue/rowData['MaxSupply']) * 100);
    return `<span class="circulating-supply"${cellValue.toLocaleString(undefined ${rowData['Coin']}</span>` + `<div width="160" class="maxsupply-bar" title="Percentage: ${percentageOfMaxSupply}% of Max Supply of ${rowData['MaxSupply']}"><div style="width:${percentageOfMaxSupply}px" class="percentage-of-maxsupply"></div></div>`;
  }
  return `${cellValue.toLocaleString(undefined,{})}`;
}

It looks pretty good!

Real-Time Data via Binance WebSocket

Last but not least, the data must be updated in real-time, similar to CoinMarketCap or CoinGecko, without requiring the entire page to be refreshed. For this experiment, I want the price to tick in the same way as CMC does.

WebSocket is supported by all major web browsers, with the exception of Opera Mini, according to caniuse.com. I was concerned that it would be a huge undertaking. As a result, I pushed this to the bottom of my to-do list. Fortunately, this was not the case. Binance’s websocket trade stream API made it simple.

1
2
3
4
5
6
7
8
9
10
11
// real time data via Websocket
$(document).ready(function(){
  let coins = ['BTC', 'ETH', 'BNB', 'USDT', 'SOL', 'ADA', 'XRP', 'DOT', 'USDC', 'DOGE'];
  coins.forEach(function(coin){
    var wss = new WebSocket(`wss://stream.binance.com:9443/ws/${coin.toLowerCase()}usdt@trade`);
    wss.onmessage = function (event) {
      var messageObject = JSON.parse(event.data)
      $("#CoinMarket").jqGrid("setCell", coin, "Price" ,(messageObject.p));
    }
   })
})

From its API, there are tons of great data can be consumed. For our purpose, we will only need messageObject.p, which returns ‘Order Price’.

Bonus: Adding Sparkline Chart of “last 7 days”

On the coin market cap, todays’ cryptocurrency price table also features a lovely “mini” line chart for column “last 7 days”. The name for the type of chart is “sparkline”, and it is typically drawn without axes or coordinates. I wonder if it’s possible to include that.

It turns out jQuery already has a Sparkline plugin. It takes a simple array of numbers. For example:

1
"Last7Days”: "[64125.80, 64398.60, 64134.50, 64806.70, 64932.60, 66904.40, 67527.90]”

call to the sparkline() function to display the sparkline

1
$('.sparklines').sparkline('html', { enableTagOptions: true, fillColor:false, lineWidth:2, width:'100%', height:'50px' });

remember include Sparkline plugin before </body>

1
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-sparklines/2.1.2/jquery.sparkline.min.js" type="text/javascript"></script>

The Final Outcome of CoinMarketCap.com Clone

 

 

Not too shabby!

Summary

Our little CMC cryptocurrency price chart looks darn good. Considering how little code it took. It uses custom formatter for most of the ‘fancy’ stuffs such as tickers and icons. WebSocket is definitely something very exciting to show live data stream.

Potential Enhancements

This is a fun experiment to really push the envelop with phpGrid beyond common use cases such as inventory management, CRM, timesheet applications.

Some potential useful enhancements:

  • Interactive cryptocurrency market cap chart
  • Pick and choose cryptocurrencies for display
  • Filters
  • Search
  • Database to store price history

The post Clone CoinMarketCap.com Cryptocurrency Price Table with WebSockets appeared first on phpGrid - PHP Datagrid.

]]>
9876