Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9b9e8a6b84 | |||
| de4c1e1a57 | |||
| a36ef35350 | |||
| 6da60eaa31 | |||
| 84e118a723 | |||
| e26564cde6 | |||
| 2e8daeaa0d | |||
| edde3e1123 | |||
| 1286527ddd | |||
| 98f6f9c223 | |||
| 03a9f1b237 | |||
| 308342eefc | |||
| aae2408ef7 | |||
| 1f289595f9 | |||
| 62a2507e19 | |||
| 6930cf2da2 | |||
| 7ce2ea3ae2 | |||
| 4dad914f15 | |||
| 8e8d33799b | |||
| bd4225c25c | |||
| 123418edea | |||
| c28b579ab6 | |||
| 1d476eb2b5 | |||
| 07c0b9652f | |||
| cd85ec46cd | |||
| 001841d6e6 | |||
| 9c1b16ec3d | |||
| a15bcb6699 | |||
| 43d6a7b957 | |||
| fcbbf9219b |
+1
-1
@@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: ['https://donate.stripe.com/7sIeWp3aG07vd6o8ww'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
custom: ['https://www.buymeacoffee.com/gurusabarish'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
|
||||
@@ -24,6 +24,7 @@ A high performance and mobile first hugo template for personal portfolio and blo
|
||||
- [Google Analytics](https://gohugo.io/templates/internal/#google-analytics)
|
||||
- Comment Support
|
||||
- [Disqus](https://gohugo.io/content-management/comments/)
|
||||
- Integration with [FormSpree](https://formspree.io/) for submitting "Contact me" form
|
||||
|
||||
Technology used: Bootstrap, fontawesome
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ outputs:
|
||||
|
||||
Paginate: 3
|
||||
enableRobotsTXT: true
|
||||
# disqusShortname: your-disqus-shortname
|
||||
# googleAnalytics: G-MEASUREMENT_ID
|
||||
|
||||
markup:
|
||||
goldmark:
|
||||
@@ -100,8 +102,10 @@ params:
|
||||
navbar:
|
||||
align: ms-auto # Left: ms-auto | center: mx-auto | right: me-auto | Default: ms-auto
|
||||
# brandLogo: "/logo.png" # Logo for the brand | default is the favicon variable
|
||||
# showBrandLogo: false # Show brand logo in nav bar | default is true
|
||||
brandName: "Hugo Profile" # Brand name for the brand | default is the title variable
|
||||
disableSearch: false
|
||||
# searchPlaceholder: "Search"
|
||||
menus:
|
||||
disableAbout: false
|
||||
disableExperience: false
|
||||
@@ -118,6 +122,9 @@ params:
|
||||
subtitle: "I build things for the web"
|
||||
content: "A passionate web app developer. I tend to make use of modern web technologies to build websites that looks great, feels fantastic, and functions correctly."
|
||||
image: /images/hero.svg
|
||||
bottomImage:
|
||||
enable: true
|
||||
# roundImage: true # Make hero image circular | default false
|
||||
button:
|
||||
enable: true
|
||||
name: "Resume"
|
||||
@@ -338,6 +345,11 @@ params:
|
||||
content: My inbox is always open. Whether you have a question or just want to say hi, I’ll try my best to get back to you!
|
||||
email: gurusabarisha@gmail.com
|
||||
btnName: Mail me
|
||||
# formspree:
|
||||
# enable: true # `contact.email` value will be ignored
|
||||
# formId: abcdefgh # Take it from your form's endpoint, like 'https://formspree.io/f/abcdefgh'
|
||||
# emailCaption: "Enter your email address"
|
||||
# messageCaption: "Enter your message here"
|
||||
|
||||
footer:
|
||||
recentPosts:
|
||||
@@ -356,3 +368,24 @@ params:
|
||||
# List pages like blogs and posts
|
||||
listPages:
|
||||
disableFeaturedImage: false
|
||||
|
||||
# Single pages like blog and post
|
||||
singlePages:
|
||||
readTime:
|
||||
enable: true
|
||||
content: "min read"
|
||||
scrollprogress:
|
||||
enable: true
|
||||
|
||||
# For translations
|
||||
terms:
|
||||
read: "Read"
|
||||
toc: "Table Of Contents"
|
||||
copyright: "All rights reserved"
|
||||
pageNotFound: "Page not found"
|
||||
emailText: "Check out this site"
|
||||
|
||||
datesFormat:
|
||||
article: "Jan 2, 2006"
|
||||
articleList: "Jan 2, 2006"
|
||||
articleRecent: "Jan 2, 2006"
|
||||
|
||||
+3
-3
@@ -3,12 +3,12 @@
|
||||
{{ end }}
|
||||
|
||||
{{ define "title" }}
|
||||
{{ .Site.Title }} | 404 page not found
|
||||
{{ .Site.Title }} | {{ .Site.Params.terms.pageNotFound | default "404 page not found" }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
<div class="container py-5 text-center">
|
||||
<img src="{{ .Site.Params.staticPath }}/404.png" alt="404 page not found" class="img-fluid" width="40%">
|
||||
<h1>404 Page Not Found</h1>
|
||||
<img src="{{ .Site.Params.staticPath }}/404.png" alt='{{ .Site.Params.terms.pageNotFound | default "404 page not found" }}' class="img-fluid" width="40%">
|
||||
<h1>{{ .Site.Params.terms.pageNotFound | default "404 page not found" }}</h1>
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -9,7 +9,7 @@
|
||||
</title>
|
||||
</head>
|
||||
|
||||
<body class="light" onload="loading()">
|
||||
<body class="light">
|
||||
<!-- javascripts -->
|
||||
<!-- <script src="/js/jquery-3.6.0.min.js"></script> -->
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-auto post-footer bg-transparent py-3">
|
||||
<span class="float-start bg-transparent">{{ .Date.Format "January 2, 2006" }}</span>
|
||||
<a href="{{ .RelPermalink }}" class="float-end btn btn-outline-info btn-sm">Read</a>
|
||||
<span class="float-start bg-transparent">{{ .Date.Format (.Site.Params.datesFormat.articleList | default "January 2, 2006") }}</span>
|
||||
<a href="{{ .RelPermalink }}" class="float-end btn btn-outline-info btn-sm">{{ .Site.Params.terms.read | default "Read" }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,13 @@
|
||||
<div class="text-center">
|
||||
{{ .Params.author }}
|
||||
<small>|</small>
|
||||
{{ .Date.Format "Jan 2, 2006" }}
|
||||
{{ .Date.Format (.Site.Params.datesFormat.article | default "Jan 2, 2006") }}
|
||||
|
||||
{{ if or (.Site.Params.singlePages.readTime.enable | default true) (.Params.enableReadingTime) }}
|
||||
<span id="readingTime">
|
||||
{{ .Site.Params.singlePages.readTime.content | default "min read" }}
|
||||
</span>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ if .Params.image }}
|
||||
@@ -39,7 +45,7 @@
|
||||
{{ if .Params.toc | default true}}
|
||||
<aside class="toc">
|
||||
<h5>
|
||||
Table Of Contents
|
||||
{{ .Site.Params.terms.toc | default "Table Of Contents" }}
|
||||
</h5>
|
||||
<div class="toc-content">
|
||||
{{.TableOfContents}}
|
||||
@@ -49,7 +55,7 @@
|
||||
|
||||
{{ if .Params.tags }}
|
||||
<aside class="tags">
|
||||
<h5>Tags</h5>
|
||||
<h5>{{ .Site.Params.terms.tags | default "Tags" }}</h5>
|
||||
<ul class="tags-ul list-unstyled list-inline">
|
||||
{{range .Params.tags}}
|
||||
<li class="list-inline-item"><a href="{{`tags` | absURL}}/{{.| urlize}}" target="_blank">{{.}}</a></li>
|
||||
@@ -60,7 +66,7 @@
|
||||
|
||||
{{ if .Params.socialShare | default true }}
|
||||
<aside class="social">
|
||||
<h5>Social</h5>
|
||||
<h5>{{ .Site.Params.terms.social | default "Social" }}</h5>
|
||||
<div class="social-content">
|
||||
<ul class="list-inline">
|
||||
<li class="list-inline-item text-center">
|
||||
@@ -74,7 +80,7 @@
|
||||
</a>
|
||||
</li>
|
||||
<li class="list-inline-item text-center">
|
||||
<a target="_blank" href="mailto:?subject={{ .Title }}&body=Check out this site {{ .Site.Params.hostName }}{{ .Permalink | absURL }}">
|
||||
<a target="_blank" href='mailto:?subject={{ .Title }}&body={{ .Site.Params.terms.emailText | default "Check out this site" }} {{ .Site.Params.hostName }}{{ .Permalink | absURL }}'>
|
||||
<i class="fa fa-envelope"></i>
|
||||
</a>
|
||||
</li>
|
||||
@@ -96,6 +102,13 @@
|
||||
</button>
|
||||
</section>
|
||||
|
||||
{{ if or (.Site.Params.singlePages.scrollprogress.enable | default true) (.Params.enableScrollProgress) }}
|
||||
<div class="progress">
|
||||
<div id="scroll-progress-bar" class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<Script src="{{.Site.Params.staticPath}}/js/scrollProgressBar.js"></script>
|
||||
{{ end }}
|
||||
|
||||
<script>
|
||||
var topScroll = document.getElementById("topScroll");
|
||||
window.onscroll = function() {scrollFunction()};
|
||||
@@ -114,4 +127,8 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
{{ if or (.Site.Params.singlePages.readTime.enable | default true) (.Params.enableReadingTime) }}
|
||||
<script src="{{.Site.Params.staticPath}}/js/readingTime.js"></script>
|
||||
{{end}}
|
||||
|
||||
{{ end }}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
document.body.classList.add('dark');
|
||||
} else if (localStorage.getItem("pref-theme") === "light") {
|
||||
document.body.classList.remove('dark')
|
||||
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
} else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.body.classList.add('dark');
|
||||
}
|
||||
|
||||
@@ -49,22 +49,8 @@
|
||||
</script>
|
||||
{{- end }}
|
||||
|
||||
<script>
|
||||
let loadingIcons;
|
||||
|
||||
function loading() {
|
||||
myVar = setTimeout(showPage, 100);
|
||||
}
|
||||
|
||||
function showPage() {
|
||||
try{
|
||||
document.getElementById("loading-icons").style.display = "block";
|
||||
} catch(err) {}
|
||||
}
|
||||
</script>
|
||||
|
||||
{{ if not (.Site.Params.navbar.disableSearch | default false) }}
|
||||
<script src="/js/search.js"></script>
|
||||
<script src="{{ .Site.Params.staticPath }}/js/search.js"></script>
|
||||
{{ end }}
|
||||
|
||||
|
||||
@@ -98,3 +84,7 @@
|
||||
</script>
|
||||
|
||||
{{ end }}
|
||||
|
||||
{{ if (.Site.Params.contact.formspree.enable | default false) }}
|
||||
<script src="{{ .Site.Params.staticPath }}/js/contact.js"></script>
|
||||
{{ end }}
|
||||
@@ -8,7 +8,21 @@
|
||||
<div class="text-center">
|
||||
{{ .Site.Params.contact.content | emojify | markdownify }}
|
||||
</div>
|
||||
{{ if .Site.Params.contact.email }}
|
||||
{{ if .Site.Params.contact.formspree.enable | default false }}
|
||||
<div class="row justify-content-center">
|
||||
<form id="contact-form" action="https://formspree.io/f/{{ .Site.Params.contact.formspree.formId }}" onsubmit="handleFormspreeSubmit(event)" method="POST" class="col-md-7">
|
||||
<div class="form-group pt-3">
|
||||
<input type="email" class="form-control" name="email" required="true" placeholder='{{ .Site.Params.contact.formspree.emailCaption | emojify | default "Enter your email" }}'>
|
||||
</div>
|
||||
<div class="form-group pt-3">
|
||||
<textarea class="form-control" name="message" required="true" placeholder='{{ .Site.Params.contact.formspree.messageCaption | emojify | default "Enter your message" }}' rows="3"></textarea>
|
||||
</div>
|
||||
<div class="form-group text-center pt-3">
|
||||
<button type="submit" class="btn">{{ .Site.Params.contact.btnName | default "Get in Touch" }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{ else if .Site.Params.contact.email }}
|
||||
<div class="text-center pt-3">
|
||||
<a href="mailto:{{ .Site.Params.contact.email }}" class="btn">
|
||||
{{ .Site.Params.contact.btnName | default "Get in Touch" }}
|
||||
@@ -19,5 +33,18 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="contact-form-status"></div>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||||
<symbol id="check-circle-fill" viewBox="0 0 16 16">
|
||||
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
|
||||
</symbol>
|
||||
<symbol id="info-fill" viewBox="0 0 16 16">
|
||||
<path d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm.93-9.412-1 4.705c-.07.34.029.533.304.533.194 0 .487-.07.686-.246l-.088.416c-.287.346-.92.598-1.465.598-.703 0-1.002-.422-.808-1.319l.738-3.468c.064-.293.006-.399-.287-.47l-.451-.081.082-.381 2.29-.287zM8 5.5a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/>
|
||||
</symbol>
|
||||
<symbol id="exclamation-triangle-fill" viewBox="0 0 16 16">
|
||||
<path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-sm-12 col-md-8 col-lg-8 py-5">
|
||||
<div class="experience-container px-3 pt-2">
|
||||
<ul class="nav nav-pills mb-3 bg-transparent" id="pills-tab" role="tablist">
|
||||
<ul class="nav nav-pills mb-3 bg-transparent primary-font" id="pills-tab" role="tablist">
|
||||
{{ range $index, $element := .Site.Params.experience.items }}
|
||||
{{ if (eq $index 0) }}
|
||||
<li class="nav-item px-1 bg-transparent" role="presentation">
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
height="40px" width="40px">
|
||||
</a>
|
||||
</div>
|
||||
© {{ now.Format "2006"}} {{ .Site.Params.copyright }} All Rights Reserved
|
||||
© {{ now.Format "2006"}} {{ .Site.Params.copyright }} {{ .Site.Params.terms.copyright | default "All Rights Reserved" }}
|
||||
<div class="text-secondary">
|
||||
Made with
|
||||
<span class="text-danger">
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-auto card-footer">
|
||||
<span class="float-start">{{ .Date.Format "January 2, 2006" }}</span>
|
||||
<a href="{{ .RelPermalink }}" class="float-end btn btn-outline-info btn-sm">Read</a>
|
||||
<span class="float-start">{{ .Date.Format (.Site.Params.datesFormat.articleRecent | default "January 2, 2006") }}</span>
|
||||
<a href="{{ .RelPermalink }}" class="float-end btn btn-outline-info btn-sm">{{ .Site.Params.terms.read | default "Read" }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,25 +1,22 @@
|
||||
{{- /* theme-toggle is enabled */}}
|
||||
{{- if (not .Site.Params.theme.disableThemeToggle | default false) }}
|
||||
{{- /* theme is auto */}}
|
||||
<script>
|
||||
if (localStorage.getItem("pref-theme") === "dark") {
|
||||
document.body.classList.add('dark');
|
||||
} else if (localStorage.getItem("pref-theme") === "light") {
|
||||
document.body.classList.remove('dark')
|
||||
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.body.classList.add('dark');
|
||||
}
|
||||
let localStorageValue = localStorage.getItem("pref-theme");
|
||||
let mediaQuery = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
|
||||
</script>
|
||||
{{- /* theme-toggle is disabled and theme is auto */}}
|
||||
{{- else if (and (ne .Site.Params.theme.defaultTheme "light") (ne .Site.Params.theme.defaultTheme "dark"))}}
|
||||
<script>
|
||||
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.body.classList.add('dark');
|
||||
switch (localStorageValue) {
|
||||
case "dark":
|
||||
document.body.classList.add('dark');
|
||||
break;
|
||||
case "light":
|
||||
document.body.classList.remove('dark');
|
||||
break;
|
||||
default:
|
||||
if (mediaQuery) {
|
||||
document.body.classList.add('dark');
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
</script>
|
||||
{{- end }}
|
||||
|
||||
|
||||
<!-- Navbar -->
|
||||
@@ -28,7 +25,7 @@
|
||||
<div class="container-fluid mx-xs-2 mx-sm-5 mx-md-5 mx-lg-5">
|
||||
<!-- navbar brand -->
|
||||
<a class="navbar-brand primary-font text-wrap" href="{{ .Site.BaseURL | relURL }}">
|
||||
{{ if or (.Site.Params.favicon) (.Site.Params.navbar.brandLogo) }}
|
||||
{{ if and (or (.Site.Params.favicon) (.Site.Params.navbar.brandLogo)) .Site.Params.navbar.showBrandLogo | default true }}
|
||||
<img src="{{ .Site.Params.navbar.brandLogo | default .Site.Params.favicon }}" width="30" height="30"
|
||||
class="d-inline-block align-top">
|
||||
{{ .Site.Params.navbar.brandName | default .Site.Params.title }}
|
||||
@@ -39,7 +36,7 @@
|
||||
|
||||
{{ if not (.Site.Params.navbar.disableSearch | default false) }}
|
||||
<div>
|
||||
<input id="search" autocomplete="off" class="form-control mr-sm-2 d-none d-md-block" placeholder="Search ..."
|
||||
<input id="search" autocomplete="off" class="form-control mr-sm-2 d-none d-md-block" placeholder='{{ .Site.Params.navbar.searchPlaceholder | default "Ctrl + k to Search..."}}'
|
||||
aria-label="Search" oninput="searchOnChange(event)">
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -58,7 +55,7 @@
|
||||
{{ if not (.Site.Params.navbar.disableSearch | default false) }}
|
||||
<li class="nav-item navbar-text d-block d-md-none">
|
||||
<div class="nav-link">
|
||||
<input id="search" autocomplete="off" class="form-control mr-sm-2" placeholder="Search ..." aria-label="Search" oninput="searchOnChange(event)">
|
||||
<input id="search" autocomplete="off" class="form-control mr-sm-2" placeholder='{{ .Site.Params.navbar.searchPlaceholder | default "Ctrl + k to Search..."}}' aria-label="Search" oninput="searchOnChange(event)">
|
||||
</div>
|
||||
</li>
|
||||
{{ end }}
|
||||
@@ -89,7 +86,7 @@
|
||||
</li>
|
||||
{{ end }}
|
||||
|
||||
{{ if and (.Site.Params.projects.enable | default false) (not (.Site.Params.navbar.menus.disableEducation | default false)) }}
|
||||
{{ if and (.Site.Params.projects.enable | default false) (not (.Site.Params.navbar.menus.disableProjects | default false)) }}
|
||||
<li class="nav-item navbar-text">
|
||||
<a class="nav-link" href="{{ .Site.BaseURL | relURL }}#projects"
|
||||
aria-label="projects">
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-sm-12 col-md-9 pt-5 image {{ if .Site.Params.animate }}animate{{ end }} px-5 px-md-5 px-lg-0 text-center">
|
||||
<img src="{{ .Site.Params.hero.image }}"
|
||||
class="img-thumbnail mx-auto"
|
||||
class="img-thumbnail mx-auto{{ if .Site.Params.hero.roundImage }} rounded-circle{{ end }}"
|
||||
alt=""
|
||||
>
|
||||
</div>
|
||||
@@ -43,6 +43,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ if .Site.Params.hero.bottomImage.enable | default true }}
|
||||
<div class="hero-bottom-svg d-md-block d-lg-block d-none">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="201" height="201" viewBox="0 0 201 201">
|
||||
<g id="Group_1168" data-name="Group 1168" transform="translate(-384 -1392)">
|
||||
@@ -305,5 +306,6 @@
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
{{ end }}
|
||||
@@ -1,4 +1,4 @@
|
||||
<span id="loading-icons" style="display: {{ if .Site.Params.animate }}none{{else}}block{{ end }};">
|
||||
<span>
|
||||
{{ range .Site.Params.hero.socialLinks.fontAwesomeIcons }}
|
||||
<span class="px-1">
|
||||
<a href="{{ .url }}" target="_blank" class="btn social-icon">
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -537,3 +537,40 @@ header .navbar.animate {
|
||||
#contact .btn:focus {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
#contact form .form-control {
|
||||
background-color: var(--secondary-color);
|
||||
color: var(--text-color);
|
||||
border-radius: .7rem;
|
||||
border: 1px solid var(--text-secondary-color);
|
||||
box-shadow: 0px 8px 56px rgb(15 80 100 / 5%);
|
||||
}
|
||||
|
||||
#contact-form-status {
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
z-index: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
#contact-form-status svg {
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
#contact-form-status button {
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
background-color: white;
|
||||
padding: 0.5rem;
|
||||
margin-left: 0.5rem;
|
||||
box-shadow: 0px 8px 56px rgb(15 80 100 / 5%);
|
||||
font-size: .6rem !important;
|
||||
}
|
||||
|
||||
#contact-form-status .alert {
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 0px 8px 56px rgb(15 80 100 / 5%);
|
||||
padding: .5rem 1rem;
|
||||
}
|
||||
@@ -25,6 +25,11 @@
|
||||
background-color: var(--secondary-color);
|
||||
}
|
||||
|
||||
#single .page-content img {
|
||||
max-width: 100%;
|
||||
border-radius: 1rem;
|
||||
}
|
||||
|
||||
#single .page-content a {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
@@ -282,3 +287,25 @@
|
||||
transition: .5s;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* Singlepage scroll progress start */
|
||||
.progress {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background-color: var(--background-color);
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
background-color: var(--primary-color);
|
||||
transition: width .2s;
|
||||
}
|
||||
|
||||
/* Singlepage scroll progress end */
|
||||
@@ -0,0 +1,45 @@
|
||||
async function handleFormspreeSubmit(event) {
|
||||
event.preventDefault();
|
||||
var form = document.getElementById("contact-form");
|
||||
var data = new FormData(event.target);
|
||||
fetch(event.target.action, {
|
||||
method: form.method,
|
||||
body: data,
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
contactAlert("success", "Thanks for your submission!");
|
||||
form.reset();
|
||||
} else {
|
||||
response.json().then((data) => {
|
||||
var errMessage = data.errors;
|
||||
for (var i = 0; i < errMessage.length; i++) {
|
||||
contactAlert("danger", errMessage[i].message);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
contactAlert("danger", "Oops! There was a problem submitting your form");
|
||||
});
|
||||
}
|
||||
|
||||
function contactAlert(type, message) {
|
||||
var contactFormStatus = document.getElementById("contact-form-status");
|
||||
var alert = `<div class="alert alert-${type} d-flex align-items-center" role="alert">
|
||||
<svg class="bi flex-shrink-0 me-2" role="img" aria-label="Success:">
|
||||
<use xlink:href="#check-circle-fill" />
|
||||
</svg>
|
||||
<div>${message}</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>`;
|
||||
contactFormStatus.innerHTML = alert;
|
||||
|
||||
// Remove alert after 3 seconds
|
||||
setTimeout(function () {
|
||||
contactFormStatus.innerHTML = "";
|
||||
}, 3000);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
function readingTime() {
|
||||
const text = document.querySelector("article").innerText;
|
||||
const wpm = 225;
|
||||
const words = text.trim().split(/\s+/).length;
|
||||
const time = Math.ceil(words / wpm);
|
||||
|
||||
const timeElement = document.querySelector("span#readingTime");
|
||||
timeElement.innerHTML = "<small> | </small>" + time + timeElement.innerHTML;
|
||||
}
|
||||
readingTime();
|
||||
@@ -0,0 +1,12 @@
|
||||
function getScrollPercent() {
|
||||
const totalHeight = document.body.scrollHeight - window.innerHeight;
|
||||
const scrolled = window.scrollY;
|
||||
return (scrolled / totalHeight) * 100;
|
||||
}
|
||||
const scrollProgressBar = document.getElementById("scroll-progress-bar");
|
||||
|
||||
document.onscroll = function () {
|
||||
var scrollPercent = Math.round(getScrollPercent());
|
||||
scrollProgressBar.style.width = scrollPercent + "%";
|
||||
scrollProgressBar.ariaValueNow = scrollPercent;
|
||||
};
|
||||
+79
-14
@@ -1,23 +1,15 @@
|
||||
async function searchOnChange(evt) {
|
||||
let searchQuery = evt.target.value;
|
||||
var inputEle = document.querySelectorAll("input#search");
|
||||
inputEle.forEach((element) => {
|
||||
element.value = searchQuery;
|
||||
});
|
||||
|
||||
if (searchQuery !== "") {
|
||||
const searchButtonEle = document.querySelectorAll("#search");
|
||||
let searchButtonPosition;
|
||||
if (window.innerWidth > 768) {
|
||||
searchButtonPosition = searchButtonEle[0].getBoundingClientRect();
|
||||
document.getElementById("search-content").style.width = "500px";
|
||||
} else {
|
||||
searchButtonPosition = searchButtonEle[1].getBoundingClientRect();
|
||||
document.getElementById("search-content").style.width = "300px";
|
||||
if (!window.searchJson) {
|
||||
window.searchJson = await fetch("/index.json").then((res) => res.json());
|
||||
}
|
||||
|
||||
document.getElementById("search-content").style.top =
|
||||
searchButtonPosition.top + 50 + "px";
|
||||
document.getElementById("search-content").style.left =
|
||||
searchButtonPosition.left + "px";
|
||||
|
||||
let searchJson = await fetch("/index.json").then((res) => res.json());
|
||||
let searchResults = searchJson.filter((item) => {
|
||||
let res = false;
|
||||
if (item.title && item.description && item.content) {
|
||||
@@ -65,9 +57,82 @@ async function searchOnChange(evt) {
|
||||
let searchResultsHtml = `<p class="text-center py-3">No results found for "${searchQuery}"</p>`;
|
||||
document.getElementById("search-results").innerHTML = searchResultsHtml;
|
||||
}
|
||||
alignSearchContent();
|
||||
document.getElementById("search-content").style.display = "block";
|
||||
} else {
|
||||
document.getElementById("search-content").style.display = "none";
|
||||
document.getElementById("search-results").innerHTML = "";
|
||||
}
|
||||
}
|
||||
|
||||
function alignSearchContent() {
|
||||
const searchButtonEle = document.querySelectorAll("#search");
|
||||
// check if search value is not empty
|
||||
for (let i = 0; i < searchButtonEle.length; i++) {
|
||||
if (searchButtonEle[i].value !== "") {
|
||||
let searchButtonPosition;
|
||||
if (window.innerWidth > 768) {
|
||||
searchButtonPosition = searchButtonEle[0].getBoundingClientRect();
|
||||
document.getElementById("search-content").style.width = "500px";
|
||||
} else {
|
||||
var navbarCollapse = document.querySelector("#navbarContent");
|
||||
navbarCollapse.classList.add("show");
|
||||
searchButtonPosition = searchButtonEle[1].getBoundingClientRect();
|
||||
document.getElementById("search-content").style.width = "300px";
|
||||
}
|
||||
|
||||
document.getElementById("search-content").style.top =
|
||||
searchButtonPosition.top + 50 + "px";
|
||||
document.getElementById("search-content").style.left =
|
||||
searchButtonPosition.left + "px";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resetSearch(e) {
|
||||
if (
|
||||
e.keyCode === 27 ||
|
||||
(e.target.id !== "search" &&
|
||||
e.target.closest("section#search-content") === null)
|
||||
) {
|
||||
if (document.getElementById("search-results").innerHTML !== "") {
|
||||
document.getElementById("search-content").style.display = "none";
|
||||
document.getElementById("search-results").innerHTML = "";
|
||||
var inputEle = document.querySelectorAll("input#search");
|
||||
inputEle.forEach((element) => {
|
||||
element.value = "";
|
||||
element.blur();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.onkeyup = function () {
|
||||
switch (event.keyCode) {
|
||||
// ESC
|
||||
case 27:
|
||||
resetSearch(event);
|
||||
break;
|
||||
|
||||
// ctrl + k
|
||||
case 75:
|
||||
if (event.ctrlKey) {
|
||||
document.getElementById("search").focus();
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", function (e) {
|
||||
if (e.keyCode === 75 && e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
// Close search on click outside and on resize
|
||||
document.addEventListener("click", function (e) {
|
||||
resetSearch(e);
|
||||
});
|
||||
window.addEventListener("resize", function (e) {
|
||||
alignSearchContent();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user