Skip to content

Instantly share code, notes, and snippets.

@achingachris
Created April 13, 2024 12:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save achingachris/fe705556315b67f35214bf1491529e9a to your computer and use it in GitHub Desktop.
Save achingachris/fe705556315b67f35214bf1491529e9a to your computer and use it in GitHub Desktop.
@import "https://fonts.googleapis.com/css?family=Poppins";
* {
box-sizing: border-box;
font-family: "Poppins";
}
body {
background-color: #edeef6;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
margin: 0;
padding: 20px;
}
button {
background-color: #47a386;
color: white;
border: 0;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
padding: 10px 25px;
font-size: 14px;
}
.modal-container {
/* display: none; */
opacity: 0;
pointer-events: none;
position: fixed;
display: flex;
align-items: center;
justify-content: center;
top: 0;
left: 0;
height: 100vh;
width: 100vw;
background-color: rgba(0, 0, 0, 0.3);
transition: opacity 0.3s ease;
}
.modal-container.show {
pointer-events: auto;
opacity: 1;
}
.modal {
border-radius: 5px;
padding: 30px 50px;
background-color: white;
width: 600px;
max-width: 100%;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
text-align: center;
height: 300px;
overflow-y: auto;
}
.modal h1 {
margin: 0;
}
.modal p {
font-size: 14px;
opacity: 0.7;
}
input[type="text"] {
padding: 10px;
width: 50%;
outline: none;
border: 1px solid white;
border-radius: 10px;
}
input[type="text"]:focus {
font-size: 1.2rem;
outline: none;
background: rgba(0, 120, 250, 0.1);
transition: transform 0.2s ease;
}
dialog {
max-width: 500px;
border: 1px solid #ddd;
border-radius: 8px;
padding: 15px;
}
textarea {
margin: 15px auto;
outline: 2px solid #ddd;
border: 0;
width: 100%;
padding: 10px;
border-radius: 5px;
}
.file {
background-color: #fff;
outline: 2px solid #ddd;
border: 0;
padding: 8px;
border-radius: 5px;
margin-left: 5px;
}
button,
textarea,
.file {
cursor: pointer;
}
textarea:hover,
textarea:focus,
.file:hover,
.file:focus {
outline: 2px solid #47a386;
border: 0;
}
.dialog-form {
margin-top: 10px;
}
.images img {
overflow: contain;
border: 1px solid #ddd;
border-radius: 8px;
margin: 0 auto;
margin-bottom: 10px;
width: 100%;
height: auto;
}
.images {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Gemini AI for Web</title>
<link rel="stylesheet" href="index.css" />
<link rel="manifest" href="manifest.json">
</head>
<body>
<main>
<div>
<hi>Gemini Web Demo</h1>
<textarea id="gemini-prompt" placeholder="Type in a prompt..."></textarea>
<button id="open">Generate</button>
<input multiple class="file" type="file" id="file" />
</div>
<div class="modal-container" id="modal_container">
<div class="modal">
<h1>Gemini Response</h1>
<p id="gemini-response"></p>
<button id="close">Close Me</button>
</div>
</div>
</main>
<dialog id="response-dialog">
<div id="images" class="images"></div>
<div id="message"></div>
<form class="dialog-form" method="dialog">
<button>OK</button>
</form>
</dialog>
</body>
<script type="module" src="index.js"></script>
</html>
import { GoogleGenerativeAI } from "https://esm.run/@google/generative-ai";
// Fetch your API Key : > config
const API_KEY = "YOUR-KEY";
const genAI = new GoogleGenerativeAI(API_KEY);
// Get elements from the DOM
const open = document.getElementById("open");
const modal_container = document.getElementById("modal_container");
const close = document.getElementById("close");
const respDialog = document.querySelector("dialog");
const message = document.getElementById("message");
const filePicker = document.getElementById("file");
const afterPromptResponse = document.getElementById("gemini-response");
const images = document.getElementById("images");
// Ask gemini anything using text - text-only input
open.addEventListener("click", async () => {
try {
const askGemini = async () => {
const model = genAI.getGenerativeModel({ model: "gemini-pro" });
const promptText = document.getElementById("gemini-prompt").value;
const result = await model.generateContent(promptText);
const response = await result.response;
const text = response.text();
afterPromptResponse.innerText = text;
};
await askGemini();
modal_container.classList.add("show");
} catch (error) {
const message = error?.message ?? "Something went wrong"
console.warn(message);
alert(message)
}
});
close.addEventListener("click", () => {
modal_container.classList.remove("show");
});
// Use image only to prompt gemini
filePicker.addEventListener("change", async (event) => {
event.preventDefault();
try {
// Converts a File object to a GoogleGenerativeAI.Part object.
async function fileToGenerativePart(file) {
const base64EncodedDataPromise = new Promise((resolve) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result.split(",")[1]);
reader.readAsDataURL(file);
});
return {
inlineData: {
data: await base64EncodedDataPromise,
mimeType: file.type,
},
};
}
const askGemini = async () => {
// For text-and-images input (multimodal), use the gemini-pro-vision model
const model = genAI.getGenerativeModel({ model: "gemini-pro-vision" });
const prompt = "Please explain the image attached";
const fileInputEl = document.querySelector("input[type=file]");
const imageParts = await Promise.all(
[...fileInputEl.files].map(fileToGenerativePart)
);
const result = await model.generateContent([prompt, ...imageParts]);
const response = await result.response;
const text = response.text();
message.innerText = text;
const fileList = [...fileInputEl.files]
fileList.forEach(file => {
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
const el = document.createElement('img')
el.src = e.target.result
images.appendChild(el)
};
reader.readAsDataURL(file);
}
})
};
await askGemini();
respDialog.show();
} catch (error) {
const message = error?.message ?? "Something went wrong"
console.warn(message);
alert(message)
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment