Started massive refactoring, Removed halfmoon, Added new personnal common CSS, Site now runs at >5 fps on low-end
Update .gitignore, .htaccess, and 264 more files...
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 87 B |
|
Before Width: | Height: | Size: 427 B |
|
Before Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 166 B |
|
Before Width: | Height: | Size: 166 B |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 221 B |
|
Before Width: | Height: | Size: 221 B |
|
Before Width: | Height: | Size: 220 B |
|
Before Width: | Height: | Size: 220 B |
|
Before Width: | Height: | Size: 272 B |
|
Before Width: | Height: | Size: 272 B |
|
Before Width: | Height: | Size: 275 B |
|
Before Width: | Height: | Size: 275 B |
|
Before Width: | Height: | Size: 213 B |
|
Before Width: | Height: | Size: 220 B |
|
Before Width: | Height: | Size: 288 B |
|
Before Width: | Height: | Size: 420 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 283 KiB |
|
Before Width: | Height: | Size: 223 B |
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -1,49 +0,0 @@
|
||||
// Highlights the code blocks when included on a page.
|
||||
// This command is separated in its own file since highlight.js isn't on every page and because I can't use JS
|
||||
// in a script element without using an external .js file.
|
||||
|
||||
Array.from(document.getElementsByClassName("code")).forEach(eCodeContainer => {
|
||||
let language = null;
|
||||
|
||||
eCodeContainer.classList.forEach(cCodeContainer => {
|
||||
if(cCodeContainer.startsWith("language-")) {
|
||||
language = cCodeContainer;
|
||||
}
|
||||
});
|
||||
|
||||
if(language !== null) {
|
||||
Array.from(eCodeContainer.children).forEach(eCodeLine => {
|
||||
if(eCodeLine.classList.contains("code-line")) {
|
||||
eCodeLine.classList.add(language);
|
||||
hljs.highlightElement(eCodeLine);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Adding the action to copy the code to elements with the "js-code-copy" class.
|
||||
// The search works by searching the closest parent with the "code" class or that is a "code" element, and then
|
||||
// reading each of its children with the "code-line" class.
|
||||
|
||||
Array.from(document.getElementsByClassName("js-code-copy")).forEach(eCodeCopyButton => {
|
||||
let eParentCodeBlock = eCodeCopyButton;
|
||||
|
||||
while(eParentCodeBlock != null &&!eParentCodeBlock.classList.contains("code") &&
|
||||
eParentCodeBlock.nodeName.toLowerCase() !== "code") {
|
||||
eParentCodeBlock = eParentCodeBlock.parentElement;
|
||||
}
|
||||
|
||||
if(eParentCodeBlock != null) {
|
||||
let code = "";
|
||||
|
||||
Array.from(eParentCodeBlock.children).forEach(eCodeLine => {
|
||||
if(eCodeLine.classList.contains("code-line")) {
|
||||
code += eCodeLine.textContent + "\n"
|
||||
}
|
||||
});
|
||||
|
||||
eCodeCopyButton.onclick = function() {
|
||||
navigator.clipboard.writeText(code);
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -1,104 +0,0 @@
|
||||
// Toggle button for the side menu. (Global)
|
||||
document.getElementById('button-sidebar').addEventListener("click", () => {
|
||||
halfmoon.toggleSidebar();
|
||||
// TODO: Fix the slide size in gliders
|
||||
});
|
||||
|
||||
// Adding the last URL to every "a" element with the 'js-set-previous-url' class.
|
||||
document.querySelectorAll("a.js-set-previous-url").forEach(element => {
|
||||
element.href = document.referrer;
|
||||
//element.addEventListener('click', function(e) {
|
||||
// window.history.go(-2);
|
||||
//});
|
||||
});
|
||||
|
||||
// TOX ID copiers. (Contact page)
|
||||
if(document.getElementById('button-copy-tox-id-main') != null) {
|
||||
document.getElementById('button-copy-tox-id-main').addEventListener("click", () => {
|
||||
navigator.clipboard.writeText("62C1A91A425F90D7B4F047D70CCF31E7402C9EC37B93604B0F37C416442D15044AF6C1AE033B");
|
||||
});
|
||||
}
|
||||
|
||||
if(document.getElementById('button-copy-tox-id-backup') != null) {
|
||||
document.getElementById('button-copy-tox-id-backup').addEventListener("click", () => {
|
||||
navigator.clipboard.writeText("01ABBD4515C8FA56231333D1022CEEE0A605F4E85F8A945365F56D196A1BBA10FB4DCE08DBE8");
|
||||
});
|
||||
}
|
||||
|
||||
// Creating the galleries from Glider.js
|
||||
window.addEventListener('load', function(){
|
||||
document.querySelectorAll(".glider").forEach(element => {
|
||||
new Glider(element, {
|
||||
slidesToShow: 1,
|
||||
draggable: true,
|
||||
scrollLock: true,
|
||||
scrollLockDelay: 125,
|
||||
rewind: true,
|
||||
arrows: {
|
||||
prev: element.previousSibling,
|
||||
next: element.nextSibling
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 768,
|
||||
settings: {
|
||||
slidesToShow: 2,
|
||||
duration: 0.25
|
||||
}
|
||||
},{
|
||||
breakpoint: 992,
|
||||
settings: {
|
||||
slidesToShow: 3,
|
||||
slidesToScroll: 1
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// Processing the images
|
||||
const eImages = [];
|
||||
|
||||
// Converting the Node to a HTMLElement if needed and desired.
|
||||
element.childNodes[0].childNodes.forEach(childrenNode => {
|
||||
if(childrenNode.nodeType !== Node.ELEMENT_NODE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Casting from a Node to a proper HTMLElement because of course we have to add this step in JS...
|
||||
const eChildElement = childrenNode.cloneNode(true);
|
||||
|
||||
if(eChildElement.tagName.toLowerCase() !== "img") {
|
||||
return;
|
||||
}
|
||||
|
||||
eChildElement.onclick = function() {
|
||||
let imageElement = document.getElementById("modal-img");
|
||||
imageElement.src = eChildElement.src;
|
||||
imageElement.alt = eChildElement.alt;
|
||||
halfmoon.toggleModal('modal-content-image-viewer');
|
||||
console.log("Opening image...");
|
||||
};
|
||||
|
||||
// Saving the element for later.
|
||||
eImages.push(eChildElement);
|
||||
});
|
||||
|
||||
// Removing the nodes so that the desired ones can be reinserted later.
|
||||
// We start from the rear to prevent issues with de-ordering as we delete them !
|
||||
for(let i = element.childNodes[0].childNodes.length - 1; i >= 0; i--) {
|
||||
element.childNodes[0].removeChild(element.childNodes[0].childNodes[i]);
|
||||
}
|
||||
|
||||
eImages.forEach(eImageElement => {
|
||||
element.childNodes[0].appendChild(eImageElement);
|
||||
});
|
||||
});
|
||||
|
||||
// The default modal animation looks like ass, jesus...
|
||||
let eImgModalCloseButton = document.getElementById("modal-img-close");
|
||||
if(eImgModalCloseButton != null) {
|
||||
eImgModalCloseButton.onclick = function() {
|
||||
halfmoon.toggleModal('modal-content-image-viewer');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,21 +0,0 @@
|
||||
/* Halfmoon > Background */
|
||||
|
||||
div#body-overlay {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url("/resources/Azias/imgs/3px-tile.png");
|
||||
opacity: 0.3;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.dark-mode .card.card-bkgd {
|
||||
background: var(--dm-card-bg-color) url("/resources/Azias/imgs/3px-tile-0.2.png") repeat fixed center center;
|
||||
}
|
||||
|
||||
.bg-very-dark.title-bkgd {
|
||||
background: repeat center center fixed;
|
||||
background-color: var(--dark-color-dark) !important;
|
||||
background-image: url("/resources/Azias/imgs/3px-tile-0.1.png");
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
/* Halfmoon > Elements > Code */
|
||||
|
||||
code.w-full {
|
||||
white-space: pre;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
/* Halfmoon > Elements > Containers */
|
||||
|
||||
.w-lg-p90 {
|
||||
width: 95% !important;
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.w-95 {
|
||||
width: 95% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 993px) {
|
||||
.w-lg-p90 {
|
||||
width: 90% !important;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
/* Halfmoon > Elements > Glider */
|
||||
|
||||
.glider {
|
||||
border: var(--card-border-width) solid var(--dm-card-border-color);
|
||||
box-shadow: inset 1px 0 25px 5px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.glider-nav {
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
div.glider-slide > * {
|
||||
border: var(--card-border-width) solid var(--dm-card-border-color);
|
||||
box-shadow: inset 1px 0 25px 5px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/* Halfmoon > Elements > HR */
|
||||
|
||||
hr, hr.dark-mde, hr.subtle {
|
||||
background-color: rgba(0, 0, 0, 0) !important;
|
||||
background: rgb(93,95,97);
|
||||
background: radial-gradient(circle, rgba(83,85,87,0.8) 0%, rgba(65,67,69,0.65) 75%, rgba(17,20,23,0) 100%);
|
||||
opacity: 0.1;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
/* Halfmoon > Elements > Images */
|
||||
|
||||
img.fill-height {
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: 0 0;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
/*@keyframes modalFadeIn {
|
||||
0% { opacity: 0; }
|
||||
50% { opacity: 0.25; }
|
||||
75% { opacity: 0.5; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
.modal {
|
||||
transition: none;
|
||||
animation: modalFadeIn 3s;
|
||||
}*/
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
/* Halfmoon > Elements > Videos */
|
||||
|
||||
video {
|
||||
// https://css-tricks.com/fluid-width-video/
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/* Halfmoon > Fixes */
|
||||
|
||||
.py-01 {
|
||||
// Helps in some specific area where a padding of 0 causes alignment issues.
|
||||
// This is mostly used in cards and collapse elements.
|
||||
padding-top: 0.01rem!important;
|
||||
padding-bottom: 0.01rem!important;
|
||||
}
|
||||
|
||||
// Adding a margin to buttons present right after another one.
|
||||
button + button, .button-link + .button-link > button {
|
||||
margin-left: 1.5rem !important;
|
||||
}
|
||||
|
||||
// No idea where this is used.
|
||||
div.last-inner-collapse-border-fix {
|
||||
// TODO: Fix it when it is closed.
|
||||
border: var(--collapse-content-border-width) solid var(--dm-collapse-content-border-color) !important;
|
||||
border-top: 0 !important;
|
||||
border-bottom-left-radius: var(--collapse-content-border-radius) !important;
|
||||
border-bottom-right-radius: var(--collapse-content-border-radius) !important;
|
||||
}
|
||||
|
||||
// Fix for ".content-wrapper" on mobile which can be too large due to the main title.
|
||||
.content-wrapper {
|
||||
max-width: 100vw;
|
||||
}
|
||||
|
||||
// Removes the wasted space on Chrome !
|
||||
.overflow-x-scroll {
|
||||
overflow-x: auto !important;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/* Halfmoon > Fonts & Text */
|
||||
// Mostly consist of stuff that's missing in Halfmoon.
|
||||
|
||||
.font-size-8 {
|
||||
font-size: 0.8rem!important;
|
||||
}
|
||||
|
||||
.font-size-10 {
|
||||
font-size: 1.0rem!important;
|
||||
}
|
||||
|
||||
.font-size-26 {
|
||||
font-size: 2.6rem!important;
|
||||
}
|
||||
|
||||
.font-size-28 {
|
||||
font-size: 2.8rem!important;
|
||||
}
|
||||
|
||||
.font-size-30 {
|
||||
font-size: 3.0rem!important;
|
||||
}
|
||||
|
||||
.font-size-35 {
|
||||
font-size: 3.5rem!important;
|
||||
}
|
||||
|
||||
.font-size-40 {
|
||||
font-size: 4.0rem!important;
|
||||
}
|
||||
|
||||
.text-super-muted {
|
||||
color: #89898A;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
/* Halfmoon > Page > Contact */
|
||||
|
||||
// No longer used since the QR codes have been removed !
|
||||
//#contact-tox-qrcode > img {
|
||||
// height: calc( 256px * 0.75);
|
||||
// -webkit-filter: invert(100%);
|
||||
// filter: invert(100%);
|
||||
// image-rendering: pixelated;
|
||||
//}
|
||||
@@ -1,63 +0,0 @@
|
||||
/* Halfmoon > Page > Content */
|
||||
|
||||
@media (max-width: 992px) {
|
||||
:root {
|
||||
--content-search-image-size: 96px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 993px) {
|
||||
:root {
|
||||
--content-search-image-size: 128px;
|
||||
}
|
||||
}
|
||||
|
||||
div.content-presentation-container {
|
||||
margin-bottom: 10px;
|
||||
min-height: var(--content-search-image-size);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
div.content-presentation-container > a {
|
||||
width: 100%;
|
||||
min-height: var(--content-search-image-size);
|
||||
text-align: justify;
|
||||
color: var(--dm-card-text-color);
|
||||
}
|
||||
|
||||
div.content-presentation-container > a:hover {
|
||||
color: var(--dm-card-text-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
div.content-search-image-container {
|
||||
background: var(--dm-card-bg-color) url("/resources/Azias/imgs/3px-tile-0.2.png") repeat fixed center center;
|
||||
box-shadow: inset 0 0 25px 1px rgba(255,255,255,0.05);
|
||||
border-radius: 8px;
|
||||
width: var(--content-search-image-size);
|
||||
height: var(--content-search-image-size);
|
||||
margin-right: 10px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
img.content-search-image {
|
||||
max-width: var(--content-search-image-size);
|
||||
max-height: var(--content-search-image-size);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 5px 1px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
h3.content-search-title {
|
||||
float: none;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.content-tag-container a:not(:first-child) {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
div.content-tag-container a, div.content-tag-container i {
|
||||
/* Doesn't fix the line return issue ! */
|
||||
display: inline-block;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/* Halfmoon > Page > Home */
|
||||
|
||||
// Gradient used on home page's applications card
|
||||
@media (min-width: 993px) {
|
||||
.l-lab-web {
|
||||
background: linear-gradient(90deg, rgba(101,144,134,0.3) 0%, rgba(101,144,134,0.2) 1.5px, rgba(101,144,134,0.0) 7px);
|
||||
border-radius: 5px 0 0 5px;
|
||||
}
|
||||
.l-lab-office {
|
||||
background: linear-gradient(90deg, rgba(64,84,59,0.5) 0%, rgba(64,84,59,0.3) 2px, rgba(64,84,59,0.0) 7px);
|
||||
border-radius: 5px 0 0 5px;
|
||||
}
|
||||
.l-lab-app {
|
||||
background: linear-gradient(90deg, rgba(156,23,34,0.4) 0%, rgba(156,23,34,0.3) 1.5px, rgba(156,23,34,0.0) 7px);
|
||||
border-radius: 5px 0 0 5px;
|
||||
}
|
||||
.l-lab-game {
|
||||
background: linear-gradient(90deg, rgba(180,134,77,0.4) 0%, rgba(180,134,77,0.3) 1.5px, rgba(180,134,77,0.0) 7px);
|
||||
border-radius: 5px 0 0 5px;
|
||||
}
|
||||
.l-lab-dotnet {
|
||||
background: linear-gradient(90deg, rgba(81,43,212,0.4) 0%, rgba(81,43,212,0.3) 1.5px, rgba(81,43,212,0.0) 7px);
|
||||
border-radius: 5px 0 0 5px;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/* Halfmoon > Section > Footer */
|
||||
|
||||
#copyright-text {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
#privacy-footer-link {
|
||||
opacity: 0.3;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#privacy-footer-link:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
#logo-footer {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
/* Halfmoon > Section > Sidebar */
|
||||
|
||||
#logo-sidebar {
|
||||
filter: grayscale(100%);
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/* Halfmoon > Section > Title bar */
|
||||
|
||||
#page-title-bar {
|
||||
min-height: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
#header-lang-menu {
|
||||
margin-right: calc(var(--content-and-card-spacing) * ( 2 / 3 ) );
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
.code-line {
|
||||
background: transparent !important;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/* Standalone */
|
||||
@import 'standalone/fonts';
|
||||
@import 'standalone/utils';
|
||||
|
||||
/* Halfmoon */
|
||||
@import 'halfmoon/fixes';
|
||||
@import 'halfmoon/fonts';
|
||||
@import 'halfmoon/background';
|
||||
|
||||
/* Halfmoon > Sections */
|
||||
@import 'halfmoon/section/footer';
|
||||
@import 'halfmoon/section/sidebar';
|
||||
@import 'halfmoon/section/titlebar';
|
||||
|
||||
/* Halfmoon > Pages */
|
||||
@import 'halfmoon/page/home';
|
||||
@import 'halfmoon/page/content';
|
||||
@import 'halfmoon/page/contact';
|
||||
|
||||
/* Halfmoon > Elements */
|
||||
@import 'halfmoon/element/card';
|
||||
@import 'halfmoon/element/code';
|
||||
@import 'halfmoon/element/containers';
|
||||
@import 'halfmoon/element/glider';
|
||||
@import 'halfmoon/element/hr';
|
||||
@import 'halfmoon/element/image';
|
||||
@import 'halfmoon/element/modal';
|
||||
@import 'halfmoon/element/video';
|
||||
|
||||
/* Highlight.JS */
|
||||
@import 'highlightjs/fixes';
|
||||
@@ -1,24 +0,0 @@
|
||||
/* Standalone > Fonts & Text */
|
||||
|
||||
@font-face {
|
||||
font-family: 'Quantum';
|
||||
src: url("/resources/Quantum/Quantum.otf") format('opentype');
|
||||
}
|
||||
|
||||
.quantum {
|
||||
// Only really used for the logo title in the sidebar.
|
||||
font-family: 'Quantum', sans-serif;
|
||||
}
|
||||
|
||||
.ucase {
|
||||
// Same as above.
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.r-45 {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.r-135 {
|
||||
transform: rotate(135deg);
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/* Standalone > Utils */
|
||||
|
||||
img.no-save {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.no-select {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.hide-scrollbar {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.square-corners {
|
||||
border-radius: 0!important;
|
||||
}
|
||||
|
||||
.stretch-align-items {
|
||||
align-items: stretch;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
# Contributing to Halfmoon
|
||||
|
||||
Please read this short document if you want to contribute to Halfmoon.
|
||||
|
||||
## Our goal
|
||||
|
||||
Before getting to the issues and pull requests, it is important to understand what the framework is trying to do.
|
||||
|
||||
Halfmoon's stated goal is really simple - create a customizable frontend framework, with a built-in dark mode, that is great for building dashboards and tools. However, our other goals are more implicit:
|
||||
|
||||
- Everything has to be **super functional and snappy**. Ideally, that means no performance issues and just consistently good execution.
|
||||
- Everything has to **look good** as well, and have a **single, consistent style**.
|
||||
|
||||
The most important thing here is building a **really good (looking) framework that also works very well**, and that should always be the top priority.
|
||||
|
||||
## Issues
|
||||
|
||||
Please keep the following things in mind when raising issues:
|
||||
|
||||
- Feature requests are welcome. However, please make sure that the feature you are requesting falls under the scope of the project.
|
||||
- **Do not** post personal support questions as issues. For those, use this [tag on Stack Overflow](https://stackoverflow.com/questions/tagged/halfmoon).
|
||||
- When raising an issue, please be as thorough as possible. For possible bugs, reproducible code is always a great sign.
|
||||
|
||||
## Pull requests
|
||||
|
||||
**Please ask first** before you put in work for a pull request. Things are constantly being worked on, and it is very difficult to share everything publicly in a meaningful way. So asking lets us avoid working on the same thing, or worse, someone putting in a lot of work for a PR that does not fit into the scope of the project. Please do not take this the wrong way; at this stage, the project needs strong leadership to become something special.
|
||||
|
||||
The best way to ask is through email: [hey.halfmoon@gmail.com](mailto:hey.halfmoon@gmail.com). I am always open to proper discussions about the framework, especially when it comes to contributions and pull requests.
|
||||
|
||||
## License
|
||||
|
||||
Any contribution you make will fall under the license being used by the framework: [MIT license](https://www.gethalfmoon.com/license/).
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Halfmoon UI
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,95 +0,0 @@
|
||||
# [Halfmoon](https://www.gethalfmoon.com)
|
||||
|
||||
> Front-end framework with a built-in dark mode and full customizability using CSS variables; great for building dashboards and tools.
|
||||
|
||||
- **Built-in dark mode**—Halfmoon comes with a built-in, toggleable dark mode, which is one of its most important and defining features.
|
||||
- **Fully customizable using CSS variables**—The framework is built entirely using CSS variables (also known as CSS custom properties). There are close to *1,500 CSS variables*, which means that almost everything can be customized by overriding a property, making it very easy to theme Halfmoon to fit your brand. [Learn more about customization](https://www.gethalfmoon.com/docs/customize/).
|
||||
- **Great for building dashboards and tools**—The components have a very standard look and feel to them, making them suitable for dashboards and tools. Moreover, a lot of importance is placed on components such as forms, navbars, sidebars, dropdowns, toasts, shortcuts, etc. and there are also *tons of utilities* available.
|
||||
- **Optional JS library**—Many of the components found in Halfmoon are built to work without JavaScript. However, the framework still comes with a powerful JavaScript library with no extra dependencies, such as jQuery.
|
||||
- **Bootstrap like classes**—The class names should be instantly familiar to anyone who has used Bootstrap.
|
||||
- **Cross-browser compatibility**—Fully supports almost all the browsers under the sun, including really old ones like Internet Explorer 11.
|
||||
|
||||
To learn more, go to [the documentation](https://www.gethalfmoon.com/docs/introduction/).
|
||||
|
||||
## Quickstart
|
||||
|
||||
The quickest way to get started with Halfmoon is by using the CDN to include the following files:
|
||||
|
||||
```html
|
||||
<!-- Halfmoon CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/halfmoon@1.1.1/css/halfmoon-variables.min.css" rel="stylesheet" />
|
||||
<!--
|
||||
Or,
|
||||
Use the following (no variables, supports IE11):
|
||||
<link href="https://cdn.jsdelivr.net/npm/halfmoon@1.1.1/css/halfmoon.min.css" rel="stylesheet" />
|
||||
-->
|
||||
|
||||
<!-- Halfmoon JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/halfmoon@1.1.1/js/halfmoon.min.js"></script>
|
||||
```
|
||||
|
||||
**Pleast note**, the JS file should be placed at the end of the `<body>` tag. Otherwise, some things may not work as expected. For example, using the `onclick="..."` event to call one of Halfmoon's built-in methods will not work **unless** the JS file is placed at the end of the `<body>` tag.
|
||||
|
||||
## Using npm
|
||||
|
||||
```
|
||||
npm install halfmoon
|
||||
```
|
||||
|
||||
After installation, the required CSS and JS file can be imported in the following way:
|
||||
|
||||
```javascript
|
||||
// Include CSS file
|
||||
require("halfmoon/css/halfmoon-variables.min.css");
|
||||
/*
|
||||
Or,
|
||||
Include the following (no variables, supports IE11):
|
||||
require("halfmoon/css/halfmoon.min.css");
|
||||
*/
|
||||
|
||||
// Import JS library
|
||||
const halfmoon = require("halfmoon");
|
||||
```
|
||||
|
||||
Please note that manual initialization is required for some components, that is, after the DOM is loaded, the following method needs to be called:
|
||||
|
||||
```javascript
|
||||
// Call this method after the DOM has been loaded
|
||||
halfmoon.onDOMContentLoaded();
|
||||
```
|
||||
|
||||
This initializes all of the components that require JavaScript, such as dropdowns, custom file inputs, shortcuts, etc.
|
||||
|
||||
In this way, Halfmoon can be used with frameworks that use the virtual DOM, such as React and Vue. For instance, in the case of Vue, the `halfmoon.onDOMContentLoaded()` method would be called inside the `mounted()` hook of your component.
|
||||
|
||||
## Using React
|
||||
|
||||
If you are using React to call the built-in methods, such as `halfmoon.toggleSidebar()`, please make sure the call is made in a way that binds the correct context. There are two ways to do this:
|
||||
|
||||
1. Using an anonymous method:
|
||||
|
||||
```html
|
||||
<button className="btn" type="button" onClick={() => halfmoon.toggleSidebar()}>
|
||||
```
|
||||
|
||||
2. Using `bind`:
|
||||
|
||||
```html
|
||||
<button className="btn" type="button" onClick={halfmoon.toggleSidebar.bind(halfmoon)}>
|
||||
```
|
||||
|
||||
You can find more details in the [React documentation](https://reactjs.org/docs/faq-functions.html#why-is-binding-necessary-at-all).
|
||||
|
||||
## Starter template generator
|
||||
|
||||
You can use the [starter template generator](https://www.gethalfmoon.com/docs/page-building/#starter-template-generator) to generate boilerplates for your project. The generator takes your settings and adds the appropriate classes and defines the required containers and elements.
|
||||
|
||||
Once again, we recommend reading [the documentation](https://www.gethalfmoon.com/docs/introduction/), as it contains a lot of examples to help you quickly build websites.
|
||||
|
||||
## License
|
||||
|
||||
Halfmoon is licensed under the [MIT](https://www.gethalfmoon.com/license/) license.
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright 2020, Halfmoon UI
|
||||
11
resources/HalfMoon/1.1.1/css/halfmoon.min.css
vendored
@@ -1,3 +0,0 @@
|
||||
var halfmoon = require("./js/halfmoon-module");
|
||||
|
||||
module.exports = halfmoon;
|
||||
@@ -1,513 +0,0 @@
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* Halfmoon JS (module)
|
||||
* Version: 1.1.1
|
||||
* https://www.gethalfmoon.com
|
||||
* Copyright, Halfmoon UI
|
||||
* Licensed under MIT (https://www.gethalfmoon.com/license)
|
||||
* -----------------------------------------------------------------------------
|
||||
* The above notice must be included in its entirety when this file is used.
|
||||
*/
|
||||
|
||||
/* Start polyfills */
|
||||
|
||||
// Polyfill for Element.matches()
|
||||
if (!Element.prototype.matches) {
|
||||
Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
|
||||
}
|
||||
|
||||
// Polyfill for Element.closest()
|
||||
if (!Element.prototype.closest) {
|
||||
Element.prototype.closest = function(s) {
|
||||
var el = this;
|
||||
do {
|
||||
if (el.matches(s)) return el;
|
||||
el = el.parentElement || el.parentNode;
|
||||
} while (el !== null && el.nodeType === 1);
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
// Polyfill for Element.classList (http://purl.eligrey.com/github/classList.js/blob/master/classList.js)
|
||||
"document"in self&&("classList"in document.createElement("_")&&(!document.createElementNS||"classList"in document.createElementNS("http://www.w3.org/2000/svg","g"))||!function(t){"use strict";if("Element"in t){var e="classList",n="prototype",i=t.Element[n],s=Object,r=String[n].trim||function(){return this.replace(/^\s+|\s+$/g,"")},o=Array[n].indexOf||function(t){for(var e=0,n=this.length;n>e;e++)if(e in this&&this[e]===t)return e;return-1},c=function(t,e){this.name=t,this.code=DOMException[t],this.message=e},a=function(t,e){if(""===e)throw new c("SYNTAX_ERR","The token must not be empty.");if(/\s/.test(e))throw new c("INVALID_CHARACTER_ERR","The token must not contain space characters.");return o.call(t,e)},l=function(t){for(var e=r.call(t.getAttribute("class")||""),n=e?e.split(/\s+/):[],i=0,s=n.length;s>i;i++)this.push(n[i]);this._updateClassName=function(){t.setAttribute("class",this.toString())}},u=l[n]=[],h=function(){return new l(this)};if(c[n]=Error[n],u.item=function(t){return this[t]||null},u.contains=function(t){return~a(this,t+"")},u.add=function(){var t,e=arguments,n=0,i=e.length,s=!1;do t=e[n]+"",~a(this,t)||(this.push(t),s=!0);while(++n<i);s&&this._updateClassName()},u.remove=function(){var t,e,n=arguments,i=0,s=n.length,r=!1;do for(t=n[i]+"",e=a(this,t);~e;)this.splice(e,1),r=!0,e=a(this,t);while(++i<s);r&&this._updateClassName()},u.toggle=function(t,e){var n=this.contains(t),i=n?e!==!0&&"remove":e!==!1&&"add";return i&&this[i](t),e===!0||e===!1?e:!n},u.replace=function(t,e){var n=a(t+"");~n&&(this.splice(n,1,e),this._updateClassName())},u.toString=function(){return this.join(" ")},s.defineProperty){var f={get:h,enumerable:!0,configurable:!0};try{s.defineProperty(i,e,f)}catch(p){void 0!==p.number&&-2146823252!==p.number||(f.enumerable=!1,s.defineProperty(i,e,f))}}else s[n].__defineGetter__&&i.__defineGetter__(e,h)}}(self),function(){"use strict";var t=document.createElement("_");if(t.classList.add("c1","c2"),!t.classList.contains("c2")){var e=function(t){var e=DOMTokenList.prototype[t];DOMTokenList.prototype[t]=function(t){var n,i=arguments.length;for(n=0;i>n;n++)t=arguments[n],e.call(this,t)}};e("add"),e("remove")}if(t.classList.toggle("c3",!1),t.classList.contains("c3")){var n=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(t,e){return 1 in arguments&&!this.contains(t)==!e?e:n.call(this,t)}}"replace"in document.createElement("_").classList||(DOMTokenList.prototype.replace=function(t,e){var n=this.toString().split(" "),i=n.indexOf(t+"");~i&&(n=n.slice(i),this.remove.apply(this,n),this.add(e),this.add.apply(this,n.slice(1)))}),t=null}());
|
||||
|
||||
/* End polyfills */
|
||||
|
||||
|
||||
/* Halfmoon JS core */
|
||||
|
||||
var halfmoon = {
|
||||
// Getting the required elements
|
||||
// Re-initialized once the DOM is loaded (to avoid issues with virtual DOM)
|
||||
pageWrapper: document.getElementsByClassName("page-wrapper")[0],
|
||||
stickyAlerts: document.getElementsByClassName("sticky-alerts")[0],
|
||||
|
||||
darkModeOn: false, // Also re-initialized once the DOM is loaded (see below)
|
||||
|
||||
// Create cookie
|
||||
createCookie: function(name, value, days) {
|
||||
var expires;
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
expires = "; expires=" + date.toGMTString();
|
||||
}
|
||||
else {
|
||||
expires = "";
|
||||
}
|
||||
document.cookie = name + "=" + value + expires + "; path=/";
|
||||
},
|
||||
|
||||
// Read cookie
|
||||
readCookie: function(name) {
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(";");
|
||||
for(var i=0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) === " ") {
|
||||
c = c.substring(1, c.length);
|
||||
}
|
||||
if (c.indexOf(nameEQ) === 0) {
|
||||
return c.substring(nameEQ.length,c.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
// Erase cookie
|
||||
eraseCookie: function(name) {
|
||||
this.createCookie(name, "", -1);
|
||||
},
|
||||
|
||||
// Toggle light/dark mode
|
||||
toggleDarkMode: function() {
|
||||
if (document.body.classList.contains("dark-mode")) {
|
||||
document.body.classList.remove("dark-mode");
|
||||
this.darkModeOn = false;
|
||||
this.createCookie("halfmoon_preferredMode", "light-mode", 365);
|
||||
} else {
|
||||
document.body.classList.add("dark-mode");
|
||||
this.darkModeOn = true;
|
||||
this.createCookie("halfmoon_preferredMode", "dark-mode", 365);
|
||||
}
|
||||
},
|
||||
|
||||
// Get preferred mode
|
||||
getPreferredMode: function() {
|
||||
if (this.readCookie("halfmoon_preferredMode")) {
|
||||
return this.readCookie("halfmoon_preferredMode");
|
||||
} else {
|
||||
return "not-set";
|
||||
}
|
||||
},
|
||||
|
||||
// Toggles sidebar
|
||||
toggleSidebar: function() {
|
||||
if (this.pageWrapper) {
|
||||
if (this.pageWrapper.getAttribute("data-sidebar-hidden")) {
|
||||
this.pageWrapper.removeAttribute("data-sidebar-hidden");
|
||||
} else {
|
||||
this.pageWrapper.setAttribute("data-sidebar-hidden", "hidden");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Deactivate all the dropdown toggles when another one is active
|
||||
deactivateAllDropdownToggles: function() {
|
||||
var activeDropdownToggles = document.querySelectorAll("[data-toggle='dropdown'].active");
|
||||
for (var i = 0; i < activeDropdownToggles.length; i++) {
|
||||
activeDropdownToggles[i].classList.remove("active");
|
||||
activeDropdownToggles[i].closest(".dropdown").classList.remove("show");
|
||||
}
|
||||
},
|
||||
|
||||
// Toggle modal (using Javascript)
|
||||
toggleModal: function(modalId) {
|
||||
var modal = document.getElementById(modalId);
|
||||
|
||||
if (modal) {
|
||||
modal.classList.toggle("show");
|
||||
}
|
||||
},
|
||||
|
||||
/* Code block for handling sticky alerts */
|
||||
|
||||
// Make an ID for an element
|
||||
makeId: function(length) {
|
||||
var result = "";
|
||||
var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
var charactersLength = characters.length;
|
||||
for ( var i = 0; i < length; i++ ) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
// Toast an alert (show, fade, dispose)
|
||||
toastAlert: function(alertId, timeShown) {
|
||||
var alertElement = document.getElementById(alertId);
|
||||
|
||||
// Setting the default timeShown
|
||||
if (timeShown === undefined) {
|
||||
timeShown = 5000;
|
||||
}
|
||||
|
||||
// Alert is only toasted if it does not have the .show class
|
||||
if (!alertElement.classList.contains("show")) {
|
||||
// Add .alert-block class if it does not exist
|
||||
if (!alertElement.classList.contains("alert-block")) {
|
||||
alertElement.classList.add("alert-block");
|
||||
}
|
||||
|
||||
// Show the alert
|
||||
// The 0.25 seconds delay is for the animation
|
||||
setTimeout(function() {
|
||||
alertElement.classList.add("show");
|
||||
}, 250);
|
||||
|
||||
// Wait some time (timeShown + 250) and fade out the alert
|
||||
var timeToFade = timeShown + 250;
|
||||
setTimeout(function() {
|
||||
alertElement.classList.add("fade");
|
||||
}, timeToFade);
|
||||
|
||||
// Wait some more time (timeToFade + 500) and dispose the alert (by removing the .alert-block class)
|
||||
// Again, the extra delay is for the animation
|
||||
// Remove the .show and .fade classes (so the alert can be toasted again)
|
||||
var timeToDestroy = timeToFade + 500;
|
||||
setTimeout(function() {
|
||||
alertElement.classList.remove("alert-block");
|
||||
alertElement.classList.remove("show");
|
||||
alertElement.classList.remove("fade");
|
||||
}, timeToDestroy);
|
||||
}
|
||||
},
|
||||
|
||||
// Create a sticky alert, display it, and then remove it
|
||||
initStickyAlert: function(param) {
|
||||
// Setting the variables from the param
|
||||
var content = ("content" in param) ? param.content: "";
|
||||
var title = ("title" in param) ? param.title: "";
|
||||
var alertType = ("alertType" in param) ? param.alertType: "";
|
||||
var fillType = ("fillType" in param) ? param.fillType: "";
|
||||
var hasDismissButton = ("hasDismissButton" in param) ? param.hasDismissButton: true;
|
||||
var timeShown = ("timeShown" in param) ? param.timeShown: 5000;
|
||||
|
||||
// Create the alert element
|
||||
var alertElement = document.createElement("div");
|
||||
|
||||
// Set ID to the alert element
|
||||
alertElement.setAttribute("id", this.makeId(6));
|
||||
|
||||
// Add the title
|
||||
if (title) {
|
||||
content = "<h4 class='alert-heading'>" + title + "</h4>" + content;
|
||||
}
|
||||
|
||||
// Add the classes to the alert element
|
||||
alertElement.classList.add("alert");
|
||||
if (alertType) {
|
||||
alertElement.classList.add(alertType);
|
||||
}
|
||||
if (fillType) {
|
||||
alertElement.classList.add(fillType);
|
||||
}
|
||||
|
||||
// Add the close button to the content (if required)
|
||||
if (hasDismissButton) {
|
||||
content = "<button class='close' data-dismiss='alert' type='button' aria-label='Close'><span aria-hidden='true'>×</span></button>" + content;
|
||||
}
|
||||
|
||||
// Add the content to the alert element
|
||||
alertElement.innerHTML = content;
|
||||
|
||||
// Append the alert element to the sticky alerts
|
||||
this.stickyAlerts.insertBefore(alertElement, this.stickyAlerts.childNodes[0]);
|
||||
|
||||
// Toast the alert
|
||||
this.toastAlert(alertElement.getAttribute("id"), timeShown);
|
||||
},
|
||||
|
||||
/* End code block for handling sticky alerts */
|
||||
|
||||
// Click handler that can be overridden by users if needed
|
||||
clickHandler: function(event) {},
|
||||
|
||||
// Keydown handler that can be overridden by users if needed
|
||||
keydownHandler: function(event) {},
|
||||
}
|
||||
|
||||
|
||||
/* Things done once the DOM is loaded */
|
||||
|
||||
function halfmoonOnDOMContentLoaded() {
|
||||
// Re-initializing the required elements (to avoid issues with virtual DOM)
|
||||
if (!halfmoon.pageWrapper) {
|
||||
halfmoon.pageWrapper = document.getElementsByClassName("page-wrapper")[0];
|
||||
}
|
||||
if (!halfmoon.stickyAlerts) {
|
||||
halfmoon.stickyAlerts = document.getElementsByClassName("sticky-alerts")[0];
|
||||
}
|
||||
|
||||
// Handle the cookie and variable for dark mode
|
||||
// 1. First preference is given to the cookie if it exists
|
||||
if (halfmoon.readCookie("halfmoon_preferredMode")) {
|
||||
if (halfmoon.readCookie("halfmoon_preferredMode") == "dark-mode") {
|
||||
halfmoon.darkModeOn = true;
|
||||
} else {
|
||||
halfmoon.darkModeOn = false;
|
||||
}
|
||||
} else {
|
||||
// 2. If cookie does not exist, next preference is for the dark mode setting
|
||||
if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||
halfmoon.darkModeOn = true;
|
||||
} else {
|
||||
// 3. If all else fails, re-initialize the dark mode preference depending on the .dark-mode class
|
||||
if (document.body.classList.contains("dark-mode")) {
|
||||
halfmoon.darkModeOn = true;
|
||||
} else {
|
||||
halfmoon.darkModeOn = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Automatically set preferred theme
|
||||
// But only if one of the data-attribute is provided
|
||||
if (document.body.getAttribute("data-set-preferred-mode-onload") || document.body.getAttribute("data-set-preferred-theme-onload")) {
|
||||
if (halfmoon.darkModeOn) {
|
||||
if (!document.body.classList.contains("dark-mode")) {
|
||||
document.body.classList.add("dark-mode");
|
||||
}
|
||||
} else {
|
||||
if (document.body.classList.contains("dark-mode")) {
|
||||
document.body.classList.remove("dark-mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hiding sidebar on first load on small screens (unless data-attribute provided)
|
||||
// Or on larger screens when sidebar type is overlayed-all
|
||||
if (document.documentElement.clientWidth <= 768) {
|
||||
if (halfmoon.pageWrapper) {
|
||||
if (!halfmoon.pageWrapper.getAttribute("data-show-sidebar-onload-sm-and-down")) {
|
||||
halfmoon.pageWrapper.setAttribute("data-sidebar-hidden", "hidden");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (halfmoon.pageWrapper) {
|
||||
if (halfmoon.pageWrapper.getAttribute("data-sidebar-type") === "overlayed-all") {
|
||||
halfmoon.pageWrapper.setAttribute("data-sidebar-hidden", "hidden");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adding the click event listener
|
||||
document.addEventListener(
|
||||
"click",
|
||||
function(event) {
|
||||
var eventCopy = event;
|
||||
var target = event.target;
|
||||
|
||||
// Handle clicks on dropdown toggles
|
||||
if (target.matches("[data-toggle='dropdown']") || target.matches("[data-toggle='dropdown'] *")) {
|
||||
if (target.matches("[data-toggle='dropdown'] *")) {
|
||||
target = target.closest("[data-toggle='dropdown']");
|
||||
}
|
||||
if (target.classList.contains("active")) {
|
||||
target.classList.remove("active");
|
||||
target.closest(".dropdown").classList.remove("show");
|
||||
} else {
|
||||
halfmoon.deactivateAllDropdownToggles();
|
||||
target.classList.add("active");
|
||||
target.closest(".dropdown").classList.add("show");
|
||||
}
|
||||
} else {
|
||||
if (!target.matches(".dropdown-menu *")) {
|
||||
halfmoon.deactivateAllDropdownToggles();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle clicks on alert dismiss buttons
|
||||
if (target.matches(".alert [data-dismiss='alert']") || target.matches(".alert [data-dismiss='alert'] *")) {
|
||||
if (target.matches(".alert [data-dismiss='alert'] *")) {
|
||||
target = target.closest(".alert [data-dismiss='alert']");
|
||||
}
|
||||
target.parentNode.classList.add("dispose");
|
||||
}
|
||||
|
||||
// Handle clicks on modal toggles
|
||||
if (target.matches("[data-toggle='modal']") || target.matches("[data-toggle='modal'] *")) {
|
||||
if (target.matches("[data-toggle='modal'] *")) {
|
||||
target = target.closest("[data-toggle='modal']");
|
||||
}
|
||||
var targetModal = document.getElementById(target.getAttribute("data-target"));
|
||||
if (targetModal) {
|
||||
if (targetModal.classList.contains("modal")) {
|
||||
halfmoon.toggleModal(target.getAttribute("data-target"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle clicks on modal dismiss buttons
|
||||
if (target.matches(".modal [data-dismiss='modal']") || target.matches(".modal [data-dismiss='modal'] *")) {
|
||||
if (target.matches(".modal [data-dismiss='modal'] *")) {
|
||||
target = target.closest(".modal [data-dismiss='modal']");
|
||||
}
|
||||
target.closest(".modal").classList.remove("show");
|
||||
}
|
||||
|
||||
// Handle clicks on modal overlays
|
||||
if (target.matches(".modal-dialog")) {
|
||||
var parentModal = target.closest(".modal");
|
||||
|
||||
if (!parentModal.getAttribute("data-overlay-dismissal-disabled")) {
|
||||
if (parentModal.classList.contains("show")) {
|
||||
parentModal.classList.remove("show");
|
||||
} else {
|
||||
window.location.hash = "#";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call the click handler method to handle any logic set by the user in their projects to handle clicks
|
||||
halfmoon.clickHandler(eventCopy);
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
// Adding the key down event listener (for shortcuts and accessibility)
|
||||
document.addEventListener(
|
||||
"keydown",
|
||||
function(event) {
|
||||
var eventCopy = event;
|
||||
|
||||
// Shortcuts are triggered only if no input, textarea, or select has focus,
|
||||
// If the control key or command key is not pressed down,
|
||||
// And if the enabling data attribute is present on the DOM's body
|
||||
if (!(document.querySelector("input:focus") || document.querySelector("textarea:focus") || document.querySelector("select:focus"))) {
|
||||
event = event || window.event;
|
||||
|
||||
if (!(event.ctrlKey || event.metaKey)) {
|
||||
// Toggle sidebar when [shift] + [S] keys are pressed
|
||||
if (document.body.getAttribute("data-sidebar-shortcut-enabled")) {
|
||||
if (event.shiftKey && event.which == 83) {
|
||||
// Variable to store whether a modal is open or not
|
||||
var modalOpen = false;
|
||||
|
||||
// Hash exists, so we check if it belongs to a modal
|
||||
if (window.location.hash) {
|
||||
var hash = window.location.hash.substring(1);
|
||||
var elem = document.getElementById(hash);
|
||||
if (elem) {
|
||||
if (elem.classList.contains("modal")) {
|
||||
modalOpen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check for a modal with the .show class
|
||||
if (document.querySelector(".modal.show")) {
|
||||
modalOpen = true;
|
||||
}
|
||||
|
||||
// This shortcut works only if no modal is open
|
||||
if (!modalOpen) {
|
||||
halfmoon.toggleSidebar();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle dark mode when [shift] + [D] keys are pressed
|
||||
if (document.body.getAttribute("data-dm-shortcut-enabled")) {
|
||||
if (event.shiftKey && event.which == 68) {
|
||||
halfmoon.toggleDarkMode();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handling other keydown events
|
||||
if (event.which === 27) {
|
||||
// Close dropdown menu (if one is open) when [esc] key is pressed
|
||||
if (document.querySelector("[data-toggle='dropdown'].active")) {
|
||||
var elem = document.querySelector("[data-toggle='dropdown'].active");
|
||||
elem.classList.remove("active");
|
||||
elem.closest(".dropdown").classList.remove("show");
|
||||
event.preventDefault();
|
||||
}
|
||||
// Close modal (if one is open, and if no dropdown menu is open) when [esc] key is pressed
|
||||
// Conditional on dropdowns so that dropdowns on modals can be closed with the keyboard without closing the modal
|
||||
else {
|
||||
// Hash exists, so we check if it belongs to a modal
|
||||
if (window.location.hash) {
|
||||
var hash = window.location.hash.substring(1);
|
||||
var elem = document.getElementById(hash);
|
||||
if (elem) {
|
||||
if (elem.classList.contains("modal")) {
|
||||
if (!elem.getAttribute("data-esc-dismissal-disabled")) {
|
||||
window.location.hash = "#";
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check for a modal with the .show class
|
||||
if (document.querySelector(".modal.show")) {
|
||||
var elem = document.querySelector(".modal.show");
|
||||
if (!elem.getAttribute("data-esc-dismissal-disabled")) {
|
||||
elem.classList.remove("show");
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call the keydown handler method to handle any logic set by the user in their projects to handle keydown events
|
||||
halfmoon.keydownHandler(eventCopy);
|
||||
}
|
||||
);
|
||||
|
||||
// Handling custom file inputs
|
||||
var halfmoonCustomFileInputs = document.querySelectorAll(".custom-file input");
|
||||
for (var i = 0; i < halfmoonCustomFileInputs.length; i++) {
|
||||
var customFile = halfmoonCustomFileInputs[i];
|
||||
// Create file name container element, add the class name, and set default value
|
||||
// Append it to the custom file element
|
||||
var fileNamesContainer = document.createElement("div");
|
||||
fileNamesContainer.classList.add("file-names");
|
||||
var dataDefaultValue = customFile.getAttribute("data-default-value");
|
||||
if (dataDefaultValue) {
|
||||
fileNamesContainer.innerHTML = dataDefaultValue;
|
||||
} else {
|
||||
fileNamesContainer.innerHTML = "No file chosen";
|
||||
}
|
||||
customFile.parentNode.appendChild(fileNamesContainer);
|
||||
|
||||
// Add the event listener that will update the contents of the file name container element on change
|
||||
customFile.addEventListener(
|
||||
"change",
|
||||
function(event) {
|
||||
fileNamesContainer = event.target.parentNode.querySelector(".file-names");
|
||||
if (event.target.files.length === 1) {
|
||||
fileNamesContainer.innerHTML = event.target.files[0].name;
|
||||
} else if (event.target.files.length > 1) {
|
||||
fileNamesContainer.innerHTML = event.target.files.length + " files";
|
||||
} else {
|
||||
fileNamesContainer.innerHTML = "No file chosen";
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Adding the .with-transitions class to the page-wrapper so that transitions are enabled
|
||||
// This way, the weird bug on Chrome is avoided, where the transitions run on load
|
||||
if (halfmoon.pageWrapper) {
|
||||
halfmoon.pageWrapper.classList.add("with-transitions");
|
||||
}
|
||||
}
|
||||
|
||||
// Add the halfmoonOnDOMContentLoaded to the main halfmoon object
|
||||
// And export the halfmoon object as a module
|
||||
halfmoon.onDOMContentLoaded = halfmoonOnDOMContentLoaded;
|
||||
module.exports = halfmoon;
|
||||
@@ -1,511 +0,0 @@
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* Halfmoon JS
|
||||
* Version: 1.1.1
|
||||
* https://www.gethalfmoon.com
|
||||
* Copyright, Halfmoon UI
|
||||
* Licensed under MIT (https://www.gethalfmoon.com/license)
|
||||
* -----------------------------------------------------------------------------
|
||||
* The above notice must be included in its entirety when this file is used.
|
||||
*/
|
||||
|
||||
/* Start polyfills */
|
||||
|
||||
// Polyfill for Element.matches()
|
||||
if (!Element.prototype.matches) {
|
||||
Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
|
||||
}
|
||||
|
||||
// Polyfill for Element.closest()
|
||||
if (!Element.prototype.closest) {
|
||||
Element.prototype.closest = function(s) {
|
||||
var el = this;
|
||||
do {
|
||||
if (el.matches(s)) return el;
|
||||
el = el.parentElement || el.parentNode;
|
||||
} while (el !== null && el.nodeType === 1);
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
// Polyfill for Element.classList (http://purl.eligrey.com/github/classList.js/blob/master/classList.js)
|
||||
"document"in self&&("classList"in document.createElement("_")&&(!document.createElementNS||"classList"in document.createElementNS("http://www.w3.org/2000/svg","g"))||!function(t){"use strict";if("Element"in t){var e="classList",n="prototype",i=t.Element[n],s=Object,r=String[n].trim||function(){return this.replace(/^\s+|\s+$/g,"")},o=Array[n].indexOf||function(t){for(var e=0,n=this.length;n>e;e++)if(e in this&&this[e]===t)return e;return-1},c=function(t,e){this.name=t,this.code=DOMException[t],this.message=e},a=function(t,e){if(""===e)throw new c("SYNTAX_ERR","The token must not be empty.");if(/\s/.test(e))throw new c("INVALID_CHARACTER_ERR","The token must not contain space characters.");return o.call(t,e)},l=function(t){for(var e=r.call(t.getAttribute("class")||""),n=e?e.split(/\s+/):[],i=0,s=n.length;s>i;i++)this.push(n[i]);this._updateClassName=function(){t.setAttribute("class",this.toString())}},u=l[n]=[],h=function(){return new l(this)};if(c[n]=Error[n],u.item=function(t){return this[t]||null},u.contains=function(t){return~a(this,t+"")},u.add=function(){var t,e=arguments,n=0,i=e.length,s=!1;do t=e[n]+"",~a(this,t)||(this.push(t),s=!0);while(++n<i);s&&this._updateClassName()},u.remove=function(){var t,e,n=arguments,i=0,s=n.length,r=!1;do for(t=n[i]+"",e=a(this,t);~e;)this.splice(e,1),r=!0,e=a(this,t);while(++i<s);r&&this._updateClassName()},u.toggle=function(t,e){var n=this.contains(t),i=n?e!==!0&&"remove":e!==!1&&"add";return i&&this[i](t),e===!0||e===!1?e:!n},u.replace=function(t,e){var n=a(t+"");~n&&(this.splice(n,1,e),this._updateClassName())},u.toString=function(){return this.join(" ")},s.defineProperty){var f={get:h,enumerable:!0,configurable:!0};try{s.defineProperty(i,e,f)}catch(p){void 0!==p.number&&-2146823252!==p.number||(f.enumerable=!1,s.defineProperty(i,e,f))}}else s[n].__defineGetter__&&i.__defineGetter__(e,h)}}(self),function(){"use strict";var t=document.createElement("_");if(t.classList.add("c1","c2"),!t.classList.contains("c2")){var e=function(t){var e=DOMTokenList.prototype[t];DOMTokenList.prototype[t]=function(t){var n,i=arguments.length;for(n=0;i>n;n++)t=arguments[n],e.call(this,t)}};e("add"),e("remove")}if(t.classList.toggle("c3",!1),t.classList.contains("c3")){var n=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(t,e){return 1 in arguments&&!this.contains(t)==!e?e:n.call(this,t)}}"replace"in document.createElement("_").classList||(DOMTokenList.prototype.replace=function(t,e){var n=this.toString().split(" "),i=n.indexOf(t+"");~i&&(n=n.slice(i),this.remove.apply(this,n),this.add(e),this.add.apply(this,n.slice(1)))}),t=null}());
|
||||
|
||||
/* End polyfills */
|
||||
|
||||
|
||||
/* Halfmoon JS core */
|
||||
|
||||
var halfmoon = {
|
||||
// Getting the required elements
|
||||
// Re-initialized once the DOM is loaded (to avoid issues with virtual DOM)
|
||||
pageWrapper: document.getElementsByClassName("page-wrapper")[0],
|
||||
stickyAlerts: document.getElementsByClassName("sticky-alerts")[0],
|
||||
|
||||
darkModeOn: false, // Also re-initialized once the DOM is loaded (see below)
|
||||
|
||||
// Create cookie
|
||||
createCookie: function(name, value, days) {
|
||||
var expires;
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
expires = "; expires=" + date.toGMTString();
|
||||
}
|
||||
else {
|
||||
expires = "";
|
||||
}
|
||||
document.cookie = name + "=" + value + expires + "; path=/";
|
||||
},
|
||||
|
||||
// Read cookie
|
||||
readCookie: function(name) {
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(";");
|
||||
for(var i=0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) === " ") {
|
||||
c = c.substring(1, c.length);
|
||||
}
|
||||
if (c.indexOf(nameEQ) === 0) {
|
||||
return c.substring(nameEQ.length,c.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
// Erase cookie
|
||||
eraseCookie: function(name) {
|
||||
this.createCookie(name, "", -1);
|
||||
},
|
||||
|
||||
// Toggle light/dark mode
|
||||
toggleDarkMode: function() {
|
||||
if (document.body.classList.contains("dark-mode")) {
|
||||
document.body.classList.remove("dark-mode");
|
||||
this.darkModeOn = false;
|
||||
this.createCookie("halfmoon_preferredMode", "light-mode", 365);
|
||||
} else {
|
||||
document.body.classList.add("dark-mode");
|
||||
this.darkModeOn = true;
|
||||
this.createCookie("halfmoon_preferredMode", "dark-mode", 365);
|
||||
}
|
||||
},
|
||||
|
||||
// Get preferred mode
|
||||
getPreferredMode: function() {
|
||||
if (this.readCookie("halfmoon_preferredMode")) {
|
||||
return this.readCookie("halfmoon_preferredMode");
|
||||
} else {
|
||||
return "not-set";
|
||||
}
|
||||
},
|
||||
|
||||
// Toggles sidebar
|
||||
toggleSidebar: function() {
|
||||
if (this.pageWrapper) {
|
||||
if (this.pageWrapper.getAttribute("data-sidebar-hidden")) {
|
||||
this.pageWrapper.removeAttribute("data-sidebar-hidden");
|
||||
} else {
|
||||
this.pageWrapper.setAttribute("data-sidebar-hidden", "hidden");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Deactivate all the dropdown toggles when another one is active
|
||||
deactivateAllDropdownToggles: function() {
|
||||
var activeDropdownToggles = document.querySelectorAll("[data-toggle='dropdown'].active");
|
||||
for (var i = 0; i < activeDropdownToggles.length; i++) {
|
||||
activeDropdownToggles[i].classList.remove("active");
|
||||
activeDropdownToggles[i].closest(".dropdown").classList.remove("show");
|
||||
}
|
||||
},
|
||||
|
||||
// Toggle modal (using Javascript)
|
||||
toggleModal: function(modalId) {
|
||||
var modal = document.getElementById(modalId);
|
||||
|
||||
if (modal) {
|
||||
modal.classList.toggle("show");
|
||||
}
|
||||
},
|
||||
|
||||
/* Code block for handling sticky alerts */
|
||||
|
||||
// Make an ID for an element
|
||||
makeId: function(length) {
|
||||
var result = "";
|
||||
var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
var charactersLength = characters.length;
|
||||
for ( var i = 0; i < length; i++ ) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
// Toast an alert (show, fade, dispose)
|
||||
toastAlert: function(alertId, timeShown) {
|
||||
var alertElement = document.getElementById(alertId);
|
||||
|
||||
// Setting the default timeShown
|
||||
if (timeShown === undefined) {
|
||||
timeShown = 5000;
|
||||
}
|
||||
|
||||
// Alert is only toasted if it does not have the .show class
|
||||
if (!alertElement.classList.contains("show")) {
|
||||
// Add .alert-block class if it does not exist
|
||||
if (!alertElement.classList.contains("alert-block")) {
|
||||
alertElement.classList.add("alert-block");
|
||||
}
|
||||
|
||||
// Show the alert
|
||||
// The 0.25 seconds delay is for the animation
|
||||
setTimeout(function() {
|
||||
alertElement.classList.add("show");
|
||||
}, 250);
|
||||
|
||||
// Wait some time (timeShown + 250) and fade out the alert
|
||||
var timeToFade = timeShown + 250;
|
||||
setTimeout(function() {
|
||||
alertElement.classList.add("fade");
|
||||
}, timeToFade);
|
||||
|
||||
// Wait some more time (timeToFade + 500) and dispose the alert (by removing the .alert-block class)
|
||||
// Again, the extra delay is for the animation
|
||||
// Remove the .show and .fade classes (so the alert can be toasted again)
|
||||
var timeToDestroy = timeToFade + 500;
|
||||
setTimeout(function() {
|
||||
alertElement.classList.remove("alert-block");
|
||||
alertElement.classList.remove("show");
|
||||
alertElement.classList.remove("fade");
|
||||
}, timeToDestroy);
|
||||
}
|
||||
},
|
||||
|
||||
// Create a sticky alert, display it, and then remove it
|
||||
initStickyAlert: function(param) {
|
||||
// Setting the variables from the param
|
||||
var content = ("content" in param) ? param.content: "";
|
||||
var title = ("title" in param) ? param.title: "";
|
||||
var alertType = ("alertType" in param) ? param.alertType: "";
|
||||
var fillType = ("fillType" in param) ? param.fillType: "";
|
||||
var hasDismissButton = ("hasDismissButton" in param) ? param.hasDismissButton: true;
|
||||
var timeShown = ("timeShown" in param) ? param.timeShown: 5000;
|
||||
|
||||
// Create the alert element
|
||||
var alertElement = document.createElement("div");
|
||||
|
||||
// Set ID to the alert element
|
||||
alertElement.setAttribute("id", this.makeId(6));
|
||||
|
||||
// Add the title
|
||||
if (title) {
|
||||
content = "<h4 class='alert-heading'>" + title + "</h4>" + content;
|
||||
}
|
||||
|
||||
// Add the classes to the alert element
|
||||
alertElement.classList.add("alert");
|
||||
if (alertType) {
|
||||
alertElement.classList.add(alertType);
|
||||
}
|
||||
if (fillType) {
|
||||
alertElement.classList.add(fillType);
|
||||
}
|
||||
|
||||
// Add the close button to the content (if required)
|
||||
if (hasDismissButton) {
|
||||
content = "<button class='close' data-dismiss='alert' type='button' aria-label='Close'><span aria-hidden='true'>×</span></button>" + content;
|
||||
}
|
||||
|
||||
// Add the content to the alert element
|
||||
alertElement.innerHTML = content;
|
||||
|
||||
// Append the alert element to the sticky alerts
|
||||
this.stickyAlerts.insertBefore(alertElement, this.stickyAlerts.childNodes[0]);
|
||||
|
||||
// Toast the alert
|
||||
this.toastAlert(alertElement.getAttribute("id"), timeShown);
|
||||
},
|
||||
|
||||
/* End code block for handling sticky alerts */
|
||||
|
||||
// Click handler that can be overridden by users if needed
|
||||
clickHandler: function(event) {},
|
||||
|
||||
// Keydown handler that can be overridden by users if needed
|
||||
keydownHandler: function(event) {},
|
||||
}
|
||||
|
||||
|
||||
/* Things done once the DOM is loaded */
|
||||
|
||||
function halfmoonOnDOMContentLoaded() {
|
||||
// Re-initializing the required elements (to avoid issues with virtual DOM)
|
||||
if (!halfmoon.pageWrapper) {
|
||||
halfmoon.pageWrapper = document.getElementsByClassName("page-wrapper")[0];
|
||||
}
|
||||
if (!halfmoon.stickyAlerts) {
|
||||
halfmoon.stickyAlerts = document.getElementsByClassName("sticky-alerts")[0];
|
||||
}
|
||||
|
||||
// Handle the cookie and variable for dark mode
|
||||
// 1. First preference is given to the cookie if it exists
|
||||
if (halfmoon.readCookie("halfmoon_preferredMode")) {
|
||||
if (halfmoon.readCookie("halfmoon_preferredMode") == "dark-mode") {
|
||||
halfmoon.darkModeOn = true;
|
||||
} else {
|
||||
halfmoon.darkModeOn = false;
|
||||
}
|
||||
} else {
|
||||
// 2. If cookie does not exist, next preference is for the dark mode setting
|
||||
if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||
halfmoon.darkModeOn = true;
|
||||
} else {
|
||||
// 3. If all else fails, re-initialize the dark mode preference depending on the .dark-mode class
|
||||
if (document.body.classList.contains("dark-mode")) {
|
||||
halfmoon.darkModeOn = true;
|
||||
} else {
|
||||
halfmoon.darkModeOn = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Automatically set preferred theme
|
||||
// But only if one of the data-attribute is provided
|
||||
if (document.body.getAttribute("data-set-preferred-mode-onload") || document.body.getAttribute("data-set-preferred-theme-onload")) {
|
||||
if (halfmoon.darkModeOn) {
|
||||
if (!document.body.classList.contains("dark-mode")) {
|
||||
document.body.classList.add("dark-mode");
|
||||
}
|
||||
} else {
|
||||
if (document.body.classList.contains("dark-mode")) {
|
||||
document.body.classList.remove("dark-mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hiding sidebar on first load on small screens (unless data-attribute provided)
|
||||
// Or on larger screens when sidebar type is overlayed-all
|
||||
if (document.documentElement.clientWidth <= 768) {
|
||||
if (halfmoon.pageWrapper) {
|
||||
if (!halfmoon.pageWrapper.getAttribute("data-show-sidebar-onload-sm-and-down")) {
|
||||
halfmoon.pageWrapper.setAttribute("data-sidebar-hidden", "hidden");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (halfmoon.pageWrapper) {
|
||||
if (halfmoon.pageWrapper.getAttribute("data-sidebar-type") === "overlayed-all") {
|
||||
halfmoon.pageWrapper.setAttribute("data-sidebar-hidden", "hidden");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adding the click event listener
|
||||
document.addEventListener(
|
||||
"click",
|
||||
function(event) {
|
||||
var eventCopy = event;
|
||||
var target = event.target;
|
||||
|
||||
// Handle clicks on dropdown toggles
|
||||
if (target.matches("[data-toggle='dropdown']") || target.matches("[data-toggle='dropdown'] *")) {
|
||||
if (target.matches("[data-toggle='dropdown'] *")) {
|
||||
target = target.closest("[data-toggle='dropdown']");
|
||||
}
|
||||
if (target.classList.contains("active")) {
|
||||
target.classList.remove("active");
|
||||
target.closest(".dropdown").classList.remove("show");
|
||||
} else {
|
||||
halfmoon.deactivateAllDropdownToggles();
|
||||
target.classList.add("active");
|
||||
target.closest(".dropdown").classList.add("show");
|
||||
}
|
||||
} else {
|
||||
if (!target.matches(".dropdown-menu *")) {
|
||||
halfmoon.deactivateAllDropdownToggles();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle clicks on alert dismiss buttons
|
||||
if (target.matches(".alert [data-dismiss='alert']") || target.matches(".alert [data-dismiss='alert'] *")) {
|
||||
if (target.matches(".alert [data-dismiss='alert'] *")) {
|
||||
target = target.closest(".alert [data-dismiss='alert']");
|
||||
}
|
||||
target.parentNode.classList.add("dispose");
|
||||
}
|
||||
|
||||
// Handle clicks on modal toggles
|
||||
if (target.matches("[data-toggle='modal']") || target.matches("[data-toggle='modal'] *")) {
|
||||
if (target.matches("[data-toggle='modal'] *")) {
|
||||
target = target.closest("[data-toggle='modal']");
|
||||
}
|
||||
var targetModal = document.getElementById(target.getAttribute("data-target"));
|
||||
if (targetModal) {
|
||||
if (targetModal.classList.contains("modal")) {
|
||||
halfmoon.toggleModal(target.getAttribute("data-target"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle clicks on modal dismiss buttons
|
||||
if (target.matches(".modal [data-dismiss='modal']") || target.matches(".modal [data-dismiss='modal'] *")) {
|
||||
if (target.matches(".modal [data-dismiss='modal'] *")) {
|
||||
target = target.closest(".modal [data-dismiss='modal']");
|
||||
}
|
||||
target.closest(".modal").classList.remove("show");
|
||||
}
|
||||
|
||||
// Handle clicks on modal overlays
|
||||
if (target.matches(".modal-dialog")) {
|
||||
var parentModal = target.closest(".modal");
|
||||
|
||||
if (!parentModal.getAttribute("data-overlay-dismissal-disabled")) {
|
||||
if (parentModal.classList.contains("show")) {
|
||||
parentModal.classList.remove("show");
|
||||
} else {
|
||||
window.location.hash = "#";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call the click handler method to handle any logic set by the user in their projects to handle clicks
|
||||
halfmoon.clickHandler(eventCopy);
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
// Adding the key down event listener (for shortcuts and accessibility)
|
||||
document.addEventListener(
|
||||
"keydown",
|
||||
function(event) {
|
||||
var eventCopy = event;
|
||||
|
||||
// Shortcuts are triggered only if no input, textarea, or select has focus,
|
||||
// If the control key or command key is not pressed down,
|
||||
// And if the enabling data attribute is present on the DOM's body
|
||||
if (!(document.querySelector("input:focus") || document.querySelector("textarea:focus") || document.querySelector("select:focus"))) {
|
||||
event = event || window.event;
|
||||
|
||||
if (!(event.ctrlKey || event.metaKey)) {
|
||||
// Toggle sidebar when [shift] + [S] keys are pressed
|
||||
if (document.body.getAttribute("data-sidebar-shortcut-enabled")) {
|
||||
if (event.shiftKey && event.which == 83) {
|
||||
// Variable to store whether a modal is open or not
|
||||
var modalOpen = false;
|
||||
|
||||
// Hash exists, so we check if it belongs to a modal
|
||||
if (window.location.hash) {
|
||||
var hash = window.location.hash.substring(1);
|
||||
var elem = document.getElementById(hash);
|
||||
if (elem) {
|
||||
if (elem.classList.contains("modal")) {
|
||||
modalOpen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check for a modal with the .show class
|
||||
if (document.querySelector(".modal.show")) {
|
||||
modalOpen = true;
|
||||
}
|
||||
|
||||
// This shortcut works only if no modal is open
|
||||
if (!modalOpen) {
|
||||
halfmoon.toggleSidebar();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle dark mode when [shift] + [D] keys are pressed
|
||||
if (document.body.getAttribute("data-dm-shortcut-enabled")) {
|
||||
if (event.shiftKey && event.which == 68) {
|
||||
halfmoon.toggleDarkMode();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handling other keydown events
|
||||
if (event.which === 27) {
|
||||
// Close dropdown menu (if one is open) when [esc] key is pressed
|
||||
if (document.querySelector("[data-toggle='dropdown'].active")) {
|
||||
var elem = document.querySelector("[data-toggle='dropdown'].active");
|
||||
elem.classList.remove("active");
|
||||
elem.closest(".dropdown").classList.remove("show");
|
||||
event.preventDefault();
|
||||
}
|
||||
// Close modal (if one is open, and if no dropdown menu is open) when [esc] key is pressed
|
||||
// Conditional on dropdowns so that dropdowns on modals can be closed with the keyboard without closing the modal
|
||||
else {
|
||||
// Hash exists, so we check if it belongs to a modal
|
||||
if (window.location.hash) {
|
||||
var hash = window.location.hash.substring(1);
|
||||
var elem = document.getElementById(hash);
|
||||
if (elem) {
|
||||
if (elem.classList.contains("modal")) {
|
||||
if (!elem.getAttribute("data-esc-dismissal-disabled")) {
|
||||
window.location.hash = "#";
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check for a modal with the .show class
|
||||
if (document.querySelector(".modal.show")) {
|
||||
var elem = document.querySelector(".modal.show");
|
||||
if (!elem.getAttribute("data-esc-dismissal-disabled")) {
|
||||
elem.classList.remove("show");
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call the keydown handler method to handle any logic set by the user in their projects to handle keydown events
|
||||
halfmoon.keydownHandler(eventCopy);
|
||||
}
|
||||
);
|
||||
|
||||
// Handling custom file inputs
|
||||
var halfmoonCustomFileInputs = document.querySelectorAll(".custom-file input");
|
||||
for (var i = 0; i < halfmoonCustomFileInputs.length; i++) {
|
||||
var customFile = halfmoonCustomFileInputs[i];
|
||||
// Create file name container element, add the class name, and set default value
|
||||
// Append it to the custom file element
|
||||
var fileNamesContainer = document.createElement("div");
|
||||
fileNamesContainer.classList.add("file-names");
|
||||
var dataDefaultValue = customFile.getAttribute("data-default-value");
|
||||
if (dataDefaultValue) {
|
||||
fileNamesContainer.innerHTML = dataDefaultValue;
|
||||
} else {
|
||||
fileNamesContainer.innerHTML = "No file chosen";
|
||||
}
|
||||
customFile.parentNode.appendChild(fileNamesContainer);
|
||||
|
||||
// Add the event listener that will update the contents of the file name container element on change
|
||||
customFile.addEventListener(
|
||||
"change",
|
||||
function(event) {
|
||||
fileNamesContainer = event.target.parentNode.querySelector(".file-names");
|
||||
if (event.target.files.length === 1) {
|
||||
fileNamesContainer.innerHTML = event.target.files[0].name;
|
||||
} else if (event.target.files.length > 1) {
|
||||
fileNamesContainer.innerHTML = event.target.files.length + " files";
|
||||
} else {
|
||||
fileNamesContainer.innerHTML = "No file chosen";
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Adding the .with-transitions class to the page-wrapper so that transitions are enabled
|
||||
// This way, the weird bug on Chrome is avoided, where the transitions run on load
|
||||
if (halfmoon.pageWrapper) {
|
||||
halfmoon.pageWrapper.classList.add("with-transitions");
|
||||
}
|
||||
}
|
||||
|
||||
// Call the function when the DOM is loaded
|
||||
document.addEventListener("DOMContentLoaded", halfmoonOnDOMContentLoaded);
|
||||
11
resources/HalfMoon/1.1.1/js/halfmoon.min.js
vendored
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"name": "halfmoon",
|
||||
"version": "1.1.1",
|
||||
"description": "Front-end framework with a built-in dark mode and full customizability using CSS variables; great for building dashboards and tools",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/halfmoonui/halfmoon.git"
|
||||
},
|
||||
"keywords": [
|
||||
"halfmoon",
|
||||
"css",
|
||||
"javascript",
|
||||
"dark-theme",
|
||||
"dark-mode",
|
||||
"dashboard",
|
||||
"web-framework",
|
||||
"css-framework",
|
||||
"css-variables",
|
||||
"css-custom-properties"
|
||||
],
|
||||
"author": "Halfmoon UI",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/halfmoonui/halfmoon/issues"
|
||||
},
|
||||
"homepage": "https://github.com/halfmoonui/halfmoon#readme"
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Meta tags -->
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
|
||||
<!-- Favicon and title -->
|
||||
<link rel="icon" href="path/to/fav.png">
|
||||
<title>Starter template - Halfmoon</title>
|
||||
|
||||
<!-- Halfmoon CSS -->
|
||||
<link href="css/halfmoon-variables.min.css" rel="stylesheet" />
|
||||
<!--
|
||||
Or,
|
||||
Use the following (no variables, supports IE11):
|
||||
<link href="css/halfmoon.min.css" rel="stylesheet" />
|
||||
-->
|
||||
</head>
|
||||
<body class="with-custom-webkit-scrollbars with-custom-css-scrollbars" data-dm-shortcut-enabled="true" data-sidebar-shortcut-enabled="true" data-set-preferred-theme-onload="true">
|
||||
<!-- Modals go here -->
|
||||
<!-- Reference: https://www.gethalfmoon.com/docs/modal -->
|
||||
|
||||
<!-- Page wrapper start -->
|
||||
<div class="page-wrapper with-navbar with-sidebar with-navbar-fixed-bottom" data-sidebar-type="overlayed-sm-and-down">
|
||||
|
||||
<!-- Sticky alerts (toasts), empty container -->
|
||||
<!-- Reference: https://www.gethalfmoon.com/docs/sticky-alerts-toasts -->
|
||||
<div class="sticky-alerts"></div>
|
||||
|
||||
<!-- Navbar start -->
|
||||
<nav class="navbar">
|
||||
<!-- Reference: https://www.gethalfmoon.com/docs/navbar -->
|
||||
</nav>
|
||||
<!-- Navbar end -->
|
||||
|
||||
<!-- Sidebar overlay -->
|
||||
<div class="sidebar-overlay" onclick="halfmoon.toggleSidebar()"></div>
|
||||
|
||||
<!-- Sidebar start -->
|
||||
<div class="sidebar">
|
||||
<!-- Reference: https://www.gethalfmoon.com/docs/sidebar -->
|
||||
</div>
|
||||
<!-- Sidebar end -->
|
||||
|
||||
<!-- Content wrapper start -->
|
||||
<div class="content-wrapper">
|
||||
<!--
|
||||
Add your page's main content here
|
||||
Examples:
|
||||
1. https://www.gethalfmoon.com/docs/content-and-cards/#building-a-page
|
||||
2. https://www.gethalfmoon.com/docs/grid-system/#building-a-dashboard
|
||||
-->
|
||||
<div class="w-full h-full d-flex align-items-center justify-content-center">
|
||||
<div class="content">
|
||||
<h1 class="content-title">Halfmoon starter template</h1>
|
||||
<div>
|
||||
<a href="https://www.gethalfmoon.com" class="btn btn-link px-0">Halfmoon website</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://www.gethalfmoon.com/docs" class="btn btn-link px-0">Halfmoon docs</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://www.gethalfmoon.com/docs/page-building/#starter-template-generator" class="btn btn-link px-0">Starter template generator</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://www.twitter.com/halfmoonui" class="btn btn-link px-0">Follow on Twitter for updates</a>
|
||||
</div>
|
||||
<div class="mt-20">
|
||||
Toggles:
|
||||
<button class="btn btn-sm" type="button" onclick="halfmoon.toggleDarkMode()">Dark mode</button>
|
||||
<button class="btn btn-sm" type="button" onclick="halfmoon.toggleSidebar()">Sidebar</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Content wrapper end -->
|
||||
|
||||
<!-- Navbar fixed bottom start -->
|
||||
<nav class="navbar navbar-fixed-bottom">
|
||||
<!-- Reference: https://www.gethalfmoon.com/docs/navbar#navbar-fixed-bottom -->
|
||||
</nav>
|
||||
<!-- Navbar fixed bottom end -->
|
||||
</div>
|
||||
<!-- Page wrapper end -->
|
||||
|
||||
<!-- Halfmoon JS -->
|
||||
<script src="js/halfmoon.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,4 @@
|
||||
# Warning
|
||||
The files present in this directory are compiled from the files present in `../sass` !
|
||||
The files present in this directory are compiled from the files present in `../scss` !
|
||||
|
||||
Do not edit these files, the changes will be lost !
|
||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
BIN
resources/NibblePoker/images/backgrounds/3px-tile-0.5.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |