![]() |
![]() |
You are not logged in. Please Login.
|
![]() |
|
---|---|
![]() ![]() Administrator Programming King
Posts: 95
Registered: 2013-12-25 |
_deep/
├── app/ │ ├── public/ # Web-accessible files │ │ ├── components/ # Your toast/grid components │ │ ├── index.html # Your HTML form │ │ ├── submit.php # PHP backend (moved here) │ │ └── js/ │ │ └── main.js # Frontend logic │ │ │ └── private/ # Protected server-side files │ └── database/ │ └── data.db # SQLite database └── .htaccess # Security rules (in the root directory) |
Last edited by: cgetty on Jan 31, 2025 3:51:58 pm
|
![]() |
|
---|---|
![]() ![]() Administrator Programming King
Posts: 95
Registered: 2013-12-25 |
The Components directory and files.
_deep/ ├── app/ │ ├── public/ # Web-accessible files │ │ ├── components/ # Your toast/grid components ![]() // Grid class Grid extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); } connectedCallback() { this.render(); } render() { this.shadowRoot.innerHTML = ` <style> table { width: 100%; border-collapse: collapse; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } </style> <table> <thead> <tr> ${this.columns.map(col => `<th>${col}</th>`).join('')} </tr> </thead> <tbody> ${this.data.map(row => ` <tr> ${row.map(cell => `<td>${cell}</td>`).join('')} </tr> `).join('')} </tbody> </table> `; } set columns(value) { this._columns = value; this.render(); } get columns() { return this._columns || []; } set data(value) { this._data = value; this.render(); } get data() { return this._data || []; } } customElements.define('my-grid', Grid); ![]() // Toast class ToastMessage extends HTMLElement { constructor() { super(); // Create Shadow DOM const shadow = this.attachShadow({ mode: 'open' }); // Define template with scoped CSS const template = document.createElement('template'); template.innerHTML = ` <style> /* styles are SCOPED to this component! */ :host { position: fixed; bottom: 20px; right: 20px; padding: 12px 24px; border-radius: 4px; font-family: Arial, sans-serif; opacity: 0; transition: opacity 0.3s ease-in-out; z-index: 1000; color: white; } :host([type="success"]) { background-color: #4CAF50; } :host([type="error"]) { background-color: #f44336; } :host([type="info"]) { background-color: #2196F3; } :host([type="warning"]) { background-color: #ff9800; } </style> <slot></slot> <!-- Renders inner HTML --> `; // Attach template to Shadow DOM shadow.appendChild(template.content.cloneNode(true)); } /** * Public method to show the toast. * @param {string} message - The message to display. * @param {string} type - The type of toast (success, error, info, warning). * @param {number} duration - How long the toast should stay visible (in milliseconds). */ show(message, type = 'success', duration = 3000) { // Set attributes this.setAttribute('type', type); this.textContent = message; // Fade in this.style.opacity = '1'; // Auto-remove after duration setTimeout(() => { this.style.opacity = '0'; setTimeout(() => this.remove(), 300); // Wait for fade-out }, duration); } } // Register the custom element customElements.define('toast-message', ToastMessage); |
![]() |
|
---|---|
![]() ![]() Administrator Programming King
Posts: 95
Registered: 2013-12-25 |
├── public/ # Web-accessible files │ │ ├── components/ # Your toast/grid components │ │ ├── index.html # Your HTML form │ │ ├── submit.php # PHP backend (moved here) ![]() // index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Enhanced Complete Demo</title> <style> body { font-family: Arial, sans-serif; padding: 20px; } .outer-frame { border: 3px solid #444; border-radius: 15px; padding: 20px; max-width: 800px; margin: 0 auto; background-color: #f9f9f9; position: relative; /* For positioning the record count */ } .inner-frame { border: 1px solid #ccc; border-radius: 10px; padding: 20px; margin-top: 20px; background-color: white; } .input-group { margin-bottom: 15px; } label { display: inline-block; width: 100px; } input, textarea { width: 250px; padding: 5px; } textarea { vertical-align: top; } button { padding: 10px; margin-right: 10px; margin-top: 10px; } #dataGrid { margin-top: 20px; width: 100%; border-collapse: collapse; } #dataGrid th, #dataGrid td { padding: 10px; border: 1px solid #ddd; text-align: left; } #dataGrid th { background-color: #f5f5f5; } #recordCount { position: absolute; top: 2px; right: 30px; /* Moved to upper-right corner */ font-size: 16px; font-weight: bold; } </style> </head> <body> <div class="outer-frame"> <!-- Record Count --> <p id="recordCount">Total Records: 0</p> <h1>Enhanced Complete Demo</h1> <!-- Form Section --> <form id="mainForm" novalidate> <div class="inner-frame"> <div class="input-group"> <label for="username">Username:</label> <input type="text" id="username" name="username" required> </div> <div class="input-group"> <label for="email">Email:</label> <input type="email" id="email" name="email" required> </div> <div class="input-group"> <label for="notes">Notes:</label> <textarea id="notes" name="notes" rows="4"></textarea> </div> <!-- Buttons --> <button type="submit" id="submitBtn">Submit</button> <button type="button" id="refreshBtn">Refresh</button> <button type="button" id="clearCacheBtn">Clear Cache</button> <button type="button" id="testToastBtn">Test Toast</button> </div> </form> <!-- Grid Section --> <div class="inner-frame"> <table id="dataGrid"> <thead> <tr> <th>ID</th> <th>Username</th> <th>Email</th> <th>Notes</th> <th>Created At</th> </tr> </thead> <tbody> <!-- Rows will be populated dynamically --> </tbody> </table> </div> </div> <!-- Component scripts --> <script type="module" src="components/toast/toast.js"></script> <script type="module" src="js/main.js"></script> </body> </html> ![]() // submit.php <?php header('Content-Type: application/json'); try { // Sanitize inputs $username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING); $email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL); $notes = filter_input(INPUT_POST, 'notes', FILTER_SANITIZE_STRING); // Validate if (empty($username) || empty($email)) { throw new Exception('Username and email are required'); } if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { throw new Exception('Invalid email format'); } // Connect to SQLite database $dbPath = __DIR__ . '/../private/database/data.db'; $db = new PDO("sqlite:$dbPath"); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Create table if it doesn't exist $db->exec(" CREATE TABLE IF NOT EXISTS submissions ( rec_id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL, email TEXT NOT NULL, notes TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) "); // Insert data using prepared statements $stmt = $db->prepare("INSERT INTO submissions (username, email, notes) VALUES (:username, :email, :notes)"); $stmt->execute(array( ':username' => $username, ':email' => $email, ':notes' => $notes )); // Success response echo json_encode(array( 'success' => true, 'message' => 'Record saved successfully!' )); } catch (Exception $e) { // Error response (workaround for http_response_code in PHP 5.3) header('HTTP/1.1 500 Internal Server Error'); echo json_encode(array( 'success' => false, 'error' => $e->getMessage() )); } |
Last edited by: cgetty on Jan 31, 2025 3:50:35 pm
|