Many updates
parent
a02b607bc6
commit
87754c8e06
@ -1,16 +0,0 @@
|
||||
@page "/counter"
|
||||
|
||||
<h1>Counter</h1>
|
||||
|
||||
<p>Current count: @currentCount</p>
|
||||
|
||||
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
|
||||
|
||||
@code {
|
||||
private int currentCount = 0;
|
||||
|
||||
private void IncrementCount()
|
||||
{
|
||||
currentCount++;
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
@page "/dmesg"
|
||||
|
||||
<h3>Dmesg</h3>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
@page "/fetchdata"
|
||||
|
||||
@using Seenginx.Data
|
||||
@inject WeatherForecastService ForecastService
|
||||
|
||||
<h1>Weather forecast</h1>
|
||||
|
||||
<p>This component demonstrates fetching data from a service.</p>
|
||||
|
||||
@if (forecasts == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Temp. (C)</th>
|
||||
<th>Temp. (F)</th>
|
||||
<th>Summary</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var forecast in forecasts)
|
||||
{
|
||||
<tr>
|
||||
<td>@forecast.Date.ToShortDateString()</td>
|
||||
<td>@forecast.TemperatureC</td>
|
||||
<td>@forecast.TemperatureF</td>
|
||||
<td>@forecast.Summary</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
|
||||
@code {
|
||||
private WeatherForecast[] forecasts;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
@page "/nginx"
|
||||
|
||||
<h3>Nginx</h3>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
@page "/systemd"
|
||||
|
||||
<h3>SystemD</h3>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
@ -0,0 +1,182 @@
|
||||
body {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
:root {
|
||||
--leftPanel: 150px;
|
||||
--negativeLeftPanel: -150px;
|
||||
--mobileLeftPanel: 150px;
|
||||
--mobileNegativeLeftPanel: -150px;
|
||||
}
|
||||
|
||||
.pure-img-responsive {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
Add transition to containers so they can push in and out.
|
||||
*/
|
||||
#layout,
|
||||
#menu,
|
||||
.menu-link {
|
||||
-webkit-transition: all 0.2s ease-out;
|
||||
-moz-transition: all 0.2s ease-out;
|
||||
-ms-transition: all 0.2s ease-out;
|
||||
-o-transition: all 0.2s ease-out;
|
||||
transition: all 0.2s ease-out;
|
||||
}
|
||||
|
||||
/*
|
||||
This is the parent `<div>` that contains the menu and the content area.
|
||||
*/
|
||||
#layout {
|
||||
position: relative;
|
||||
left: 0;
|
||||
padding-left: 0;
|
||||
|
||||
&.active {
|
||||
|
||||
& .menu-link {
|
||||
left: var(--leftPanel);
|
||||
}
|
||||
|
||||
& #menu {
|
||||
left: var(--leftPanel);
|
||||
width: var(--leftPanel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
The `#menu` `<div>` is the parent `<div>` that contains the `.pure-menu` that
|
||||
appears on the left side of the page.
|
||||
*/
|
||||
|
||||
#menu {
|
||||
margin-left: var(--negativeLeftPanel); /* "#menu" width */
|
||||
width: var(--leftPanel);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000; /* so the menu or its navicon stays above all content */
|
||||
background: #191818;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
//All anchors inside the menu should be styled like this.
|
||||
& a {
|
||||
color: #999;
|
||||
border: none;
|
||||
padding: 0.6em 0 0.6em 0.6em;
|
||||
}
|
||||
//Remove all background/borders, since we are applying them to #menu.
|
||||
& .pure-menu,
|
||||
& .pure-menu ul {
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
//Add that light border to separate items into groups.
|
||||
& .pure-menu ul,
|
||||
& .pure-menu .menu-item-divided {
|
||||
border-top: 1px solid #333;
|
||||
}
|
||||
//Change color of the anchor links on hover/focus.
|
||||
& .pure-menu li a:hover,
|
||||
& .pure-menu li a:focus {
|
||||
background: #333;
|
||||
}
|
||||
//This styles the selected menu item `<li>`.
|
||||
& .pure-menu-selected,
|
||||
& .pure-menu-heading {
|
||||
background: #1f8dd6;
|
||||
}
|
||||
//This styles a link within a selected menu item `<li>`.
|
||||
& .pure-menu-selected a {
|
||||
color: #fff;
|
||||
}
|
||||
//This styles the menu heading.
|
||||
& .pure-menu-heading {
|
||||
font-size: 110%;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* -- Dynamic Button For Responsive Menu -------------------------------------*/
|
||||
|
||||
/*
|
||||
The button to open/close the Menu is custom-made and not part of Pure. Here's
|
||||
how it works:
|
||||
*/
|
||||
|
||||
/*
|
||||
`.menu-link` represents the responsive menu toggle that shows/hides on
|
||||
small screens.
|
||||
*/
|
||||
.menu-link {
|
||||
position: fixed;
|
||||
display: block; /* show this only on small screens */
|
||||
top: 0;
|
||||
left: 0; /* "#menu width" */
|
||||
background: #000;
|
||||
background: rgba(0,0,0,0.7);
|
||||
font-size: 16px; /* change this value to increase/decrease button size */
|
||||
z-index: 10;
|
||||
width: min-content;
|
||||
height: auto;
|
||||
padding: 14px;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: #000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -- Responsive Styles (Media Queries) ------------------------------------- */
|
||||
|
||||
/*
|
||||
Hides the menu at `48em`, but modify this based on your app's needs.
|
||||
*/
|
||||
@media (min-width: 48em) {
|
||||
|
||||
.header,
|
||||
.content {
|
||||
padding-left: 2em;
|
||||
padding-right: 2em;
|
||||
}
|
||||
|
||||
#layout {
|
||||
padding-left: var(--leftPanel); /* left col width "#menu" */
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#menu {
|
||||
left: var(--leftPanel);
|
||||
}
|
||||
|
||||
.menu-link {
|
||||
position: fixed;
|
||||
left: var(--leftPanel);
|
||||
display: none;
|
||||
}
|
||||
|
||||
#layout.active .menu-link {
|
||||
left: var(--leftPanel);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 48em) {
|
||||
/* Only apply this when the window is small. Otherwise, the following
|
||||
case results in extra padding on the left:
|
||||
* Make the window small.
|
||||
* Tap the menu to trigger the active state.
|
||||
* Make the window large again.
|
||||
*/
|
||||
#layout.active {
|
||||
position: relative;
|
||||
left: var(--leftPanel);
|
||||
}
|
||||
}
|
@ -1,15 +1,14 @@
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<div class="sidebar">
|
||||
<NavMenu />
|
||||
</div>
|
||||
<div id="layout" class="@MenuActiveClass">
|
||||
|
||||
<div class="main">
|
||||
<div class="top-row px-4">
|
||||
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
|
||||
</div>
|
||||
<NavMenu @bind-MenuActiveClass="MenuActiveClass" />
|
||||
|
||||
<div class="content px-4">
|
||||
@Body
|
||||
</div>
|
||||
<div id="main">
|
||||
@Body
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code{
|
||||
public string MenuActiveClass { get; set; } = null;
|
||||
}
|
@ -1,37 +1,36 @@
|
||||
<div class="top-row pl-4 navbar navbar-dark">
|
||||
<a class="navbar-brand" href="">Seenginx</a>
|
||||
<button class="navbar-toggler" @onclick="ToggleNavMenu">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
@inherits NavMenuBase
|
||||
|
||||
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
|
||||
<span class="oi oi-home" aria-hidden="true"></span> Home
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="counter">
|
||||
<span class="oi oi-plus" aria-hidden="true"></span> Counter
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="fetchdata">
|
||||
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
|
||||
</NavLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<a href="#menu" id="menuLink" class="menu-link @MenuActiveClass" @onclick="ToggleMenu">
|
||||
<span class="oi" data-glyph="menu"></span>
|
||||
</a>
|
||||
|
||||
@code {
|
||||
private bool collapseNavMenu = true;
|
||||
<div id="menu" class="@MenuActiveClass">
|
||||
<div class="pure-menu">
|
||||
<NavLink class="pure-menu-heading" href="/" Match="NavLinkMatch.All">
|
||||
<span class="oi" data-glyph="bolt"></span>
|
||||
<span class="isHiddenMobile">Seenginx</span>
|
||||
</NavLink>
|
||||
|
||||
private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;
|
||||
<ul class="pure-menu-list">
|
||||
<li class="pure-menu-item @ActiveNav.GetValueOrDefault("nginx")">
|
||||
<NavLink href="/nginx" class="pure-menu-link" @onclick="@(e => SelectMenuItem("nginx"))">
|
||||
<span class="oi" data-glyph="code"></span>
|
||||
<span class="isHiddenMobile">NGINX</span>
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="pure-menu-item @ActiveNav.GetValueOrDefault("systemd")">
|
||||
<NavLink href="/systemd" class="pure-menu-link" @onclick="@(e => SelectMenuItem("systemd"))">
|
||||
<span class="oi" data-glyph="cog"></span>
|
||||
<span class="isHiddenMobile">SystemD</span>
|
||||
</NavLink>
|
||||
</li>
|
||||
|
||||
private void ToggleNavMenu()
|
||||
{
|
||||
collapseNavMenu = !collapseNavMenu;
|
||||
}
|
||||
}
|
||||
<li class="pure-menu-item @ActiveNav.GetValueOrDefault("dmesg")">
|
||||
<NavLink href="/dmesg" class="pure-menu-link" @onclick="@(e => SelectMenuItem("dmesg"))">
|
||||
<span class="oi" data-glyph="dashboard"></span>
|
||||
<span class="isHiddenMobile">Dmesg</span>
|
||||
</NavLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,63 @@
|
||||
{
|
||||
"compilers": {
|
||||
"less": {
|
||||
"autoPrefix": "",
|
||||
"cssComb": "none",
|
||||
"ieCompat": true,
|
||||
"strictMath": false,
|
||||
"strictUnits": false,
|
||||
"relativeUrls": true,
|
||||
"rootPath": "",
|
||||
"sourceMapRoot": "",
|
||||
"sourceMapBasePath": "",
|
||||
"sourceMap": false
|
||||
},
|
||||
"sass": {
|
||||
"autoPrefix": "",
|
||||
"includePath": "",
|
||||
"indentType": "space",
|
||||
"indentWidth": 2,
|
||||
"outputStyle": "nested",
|
||||
"Precision": 5,
|
||||
"relativeUrls": true,
|
||||
"sourceMapRoot": "",
|
||||
"lineFeed": "",
|
||||
"sourceMap": false
|
||||
},
|
||||
"stylus": {
|
||||
"sourceMap": false
|
||||
},
|
||||
"babel": {
|
||||
"sourceMap": false
|
||||
},
|
||||
"coffeescript": {
|
||||
"bare": false,
|
||||
"runtimeMode": "node",
|
||||
"sourceMap": false
|
||||
},
|
||||
"handlebars": {
|
||||
"root": "",
|
||||
"noBOM": false,
|
||||
"name": "",
|
||||
"namespace": "",
|
||||
"knownHelpersOnly": false,
|
||||
"forcePartial": false,
|
||||
"knownHelpers": [],
|
||||
"commonjs": "",
|
||||
"amd": false,
|
||||
"sourceMap": false
|
||||
}
|
||||
},
|
||||
"minifiers": {
|
||||
"css": {
|
||||
"enabled": true,
|
||||
"termSemicolons": true,
|
||||
"gzip": false
|
||||
},
|
||||
"javascript": {
|
||||
"enabled": true,
|
||||
"termSemicolons": true,
|
||||
"gzip": false
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
body {
|
||||
box-sizing: border-box
|
||||
}
|
||||
|
||||
*, ::before, ::after {
|
||||
box-sizing: inherit
|
||||
}
|
@ -0,0 +1,540 @@
|
||||
/*!
|
||||
* CSS Modal
|
||||
* http://drublic.github.com/css-modal
|
||||
*
|
||||
* @author Hans Christian Reinl - @drublic
|
||||
*/
|
||||
|
||||
(function (global, $) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
* Storage for functions and attributes
|
||||
*/
|
||||
var modal = {
|
||||
|
||||
activeElement: undefined, // Store for currently active element
|
||||
lastActive: undefined, // Store for last active elemet
|
||||
stackedElements: [], // Store for stacked elements
|
||||
|
||||
// All elements that can get focus, can be tabbed in a modal
|
||||
tabbableElements: 'a[href], area[href], input:not([disabled]),' +
|
||||
'select:not([disabled]), textarea:not([disabled]),' +
|
||||
'button:not([disabled]), iframe, object, embed, *[tabindex],' +
|
||||
'*[contenteditable]',
|
||||
|
||||
/*
|
||||
* Polyfill addEventListener for IE8 (only very basic)
|
||||
* @param event {string} event type
|
||||
* @param element {Node} node to fire event on
|
||||
* @param callback {function} gets fired if event is triggered
|
||||
*/
|
||||
on: function (event, elements, callback) {
|
||||
var i = 0;
|
||||
|
||||
if (typeof event !== 'string') {
|
||||
throw new Error('Type error: `event` has to be a string');
|
||||
}
|
||||
|
||||
if (typeof callback !== 'function') {
|
||||
throw new Error('Type error: `callback` has to be a function');
|
||||
}
|
||||
|
||||
if (!elements) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make elements an array and attach event listeners
|
||||
if (!elements.length) {
|
||||
elements = [elements];
|
||||
}
|
||||
|
||||
for (; i < elements.length; i++) {
|
||||
|
||||
// If jQuery is supported
|
||||
if ($) {
|
||||
$(elements[i]).on(event, callback);
|
||||
|
||||
// Default way to support events
|
||||
} else if ('addEventListener' in elements[i]) {
|
||||
elements[i].addEventListener(event, callback, false);
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Convenience function to trigger event
|
||||
* @param event {string} event type
|
||||
* @param modal {string} id of modal that the event is triggered on
|
||||
*/
|
||||
trigger: function (event, modal) {
|
||||
var eventTrigger;
|
||||
var eventParams = {
|
||||
detail: {
|
||||
'modal': modal
|
||||
}
|
||||
};
|
||||
|
||||
// Use jQuery to fire the event if it is included
|
||||
if ($) {
|
||||
$(document).trigger(event, eventParams);
|
||||
|
||||
// Use createEvent if supported (that's mostly the case)
|
||||
} else if (document.createEvent) {
|
||||
eventTrigger = document.createEvent('CustomEvent');
|
||||
|
||||
eventTrigger.initCustomEvent(event, false, false, {
|
||||
'modal': modal
|
||||
});
|
||||
|
||||
document.dispatchEvent(eventTrigger);
|
||||
|
||||
// Use CustomEvents if supported
|
||||
} else {
|
||||
eventTrigger = new CustomEvent(event, eventParams);
|
||||
|
||||
document.dispatchEvent(eventTrigger);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Convenience function to add a class to an element
|
||||
* @param element {Node} element to add class to
|
||||
* @param className {string}
|
||||
*/
|
||||
addClass: function (element, className) {
|
||||
if (element && !element.className.match(className)) {
|
||||
element.className += ' ' + className;
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Convenience function to remove a class from an element
|
||||
* @param element {Node} element to remove class off
|
||||
* @param className {string}
|
||||
*/
|
||||
removeClass: function (element, className) {
|
||||
element.className = element.className.replace(className, '').replace(' ', ' ');
|
||||
},
|
||||
|
||||
/**
|
||||
* Convenience function to check if an element has a class
|
||||
* @param {Node} element Element to check classname on
|
||||
* @param {string} className Class name to check for
|
||||
* @return {Boolean} true, if class is available on modal
|
||||
*/
|
||||
hasClass: function (element, className) {
|
||||
return !!element.className.match(className);
|
||||
},
|
||||
|
||||
/*
|
||||
* Focus modal
|
||||
*/
|
||||
setFocus: function () {
|
||||
if (modal.activeElement) {
|
||||
|
||||
// Set element with last focus
|
||||
modal.lastActive = document.activeElement;
|
||||
|
||||
// New focussing
|
||||
modal.activeElement.focus();
|
||||
|
||||
// Add handler to keep the focus
|
||||
modal.keepFocus(modal.activeElement);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Unfocus
|
||||
*/
|
||||
removeFocus: function () {
|
||||
if (modal.lastActive) {
|
||||
modal.lastActive.focus();
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Keep focus inside the modal
|
||||
* @param element {node} element to keep focus in
|
||||
*/
|
||||
keepFocus: function (element) {
|
||||
var allTabbableElements = [];
|
||||
|
||||
// Don't keep the focus if the browser is unable to support
|
||||
// CSS3 selectors
|
||||
try {
|
||||
allTabbableElements = element.querySelectorAll(modal.tabbableElements);
|
||||
} catch (ex) {
|
||||
return;
|
||||
}
|
||||
|
||||
var firstTabbableElement = modal.getFirstElementVisible(allTabbableElements);
|
||||
var lastTabbableElement = modal.getLastElementVisible(allTabbableElements);
|
||||
|
||||
var focusHandler = function (event) {
|
||||
var keyCode = event.which || event.keyCode;
|
||||
|
||||
// TAB pressed
|
||||
if (keyCode !== 9) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Polyfill to prevent the default behavior of events
|
||||
event.preventDefault = event.preventDefault || function () {
|
||||
event.returnValue = false;
|
||||
};
|
||||
|
||||
// Move focus to first element that can be tabbed if Shift isn't used
|
||||
if (event.target === lastTabbableElement && !event.shiftKey) {
|
||||
event.preventDefault();
|
||||
firstTabbableElement.focus();
|
||||
|
||||
// Move focus to last element that can be tabbed if Shift is used
|
||||
} else if (event.target === firstTabbableElement && event.shiftKey) {
|
||||
event.preventDefault();
|
||||
lastTabbableElement.focus();
|
||||
}
|
||||
};
|
||||
|
||||
modal.on('keydown', element, focusHandler);
|
||||
},
|
||||
|
||||
/*
|
||||
* Return the first visible element of a nodeList
|
||||
*
|
||||
* @param nodeList The nodelist to parse
|
||||
* @return {Node|null} Returns a specific node or null if no element found
|
||||
*/
|
||||
getFirstElementVisible: function (nodeList) {
|
||||
var nodeListLength = nodeList.length;
|
||||
|
||||
// If the first item is not visible
|
||||
if (!modal.isElementVisible(nodeList[0])) {
|
||||
for (var i = 1; i < nodeListLength - 1; i++) {
|
||||
|
||||
// Iterate elements in the NodeList, return the first visible
|
||||
if (modal.isElementVisible(nodeList[i])) {
|
||||
return nodeList[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nodeList[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/*
|
||||
* Return the last visible element of a nodeList
|
||||
*
|
||||
* @param nodeList The nodelist to parse
|
||||
* @return {Node|null} Returns a specific node or null if no element found
|
||||
*/
|
||||
getLastElementVisible: function (nodeList) {
|
||||
var nodeListLength = nodeList.length;
|
||||
var lastTabbableElement = nodeList[nodeListLength - 1];
|
||||
|
||||
// If the last item is not visible
|
||||
if (!modal.isElementVisible(lastTabbableElement)) {
|
||||
for (var i = nodeListLength - 1; i >= 0; i--) {
|
||||
|
||||
// Iterate elements in the NodeList, return the first visible
|
||||
if (modal.isElementVisible(nodeList[i])) {
|
||||
return nodeList[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return lastTabbableElement;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/*
|
||||
* Convenience function to check if an element is visible
|
||||
*
|
||||
* Test idea taken from jQuery 1.3.2 source code
|
||||
*
|
||||
* @param element {Node} element to test
|
||||
* @return {boolean} is the element visible or not
|
||||
*/
|
||||
isElementVisible: function (element) {
|
||||
return !(element.offsetWidth === 0 && element.offsetHeight === 0);
|
||||
},
|
||||
|
||||
/*
|
||||
* Mark modal as active
|
||||
* @param element {Node} element to set active
|
||||
*/
|
||||
setActive: function (element) {
|
||||
modal.addClass(element, 'is-active');
|
||||
modal.activeElement = element;
|
||||
|
||||
// Update aria-hidden
|
||||
modal.activeElement.setAttribute('aria-hidden', 'false');
|
||||
|
||||
// Set the focus to the modal
|
||||
modal.setFocus(element.id);
|
||||
|
||||
// Fire an event
|
||||
modal.trigger('cssmodal:show', modal.activeElement);
|
||||
},
|
||||
|
||||
/*
|
||||
* Unset previous active modal
|
||||
* @param isStacked {boolean} `true` if element is stacked above another
|
||||
* @param shouldNotBeStacked {boolean} `true` if next element should be stacked
|
||||
*/
|
||||
unsetActive: function (isStacked, shouldNotBeStacked) {
|
||||
modal.removeClass(document.documentElement, 'has-overlay');
|
||||
|
||||
if (modal.activeElement) {
|
||||
modal.removeClass(modal.activeElement, 'is-active');
|
||||
|
||||
// Fire an event
|
||||
modal.trigger('cssmodal:hide', modal.activeElement);
|
||||
|
||||
// Update aria-hidden
|
||||
modal.activeElement.setAttribute('aria-hidden', 'true');
|
||||
|
||||
// Unfocus
|
||||
modal.removeFocus();
|
||||
|
||||
// Make modal stacked if needed
|
||||
if (isStacked && !shouldNotBeStacked) {
|
||||
modal.stackModal(modal.activeElement);
|
||||
}
|
||||
|
||||
// If there are any stacked elements
|
||||
if (!isStacked && modal.stackedElements.length > 0) {
|
||||
modal.unstackModal();
|
||||
}
|
||||
|
||||
// Reset active element
|
||||
modal.activeElement = null;
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Stackable modal
|
||||
* @param stackableModal {node} element to be stacked
|
||||
*/
|
||||
stackModal: function (stackableModal) {
|
||||
modal.addClass(stackableModal, 'is-stacked');
|
||||
|
||||
// Set modal as stacked
|
||||
modal.stackedElements.push(modal.activeElement);
|
||||
},
|
||||
|
||||
/*
|
||||
* Reactivate stacked modal
|
||||
*/
|
||||
unstackModal: function () {
|
||||
var stackedCount = modal.stackedElements.length;
|
||||
var lastStacked = modal.stackedElements[stackedCount - 1];
|
||||
|
||||
modal.removeClass(lastStacked, 'is-stacked');
|
||||
|
||||
// Set hash to modal, activates the modal automatically
|
||||
global.location.hash = lastStacked.id;
|
||||
|
||||
// Remove modal from stackedElements array
|
||||
modal.stackedElements.splice(stackedCount - 1, 1);
|
||||
},
|
||||
|
||||
/*
|
||||
* When displaying modal, prevent background from scrolling
|
||||
* @param {Object} event The incoming hashChange event
|
||||
* @return {void}
|
||||
*/
|
||||
mainHandler: function (event, noHash) {
|
||||
var hash = global.location.hash.replace('#', '');
|
||||
var index = 0;
|
||||
var tmp = [];
|
||||
var modalElement;
|
||||
var modalChild;
|
||||
|
||||
// JS-only: no hash present
|
||||
if (noHash) {
|
||||
hash = event.currentTarget.getAttribute('href').replace('#', '');
|
||||
}
|
||||
|
||||
modalElement = document.getElementById(hash);
|
||||
|
||||
// Check if the hash contains an index
|
||||
if (hash.indexOf('/') !== -1) {
|
||||
tmp = hash.split('/');
|
||||
index = tmp.pop();
|
||||
hash = tmp.join('/');
|
||||
|
||||
// Remove the index from the hash...
|
||||
modalElement = document.getElementById(hash);
|
||||
|
||||
// ... and store the index as a number on the element to
|
||||
// make it accessible for plugins
|
||||
if (!modalElement) {
|
||||
throw new Error('ReferenceError: element "' + hash + '" does not exist!');
|
||||
}
|
||||
|
||||
modalElement.index = (1 * index);
|
||||
}
|
||||
|
||||
// If the hash element exists
|
||||
if (modalElement) {
|
||||
|
||||
// Polyfill to prevent the default behavior of events
|
||||
try {
|
||||
event.preventDefault();
|
||||
} catch (ex) {
|
||||
event.returnValue = false;
|
||||
}
|
||||
|
||||
// Get first element in selected element
|
||||
modalChild = modalElement.children[0];
|
||||
|
||||
// When we deal with a modal and body-class `has-overlay` is not set
|
||||
if (modalChild && modalChild.className.match(/modal-inner/)) {
|
||||
|
||||
// Make previous element stackable if it is not the same modal
|
||||
modal.unsetActive(
|
||||
!modal.hasClass(modalElement, 'is-active'),
|
||||
(modalElement.getAttribute('data-stackable') === 'false')
|
||||
);
|
||||
|
||||
// Set an html class to prevent scrolling
|
||||
modal.addClass(document.documentElement, 'has-overlay');
|
||||
|
||||
// Set scroll position for modal
|
||||
modal._currentScrollPositionY = global.scrollY;
|
||||
modal._currentScrollPositionX = global.scrollX;
|
||||
|
||||
// Mark the active element
|
||||
modal.setActive(modalElement);
|
||||
modal.activeElement._noHash = noHash;
|
||||
}
|
||||
} else {
|
||||
|
||||
// If activeElement is already defined, delete it
|
||||
modal.unsetActive();
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Inject iframes
|
||||
*/
|
||||
injectIframes: function () {
|
||||
var iframes = document.querySelectorAll('[data-iframe-src]');
|
||||
var iframe;
|
||||
var i = 0;
|
||||
|
||||
for (; i < iframes.length; i++) {
|
||||
iframe = document.createElement('iframe');
|
||||
|
||||
iframe.src = iframes[i].getAttribute('data-iframe-src');
|
||||
iframe.setAttribute('webkitallowfullscreen', true);
|
||||
iframe.setAttribute('mozallowfullscreen', true);
|
||||
iframe.setAttribute('allowfullscreen', true);
|
||||
|
||||
iframes[i].appendChild(iframe);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Listen to all relevant events
|
||||
* @return {void}
|
||||
*/
|
||||
init: function () {
|
||||
|
||||
/*
|
||||
* Hide overlay when ESC is pressed
|
||||
*/
|
||||
this.on('keyup', document, function (event) {
|
||||
var hash = global.location.hash.replace('#', '');
|
||||
|
||||
// If key ESC is pressed
|
||||
if (event.keyCode === 27) {
|
||||
if (modal.activeElement && hash === modal.activeElement.id) {
|
||||
global.location.hash = '!';
|
||||
} else {
|
||||
modal.unsetActive();
|
||||
}
|
||||
|
||||
if (modal.lastActive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unfocus
|
||||
modal.removeFocus();
|
||||
}
|
||||
}, false);
|
||||
|
||||
/**
|
||||
* Trigger main handler on click if hash is deactivated
|
||||
*/
|
||||
this.on('click', document.querySelectorAll('[data-cssmodal-nohash]'), function (event) {
|
||||
modal.mainHandler(event, true);
|
||||
});
|
||||
|
||||
// And close modal without hash
|
||||
this.on('click', document.querySelectorAll('.modal-close'), function (event) {
|
||||
if (modal.activeElement._noHash){
|
||||
modal.mainHandler(event, true);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Trigger main handler on load and hashchange
|
||||
*/
|
||||
this.on('hashchange', global, modal.mainHandler);
|
||||
this.on('load', global, modal.mainHandler);
|
||||
|
||||
/**
|
||||
* Prevent scrolling when modal is active
|
||||
* @return {void}
|
||||
*/
|
||||
global.onscroll = global.onmousewheel = function () {
|
||||
if (document.documentElement.className.match(/has-overlay/)) {
|
||||
global.scrollTo(modal._currentScrollPositionX, modal._currentScrollPositionY);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject iframes
|
||||
*/
|
||||
modal.injectIframes();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* AMD, module loader, global registration
|
||||
*/
|
||||
|
||||
// Expose modal for loaders that implement the Node module pattern.
|
||||
if (typeof module === 'object' && module && typeof module.exports === 'object') {
|
||||
module.exports = modal;
|
||||
|
||||
// Register as an AMD module
|
||||
} else if (typeof define === 'function' && define.amd) {
|
||||
define('CSSModal', [], function () {
|
||||
|
||||
// We use jQuery if the browser doesn't support CustomEvents
|
||||
if (!global.CustomEvent && !$) {
|
||||
throw new Error('This browser doesn\'t support CustomEvent - please include jQuery.');
|
||||
}
|
||||
|
||||
modal.init();
|
||||
|
||||
return modal;
|
||||
});
|
||||
|
||||
// Export CSSModal into global space
|
||||
} else if (typeof global === 'object' && typeof global.document === 'object') {
|
||||
global.CSSModal = modal;
|
||||
modal.init();
|
||||
}
|
||||
|
||||
}(window, window.jQuery));
|
@ -0,0 +1,46 @@
|
||||
(function (window, document) {
|
||||
|
||||
var layout = document.getElementById('layout'),
|
||||
menu = document.getElementById('menu'),
|
||||
menuLink = document.getElementById('menuLink'),
|
||||
content = document.getElementById('main');
|
||||
|
||||
function toggleClass(element, className) {
|
||||
var classes = element.className.split(/\s+/),
|
||||
length = classes.length,
|
||||
i = 0;
|
||||
|
||||
for(; i < length; i++) {
|
||||
if (classes[i] === className) {
|
||||
classes.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// The className is not found
|
||||
if (length === classes.length) {
|
||||
classes.push(className);
|
||||
}
|
||||
|
||||
element.className = classes.join(' ');
|
||||
}
|
||||
|
||||
function toggleAll(e) {
|
||||
var active = 'active';
|
||||
|
||||
e.preventDefault();
|
||||
toggleClass(layout, active);
|
||||
toggleClass(menu, active);
|
||||
toggleClass(menuLink, active);
|
||||
}
|
||||
|
||||
menuLink.onclick = function (e) {
|
||||
toggleAll(e);
|
||||
};
|
||||
|
||||
content.onclick = function(e) {
|
||||
if (menu.className.indexOf('active') !== -1) {
|
||||
toggleAll(e);
|
||||
}
|
||||
};
|
||||
|
||||
}(this, this.document));
|
Loading…
Reference in New Issue