Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

CSS resize property is not working with the sidebar that I created

Description

I am developing a website that has a button on the top right side and if the user clicks this button, the sidebar with a chatbot shows up. I want to make this chatbot sidebar resizable by using the resize property to allow the user to resize the sidebar with their mouse.

img1

Current Behavior

Even though I have added the resize property to .sidebar-content, I can’t resize the chatbot sidebar.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

/* Side bar */
.sidebar {
    position: fixed;
    top: 10px;
    right: 10px;
    height: 100%;
    width: 100%;
    max-width: 500px;
    background-color: none;
    overflow-x: hidden;
    transition: 0.5s;
    padding-top: 60px;
    color: white;
}

.sidebar-content {
    resize: both;
    display: none;
}
const promptInput = document.getElementById("userInput");
const chatContainer = document.getElementById("chatContainer");
const typingIndicator = document.getElementById("typingIndicator");
const sidebar = document.getElementById("sidebar");
const sidebarContent = document.getElementById("sidebarContent");
const imageContainer = document.getElementById("imageContainer");

async function sendMessage() {
  const prompt = promptInput.value.trim();
  if (!prompt && imageContainer.children.length === 0) {
    alert("Please enter a message or add an image.");  // Browser pop up message
    return;
  }

  // Collect image data
  const images = Array.from(imageContainer.querySelectorAll('.img-preview'))
    .map(img => img.src.split(',')[1]); // Extract base64 data

  addMessage(prompt, 'user', images);
  promptInput.value = "";

  showTypingIndicator();

  const generatedText = await generateText(prompt, images);
  addMessage(generatedText, 'bot');

  hideTypingIndicator();
  //clearImagePreviews(); Add this code if you want the image in the imageContainer disappear if the user sends the image.
}

async function generateText(prompt, images) {
  try {
    const response = await fetch("https://idx-polapo-invest-test-6163648-nylaufaarq-uc.a.run.app/generate_text_stream", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ prompt, images }),
    });

    if (!response.ok) {
      console.error("Error:", response.statusText);
      return "Error occurred while generating response.";
    }

    const reader = response.body.getReader();
    const decoder = new TextDecoder();
    let isFinished = false;
    let generatedTextContent = "";

    while (!isFinished) {
      const { done, value } = await reader.read();
      if (done) {
        isFinished = true;
        break;
      }
      generatedTextContent += decoder.decode(value, { stream: true });
    }

    return generatedTextContent;
  } catch (error) {
    console.error("Error:", error);
    return "An error occurred.";
  }
}

function addMessage(text, type, images = []) {

  let md = window.markdownit();

  const messageDiv = document.createElement("div");
  messageDiv.className = `message ${type}`;

  const messageContent = document.createElement("div");
  messageContent.className = "message-bubble fadeIn";
  const render = () => {
    messageContent.innerHTML = md.render(text);
  }
  render()

  images.forEach(src => {
    const img = document.createElement("img");
    img.src = `data:image/png;base64,${src}`;
    img.classList.add("message-image");
    messageContent.appendChild(img);
  });

  messageDiv.appendChild(messageContent);
  chatContainer.appendChild(messageDiv);
  chatContainer.scrollTop = chatContainer.scrollHeight;
}

function clearImagePreviews() {
  while (imageContainer.firstChild) {
    imageContainer.removeChild(imageContainer.firstChild);
  }
  checkImageContainerVisibility();
}

let typingTimeout;

function showTypingIndicator() {
  clearTimeout(typingTimeout);
  typingIndicator.style.display = "inline-block";
}

function hideTypingIndicator() {
  typingTimeout = setTimeout(() => {
    typingIndicator.style.display = "none";
  }, 1000);
}

function handleKeyPress(event) {
  if (event.key === "Enter") {
    sendMessage();
  }
}

function toggleSidebar() {
  if (sidebar.style.width === "500px") {
    sidebar.style.width = "0";
    sidebarContent.style.display = "none";
  } else {
    sidebar.style.width = "500px";
    sidebarContent.style.display = "block";
  }
}

window.onload = () => addMessage("Hello! How can I assist you today?", 'bot');

document.addEventListener('DOMContentLoaded', () => {
  const textInput = document.getElementById('userInput');

  textInput.addEventListener('paste', (event) => {
    const items = (event.clipboardData || window.clipboardData).items;
    for (const item of items) {
      if (item.type.indexOf('image') !== -1) {
        const file = item.getAsFile();
        const reader = new FileReader();
        reader.onload = (event) => {
          displayImage(event.target.result);
        };
        reader.readAsDataURL(file);
        event.preventDefault();
      }
    }
  });

  function displayImage(src) {
    const imgContainer = document.createElement('div');
    imgContainer.classList.add('img-preview-container');

    const img = document.createElement('img');
    img.src = src;
    img.classList.add('img-preview');

    const removeButton = document.createElement('button');
    removeButton.classList.add('remove-button');
    removeButton.textContent = '✖';
    removeButton.addEventListener('click', () => {
      imgContainer.remove();
      checkImageContainerVisibility();
    });

    imgContainer.appendChild(img);
    imgContainer.appendChild(removeButton);
    imageContainer.appendChild(imgContainer);
    checkImageContainerVisibility();

    const all_images = imageContainer.querySelectorAll('.img-preview-container');
    all_images.forEach(img => img.style.width = `${100 / all_images.length - 10}%`);
  }

  function checkImageContainerVisibility() {
    if (imageContainer.children.length > 0) {
      imageContainer.classList.remove('hidden');
    } else {
      imageContainer.classList.add('hidden');
    }
  }

  // Initial check to hide image container if empty
  checkImageContainerVisibility();
});

// Backtest Result and Detailed Report buttons
document.getElementById('backtestResultButton').addEventListener('click', function() {
  const cs_model = document.getElementById('cs_model').value;
  const ts_model = document.getElementById('ts_model').value;

  fetch('/Backtest_result', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ cs_model: cs_model, ts_model: ts_model }),
  })
    .then(response => response.json())
    .then(data => {
      if (data.error) {
        console.error('Error:', data.error);
        return;
      }
      document.getElementById('backtestResult').innerHTML = `
        <div class="image" id="image1">
          <img src="data:image/png;base64,${data.port_weights_img}" alt="Portfolio Weights" style="width: 80%; height: auto;">
        </div>
        <div class="image" id="image2">
          <img src="data:image/png;base64,${data.asset_performance_img}" alt="Asset Performance" style="width: 80%; height: auto;">
        </div>
        <div class="image" id="image3">
          <img src="data:image/png;base64,${data.portfolio_performance_img}" alt="Portfolio Performance" style="width: 80%; height: auto;">
        </div>
      `;
      document.getElementById('backtestResult').classList.add('active');
      document.getElementById('detailedReport').classList.remove('active');
    })
    .catch(error => {
      console.error('Error:', error);
    });
});

document.getElementById('detailedReportButton').addEventListener('click', function() {
  const cs_model = document.getElementById('cs_model').value;
  const ts_model = document.getElementById('ts_model').value;

  fetch('/generate_html_report', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ cs_model: cs_model, ts_model: ts_model }),
  })
    .then(response => response.json())
    .then(data => {
      if (data.error) {
        console.error('Error:', data.error);
        return;
      }
      document.getElementById('detailedReport').innerHTML = data.report_html;
      document.getElementById('detailedReport').classList.add('active');
      document.getElementById('backtestResult').classList.remove('active');
    })
    .catch(error => {
      console.error('Error:', error);
    });
});
body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: #f0f2f5;
    color: #333;
    margin: 0;
    padding: 0;
    text-align: center;
}

h1 {
    color: #333;
    text-align: center;
    margin: 20px 0;
}

/* Generate report button styling */
button, input[type="submit"] {
    padding: 12px 24px;
    background-color: #007bff;
    color: #fff;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    font-size: 16px;
    transition: background-color 0.3s, transform 0.3s;
}

button:hover, input[type="submit"]:hover {
    background-color: #0056b3;
    transform: translateY(-2px);
}

/* Form styling */
form {
    background: #fff;
    border-radius: 8px;
    padding: 20px;
    max-width: 600px;
    margin: 20px auto;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

label {
    display: block;
    margin-bottom: 8px;
    font-weight: 600;
    font-size: 16px;
}

select, input[type="submit"] {
    width: calc(100% - 22px);
    padding: 12px;
    margin-bottom: 20px;
    border-radius: 6px;
    border: 1px solid #ddd;
    font-size: 16px;
}

select {
    background-color: #f9f9f9;
}

/* Report page styling */
.report-container {
    background: #fff;
    border-radius: 8px;
    padding: 20px;
    max-width: 1200px;
    margin: 20px auto;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    overflow: auto;
}

a {
    color: #007bff;
    text-decoration: none;
    font-weight: 500;
}

a:hover {
    text-decoration: underline;
}

/* Section that will show report content */
.report-content {
    margin-top: 20px;
}

.report-content iframe {
    width: 100%;
    border: none;
    height: 600px;
}



/* Side bar */
.sidebar {
    position: fixed;
    top: 10px;
    right: 10px;
    height: 100%;
    width: 100%;
    max-width: 500px;
    background-color: none;
    overflow-x: hidden;
    transition: 0.5s;
    padding-top: 60px;
    color: white;
}

.sidebar-content {
    resize: both;
    display: none;
}

.sidebar-content h2 {
    text-align: center;
}

.sidebar-content p {
    padding: 10px;
}

.toggle-button {
    position: fixed;
    top: 10px;
    right: 10px;
    padding: 15px;
    background-color: #3182ce;
    color: white;
    border: none;
    cursor: pointer;
}

.toggle-button:hover {
    background-color: #2c5282;
}

img {
    max-width: 90%;
    margin: 20px 0;
    border: 1px solid #ddd;
    border-radius: 10px;
}

.image-container {
    width: 100%;
    /*padding: 12px 18px;*/
    overflow: hidden;

    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    background-color: #fff;
    /*border: 1px solid #444;*/
    min-height: 50px;
    max-height: 70px;
    margin-bottom: 10px;

    border: 2px solid #e2e2e2;
    border-radius: 8px 8px 8px 8px;
}

.hidden {
    display: none;
}

.img-preview-container {
    position: relative;
    display: inline-block;
    max-width: 15%;
}

.img-preview {
    max-width: 100%;
    border-radius: 5px;
}


.remove-button:hover {
    background-color: #45a049;
}

.remove-button {
    position: absolute;
    top: 5px;
    right: 5px;
    background-color: #ff4d4d;
    border: none;
    border-radius: 50%;
    color: white;
    cursor: pointer;
    width: 20px;
    height: 20px;
    font-size: 12px;
    line-height: 20px;
    text-align: center;
    padding: 0;
}



/* Chat Bot */
.container {
    margin-top: 0;
    width: 90%;
    max-width: 450px;
    margin: 10px auto 0;
    background-color: #fff;
    border-radius: 12px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);
    padding: 20px;
    transition: all 0.3s;
}

.chat {
    overflow-y: auto;
    height: 400px;
    margin-bottom: 20px;
    border-bottom: 2px solid #e2e2e2;
}

.message {
    display: flex;
    margin-bottom: 12px;
}

.message.user {
    justify-content: flex-end;
}

.message-bubble {
    padding: 12px 18px;
    max-width: 70%;
    border-radius: 20px;
    line-height: 1.6;
    font-size: 0.95rem;
}

.message.user .message-bubble {
    background-color: #3182ce;
    color: white;
}

.message.bot .message-bubble {
    background-color: #e2e2e2;
    color: #333;
}


.message-image {
    max-width: 100px; /* Set the maximum width for the image */
    max-height: 100px; /* Set the maximum height for the image */
    margin: 5px;
    display: inline-block;
    object-fit: cover; /* Ensures the image retains its aspect ratio */
}


input[type="text"] {
    flex: 1;
    padding: 12px 18px;
    border: 2px solid #e2e2e2;
    border-radius: 8px 0 0 8px;
    font-size: 1rem;
    outline: none;
    color: black;
}

.send-button {
    width: 110px;
    background-color: #3182ce;
    color: white;
    padding: 12px 18px;
    border: none;
    border-radius: 0 8px 8px 0;
    cursor: pointer;
    transition: background-color 0.3s;
}

.send-button:hover {
    background-color: #2c5282;
}

.footer {
    text-align: center;
    padding: 15px 0;
    font-size: 0.9rem;
    color: #666;
    position: static;
    border-top: 1px solid #e2e2e2;
    background-color: #fff;
    position: fixed;
    bottom: 0;
    width: 100%;
}

@keyframes fadeIn {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

.fadeIn {
    animation: fadeIn 1s;
}

@media (max-width: 600px) {
    .container {
        width: 95%;
        margin: 10px auto 0;
    }

    .chat {
        height: 300px;
    }

    .input-container {
        max-width: 95%;
    }

    input[type="text"],
    .send-button {
        padding: 10px 14px;
        font-size: 0.9rem;
    }

    .footer {
        font-size: 0.8rem;
        margin-top: 30px;
    }
}

.typing-indicator {
    display: none;
    align-items: center;
    justify-content: flex-end;
    margin-top: 8px;
    width: 10px;
    height: 10px;
    background-color: #333;
    border-radius: 50%;
    margin-left: 4px;
    animation: typing 1s infinite;
}

@keyframes typing {
    0%,
    100% {
        transform: scale(1);
        opacity: 1;
    }

    50% {
        transform: scale(1.2);
        opacity: 0.7;
    }
}


/*the backtest result and detailed report buttons */
.button-container {
    display: flex;
    justify-content: center;
    gap: 10px;
    margin: 20px 0;
}

.content {
    display: flex;
    justify-content: center;
    margin-top: 20px;
}

.content-box {
    display: none;
    flex-direction: row;
}

.content-box.active {
    display: flex;
}

/*Backtest_result style*/
.image img {
    width: auto;
    height: auto; 
    margin: 10px auto; 
    display: block; 
    cursor: pointer; 
}

#detailedReport {
    width: 90%; 
    margin: 0 auto; 
  }
  
/*image modal style*/
.modal {
    display: none; 
    position: fixed;
    z-index: 1;
    padding-top: 100px;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    overflow: auto;
    background-color: rgb(0,0,0);
    background-color: rgba(0,0,0,0.9);
  }

.modal-content {
    margin: auto;
    display: block;
    width: 80%;
    max-width: 700px;
  }

.modal-content, #caption {
    -webkit-animation-name: zoom;
    -webkit-animation-duration: 0.6s;
    animation-name: zoom;
    animation-duration: 0.6s;
  }

@-webkit-keyframes zoom {
    from { -webkit-transform: scale(0) } 
    to { -webkit-transform: scale(1) }
  }
@keyframes zoom {
    from { transform: scale(0) } 
    to { transform: scale(1) }
  }

.close {
    position: absolute;
    top: 50px;
    right: 50px;
    color: #f1f1f1;
    font-size: 40px;
    font-weight: bold;
    transition: 0.3s;
  }
  
.close:hover,
.close:focus {
    color: #bbb;
    text-decoration: none;
    cursor: pointer;
  }
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Portfolio Backtesting</title>
    <link
      rel="stylesheet"
      href="{{ url_for('static', filename='css/style.css') }}"
    />
  </head>
  <body>
    <h1>Portfolio Backtesting</h1>
    <form id="reportForm" method="post" action="/">
      <label for="cs_model">Choose Cross-Sectional Model:</label>
      <select id="cs_model" name="cs_model">
        <option value="EW">Equal Weight (EW)</option>
        <option value="MSR">Maximum Sharpe Ratio (MSR)</option>
        <option value="GMV">Global Minimum Variance (GMV)</option>
        <option value="MDP">Minimum Drawdown Risk (MDP)</option>
        <option value="EMV">Equal Risk Contribution (EMV)</option>
        <option value="RP">Risk Parity (RP)</option>
      </select>

      <label for="ts_model">Choose Time-Series Model:</label>
      <select id="ts_model" name="ts_model">
        <option value="VT">Volatility Targeting (VT)</option>
        <option value="CVT">Conditional Value at Risk Targeting (CVT)</option>
        <option value="KL">Kelly Criterion (KL)</option>
        <option value="CPPI">
          Constant Proportion Portfolio Insurance (CPPI)
        </option>
      </select>

      <button type="submit" class="button">Generate Report</button>
    </form>

    <div class="button-container">
      <button type="button" id="backtestResultButton" class="button">
        Backtest Result
      </button>
      <button type="button" id="detailedReportButton" class="button">
        Detailed Report
      </button>
    </div>

    <div class="content">
      <div id="backtestResult" class="content-box"></div>
      <div id="detailedReport" class="content-box"></div>
    </div>

    <div class="sidebar" id="sidebar">
      <button class="toggle-button" onclick="toggleSidebar()">☰</button>
      <div class="sidebar-content" id="sidebarContent">
        <div class="container bg-white rounded-lg shadow-md">
          <h1 class="text-3xl font-bold mb-4 text-center">ChatBot</h1>
          <div class="chat" id="chatContainer"></div>
          <div class="image-container hidden" id="imageContainer"></div>
          <div class="flex">
            <input
              type="text"
              id="userInput"
              placeholder="Type your message here..."
              class="outline-none"
              onkeyup="handleKeyPress(event)"
            />
            <button class="send-button" onclick="sendMessage()">Send</button>
          </div>
          <div class="typing-indicator" id="typingIndicator"></div>
        </div>
      </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/markdown-it@14.1.0/dist/markdown-it.min.js"></script>
    <script src="{{ url_for('static', filename='js/script.js') }}"></script>
    <!-- image moddal -->
    <div id="myModal" class="modal">
      <span class="close">&times;</span>
      <img class="modal-content" id="img01" />
      <div id="caption"></div>
    </div>

    <script src="{{ url_for('static', filename='js/script.js') }}"></script>
    <script>
      document
        .getElementById("backtestResultButton")
        .addEventListener("click", function () {
          const cs_model = document.getElementById("cs_model").value;
          const ts_model = document.getElementById("ts_model").value;

          fetch("/Backtest_result", {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            body: JSON.stringify({ cs_model: cs_model, ts_model: ts_model }),
          })
            .then((response) => response.json())
            .then((data) => {
              if (data.error) {
                console.error("Error:", data.error);
                return;
              }
              document.getElementById("backtestResult").innerHTML = `
          <div class="image" id="image1">
            <img src="data:image/png;base64,${data.port_weights_img}" alt="Portfolio Weights">
          </div>
          <div class="image" id="image2">
            <img src="data:image/png;base64,${data.asset_performance_img}" alt="Asset Performance">
          </div>
          <div class="image" id="image3">
            <img src="data:image/png;base64,${data.portfolio_performance_img}" alt="Portfolio Performance">
          </div>
        `;
              document.getElementById("backtestResult").classList.add("active");
              document
                .getElementById("detailedReport")
                .classList.remove("active");

              // image click event
              const images = document.querySelectorAll(".image img");
              images.forEach((img) => {
                img.addEventListener("click", function () {
                  const modal = document.getElementById("myModal");
                  const modalImg = document.getElementById("img01");
                  const captionText = document.getElementById("caption");
                  modal.style.display = "block";
                  modalImg.src = this.src;
                  captionText.innerHTML = this.alt;
                });
              });
            })
            .catch((error) => {
              console.error("Error:", error);
            });
        });

      document
        .getElementById("detailedReportButton")
        .addEventListener("click", function () {
          const cs_model = document.getElementById("cs_model").value;
          const ts_model = document.getElementById("ts_model").value;

          fetch("/generate_html_report", {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            body: JSON.stringify({ cs_model: cs_model, ts_model: ts_model }),
          })
            .then((response) => response.json())
            .then((data) => {
              if (data.error) {
                console.error("Error:", data.error);
                return;
              }
              document.getElementById("detailedReport").innerHTML =
                data.report_html;
              document.getElementById("detailedReport").classList.add("active");
              document
                .getElementById("backtestResult")
                .classList.remove("active");
            })
            .catch((error) => {
              console.error("Error:", error);
            });
        });

      // modal close
      const modal = document.getElementById("myModal");
      const span = document.getElementsByClassName("close")[0];
      span.onclick = function () {
        modal.style.display = "none";
      };
    </script>
  </body>
</html>

>Solution :

try adding
overflow: auto;

.sidebar-content {
    resize: both;
    overflow: auto;
    display: none;
}

and don’t forget to specify max-width/min-width and max-height/min-height if required.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading