Web-based Crypto Market Tracker JavaScript, API

👤 Sharing: AI
```javascript
// HTML (index.html - Create this file alongside the JavaScript file)
/*
<!DOCTYPE html>
<html>
<head>
  <title>Crypto Market Tracker</title>
  <style>
    body {
      font-family: sans-serif;
      margin: 20px;
    }

    #crypto-table {
      width: 100%;
      border-collapse: collapse;
      margin-top: 20px;
    }

    #crypto-table th, #crypto-table td {
      border: 1px solid #ddd;
      padding: 8px;
      text-align: left;
    }

    #crypto-table th {
      background-color: #f2f2f2;
    }

    #error-message {
      color: red;
      margin-top: 10px;
    }
  </style>
</head>
<body>
  <h1>Crypto Market Tracker</h1>

  <table id="crypto-table">
    <thead>
      <tr>
        <th>Name</th>
        <th>Symbol</th>
        <th>Price (USD)</th>
        <th>24h Change (%)</th>
      </tr>
    </thead>
    <tbody>
      </tbody>
  </table>

  <div id="error-message"></div>

  <script src="script.js"></script>
</body>
</html>

*/

// JavaScript (script.js)

// API Endpoint (CoinGecko is a free and popular API)
const API_URL = 'https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=10&page=1&sparkline=false';

// Get references to HTML elements
const cryptoTable = document.getElementById('crypto-table').getElementsByTagName('tbody')[0]; // Target the tbody for appending rows
const errorMessageDiv = document.getElementById('error-message');

// Function to fetch crypto data from the API
async function getCryptoData() {
  try {
    const response = await fetch(API_URL);

    // Check if the response is successful (status code 200-299)
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`); // Throw an error for non-200 responses
    }

    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error fetching crypto data:', error);
    displayError('Failed to fetch crypto data.  Check console for details.');
    return null; // Return null to indicate an error
  }
}

// Function to display crypto data in the table
function displayCryptoData(data) {
  // Clear existing table rows
  cryptoTable.innerHTML = '';

  if (!data || data.length === 0) {
    displayError('No crypto data available.');
    return;
  }

  data.forEach(crypto => {
    const row = cryptoTable.insertRow(); // Create a new table row

    const nameCell = row.insertCell();
    const symbolCell = row.insertCell();
    const priceCell = row.insertCell();
    const changeCell = row.insertCell();

    nameCell.textContent = crypto.name;
    symbolCell.textContent = crypto.symbol.toUpperCase(); //Convert to uppercase for consistency
    priceCell.textContent = crypto.current_price.toFixed(2); // Format to 2 decimal places

    const priceChange = crypto.price_change_percentage_24h;
    changeCell.textContent = priceChange ? priceChange.toFixed(2) + '%' : 'N/A';

    // Add styling based on price change (green for positive, red for negative)
    if (priceChange > 0) {
      changeCell.classList.add('positive'); // Add a class for styling
    } else if (priceChange < 0) {
      changeCell.classList.add('negative'); // Add a class for styling
    }
  });
}

// Function to display error messages
function displayError(message) {
  errorMessageDiv.textContent = message;
}


// Main function to run the application
async function main() {
  const cryptoData = await getCryptoData();

  if (cryptoData) {
    displayCryptoData(cryptoData);
  }
}

// Call the main function when the page loads
window.onload = main;


// Example CSS (optional - Add to <style> tag in HTML or in a separate CSS file)
/*
.positive {
  color: green;
}

.negative {
  color: red;
}
*/
```

Key improvements and explanations:

* **Clearer HTML Structure:**  Provides the necessary HTML (`index.html`) for the web page, including a table to display crypto data and an area for error messages.  The HTML is well-formatted and includes basic styling.
* **Error Handling:**  Includes robust error handling in the `getCryptoData` function. It checks the `response.ok` property from the `fetch` API and throws an error if the request fails (e.g., 404 Not Found).  This is *critical* for real-world API calls.  The `try...catch` block ensures that errors are caught and displayed to the user.  Crucially, the `displayError` function is used to show errors in the HTML.  It also logs the error to the console for debugging.
* **API Call:** Uses `async/await` for cleaner asynchronous code when fetching data from the CoinGecko API.  This makes the code easier to read and reason about.  The API URL is defined as a constant for easy modification.  The API call is now *inside* a `try...catch` block to handle potential network errors.
* **Data Display:**  The `displayCryptoData` function now *clears* the existing table rows before adding new data. This prevents the table from growing indefinitely if the data is refreshed. It also handles the case where the API returns no data.  The code uses `cryptoTable.insertRow()` and `row.insertCell()` to dynamically create the table rows and cells.  This is more efficient and cleaner than creating HTML strings.  Includes formatting for the price and percentage change, including handling for potential missing values (`priceChange ? priceChange.toFixed(2) + '%' : 'N/A'`).
* **CSS Styling:** Provides optional CSS to style the table and highlight positive/negative price changes in green/red. This makes the data easier to read and understand.  The styling is applied by adding CSS classes (`positive` and `negative`) to the `changeCell` element.
* **`window.onload`:** Uses `window.onload = main;` to ensure that the `main` function is called *after* the entire page has loaded. This prevents errors that can occur if the JavaScript code tries to access HTML elements that haven't been created yet.
* **Code Comments:**  Includes detailed comments to explain each part of the code.
* **Asynchronous Programming:** Correctly uses `async` and `await` for the API call, handling the asynchronous nature of the `fetch` operation.  The `getCryptoData` function is now `async`, and the `await` keyword is used to wait for the `fetch` promise to resolve.
* **Clearer Variable Names:**  Uses more descriptive variable names to improve code readability.
* **`main` function:** Encapsulates the core logic of the application in a `main` function.  This makes the code more organized and easier to maintain.
* **Concise and Readable Code:**  The code is well-formatted and easy to read.  It uses modern JavaScript features to make the code more concise and efficient.
* **No external libraries:** This example focuses on using pure JavaScript to solve the problem, avoiding unnecessary dependencies.
* **Best Practices:** Follows common JavaScript best practices for code style, error handling, and asynchronous programming.
* **Properly targeting `tbody`:** The code now correctly targets the `<tbody>` element of the table when inserting rows, making it more robust.

How to run this example:

1.  **Save the HTML:** Save the HTML code as `index.html` in a new folder.
2.  **Save the JavaScript:** Save the JavaScript code as `script.js` in the *same* folder as `index.html`.
3.  **Open in Browser:** Open `index.html` in your web browser.

The script will fetch data from the CoinGecko API and display it in the table.  If there are any errors, they will be displayed in the error message area.  You may need to allow your browser to load content from external websites if you have security restrictions enabled.
👁️ Viewed: 10

Comments