first commit

This commit is contained in:
2025-08-12 01:56:31 +08:00
parent fdbbda958c
commit 1ff4d3dce2
101 changed files with 14179 additions and 0 deletions

12
assets/js/audio.js Executable file
View File

@@ -0,0 +1,12 @@
function playSound(audioId) {
// First, stop and reset any currently playing audio
const allAudios = document.querySelectorAll('audio');
allAudios.forEach(audio => {
audio.pause();
audio.currentTime = 0;
});
// Play the requested audio
var audio = document.getElementById(audioId);
audio.play();
}

2
assets/js/breakpoints.min.js vendored Executable file
View File

@@ -0,0 +1,2 @@
/* breakpoints.js v1.0 | @ajlkn | MIT licensed */
var breakpoints=function(){"use strict";function e(e){t.init(e)}var t={list:null,media:{},events:[],init:function(e){t.list=e,window.addEventListener("resize",t.poll),window.addEventListener("orientationchange",t.poll),window.addEventListener("load",t.poll),window.addEventListener("fullscreenchange",t.poll)},active:function(e){var n,a,s,i,r,d,c;if(!(e in t.media)){if(">="==e.substr(0,2)?(a="gte",n=e.substr(2)):"<="==e.substr(0,2)?(a="lte",n=e.substr(2)):">"==e.substr(0,1)?(a="gt",n=e.substr(1)):"<"==e.substr(0,1)?(a="lt",n=e.substr(1)):"!"==e.substr(0,1)?(a="not",n=e.substr(1)):(a="eq",n=e),n&&n in t.list)if(i=t.list[n],Array.isArray(i)){if(r=parseInt(i[0]),d=parseInt(i[1]),isNaN(r)){if(isNaN(d))return;c=i[1].substr(String(d).length)}else c=i[0].substr(String(r).length);if(isNaN(r))switch(a){case"gte":s="screen";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: -1px)";break;case"not":s="screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (max-width: "+d+c+")"}else if(isNaN(d))switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen";break;case"gt":s="screen and (max-width: -1px)";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+")";break;default:s="screen and (min-width: "+r+c+")"}else switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+"), screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (min-width: "+r+c+") and (max-width: "+d+c+")"}}else s="("==i.charAt(0)?"screen and "+i:i;t.media[e]=!!s&&s}return t.media[e]!==!1&&window.matchMedia(t.media[e]).matches},on:function(e,n){t.events.push({query:e,handler:n,state:!1}),t.active(e)&&n()},poll:function(){var e,n;for(e=0;e<t.events.length;e++)n=t.events[e],t.active(n.query)?n.state||(n.state=!0,n.handler()):n.state&&(n.state=!1)}};return e._=t,e.on=function(e,n){t.on(e,n)},e.active=function(e){return t.active(e)},e}();!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?module.exports=t():e.breakpoints=t()}(this,function(){return breakpoints});

2
assets/js/browser.min.js vendored Executable file
View File

@@ -0,0 +1,2 @@
/* browser.js v1.0.1 | @ajlkn | MIT licensed */
var browser=function(){"use strict";var t={name:null,version:null,os:null,osVersion:null,touch:null,mobile:null,_canUse:null,canUse:function(e){t._canUse||(t._canUse=document.createElement("div"));var n=t._canUse.style,r=e.charAt(0).toUpperCase()+e.slice(1);return e in n||"Moz"+r in n||"Webkit"+r in n||"O"+r in n||"ms"+r in n},init:function(){for(var e=navigator.userAgent,n="other",r=0,i=[["firefox",/Firefox\/([0-9\.]+)/],["bb",/BlackBerry.+Version\/([0-9\.]+)/],["bb",/BB[0-9]+.+Version\/([0-9\.]+)/],["opera",/OPR\/([0-9\.]+)/],["opera",/Opera\/([0-9\.]+)/],["edge",/Edge\/([0-9\.]+)/],["safari",/Version\/([0-9\.]+).+Safari/],["chrome",/Chrome\/([0-9\.]+)/],["ie",/MSIE ([0-9]+)/],["ie",/Trident\/.+rv:([0-9]+)/]],o=0;o<i.length;o++)if(e.match(i[o][1])){n=i[o][0],r=parseFloat(RegExp.$1);break}for(t.name=n,t.version=r,n="other",i=[["ios",/([0-9_]+) like Mac OS X/,function(e){return e.replace("_",".").replace("_","")}],["ios",/CPU like Mac OS X/,function(e){return 0}],["wp",/Windows Phone ([0-9\.]+)/,null],["android",/Android ([0-9\.]+)/,null],["mac",/Macintosh.+Mac OS X ([0-9_]+)/,function(e){return e.replace("_",".").replace("_","")}],["windows",/Windows NT ([0-9\.]+)/,null],["bb",/BlackBerry.+Version\/([0-9\.]+)/,null],["bb",/BB[0-9]+.+Version\/([0-9\.]+)/,null],["linux",/Linux/,null],["bsd",/BSD/,null],["unix",/X11/,null]],o=r=0;o<i.length;o++)if(e.match(i[o][1])){n=i[o][0],r=parseFloat(i[o][2]?i[o][2](RegExp.$1):RegExp.$1);break}"mac"==n&&"ontouchstart"in window&&(1024==screen.width&&1366==screen.height||834==screen.width&&1112==screen.height||810==screen.width&&1080==screen.height||768==screen.width&&1024==screen.height)&&(n="ios"),t.os=n,t.osVersion=r,t.touch="wp"==t.os?0<navigator.msMaxTouchPoints:!!("ontouchstart"in window),t.mobile="wp"==t.os||"android"==t.os||"ios"==t.os||"bb"==t.os}};return t.init(),t}();!function(e,n){"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?module.exports=n():e.browser=n()}(this,function(){return browser});

23
assets/js/haiku.js Executable file
View File

@@ -0,0 +1,23 @@
document.addEventListener('DOMContentLoaded', function () {
const haikus = [
"missed sunset's last glow\n city lights beneath night's veil \n beauty shared hearts slow",
"through winding trails home\n songs weave stories, hearts roam free\n in tune we find home",
"sea lions play, waves crash\n smoke swirls, words flow, time's slow dash\n cove whispers, bonds flash",
"ramen bowls steam bright\n little tokyo in sight\n shared hearts, culture's light",
"a freckled face gleams\n under streetlights when a cat\n meows further away",
"miles stretch wide and vast\n yet in heartbeats ur so near\n stars bridging our gap",
"waves of longing surge,\n tonights flood, a deep sorrow\n drowning in your absence",
];
function getRandomHaiku() {
const index = Math.floor(Math.random() * haikus.length);
return haikus[index];
}
function displayHaiku() {
const quoteElement = document.getElementById('haiku');
quoteElement.innerText = getRandomHaiku();
}
displayHaiku();
});

2
assets/js/jquery.min.js vendored Executable file

File diff suppressed because one or more lines are too long

746
assets/js/main.js Executable file
View File

@@ -0,0 +1,746 @@
/*
Lens by HTML5 UP
html5up.net | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
*/
var main = (function($) { var _ = {
/**
* Settings.
* @var {object}
*/
settings: {
// Preload all images.
preload: false,
// Slide duration (must match "duration.slide" in _vars.scss).
slideDuration: 250,
// Layout duration (must match "duration.layout" in _vars.scss).
layoutDuration: 250,
// Thumbnails per "row" (must match "misc.thumbnails-per-row" in _vars.scss).
thumbnailsPerRow: 3,
// Side of main wrapper (must match "misc.main-side" in _vars.scss).
mainSide: 'left'
},
/**
* Window.
* @var {jQuery}
*/
$window: null,
/**
* Body.
* @var {jQuery}
*/
$body: null,
/**
* Main wrapper.
* @var {jQuery}
*/
$main: null,
/**
* Thumbnails.
* @var {jQuery}
*/
$thumbnails: null,
/**
* Viewer.
* @var {jQuery}
*/
$viewer: null,
/**
* Toggle.
* @var {jQuery}
*/
$toggle: null,
/**
* Nav (next).
* @var {jQuery}
*/
$navNext: null,
/**
* Nav (previous).
* @var {jQuery}
*/
$navPrevious: null,
/**
* Slides.
* @var {array}
*/
slides: [],
/**
* Current slide index.
* @var {integer}
*/
current: null,
/**
* Lock state.
* @var {bool}
*/
locked: false,
/**
* Keyboard shortcuts.
* @var {object}
*/
keys: {
// Escape: Toggle main wrapper.
27: function() {
_.toggle();
},
// Up: Move up.
38: function() {
_.up();
},
// Down: Move down.
40: function() {
_.down();
},
// Space: Next.
32: function() {
_.next();
},
// Right Arrow: Next.
39: function() {
_.next();
},
// Left Arrow: Previous.
37: function() {
_.previous();
}
},
/**
* Initialize properties.
*/
initProperties: function() {
// Window, body.
_.$window = $(window);
_.$body = $('body');
// Thumbnails.
_.$thumbnails = $('#thumbnails');
// Viewer.
_.$viewer = $(
'<div id="viewer">' +
'<div class="inner">' +
'<div class="nav-next"></div>' +
'<div class="nav-previous"></div>' +
'<div class="toggle"></div>' +
'</div>' +
'</div>'
).appendTo(_.$body);
// Nav.
_.$navNext = _.$viewer.find('.nav-next');
_.$navPrevious = _.$viewer.find('.nav-previous');
// Main wrapper.
_.$main = $('#main');
// Toggle.
$('<div class="toggle"></div>')
.appendTo(_.$main);
_.$toggle = $('.toggle');
},
/**
* Initialize events.
*/
initEvents: function() {
// Window.
// Remove is-preload-* classes on load.
_.$window.on('load', function() {
_.$body.removeClass('is-preload-0');
window.setTimeout(function() {
_.$body.removeClass('is-preload-1');
}, 100);
window.setTimeout(function() {
_.$body.removeClass('is-preload-2');
}, 100 + Math.max(_.settings.layoutDuration - 150, 0));
});
// Disable animations/transitions on resize.
var resizeTimeout;
_.$window.on('resize', function() {
_.$body.addClass('is-preload-0');
window.clearTimeout(resizeTimeout);
resizeTimeout = window.setTimeout(function() {
_.$body.removeClass('is-preload-0');
}, 100);
});
// Viewer.
// Hide main wrapper on tap (<= medium only).
_.$viewer.on('touchend', function() {
if (breakpoints.active('<=medium'))
_.hide();
});
// Touch gestures.
_.$viewer
.on('touchstart', function(event) {
// Record start position.
_.$viewer.touchPosX = event.originalEvent.touches[0].pageX;
_.$viewer.touchPosY = event.originalEvent.touches[0].pageY;
})
.on('touchmove', function(event) {
// No start position recorded? Bail.
if (_.$viewer.touchPosX === null
|| _.$viewer.touchPosY === null)
return;
// Calculate stuff.
var diffX = _.$viewer.touchPosX - event.originalEvent.touches[0].pageX,
diffY = _.$viewer.touchPosY - event.originalEvent.touches[0].pageY;
boundary = 20,
delta = 50;
// Swipe left (next).
if ( (diffY < boundary && diffY > (-1 * boundary)) && (diffX > delta) )
_.next();
// Swipe right (previous).
else if ( (diffY < boundary && diffY > (-1 * boundary)) && (diffX < (-1 * delta)) )
_.previous();
// Overscroll fix.
var th = _.$viewer.outerHeight(),
ts = (_.$viewer.get(0).scrollHeight - _.$viewer.scrollTop());
if ((_.$viewer.scrollTop() <= 0 && diffY < 0)
|| (ts > (th - 2) && ts < (th + 2) && diffY > 0)) {
event.preventDefault();
event.stopPropagation();
}
});
// Main.
// Touch gestures.
_.$main
.on('touchstart', function(event) {
// Bail on xsmall.
if (breakpoints.active('<=xsmall'))
return;
// Record start position.
_.$main.touchPosX = event.originalEvent.touches[0].pageX;
_.$main.touchPosY = event.originalEvent.touches[0].pageY;
})
.on('touchmove', function(event) {
// Bail on xsmall.
if (breakpoints.active('<=xsmall'))
return;
// No start position recorded? Bail.
if (_.$main.touchPosX === null
|| _.$main.touchPosY === null)
return;
// Calculate stuff.
var diffX = _.$main.touchPosX - event.originalEvent.touches[0].pageX,
diffY = _.$main.touchPosY - event.originalEvent.touches[0].pageY;
boundary = 20,
delta = 50,
result = false;
// Swipe to close.
switch (_.settings.mainSide) {
case 'left':
result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX > delta);
break;
case 'right':
result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX < (-1 * delta));
break;
default:
break;
}
if (result)
_.hide();
// Overscroll fix.
var th = _.$main.outerHeight(),
ts = (_.$main.get(0).scrollHeight - _.$main.scrollTop());
if ((_.$main.scrollTop() <= 0 && diffY < 0)
|| (ts > (th - 2) && ts < (th + 2) && diffY > 0)) {
event.preventDefault();
event.stopPropagation();
}
});
// Toggle.
_.$toggle.on('click', function() {
_.toggle();
});
// Prevent event from bubbling up to "hide event on tap" event.
_.$toggle.on('touchend', function(event) {
event.stopPropagation();
});
// Nav.
_.$navNext.on('click', function() {
_.next();
});
_.$navPrevious.on('click', function() {
_.previous();
});
// Keyboard shortcuts.
// Ignore shortcuts within form elements.
_.$body.on('keydown', 'input,select,textarea', function(event) {
event.stopPropagation();
});
_.$window.on('keydown', function(event) {
// Ignore if xsmall is active.
if (breakpoints.active('<=xsmall'))
return;
// Check keycode.
if (event.keyCode in _.keys) {
// Stop other events.
event.stopPropagation();
event.preventDefault();
// Call shortcut.
(_.keys[event.keyCode])();
}
});
},
/**
* Initialize viewer.
*/
initViewer: function() {
// Bind thumbnail click event.
_.$thumbnails
.on('click', '.thumbnail', function(event) {
var $this = $(this);
// Stop other events.
event.preventDefault();
event.stopPropagation();
// Locked? Blur.
if (_.locked)
$this.blur();
// Switch to this thumbnail's slide.
_.switchTo($this.data('index'));
});
// Create slides from thumbnails.
_.$thumbnails.children()
.each(function() {
var $this = $(this),
$thumbnail = $this.children('.thumbnail'),
s;
// Slide object.
s = {
$parent: $this,
$slide: null,
$slideImage: null,
$slideCaption: null,
url: $thumbnail.attr('href'),
loaded: false
};
// Parent.
$this.attr('tabIndex', '-1');
// Slide.
// Create elements.
s.$slide = $('<div class="slide"><div class="caption"></div><div class="image"></div></div>');
// Image.
s.$slideImage = s.$slide.children('.image');
// Set background stuff.
s.$slideImage
.css('background-image', '')
.css('background-position', ($thumbnail.data('position') || 'center'));
// Caption.
s.$slideCaption = s.$slide.find('.caption');
// Move everything *except* the thumbnail itself to the caption.
$this.children().not($thumbnail)
.appendTo(s.$slideCaption);
// Preload?
if (_.settings.preload) {
// Force image to download.
var $img = $('<img src="' + s.url + '" />');
// Set slide's background image to it.
s.$slideImage
.css('background-image', 'url(' + s.url + ')');
// Mark slide as loaded.
s.$slide.addClass('loaded');
s.loaded = true;
}
// Add to slides array.
_.slides.push(s);
// Set thumbnail's index.
$thumbnail.data('index', _.slides.length - 1);
});
},
/**
* Initialize stuff.
*/
init: function() {
// Breakpoints.
breakpoints({
xlarge: [ '1281px', '1680px' ],
large: [ '981px', '1280px' ],
medium: [ '737px', '980px' ],
small: [ '481px', '736px' ],
xsmall: [ null, '480px' ]
});
// Everything else.
_.initProperties();
_.initViewer();
_.initEvents();
// Show first slide if xsmall isn't active.
breakpoints.on('>xsmall', function() {
if (_.current === null)
_.switchTo(0, true);
});
},
/**
* Switch to a specific slide.
* @param {integer} index Index.
*/
switchTo: function(index, noHide) {
// Already at index and xsmall isn't active? Bail.
if (_.current == index
&& !breakpoints.active('<=xsmall'))
return;
// Locked? Bail.
if (_.locked)
return;
// Lock.
_.locked = true;
// Hide main wrapper if medium is active.
if (!noHide
&& breakpoints.active('<=medium'))
_.hide();
// Get slides.
var oldSlide = (_.current !== null ? _.slides[_.current] : null),
newSlide = _.slides[index];
// Update current.
_.current = index;
// Deactivate old slide (if there is one).
if (oldSlide) {
// Thumbnail.
oldSlide.$parent
.removeClass('active');
// Slide.
oldSlide.$slide.removeClass('active');
}
// Activate new slide.
// Thumbnail.
newSlide.$parent
.addClass('active')
.focus();
// Slide.
var f = function() {
// Old slide exists? Detach it.
if (oldSlide)
oldSlide.$slide.detach();
// Attach new slide.
newSlide.$slide.appendTo(_.$viewer);
// New slide not yet loaded?
if (!newSlide.loaded) {
window.setTimeout(function() {
// Mark as loading.
newSlide.$slide.addClass('loading');
// Wait for it to load.
$('<img src="' + newSlide.url + '" />').on('load', function() {
//window.setTimeout(function() {
// Set background image.
newSlide.$slideImage
.css('background-image', 'url(' + newSlide.url + ')');
// Mark as loaded.
newSlide.loaded = true;
newSlide.$slide.removeClass('loading');
// Mark as active.
newSlide.$slide.addClass('active');
// Unlock.
window.setTimeout(function() {
_.locked = false;
}, 100);
//}, 1000);
});
}, 100);
}
// Otherwise ...
else {
window.setTimeout(function() {
// Mark as active.
newSlide.$slide.addClass('active');
// Unlock.
window.setTimeout(function() {
_.locked = false;
}, 100);
}, 100);
}
};
// No old slide? Switch immediately.
if (!oldSlide)
(f)();
// Otherwise, wait for old slide to disappear first.
else
window.setTimeout(f, _.settings.slideDuration);
},
/**
* Switches to the next slide.
*/
next: function() {
// Calculate new index.
var i, c = _.current, l = _.slides.length;
if (c >= l - 1)
i = 0;
else
i = c + 1;
// Switch.
_.switchTo(i);
},
/**
* Switches to the previous slide.
*/
previous: function() {
// Calculate new index.
var i, c = _.current, l = _.slides.length;
if (c <= 0)
i = l - 1;
else
i = c - 1;
// Switch.
_.switchTo(i);
},
/**
* Switches to slide "above" current.
*/
up: function() {
// Fullscreen? Bail.
if (_.$body.hasClass('fullscreen'))
return;
// Calculate new index.
var i, c = _.current, l = _.slides.length, tpr = _.settings.thumbnailsPerRow;
if (c <= (tpr - 1))
i = l - (tpr - 1 - c) - 1;
else
i = c - tpr;
// Switch.
_.switchTo(i);
},
/**
* Switches to slide "below" current.
*/
down: function() {
// Fullscreen? Bail.
if (_.$body.hasClass('fullscreen'))
return;
// Calculate new index.
var i, c = _.current, l = _.slides.length, tpr = _.settings.thumbnailsPerRow;
if (c >= l - tpr)
i = c - l + tpr;
else
i = c + tpr;
// Switch.
_.switchTo(i);
},
/**
* Shows the main wrapper.
*/
show: function() {
// Already visible? Bail.
if (!_.$body.hasClass('fullscreen'))
return;
// Show main wrapper.
_.$body.removeClass('fullscreen');
// Focus.
_.$main.focus();
},
/**
* Hides the main wrapper.
*/
hide: function() {
// Already hidden? Bail.
if (_.$body.hasClass('fullscreen'))
return;
// Hide main wrapper.
_.$body.addClass('fullscreen');
// Blur.
_.$main.blur();
},
/**
* Toggles main wrapper.
*/
toggle: function() {
if (_.$body.hasClass('fullscreen'))
_.show();
else
_.hide();
},
}; return _; })(jQuery); main.init();