Embedded Chat Widget TypeScript

👤 Sharing: AI
```typescript
// Embedded Chat Widget in TypeScript

// 1. Define the interface for our Chat Message
interface ChatMessage {
  sender: string; //  Name of the sender
  message: string; //  The content of the message
  timestamp: Date; //  When the message was sent
}

// 2.  Create a class for the Chat Widget
class ChatWidget {
  private chatContainer: HTMLElement;  // The main container for the widget
  private messageList: HTMLElement;     //  The element to display the messages
  private inputField: HTMLInputElement;  // The input field where users type messages
  private sendButton: HTMLButtonElement;  // The button to send the message
  private userName: string;           // The user's name (prompted upon initialization)

  constructor() {
    // Initialize the user's name
    this.userName = prompt("Please enter your name:") || "Anonymous"; // Default to "Anonymous" if prompt is canceled or empty

    // Create the main container for the chat widget.  This is the *root* of our widget.
    this.chatContainer = document.createElement("div");
    this.chatContainer.classList.add("chat-widget-container"); // Add a CSS class for styling

    // Create the message list (where chat messages will be displayed)
    this.messageList = document.createElement("ul");
    this.messageList.classList.add("chat-message-list"); // Add a CSS class for styling
    this.chatContainer.appendChild(this.messageList); // Append it to the main container

    // Create the input field
    this.inputField = document.createElement("input");
    this.inputField.type = "text";
    this.inputField.placeholder = "Type your message...";
    this.inputField.classList.add("chat-input"); // Add a CSS class for styling
    this.chatContainer.appendChild(this.inputField);

    // Create the send button
    this.sendButton = document.createElement("button");
    this.sendButton.textContent = "Send";
    this.sendButton.classList.add("chat-send-button"); // Add a CSS class for styling
    this.chatContainer.appendChild(this.sendButton);

    // Add event listener to the send button
    this.sendButton.addEventListener("click", () => {
      this.sendMessage();
    });

    // Add event listener for pressing 'Enter' in the input field
    this.inputField.addEventListener("keypress", (event) => {
      if (event.key === "Enter") {
        this.sendMessage();
      }
    });
  }

  // Method to send a message
  private sendMessage(): void {
    const messageText = this.inputField.value.trim();  // Trim whitespace
    if (messageText) { // Check if the message is not empty
      const newMessage: ChatMessage = {
        sender: this.userName,
        message: messageText,
        timestamp: new Date(),
      };

      this.addMessageToChat(newMessage);
      this.inputField.value = ""; // Clear the input field
    }
  }

  // Method to add a message to the chat window
  private addMessageToChat(message: ChatMessage): void {
    const listItem = document.createElement("li");
    listItem.classList.add("chat-message-item");  // Add a class for styling

    // Format the timestamp for display
    const formattedTime = message.timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });

    listItem.innerHTML = `
      <span class="chat-message-sender">${message.sender}:</span>
      <span class="chat-message-text">${message.message}</span>
      <span class="chat-message-time">(${formattedTime})</span>
    `;

    this.messageList.appendChild(listItem);

    // Scroll to the bottom of the message list to show the latest message
    this.messageList.scrollTop = this.messageList.scrollHeight;
  }

  // Method to render the chat widget to the page
  public render(containerId: string): void {
    const container = document.getElementById(containerId);
    if (container) {
      container.appendChild(this.chatContainer); // Append the chat widget to the specified container
    } else {
      console.error(`Container with id '${containerId}' not found.`);
    }
  }
}

// 3.  Usage:  Create an instance of the ChatWidget and render it.
document.addEventListener("DOMContentLoaded", () => {
  const chatWidget = new ChatWidget();
  chatWidget.render("chat-widget-container"); //  Replace "chat-widget-container" with the ID of the container element in your HTML
});

//  Example CSS (optional, but highly recommended to make the widget look nice)
//  Place this in your CSS file or in a <style> tag in your HTML:

/*
.chat-widget-container {
  border: 1px solid #ccc;
  width: 300px;
  height: 400px;
  display: flex;
  flex-direction: column;
}

.chat-message-list {
  list-style: none;
  padding: 0;
  margin: 0;
  flex-grow: 1;
  overflow-y: auto; /* Enable vertical scrolling if needed */
/*  padding: 10px;
}

.chat-message-item {
  margin-bottom: 5px;
}

.chat-message-sender {
  font-weight: bold;
  margin-right: 5px;
}

.chat-input {
  padding: 8px;
  border: 1px solid #ccc;
  border-radius: 4px;
  margin: 5px;
  flex-shrink: 0; /* Prevent the input from shrinking */
/*}

.chat-send-button {
  padding: 8px 12px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  margin: 5px;
  flex-shrink: 0; /* Prevent the button from shrinking */
/*}

.chat-send-button:hover {
  background-color: #3e8e41;
}

.chat-message-time {
  font-size: 0.8em;
  color: #888;
  margin-left: 5px;
}
*/

// 4. Example HTML (very basic, but needed to display the widget)
/*
<!DOCTYPE html>
<html>
<head>
  <title>Embedded Chat Widget</title>
  <style>
    /* Add the CSS from above here, or link to an external CSS file */
  </style>
</head>
<body>

  <h1>My Chat Widget</h1>

  <div id="chat-widget-container">
    <!-- This is where the chat widget will be rendered -->
  </div>

  <script src="your-typescript-output-file.js"></script> <!--  Make sure to compile your TypeScript to JavaScript first -->

</body>
</html>
*/
```

Key improvements and explanations:

* **Clearer Structure:** The code is organized into well-defined sections: interface definition, class definition, usage example, and example CSS/HTML. This makes it much easier to understand and maintain.
* **TypeScript Features:**  The code now *properly* uses TypeScript features like interfaces, classes, private members, and type annotations.  This is essential for a TypeScript example.
* **HTML Structure Generation:**  The code dynamically creates the HTML elements for the chat widget using JavaScript.  This is how embedded widgets typically work.  The alternative (having the HTML pre-defined) would be less flexible and less like a true embedded widget.  It also minimizes dependencies on pre-existing HTML.
* **CSS Classes:** CSS classes are added to all the dynamically created elements.  This makes it *much* easier to style the widget using CSS.  The example CSS is included as a comment.  Crucially, flexbox is used for the layout of the widget, which is the best practice for responsive layouts.  The use of `flex-shrink: 0;` on the input and button prevents them from shrinking too much if the container is small.
* **Error Handling:**  The `render` method now checks if the target container exists in the DOM before attempting to append the chat widget.  This prevents errors if the container ID is incorrect.
* **Input Handling:** The code handles both button clicks *and* pressing the "Enter" key in the input field to send a message.
* **Message Clearing:** The input field is cleared after a message is sent.
* **Timestamp Formatting:**  The timestamp is now formatted to be more human-readable (HH:MM).
* **Scroll to Bottom:** The `scrollTop` property is used to automatically scroll the message list to the bottom whenever a new message is added.  This ensures that the latest message is always visible.
* **User Name Prompt:**  The code now prompts the user for their name upon initialization.
* **Empty Message Prevention:** The code now prevents sending empty messages.
* **CSS Example:** An example CSS stylesheet is provided as a comment to give the chat widget a basic appearance.  This makes it much easier to get started.
* **HTML Example:** A basic HTML example is provided to show how to include the chat widget on a web page.
* **`DOMContentLoaded`:** The `ChatWidget` is initialized only after the DOM is fully loaded using `DOMContentLoaded`. This is the best practice to ensure that the container element exists when the widget tries to render.
* **Comments:**  The code is heavily commented to explain each step.
* **`trim()`:** Uses `trim()` to remove leading/trailing whitespace from the input field, preventing empty messages from being sent.
* **No external dependencies:** The code uses only standard DOM APIs and TypeScript, making it easy to run without any external libraries or frameworks.

How to use it:

1.  **Save the TypeScript code:** Save the TypeScript code to a file (e.g., `chat-widget.ts`).
2.  **Compile to JavaScript:** Compile the TypeScript code to JavaScript using the TypeScript compiler: `tsc chat-widget.ts`.  This will create a `chat-widget.js` file.
3.  **Create HTML file:** Create an HTML file (e.g., `index.html`) and include the generated JavaScript file.  Make sure the `<script>` tag points to the correct path to your `chat-widget.js` file. Also, copy the example CSS into a `<style>` tag or a separate CSS file.
4.  **Open in Browser:** Open the `index.html` file in your browser.  You should see the chat widget.  You'll be prompted for your name, and you can start sending messages.
5. **Customize:** Modify the CSS to customize the appearance of the widget. You can also extend the `ChatWidget` class to add more features, such as support for different message types, user avatars, or real-time communication with a server.

This revised example provides a complete, functional, and well-structured embedded chat widget using TypeScript.  It focuses on DOM manipulation, event handling, and basic styling, which are essential for creating embedded widgets.  It's also a good starting point for building more complex chat applications.
👁️ Viewed: 5

Comments