1656748800
HTML template for vite app, like html-webpack-plugin for webpack.
It works perfectly together with vite-plugin-mpa.
<title></title>
.yarn add -D vite-plugin-html-template
// vite.config.ts
import htmlTemplate from 'vite-plugin-html-template'
// @see https://vitejs.dev/config/
export default defineConfig({
plugins: [
// ...other plugins
htmlTemplate(/* options */),
],
})
// for SPA, there is nothing to do, just use `public/index.html` as template
// for MPA, customise the template path (default is `public/index.html`) and page title:
{
// where is the pages' root directory?
pagesDir: 'src/pages',
// define pages like it is done in vue-cli
pages: {
index: {
template: './public/index.html',
title: 'Homepage',
},
subpage: {
template: './src/pages/subpage/index.html',
title: 'Subpage',
},
},
// expose to template
data: {
title: 'Homepage',
},
}
Author: IndexXuan
Source code: https://github.com/IndexXuan/vite-plugin-html-template
License:
1656747538
In this video, We'll learn how to design magic animated menu Indicator Using CSS & JavaScript | Vertical Tab Menu Design
Buy Me A Coffee : https://www.buymeacoffee.com/onlineTutorials
image source : https://www.pexels.com
icon source : https://fontawesome.com
Source Code : https://www.patreon.com/onlinetutorials
Subscribe: https://www.youtube.com/c/OnlineTutorials4Designers/featured
1656743160
Different ways of using the Label element for a form control in the Form Element - HTML. In this video we will see different ways of using the label element for a form control in the form element - HTML.
1656741600
This plugin helps us configure additional html
The plugin is based on vite transformIndexHtml hooks.
If we want to distinguish the environment and introduce resources in index.html, we can use this plugin. stand by, favicon url, metas config, link tag config, style tag config, headScripts config,body script config.
node version: >=12.0.0
vite version: >=2.0.0
yarn add vite-plugin-html-config -D
// vite.config.js
import htmlPlugin from 'vite-plugin-html-config';
const htmlPluginOpt = {
favicon: './logo.svg',
headScripts: [
`var msg = 'head script'
console.log(msg);`,
{
async: true,
src: 'https://abc.com/b.js',
type: 'module'
},
{ content: `console.log('hello')`, charset: 'utf-8' }
],
scripts: [
`var msg = 'body script'
console.log(msg);`,
{
async: true,
src: 'https://abc.com/b.js',
type: 'module'
}
],
metas: [
{
name: 'keywords',
content: 'vite html meta keywords'
},
{
name: 'description',
content: 'vite html meta description'
},
{
bar: 'custom meta'
}
],
links: [
{
rel: 'stylesheet',
href: './style.css'
},
{
rel: 'modulepreload',
href: 'https://cn.vitejs.dev/assets/guide_api-plugin.md.6884005a.lean.js'
}
],
style: `body { color: red; };*{ margin: 0px }`
}
module.exports = {
plugins: [htmlPlugin(htmlPluginOpt)]
}
We can inject different scripts through different environments
such as:script in head,script in body and more.
in config file
// vite.config.js
const headScripts = []
// from app env
const APP_ENV = 'pro'
const BAIDU_KEY = APP_ENV==='pro'?'123123':'xxxxxx'
if (APP_ENV === 'pro') {
headScripts.push(
{
src: 'https://xxxxxxx/mito.js',
apikey: '123123123123123',
crossorigin: 'anonymous',
},
{
src: 'https://bbbbb.js',
},
)
}
const htmlPluginOpt = {
headScripts,
metas: [
{
name: 'keywords',
content: 'vite html meta keywords',
},
{
name: 'description',
content: 'vite html meta description',
},
],
links: [
{
rel: 'stylesheet',
href: './style.css',
},
{
rel: 'modulepreload',
href: 'https://www.google.com/xxx.js',
},
],
scripts:[
`var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?${BAIDU_KEY}";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();`
],
style: 'body { color: red; };*{ margin: 0px }',
}
module.exports = {
plugins: [htmlPlugin(htmlPluginOpt)]
}
build index.html
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite React</title>
<meta name="keywords" content="vite html meta keywords">
<meta name="description" content="vite html meta description">
<link rel="stylesheet" href="./style.css">
<link rel="modulepreload" href="https://www.google.com/xxx.js">
<style> body { color: red; };*{ margin: 0px }</style>
<script src="https://xxxxxxx/mito.js" apikey="123123123123123" crossorigin="anonymous" customTag=""></script>
<script src="https://bbbbb.js"></script>
</head>
<body>
<div id="root"></div>
<script>var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?123123";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();</script>
</body>
</html>
other example
https://github.com/saschazar21/jpeg-butcher/blob/main/vite.config.ts#L30
Author: ahwgs
Source code: https://github.com/ahwgs/vite-plugin-html-config
License: MIT license
1656734400
vite-plugin-handlebars
Vite support for Handlebars
I really like Vite as a simple static site bundler. It can handle bundling multiple HTML files, which is great, but lacks the ability out-of-the-box to share parts of those HTML files.
While a JS framework like React or Vue could be used to solve this problem, this is heavy-handed for a simple site that could be completely pre-rendered without a JS run-time of any kind.
Handlebars provides what we need to be able to stitch together multiple HTML files, interpolate variables, etc.
Start by installing the package like you would any other
yarn add -D vite-plugin-handlebars
It can then be added to your Vite configuration as a plugin:
// vite.config.js
import handlebars from 'vite-plugin-handlebars';
export default {
plugins: [handlebars()],
};
Configuring the plugin is covered later in this guide.
fs/promises
)If you want to make use of Handlebars Context to inject variables into your HTML file, you'll need to define their values in the context
object passed to the handlebars
plugin:
<!-- index.html -->
<h1>{{title}}</h1>
// vite.config.js
import handlebars from 'vite-plugin-handlebars';
export default {
plugins: [
handlebars({
context: {
title: 'Hello, world!',
},
}),
],
};
This will result in <h1>Hello, world!</h1>
in your output HTML file.
You can also provide a (asynchronous) function, either as the context
key or any of the keys within the object, which will be evaluated to create the value that will be made available inside your page. This function is called with an identifier parameter based on the HTML file path which makes it possible to provide unique data to each HTML page in a multipage application setup.
// vite.config.js
import handlebars from 'vite-plugin-handlebars';
const pageData = {
'/index.html': {
title: 'Main Page',
},
'/nested/subpage.html': {
title: 'Sub Page',
},
};
export default {
plugins: [
handlebars({
context(pagePath) {
return pageData[pagePath];
},
}),
],
};
If you want to make use of partials in your HTML files, you must define the partialDirectory
option for the handlebars
plugin.
// vite.config.js
import { resolve } from 'path';
import handlebars from 'vite-plugin-handlebars';
export default {
plugins: [
handlebars({
partialDirectory: resolve(__dirname, 'partials'),
}),
],
};
If you want to use multiple partial folders, an array can be submitted.
Each file in these directories (.html
or .hbs
) will become registered as a partial. The name of the file is used to invoke it. So, with the above configuration and the following files:
<!-- partials/header.hbs -->
<header><a href="/">My Website</a></header>
<!-- index.html -->
{{> header }}
<h1>The Main Page</h1>
Your output website content would become:
<header><a href="/">My Website</a></header>
<h1>The Main Page</h1>
Make sure to review the quirks section for information on potentially-unexpected behavior.
Custom helpers can be registered using the helpers
configuration option:
// vite.config.js
import { resolve } from 'path';
import handlebars from 'vite-plugin-handlebars';
export default {
plugins: [
handlebars({
helpers: {
capitalize: (value) => value.toUpperCase(),
},
}),
],
};
For more information on helpers, see the Handlebars documentation.
All other Handlebars configuration options can also be passed through.
compileOptions
can be used to alter the compilation stepruntimeOptions
can be used to alter the rendering stepEach of these can also be passed through to the handlebars
plugin:
// vite.config.js
import handlebars from 'vite-plugin-handlebars';
export default {
plugins: [
handlebars({
compileOptions: {
// Example config option: avoid auto-indenting partials
preventIndent: true,
},
runtimeOptions: {
// Example config option: define custom private @variables
data: {
foo: 'bar',
},
},
}),
],
};
By default, any time a partial changes, your browser window will be full reloaded. If you want to disable this behavior, you can set reloadOnPartialChange
to false
:
// vite.config.js
import handlebars from 'vite-plugin-handlebars';
export default {
plugins: [
handlebars({
reloadOnPartialChange: false,
}),
],
};
resolve-from-root
You can resolve a file path relative to the Vite root using the resolve-from-root
helper. This assists with injecting other files, like linking to a CSS file, within a partial.
<!-- partials/head.hbs -->
<link rel="stylesheet" href="{{resolve-from-root 'css/global.css'}}" />
resolve-from-root
helper to ensure paths are resolved from the project root, rather than relative to a particular file.Author: alexlafroscia
Source code: https://github.com/alexlafroscia/vite-plugin-handlebars
License:
1656712800
English | 中文
entry
template
node version: >=12.0.0
vite version: >=2.0.0
yarn add vite-plugin-html -D
或
npm i vite-plugin-html -D
index.html
, e.g.<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%- title %></title>
<%- injectScript %>
</head>
vite.config.ts
, this method can introduce the required functions as neededimport { defineConfig, Plugin } from 'vite'
import vue from '@vitejs/plugin-vue'
import { createHtmlPlugin } from 'vite-plugin-html'
export default defineConfig({
plugins: [
vue(),
createHtmlPlugin({
minify: true,
/**
* After writing entry here, you will not need to add script tags in `index.html`, the original tags need to be deleted
* @default src/main.ts
*/
entry: 'src/main.ts',
/**
* If you want to store `index.html` in the specified folder, you can modify it, otherwise no configuration is required
* @default index.html
*/
template: 'public/index.html',
/**
* Data that needs to be injected into the index.html ejs template
*/
inject: {
data: {
title: 'index',
injectScript: `<script src="./inject.js"></script>`,
},
tags: [
{
injectTo: 'body-prepend',
tag: 'div',
attrs: {
id: 'tag',
},
},
],
},
}),
],
})
Multi-page application configuration
import { defineConfig } from 'vite'
import { createHtmlPlugin } from 'vite-plugin-html'
export default defineConfig({
plugins: [
createHtmlPlugin({
minify: true,
pages: [
{
entry: 'src/main.ts',
filename: 'index.html',
template: 'public/index.html',
injectOptions: {
data: {
title: 'index',
injectScript: `<script src="./inject.js"></script>`,
},
tags: [
{
injectTo: 'body-prepend',
tag: 'div',
attrs: {
id: 'tag1',
},
},
],
},
},
{
entry: 'src/other-main.ts',
filename: 'other.html',
template: 'public/other.html',
injectOptions: {
data: {
title: 'other page',
injectScript: `<script src="./inject.js"></script>`,
},
tags: [
{
injectTo: 'body-prepend',
tag: 'div',
attrs: {
id: 'tag2',
},
},
],
},
},
],
}),
],
})
createHtmlPlugin(options: UserOptions)
Parameter | Types | Default | Description |
---|---|---|---|
entry | string | src/main.ts | entry file path |
template | string | index.html | relative path to the template |
inject | InjectOptions | - | Data injected into HTML |
minify | boolean|MinifyOptions | - | whether to compress html |
pages | PageOption | - | Multi-page configuration |
Parameter | Types | Default | Description |
---|---|---|---|
data | Record<string, any> | - | injected data |
ejsOptions | EJSOptions | - | ejs configuration OptionsEJSOptions |
tags | HtmlTagDescriptor | - | List of tags to inject |
data
can be accessed in html
using the ejs
template syntax
By default, the contents of the .env
file will be injected into index.html, similar to vite's loadEnv
function
Parameter | Types | Default | Description |
---|---|---|---|
filename | string | - | html file name |
template | string | index.html | relative path to the template |
entry | string | src/main.ts | entry file path |
injectOptions | InjectOptions | - | Data injected into HTML |
Default compression configuration
collapseWhitespace: true,
keepClosingSlash: true,
removeComments: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
useShortDoctype: true,
minifyCSS: true,
pnpm install
# spa
cd ./packages/playground/basic
pnpm run dev
# map
cd ./packages/playground/mpa
pnpm run dev
Author: vbenjs
Source code: https://github.com/vbenjs/vite-plugin-html
License: MIT license
1656659535
How To Make Circular Progress Bar | HTML CSS JavaScript - Make a Circular Progress Bar | HTML CSS JavaScript, step-by-step from scratch.
JavaScript Circular Progress bar is used on various websites to show education and experience. I made this circle progress bar with the help of HTML CSS and javascript. In the meantime, I have designed another Progress Bar with the help of Bootstrap.
This design is made much simpler and fully responsive. Here I made three bars. The first is for displaying HTML, the second for CSS, and the third for JavaScript percentages.
First of all, I have given the background color of web page # 0d0c2d. Then I made a box on that web page. I have kept the color of the box and the background color of the webpage the same.
In this case, we have used a shadow in the box which indicates the size of this box. It has three Circular Progress Bars and each has a percentage and a text. I used color # 36e617 to show progress here. You can use any color you want here.
It is made in a very simple and easy way. Here you can add percentages as you need.
Below I have given a demo section that will help you to better understand how it works. Here you will find the required source code which you can copy and use in your own work.
If you are a beginner and want to know how to create Circle Progress Bar then follow the tutorial below.
I used some CDN links to make this. The first is JQuery and the second is easyPieChart. I have given the link of these two below. You can copy these links and add them to the head section of your HTML file.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/easy-pie-chart/2.1.6/jquery.easypiechart.min.js"></script>
First of all, I designed the background of this web page and made a box in it. In this box, I put all the Progress Bar. Webpage background: # 0d0c2d I have given blue and used height 100vh.
<div class="container">
</div>
body {
margin: 0;
padding: 0;
justify-content: center;
height: 100vh;
color:white;
background: #0d0c2d;
font-family: sans-serif;
display: flex;
}
.container {
background: #0d0c2d;
padding: 60px;
display: grid;
grid-template-columns: repeat(1, 160px);
grid-gap: 80px;
margin: auto 0;
box-shadow: -5px -5px 8px rgba(94, 104, 121, 0.288),
4px 4px 6px rgba(94, 104, 121, 0.288);
}
Now I have added all the elements of this javascript circular progress bar using HTML code. Here data-percent = "" is used to determine the value of your circle progress bar. I have 90% for HTML, 72% for CSS and 81% for JavaScript. If you want to change, you can change the values here.
With this, I have used a text that will help to know which bar is for which work. Now I have executed this Circular Progress Bar using the jQuery code. In order to execute the jquery code, I have first added the jquery CDN link.
<div class="box">
<div class="chart" data-percent="90" >90%</div>
<h2>HTML</h2>
</div>
<div class="box">
<div class="chart" data-percent="72" >72%</div>
<h2>CSS</h2>
</div>
<div class="box">
<div class="chart" data-percent="81" >81%</div>
<h2>JAVASCRIPT</h2>
</div>
➤ First I used size: 160 which will determine the size of this circle.
➤ barColor: "# 36e617" I used which will determine this progressive color. Here I have used green. You can use any other color if you want.
➤ lineWidth: 15 basically helps to determine the size of the color line in this bar.
➤ trackColor: "# 525151" is here mainly for the background of the circular.
➤ I have used animate: 2000, which means it will take 2000 milliseconds (2 seconds) for the animation to take place. As a result, when you open the page, it will take you two seconds to reach the mean you set from zero.
$(function() {
$('.chart').easyPieChart({
size: 160,
barColor: "#36e617",
scaleLength: 0,
lineWidth: 15,
trackColor: "#525151",
lineCap: "circle",
animate: 2000,
});
});
I designed the titles using the following CSS codes.
.container .box {
width: 100%;
}
.container .box h2 {
display: block;
text-align: center;
color: #fff;
}
I designed and positioned the percentage I used here using the CSS codes below. If you have seen the demo, you will understand that the text here is placed in the middle of the progress bar.
Used text-align: center and position: relative for this. I used font-size: 40px and the color white to make the text sizes a little bigger.
.container .box .chart {
position: relative;
width: 100%;
height: 100%;
text-align: center;
font-size: 40px;
line-height: 160px;
height: 160px;
color: #fff;
}
I have specified the position of this circular progress bar using the following codes. For this, I have used position: absolute and left and top zero.
.container .box canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
width: 100%;
}
Now, this design is ready to use in any of your websites or project. However, I have made it responsive for all devices using some CSS code below. I have used CSS's @media for this. Then I have determined how it will look for any screen size.
@media (min-width: 420px) and (max-width: 659px) {
.container {
grid-template-columns: repeat(2, 160px);
}
}
@media (min-width: 660px) {
.container {
grid-template-columns: repeat(3, 160px);
}
}
Hopefully from this tutorial, you have learned step by step how I have created this circular progress bar using HTML CSS and javaScript.
#html #css #javascript #programming #webdev
1656658186
Today’s tutorial will teach us how to create a movie guide app. To build this app, we need HTML, CSS and Javascript. We make use of the Open Movie Database API to fetch the information.
If the input field is empty, we display the message – ‘Please Enter A Movie Name’. In case the movie entered by the user does not exist in the database, we show the message- ‘Movie Not Found’. Finally, if some error occurs while fetching the data from the API, we display the message- ‘Error Occurred.
Before we start coding, let us take a look at the project folder structure. We create a project folder called – “Movie Guide App”. Inside this folder, we have five files. The first is index.html which is the HTML document.
The next is style.css which is the stylesheet. Next, we have script.js, a script file. We have one more script file called key.js that I have used to store the API key and keep it hidden for privacy reasons. The final file is the star icon SVG.
We start with the HTML section. First, copy the code below and paste it into your HTML document.
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Movie Guide App</title>
<!-- Google Font -->
<link
href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;500;600&display=swap"
rel="stylesheet"
/>
<!-- Stylesheet -->
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<div class="search-container">
<input
type="text"
placeholder="Enter movie name heree..."
id="movie-name"
value="dark knight"
/>
<button id="search-btn">Search</button>
</div>
<div id="result"></div>
</div>
<script src="key.js"></script>
<script src="script.js"></script>
</body>
</html>
Next, we style these elements using CSS. For this copy, the code provided to you below and paste it into your stylesheet.
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
height: 100vh;
background: linear-gradient(#000000 50%, #ffb92a 50%);
}
.container {
font-size: 16px;
width: 90vw;
max-width: 37.5em;
padding: 3em 1.8em;
background-color: #201f28;
position: absolute;
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
border-radius: 0.6em;
box-shadow: 1.2em 2em 3em rgba(0, 0, 0, 0.2);
}
.search-container {
display: grid;
grid-template-columns: 9fr 3fr;
gap: 1.2em;
}
.search-container input,
.search-container button {
font-size: 0.9em;
outline: none;
border-radius: 0.3em;
}
.search-container input {
background-color: transparent;
border: 1px solid #a0a0a0;
padding: 0.7em;
color: #ffffff;
}
.search-container input:focus {
border-color: #ffffff;
}
.search-container button {
background-color: #ffb92a;
border: none;
cursor: pointer;
}
#result {
color: #ffffff;
}
.info {
position: relative;
display: grid;
grid-template-columns: 4fr 8fr;
align-items: center;
margin-top: 1.2em;
}
.poster {
width: 100%;
}
h2 {
text-align: center;
font-size: 1.5em;
font-weight: 600;
letter-spacing: 0.06em;
}
.rating {
display: flex;
align-items: center;
justify-content: center;
gap: 0.6em;
margin: 0.6em 0 0.9em 0;
}
.rating img {
width: 1.2em;
}
.rating h4 {
display: inline-block;
font-size: 1.1em;
font-weight: 500;
}
.details {
display: flex;
font-size: 0.95em;
gap: 1em;
justify-content: center;
color: #a0a0a0;
margin: 0.6em 0;
font-weight: 300;
}
.genre {
display: flex;
justify-content: space-around;
}
.genre div {
border: 1px solid #a0a0a0;
font-size: 0.75em;
padding: 0.4em 1.6em;
border-radius: 0.4em;
font-weight: 300;
}
h3 {
font-weight: 500;
margin-top: 1.2em;
}
p {
font-size: 0.9em;
font-weight: 300;
line-height: 1.8em;
text-align: justify;
color: #a0a0a0;
}
.msg {
text-align: center;
}
@media screen and (max-width: 600px) {
.container {
font-size: 14px;
}
.info {
grid-template-columns: 1fr;
}
.poster {
margin: auto;
width: auto;
max-height: 10.8em;
}
}
Finally, we add functionality to this code using Javascript. To do this, copy the code below and paste it into your script file.
//Initial References
let movieNameRef = document.getElementById("movie-name");
let searchBtn = document.getElementById("search-btn");
let result = document.getElementById("result");
//Function to fetch data from API
let getMovie = () => {
let movieName = movieNameRef.value;
let url = `http://www.omdbapi.com/?t=${movieName}&apikey=${key}`;
//If input field is empty
if (movieName.length <= 0) {
result.innerHTML = `<h3 class="msg">Please Enter A Movie Name</h3>`;
}
//If input field is NOT empty
else {
fetch(url)
.then((resp) => resp.json())
.then((data) => {
//If movie exists in database
if (data.Response == "True") {
result.innerHTML = `
<div class="info">
<img src=${data.Poster} class="poster">
<div>
<h2>${data.Title}</h2>
<div class="rating">
<img src="star-icon.svg">
<h4>${data.imdbRating}</h4>
</div>
<div class="details">
<span>${data.Rated}</span>
<span>${data.Year}</span>
<span>${data.Runtime}</span>
</div>
<div class="genre">
<div>${data.Genre.split(",").join("</div><div>")}</div>
</div>
</div>
</div>
<h3>Plot:</h3>
<p>${data.Plot}</p>
<h3>Cast:</h3>
<p>${data.Actors}</p>
`;
}
//If movie does NOT exists in database
else {
result.innerHTML = `<h3 class='msg'>${data.Error}</h3>`;
}
})
//If error occurs
.catch(() => {
result.innerHTML = `<h3 class="msg">Error Occured</h3>`;
});
}
};
searchBtn.addEventListener("click", getMovie);
window.addEventListener("load", getMovie);
Next, go to this link. Submit the form and you will receive your API key at your email address. Copy the API key and save it as a global variable key in the key.js file.
//Enter the API key recieved on your email here
key = "12345a6b";
That’s it for this tutorial. If you have any issues while creating this code, you can download the source code
Happy Coding.
#html #css #javascript
1656656460
Fieldset and legend elements to group the Form Controls in the Form - HTML. In this video we will see about the fieldset and legend elements to group the form controls in the form - HTML.
1656651600
vite's MPA unlike @vue/cli
's pages
option have a configuration in dev mode.
vite's html file need to place in project's root to have same behavior in dev and production mode, it makes your project's root dir looks chaotic.
And if you follow vite's MPA, put other file in other directory, unlike index.html
, you need useless middle directory(Ex. from vite's MPA doc http://localhost:3000/nested/nested.html
) to located it.
so, i write this plugin to make vite's MPA more configurable and in dev mode or production has same behavior.
this plugin use vite's configureServer
Hook to intercept html request and response the html content requested from browser.
0.2.9
add a new option injectCode
to add some code before/after tag in html file0.2.8
add a new option extraGlobPattern
to customize fast-glob
's pattern. Default pattern is ['**/*.html', '!node_modules/**/*.html', '!.**/*.html']
, attention: if your config has problems, such as you didn't ignore dist
, when build,it will occur error: new Error('[vite]: Rollup failed to resolve import "${id}" from "${importer}".\n'
0.2.6
pages
now correctly identify multi-level directories0.2.3
pages
options now can set to true to allow all html in project.0.2.1
now works fine with @vitejs/plugin-react
.0.2.0
has reworked, so config have a little changepage
's config renamed to template
page
can have a independent render
functiondata
, its' config will be covered by page
's data
pages
' will be treat as template file@vue/cli
's pages
)pages
.pages
options) under dist's sub-folder to dist folder, and then delete the rest html file.build.rollupOptions.input
from pagesyarn add vite-plugin-virtual-html --dev # npm install vite-plugin-virtual-html -D
Add it to vite.config.js
// vite.config.js
const virtualHtml = require('vite-plugin-virtual-html')
const pages = {
index: '/src/index/index.html',
login: '/src/login/login.html',
}
module.exports = {
plugins: [virtualHtml({
pages,
indexPage: 'login'
})],
}
config your project's all html/template file's path
it will be used for:
build.rollupOptions.input
template
and data
to render it. By default, it will return the html content in your HTML/template file, when you define a render function, it(html template) will rendered by your custom render function.// all config
{
// 1. directly input html/template path
login1: '/src/index/index.html',
// 2. a object with template
login2: {
template: '/src/login/login.html', // if there is no data prop, the login.html must only contain HTML content
},
// 3. a object with template and data, maybe with render
login3: {
template: '/src/login1/login1.html',
data: {
users: ['a', 'b', 'c']
},
// each page can have independent render function
// render(template, data){
// return template
// }
}
}
notice:
<$= users.join(" | "); $>
), you must contain template
and data
.pages
options' key
is the real HTML file after buildpages
options' key
and value
/ template
file's name can different.login1.html
when dev
mode, and it will generate a login1.html
when build.pages
set to true
, the template.html
will only generate ONLY ONE html
fileconfig the index page
Ex. when you open http://localhost:3000
, your project's root dir has no index.html
file, then browser will show 404
.
now, if you set this, plugin will intercept /
request, and response with page you set.
Like this: when you set indexPage
to login
,then you access http://localhost:3000
in browser, it will show the /login.html
page.
it equals to access http://localhost:3000/login.html
.
from 0.1.0
, you can use render
function to render html template. i have just test in ejs
, but i think other template system will(maybe) work correctly.
Customize fast-glob
's pattern When set this options, it will replace default fast-glob
pattern, it's default value is ['**/*.html', '!node_modules/**/*.html', '!.**/*.html']
In html file, put replacement
before/after find
template
file for multiple page, plese make sure the page's key is different.Author: windsonR
Source code: https://github.com/windsonR/vite-plugin-virtual-html
License: MIT license
1656641760
HTTPlug, the HTTP client abstraction for PHP.
HTTP client standard built on PSR-7 HTTP messages. The HTTPlug client interface is compatible with the official standard for the HTTP client interface, PSR-18. HTTPlug adds an interface for asynchronous HTTP requests, which PSR-18 does not cover.
Since HTTPlug has already been widely adopted and a whole ecosystem has been built around it, we will keep maintaining this package for the time being. HTTPlug 2.0 and newer extend the PSR-18 interface to allow for a convenient migration path.
New client implementations and consumers should use the PSR-18 interfaces directly. In the long term, we expect PSR-18 to completely replace the need for HTTPlug.
HTTPlug is the official successor of the ivory http adapter. HTTPlug is a predecessor of PSR-18
Via Composer
$ composer require php-http/httplug
Please see the official documentation.
$ composer test
Author: php-http
Source Code: https://github.com/php-http/httplug
License: MIT license
1656574500
In today's tutorial we'll be creating a "Copy Link" input field using HTML, CSS and JavaScript. This is very easy to do and is a huge convenience to your users when performing an action like sharing a link.
HTML
<div class="copy-link">
<input type="text" class="copy-link-input" value="https://www.youtube.com/" readonly>
<button type="button" class="copy-link-button">
<span class="material-icons">content_copy</span>
</button>
</div>
CSS
.copy-link {
--height: 36px;
display: flex;
max-width: 250px;
}
.copy-link-input {
flex-grow: 1;
padding: 0 8px;
font-size: 14px;
border: 1px solid #cccccc;
border-right: none;
outline: none;
}
.copy-link-input:hover {
background: #eeeeee;
}
.copy-link-button {
flex-shrink: 0;
width: var(--height);
height: var(--height);
display: flex;
align-items: center;
justify-content: center;
background: #dddddd;
color: #333333;
outline: none;
border: 1px solid #cccccc;
cursor: pointer;
}
.copy-link-button:hover {
background: #cccccc;
}
JavaScript
document.querySelectorAll(".copy-link").forEach((copyLinkParent) => {
const inputField = copyLinkParent.querySelector(".copy-link-input");
const copyButton = copyLinkParent.querySelector(".copy-link-button");
const text = inputField.value;
inputField.addEventListener("focus", () => inputField.select());
copyButton.addEventListener("click", () => {
inputField.select();
navigator.clipboard.writeText(text);
inputField.value = "Copied!";
setTimeout(() => (inputField.value = text), 2000);
});
});
MATERIAL ICONS INSTALL:
https://developers.google.com/fonts/docs/material_icons#setup_method_1_using_via_google_fonts
MATERIAL ICONS LIBRARY:
https://fonts.google.com/icons?icon.style=Filled&icon.set=Material+Icons&icon.query=copy
GET THE SOURCE CODE 👇
https://codepen.io/dcode-software/pen/eYMYXrK
#html #css #javascript
1656572736
In this guide, we will learn how to create a Recipe app with HTML, CSS & JavaScript. To create a Recipe App with HTML, CSS & JavaScript. You need to create three Files HTML, CSS & JavaScript.
1: First, create an HTML file
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Recipe App</title>
<!-- Google Fonts -->
<link
href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap"
rel="stylesheet"
/>
<!-- Stylesheet -->
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<div class="search-container">
<input
type="text"
placeholder="Type A Dish Name Here.."
id="user-inp"
/>
<button id="search-btn">Search</button>
</div>
<div id="result"></div>
</div>
<!-- Script -->
<script src="script.js"></script>
</body>
</html>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
background-color: #f4c531;
}
.container {
background-color: #ffffff;
font-size: 16px;
padding: 3em 2.8em;
width: 90vw;
max-width: 32em;
position: absolute;
transform: translate(-50%, -50%);
left: 50%;
top: 50%;
border-radius: 0.6em;
}
.search-container {
width: 100%;
display: grid;
grid-template-columns: 9fr 3fr;
gap: 1.2em;
}
.search-container input {
font-size: 1em;
padding: 0.6em;
border: none;
outline: none;
border-bottom: 2px solid #202030;
}
.search-container button {
font-size: 1em;
background-color: #f4c531;
border: none;
font-weight: 600;
border-radius: 0.3em;
}
img {
display: block;
width: 50%;
margin: 1.8em auto 0 auto;
}
.details {
background-color: #f4c531;
position: relative;
margin: -4.3em 0 0 0;
text-align: center;
padding: 0.6em 0;
}
.details h2 {
font-size: 1.2em;
font-weight: 600;
}
.details h4 {
font-size: 1em;
font-weight: 400;
}
#show-recipe {
font-size: 1em;
position: relative;
left: 75%;
padding: 0.9em 0.6em;
background-color: #f4c531;
border: none;
top: 1.5em;
border-radius: 0.3em;
font-weight: 600;
}
#recipe {
position: absolute;
background-color: #ffffff;
min-height: 100%;
width: 100%;
top: 0;
left: 0;
z-index: 2;
border-radius: 0.6em;
display: none;
}
#recipe pre {
white-space: pre-wrap;
word-wrap: break-word;
padding: 2.5em 1.2em 1.2em 1.2em;
font-size: 0.92em;
color: #303040;
}
#hide-recipe {
font-size: 1em;
position: relative;
width: 1.8em;
height: 1.8em;
background-color: #f4c531;
border: none;
top: 1.2em;
left: 90%;
border-radius: 0.3em;
}
ul {
font-size: 1em;
position: relative;
display: grid;
grid-template-columns: auto auto;
gap: 0.8em 1.1em;
padding: 1.2em 0 0 1.2em;
color: #303040;
text-transform: capitalize;
}
h3 {
text-align: center;
margin-top: 1.8em;
color: #202030;
}
@media screen and (max-width: 500px) {
.container {
font-size: 14px;
}
}
//Initial References
let result = document.getElementById("result");
let searchBtn = document.getElementById("search-btn");
let url = "https://www.themealdb.com/api/json/v1/1/search.php?s=";
searchBtn.addEventListener("click", () => {
let userInp = document.getElementById("user-inp").value;
if (userInp.length == 0) {
result.innerHTML = `<h3>Input Field Cannot Be Empty</h3>`;
} else {
fetch(url + userInp)
.then((response) => response.json())
.then((data) => {
let myMeal = data.meals[0];
console.log(myMeal);
console.log(myMeal.strMealThumb);
console.log(myMeal.strMeal);
console.log(myMeal.strArea);
console.log(myMeal.strInstructions);
let count = 1;
let ingredients = [];
for (let i in myMeal) {
let ingredient = "";
let measure = "";
if (i.startsWith("strIngredient") && myMeal[i]) {
ingredient = myMeal[i];
measure = myMeal[`strMeasure` + count];
count += 1;
ingredients.push(`${measure} ${ingredient}`);
}
}
console.log(ingredients);
result.innerHTML = `
<img src=${myMeal.strMealThumb}>
<div class="details">
<h2>${myMeal.strMeal}</h2>
<h4>${myMeal.strArea}</h4>
</div>
<div id="ingredient-con"></div>
<div id="recipe">
<button id="hide-recipe">X</button>
<pre id="instructions">${myMeal.strInstructions}</pre>
</div>
<button id="show-recipe">View Recipe</button>
`;
let ingredientCon = document.getElementById("ingredient-con");
let parent = document.createElement("ul");
let recipe = document.getElementById("recipe");
let hideRecipe = document.getElementById("hide-recipe");
let showRecipe = document.getElementById("show-recipe");
ingredients.forEach((i) => {
let child = document.createElement("li");
child.innerText = i;
parent.appendChild(child);
ingredientCon.appendChild(parent);
});
hideRecipe.addEventListener("click", () => {
recipe.style.display = "none";
});
showRecipe.addEventListener("click", () => {
recipe.style.display = "block";
});
})
.catch(() => {
result.innerHTML = `<h3>Invalid Input</h3>`;
});
}
});
Now you’ve successfully a Recipe App with HTML, CSS & JavaScript.
1656570502
In this guide, we will learn how to detect the battery status with HTML, CSS & JavaScript. To detect the battery status with HTML, CSS & JavaScript. You need to create three Files HTML, CSS & JavaScript
1: First, create an HTML file
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Detect Battery Status</title>
<!-- Google Fonts -->
<link
href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500&display=swap"
rel="stylesheet"
/>
<!-- Stylesheet -->
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<div id="battery">
<div id="charge"></div>
<div id="charge-level"></div>
</div>
<div id="charging-time"></div>
</div>
<script src="script.js"></script>
</body>
</html>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: "Roboto Mono", monospace;
}
.container {
position: absolute;
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
}
#battery {
box-sizing: content-box;
height: 7.8em;
width: 17.5em;
border: 0.6em solid #246aed;
margin: auto;
border-radius: 0.6em;
position: relative;
display: grid;
place-items: center;
}
#battery:before {
position: absolute;
content: "";
height: 5em;
width: 1.1em;
background-color: #246aed;
margin: auto;
top: 0;
bottom: 0;
right: -1.6em;
border-radius: 0 0.3em 0.3em 0;
}
#charge {
position: absolute;
height: 6.5em;
width: 16.25em;
background-color: #246aed;
top: 0.6em;
left: 0.6em;
}
#charge-level {
position: absolute;
font-size: 3em;
font-weight: 500;
}
#charging-time {
text-align: center;
font-size: 1.7em;
margin-top: 1.4em;
}
.active {
animation: charge-animation 3s infinite linear;
}
@keyframes charge-animation {
0% {
width: 0;
}
100% {
width: 16.25em;
}
}
const chargeLevel = document.getElementById("charge-level");
const charge = document.getElementById("charge");
const chargingTimeRef = document.getElementById("charging-time");
window.onload = () => {
//For browsers that don't support the battery status API
if (!navigator.getBattery) {
alert("Battery Status Api Is Not Supported In Your Browser");
return false;
}
};
navigator.getBattery().then((battery) => {
function updateAllBatteryInfo() {
updateChargingInfo();
updateLevelInfo();
}
updateAllBatteryInfo();
//When the charging status changes
battery.addEventListener("chargingchange", () => {
updateAllBatteryInfo();
});
//When the Battery Levvel Changes
battery.addEventListener("levelchange", () => {
updateAllBatteryInfo();
});
function updateChargingInfo() {
if (battery.charging) {
charge.classList.add("active");
chargingTimeRef.innerText = "";
} else {
charge.classList.remove("active");
//Display time left to discharge only when it is a integer value i.e not infinity
if (parseInt(battery.dischargingTime)) {
let hr = parseInt(battery.dischargingTime / 3600);
let min = parseInt(battery.dischargingTime / 60 - hr * 60);
chargingTimeRef.innerText = `${hr}hr ${min}mins remaining`;
}
}
}
//Updating battery level
function updateLevelInfo() {
let batteryLevel = `${parseInt(battery.level * 100)}%`;
charge.style.width = batteryLevel;
chargeLevel.textContent = batteryLevel;
}
});
You have now successfully created a battery health detection app using HTML, CSS & JavaScript
1656568800
What are Web Forms. Elements present in the Web Form - HTML. In this video we will see what are the webforms and the elements present in the web form - HTML.