mirror of
https://github.com/viliusle/miniPaint.git
synced 2026-02-06 11:21:47 +00:00
Rewrite menu from scratch to support mobile screen sizes and keyboard controls
This commit is contained in:
parent
bfb85aa8e5
commit
a5b84b9d0f
@ -84,9 +84,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="mobile_menu">
|
||||
<button class="right_mobile_menu" id="mobile_menu_button" type="button"></button>
|
||||
<button class="right_mobile_menu" id="mobile_menu_button" type="button">
|
||||
<span class="sr_only">Toggle Menu</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="ddsmoothmenu" id="main_menu"></div>
|
||||
<nav aria-label="Main Menu" class="main_menu" id="main_menu"></nav>
|
||||
<div class="hidden" id="tmp"></div>
|
||||
<div id="popup"></div>
|
||||
</body>
|
||||
|
||||
347
src/css/menu.css
347
src/css/menu.css
@ -1,222 +1,193 @@
|
||||
.mobile_menu{
|
||||
display:none;
|
||||
position: absolute;
|
||||
width:100%;
|
||||
top: 0;
|
||||
:root {
|
||||
--menu-dropdown-background-color: #ffffff;
|
||||
--menu-dropdown-border-color: #5680C1;
|
||||
--menu-dropdown-text-color: #2d2b2b;
|
||||
--menu-dropdown-text-muted-color: #aaaaaa;
|
||||
--menu-dropdown-hover-background-color: #E4EBF8;
|
||||
--menu-dropdown-hover-text-color: #2d2d2d;
|
||||
--menu-dropdown-divider-color: #e5e5e5;
|
||||
}
|
||||
.left_mobile_menu, .right_mobile_menu{
|
||||
position:absolute;
|
||||
width:50px;
|
||||
height:50px;
|
||||
background: url("images/sprites.png") no-repeat 11px -86px;
|
||||
filter: invert(1);
|
||||
display:block;
|
||||
top:0;
|
||||
z-index:200;
|
||||
border:0;
|
||||
outline:0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.left_mobile_menu{left:0;}
|
||||
.right_mobile_menu{right:0;}
|
||||
|
||||
.ddsmoothmenu{
|
||||
position:fixed;
|
||||
top:0;
|
||||
left:0;
|
||||
width:100%;
|
||||
font:12px Arial,sans-serif;
|
||||
background: #2D2D2D;
|
||||
background: var(--background-color-menu);
|
||||
width: 100%;
|
||||
padding-left:10px;
|
||||
z-index:100;
|
||||
}
|
||||
.ddsmoothmenu ul{
|
||||
z-index:100;
|
||||
margin: 0;
|
||||
.sr_only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
height:30px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
.ddsmoothmenu ul li{
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
color: #2d2b2b;
|
||||
height:100%;
|
||||
|
||||
.main_menu {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
.ddsmoothmenu ul ul li a{
|
||||
width:100%;
|
||||
.main_menu > ul.menu_bar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 30px;
|
||||
padding-left: 10px;
|
||||
background: var(--background-color-menu);
|
||||
}
|
||||
.ddsmoothmenu .rightarrowclass{
|
||||
display:none !important;
|
||||
.main_menu > ul.menu_bar > li {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
.ddsmoothmenu ul li a{
|
||||
display: inline-block;
|
||||
color: #cccccc;
|
||||
.main_menu > ul.menu_bar > li > a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: var(--text-color-menu);
|
||||
text-decoration: none;
|
||||
text-align:center;
|
||||
padding: 7px 10px 8px 10px !important;
|
||||
padding: 0 10px;
|
||||
height: 100%;
|
||||
}
|
||||
.ddsmoothmenu ul ul li a{
|
||||
padding-right: 25px !important;
|
||||
.main_menu > ul.menu_bar > li > a::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
.ddsmoothmenu ul li a.selected{
|
||||
background-color: #FFFFFF !important;
|
||||
color: #2d2b2b;
|
||||
.main_menu > ul.menu_bar > li > a:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 -3px var(--menu-dropdown-background-color) inset;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li a.selected{
|
||||
background-color:#E4EBF8 !important;
|
||||
.main_menu > ul.menu_bar > li > a:hover {
|
||||
background: var(--menu-dropdown-hover-background-color);
|
||||
box-shadow: none;
|
||||
color: var(--menu-dropdown-hover-text-color);
|
||||
}
|
||||
.ddsmoothmenu ul li a:hover{
|
||||
background-color: #E4EBF8;
|
||||
color: #2D2D2D;
|
||||
.main_menu > ul.menu_bar > li > a[aria-expanded="true"] {
|
||||
background: var(--menu-dropdown-background-color);
|
||||
box-shadow: none;
|
||||
color: var(--menu-dropdown-text-color);
|
||||
}
|
||||
.ddsmoothmenu .hide_ul{
|
||||
position: absolute;
|
||||
left: -3000px;
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
border:1px solid #5680C1;
|
||||
border-top:0px;
|
||||
.main_menu > ul.menu_bar > li > a > * {
|
||||
pointer-events: none;
|
||||
}
|
||||
.ddsmoothmenu ul li ul{
|
||||
position: absolute;
|
||||
left: -3000px;
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
border:1px solid #5680C1;
|
||||
border-top:0px;
|
||||
margin-left: -1px;
|
||||
height:auto;
|
||||
min-width:140px;
|
||||
width:auto !important;
|
||||
top:30px !important;
|
||||
|
||||
.main_menu > ul.menu_dropdown {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
max-height: calc(100vh - 60px);
|
||||
min-width: 150px;
|
||||
box-shadow: 0 0 0 1px var(--menu-dropdown-border-color);
|
||||
background: var(--menu-dropdown-background-color);
|
||||
}
|
||||
.ddsmoothmenu ul li ul.expanded{
|
||||
overflow: visible;
|
||||
max-height: none;
|
||||
.main_menu > ul.menu_dropdown > li {
|
||||
padding: 0;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li{
|
||||
display: list-item;
|
||||
background: #ffffff;
|
||||
float: none;
|
||||
height:auto;
|
||||
width:100%;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li a{
|
||||
text-align:left;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li ul{
|
||||
top: 0;
|
||||
border-top:1px solid #5680C1;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li a{
|
||||
padding-left: 5px;
|
||||
padding-right:5px;
|
||||
.main_menu > ul.menu_dropdown > li > hr {
|
||||
background: none;
|
||||
border: 1px solid var(--menu-dropdown-divider-color);
|
||||
border-bottom: none;
|
||||
margin: 0;
|
||||
color: #2D2D2D;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li ul{
|
||||
top:0 !important;
|
||||
.main_menu > ul.menu_dropdown > li > a {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
height: 30px;
|
||||
padding: 0 10px;
|
||||
font-size: 12px;
|
||||
line-height: 30px;
|
||||
text-decoration: none;
|
||||
color: var(--menu-dropdown-text-color);
|
||||
}
|
||||
.ddsmoothmenu .downarrowclass{
|
||||
.main_menu > ul.menu_dropdown > li > ::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > a:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px var(--menu-dropdown-hover-background-color) inset;
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > a:hover {
|
||||
background: var(--menu-dropdown-hover-background-color);
|
||||
box-shadow: none;
|
||||
color: var(--menu-dropdown-hover-text-color);
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > a[aria-expanded="true"] {
|
||||
background: var(--menu-dropdown-hover-background-color);
|
||||
box-shadow: none;
|
||||
color: var(--menu-dropdown-hover-text-color);
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > a[aria-haspopup="true"]::after {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 7px;
|
||||
}
|
||||
.ddsmoothmenu .ddshadow{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
background-color: #ccc;
|
||||
}
|
||||
.ddsmoothmenu .mid-line{
|
||||
background-color:#ff0000;
|
||||
border-top:1px solid #e5e5e5;
|
||||
font-size:0;
|
||||
padding:0 8px 0 8px;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li.more > a{
|
||||
position:relative;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li.more > a:before{
|
||||
position: absolute;
|
||||
content:">";
|
||||
content: ">";
|
||||
right: 9px;
|
||||
width: 5px;
|
||||
height: 14px;
|
||||
transform: scaleY(2);
|
||||
color: #808080;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li ul{
|
||||
left: calc(100% + 1px) !important;
|
||||
.main_menu > ul.menu_dropdown > li > a[aria-haspopup="true"] > .name {
|
||||
margin-right: 8px;
|
||||
}
|
||||
.ddsmoothmenu .dots::after{
|
||||
content: " ...";
|
||||
.main_menu > ul.menu_dropdown > li > a[target="_blank"]::after {
|
||||
content: "";
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-left: 5px;
|
||||
background: url(images/sprites.png) no-repeat -700px 0;
|
||||
opacity: 0.3;
|
||||
}
|
||||
.ddsmoothmenu a[data-key]:after{
|
||||
position: absolute;
|
||||
content: attr(data-key) " ";
|
||||
color: #aaa;
|
||||
font-size: 12px;
|
||||
margin-left: 8px;
|
||||
right:10px;
|
||||
.main_menu > ul.menu_dropdown > li > a > * {
|
||||
pointer-events: none;
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > a > .name {
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > a > .shortcut {
|
||||
flex-shrink: 1;
|
||||
color: var(--menu-dropdown-text-muted-color);
|
||||
}
|
||||
|
||||
@media screen and (max-width:700px){
|
||||
.mobile_menu{
|
||||
display:block;
|
||||
}
|
||||
.left_mobile_menu{
|
||||
display:none;
|
||||
}
|
||||
.ddsmoothmenu{
|
||||
height:50px;
|
||||
}
|
||||
.ddsmoothmenu ul{
|
||||
width: calc(100% - 50px);
|
||||
height:50px;
|
||||
}
|
||||
.ddsmoothmenu > ul > li > a{
|
||||
height:50px;
|
||||
padding-top: 15px !important;
|
||||
}
|
||||
.ddsmoothmenu ul li ul{
|
||||
top:50px !important;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li{
|
||||
height:auto;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li a{
|
||||
height:30px;
|
||||
}
|
||||
.mobile_menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
}
|
||||
@media screen and (max-width:550px){
|
||||
.ddsmoothmenu{
|
||||
padding-left:0;
|
||||
}
|
||||
.ddsmoothmenu ul{
|
||||
width: calc(100% - 50px);
|
||||
}
|
||||
.ddsmoothmenu > ul > li{
|
||||
width: calc(100% / 7);
|
||||
}
|
||||
.ddsmoothmenu > ul > li > a{
|
||||
width:100%;
|
||||
padding-left: 3px !important;
|
||||
padding-right: 3px !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
.left_mobile_menu{
|
||||
display:block;
|
||||
}
|
||||
.left_mobile_menu, .right_mobile_menu {
|
||||
position: absolute;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: url("images/sprites.png") no-repeat 11px -86px;
|
||||
filter: invert(1);
|
||||
display: block;
|
||||
top: 0;
|
||||
z-index: 200;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.left_mobile_menu { left:0; }
|
||||
.right_mobile_menu { right:0; }
|
||||
|
||||
@media screen and (max-width:700px) {
|
||||
.mobile_menu {
|
||||
display: block;
|
||||
}
|
||||
.left_mobile_menu {
|
||||
display: none;
|
||||
}
|
||||
.main_menu > ul.menu_bar {
|
||||
height: 50px;
|
||||
padding-left: 0;
|
||||
padding-right: 50px;
|
||||
}
|
||||
}
|
||||
@ -1,204 +1,630 @@
|
||||
var menu_template = `
|
||||
<ul>
|
||||
<li>
|
||||
<a class="trn" href="#">File</a>
|
||||
<ul>
|
||||
<li><a class="trn" data-target="file/new.new" href="#">New</a></li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li class="more">
|
||||
<a class="trn" href="#">Open</a>
|
||||
<ul>
|
||||
<li><a class="trn dots" data-target="file/open.open_file" data-key="Drag&Drop" href="#">Open File</a></li>
|
||||
<li><a class="trn dots" data-target="file/open.open_dir" href="#">Open Directory</a></li>
|
||||
<li><a class="trn dots" data-target="file/open.open_webcam" href="#">Open from Webcam</a></li>
|
||||
<li><a class="trn dots" data-target="file/open.open_url" href="#">Open URL</a></li>
|
||||
<li><a class="trn dots" data-target="file/open.open_data_url" href="#">Open Data URL</a></li>
|
||||
<li><a class="trn dots" data-target="file/open.open_template_test" href="#">Open test template</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="trn dots" data-target="file/search.search" href="#">Search images</a></li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a class="trn dots" data-target="file/save.save" data-key="S" href="#">Save as</a></li>
|
||||
<li><a class="trn dots" data-target="file/save.save_data_url" href="#">Save as data URL</a></li>
|
||||
<li><a class="trn dots" data-target="file/print.print" data-key="Ctrl-P" href="#">Print</a></li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a class="trn" data-target="file/quicksave.quicksave" data-key="F9" href="#">Quick save</a></li>
|
||||
<li><a class="trn" data-target="file/quickload.quickload" data-key="F10" href="#">Quick load</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a class="trn" href="#">Edit</a>
|
||||
<ul>
|
||||
<li><a class="trn" data-target="edit/undo.undo" href="#">Undo</a></li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a class="trn" data-target="edit/selection.delete" data-key="Del" href="#">Delete selection</a></li>
|
||||
<li><a class="trn" data-target="layer/new.new_selection" href="#">Copy selection</a></li>
|
||||
<li><a class="trn" data-target="edit/paste.paste" data-key="Ctrl+V" href="#">Paste</a></li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a class="trn" data-target="edit/selection.select_all" href="#">Select all</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a class="trn" href="#">Image</a>
|
||||
<ul>
|
||||
<li><a class="trn dots" data-target="image/information.information" href="#">Information</a></li>
|
||||
<li><a class="trn dots" data-target="image/size.size" href="#">Size</a></li>
|
||||
<li><a class="trn dots" data-target="image/trim.trim" data-key="T" href="#">Trim</a>
|
||||
<li class="more">
|
||||
<a class="trn" href="#">Zoom</a>
|
||||
<ul>
|
||||
<li><a class="trn" data-target="image/zoom.in" href="#">Zoom In</a></li>
|
||||
<li><a class="trn" data-target="image/zoom.out" href="#">Zoom Out</a></li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a class="trn" data-target="image/zoom.original" href="#">Original size</a></li>
|
||||
<li><a class="trn" data-target="image/zoom.auto" href="#">Fit window</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a class="trn dots" data-target="image/resize.resize" href="#">Resize</a></li>
|
||||
<li><a class="trn dots" data-target="image/rotate.rotate" href="#">Rotate</a></li>
|
||||
<li class="more">
|
||||
<a class="trn" href="#">Flip</a>
|
||||
<ul>
|
||||
<li><a class="trn" data-target="image/flip.vertical" href="#">Vertical</a></li>
|
||||
<li><a class="trn" data-target="image/flip.horizontal" href="#">Horizontal</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="trn dots" data-target="image/translate.translate" href="#">Translate</a></li>
|
||||
<li><a class="trn dots" data-target="image/opacity.opacity" href="#">Opacity</a></li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a class="trn dots" data-target="image/color_corrections.color_corrections" href="#">Color corrections</a></li>
|
||||
<li><a class="trn" data-target="image/auto_adjust.auto_adjust" href="#">Auto adjust colors</a></li>
|
||||
<li><a class="trn" data-target="image/decrease_colors.decrease_colors" href="#">Decrease color depth</a></li>
|
||||
<li><a class="trn dots" data-target="image/palette.palette" href="#">Color palette</a></li>
|
||||
<li><a class="trn dots" data-target="image/grid.grid" data-key="G" href="#">Grid</a></li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a class="trn dots" data-target="image/histogram.histogram" data-key="H" href="#">Histogram</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a class="trn" href="#">Layers</a>
|
||||
<ul>
|
||||
<li><a class="trn" data-target="layer/new.new" data-key="N" href="#">New</a></li>
|
||||
<li><a class="trn" data-target="layer/new.new_selection" href="#">New from selection</a></li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a class="trn" data-target="layer/duplicate.duplicate" href="#">Duplicate</a></li>
|
||||
<li><a class="trn" data-target="layer/visibility.toggle" href="#">Show / Hide</a></li>
|
||||
<li><a class="trn" data-target="layer/delete.delete" href="#">Delete</a></li>
|
||||
<li><a class="trn" data-target="layer/raster.raster" href="#">Convert to raster</a></li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li class="more">
|
||||
<a class="trn" href="#">Move</a>
|
||||
<ul>
|
||||
<li><a class="trn" data-target="layer/move.up" href="#">Up</a></li>
|
||||
<li><a class="trn" data-target="layer/move.down" href="#">Down</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="trn dots" data-target="layer/composition.composition" href="#">Composition</a></li>
|
||||
<li><a class="trn dots" data-target="layer/rename.rename" href="#">Rename</a></li>
|
||||
<li><a class="trn" data-target="layer/clear.clear" href="#">Clear</a></li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a class="trn" data-target="layer/differences.differences" href="#">Differences Down</a></li>
|
||||
<li><a class="trn" data-target="layer/merge.merge" href="#">Merge Down</a></li>
|
||||
<li><a class="trn" data-target="layer/flatten.flatten" href="#">Flatten Image</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a class="trn" href="#">Effects</a>
|
||||
<ul id="effects_list">
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li class="more">
|
||||
<a class="trn" href="#">CSS filters</a>
|
||||
<ul>
|
||||
<li><a class="trn dots" data-target="effects/blur.blur" href="#">Gaussian Blur</a>
|
||||
<li><a class="trn dots" data-target="effects/brightness.brightness" href="#">Brightness</a>
|
||||
<li><a class="trn dots" data-target="effects/contrast.contrast" href="#">Contrast</a>
|
||||
<li><a class="trn dots" data-target="effects/grayscale.grayscale" href="#">Grayscale</a>
|
||||
<li><a class="trn dots" data-target="effects/hue_rotate.hue_rotate" href="#">Hue Rotate</a>
|
||||
<li><a class="trn dots" data-target="effects/negative.negative" href="#">Negative</a>
|
||||
<li><a class="trn dots" data-target="effects/saturate.saturate" href="#">Saturate</a>
|
||||
<li><a class="trn dots" data-target="effects/sepia.sepia" href="#">Sepia</a>
|
||||
<li><a class="trn dots" data-target="effects/shadow.shadow" href="#">Shadow</a>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="trn dots" data-target="effects/black_and_white.black_and_white" href="#">Black and White</a>
|
||||
<li><a class="trn dots" data-target="effects/blueprint.blueprint" href="#">Blueprint</a>
|
||||
<li><a class="trn dots" data-target="effects/box_blur.box_blur" href="#">Box Blur</a>
|
||||
<li><a class="trn dots" data-target="effects/denoise.denoise" href="#">Denoise</a>
|
||||
<li><a class="trn dots" data-target="effects/dither.dither" href="#">Dither</a>
|
||||
<li><a class="trn dots" data-target="effects/dot_screen.dot_screen" href="#">Dot Screen</a>
|
||||
<li><a class="trn dots" data-target="effects/edge.edge" href="#">Edge</a>
|
||||
<li><a class="trn dots" data-target="effects/emboss.emboss" href="#">Emboss</a>
|
||||
<li><a class="trn dots" data-target="effects/enrich.enrich" href="#">Enrich</a>
|
||||
<li><a class="trn dots" data-target="effects/grains.grains" href="#">Grains</a>
|
||||
<li><a class="trn dots" data-target="effects/heatmap.heatmap" href="#">Heatmap</a>
|
||||
<li><a class="trn dots" data-target="effects/mosaic.mosaic" href="#">Mosaic</a>
|
||||
<li><a class="trn dots" data-target="effects/night_vision.night_vision" href="#">Night Vision</a>
|
||||
<li><a class="trn dots" data-target="effects/oil.oil" href="#">Oil</a>
|
||||
<li><a class="trn dots" data-target="effects/pencil.pencil" href="#">Pencil</a>
|
||||
<li><a class="trn dots" data-target="effects/sharpen.sharpen" href="#">Sharpen</a>
|
||||
<li><a class="trn dots" data-target="effects/solarize.solarize" href="#">Solarize</a>
|
||||
<li><a class="trn dots" data-target="effects/tilt_shift.tilt_shift" href="#">Tilt Shift</a>
|
||||
<li><a class="trn dots" data-target="effects/vignette.vignette" href="#">Vignette</a>
|
||||
<li><a class="trn dots" data-target="effects/vibrance.vibrance" href="#">Vibrance</a>
|
||||
<li><a class="trn dots" data-target="effects/vintage.vintage" href="#">Vintage</a>
|
||||
<li><a class="trn dots" data-target="effects/zoom_blur.zoom_blur" href="#">Zoom Blur</a>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a class="trn" href="#">Tools</a>
|
||||
<ul>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a class="trn dots" data-target="tools/borders.borders" href="#">Borders</a></li>
|
||||
<li><a class="trn" data-target="tools/sprites.sprites" href="#">Sprites</a></li>
|
||||
<li><a class="trn" data-target="tools/keypoints.keypoints" href="#">Key-points</a></li>
|
||||
<li><a class="trn dots" data-target="tools/content_fill.content_fill" href="#">Content fill</a></li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a class="trn dots" data-target="tools/color_to_alpha.color_to_alpha" href="#">Color to alpha</a></li>
|
||||
<li><a class="trn dots" data-target="tools/color_zoom.color_zoom" href="#">Color Zoom</a></li>
|
||||
<li><a class="trn dots" data-target="tools/replace_color.replace_color" href="#">Replace Color</a></li>
|
||||
<li><a class="trn dots" data-target="tools/restore_alpha.restore_alpha" href="#">Restore alpha</a></li>
|
||||
<li class="more">
|
||||
<a class="trn" href="#">External</a>
|
||||
<ul>
|
||||
<li><a class="trn external" target="_blank" href="https://tinypng.com">TINYPNG - compress PNG and JPEG</a>
|
||||
<li><a class="trn external" target="_blank" href="https://www.remove.bg">REMOVE.BG - remove Image Background</a>
|
||||
<li><a class="trn external" target="_blank" href="https://www.pngtosvg.com">PNGTOSVG - convert image to SVG</a>
|
||||
<li><a class="trn external" target="_blank" href="https://squoosh.app">SQUOOSH - compress and compare images</a>
|
||||
</ul>
|
||||
</li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a class="trn dots" data-target="tools/settings.settings" href="#">Settings</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a class="trn" href="#">Help</a>
|
||||
<ul>
|
||||
<li><a class="trn dots" data-target="help/shortcuts.shortcuts" href="#">Keyboard Shortcuts</a></li>
|
||||
<li><a class="trn external" target="_blank" href="https://github.com/viliusle/miniPaint/issues">Report issues</a></li>
|
||||
<li class="more">
|
||||
<a class="trn" href="#">Language</a>
|
||||
<ul>
|
||||
<li><a data-target="help/translate.translate.en" href="#">English</a>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a data-target="help/translate.translate.zh" href="#">简体中文)</a>
|
||||
<li><a data-target="help/translate.translate.es" href="#">Español</a>
|
||||
<li><a data-target="help/translate.translate.fr" href="#">French</a>
|
||||
<li><a data-target="help/translate.translate.de" href="#">German</a>
|
||||
<li><a data-target="help/translate.translate.it" href="#">Italiano</a>
|
||||
<li><a data-target="help/translate.translate.ja" href="#">Japanese</a>
|
||||
<li><a data-target="help/translate.translate.ko" href="#">Korean</a>
|
||||
<li><a data-target="help/translate.translate.lt" href="#">Lietuvių</a>
|
||||
<li><a data-target="help/translate.translate.pt" href="#">Portuguese</a>
|
||||
<li><a data-target="help/translate.translate.ru" href="#">Russian</a>
|
||||
<li><a data-target="help/translate.translate.tr" href="#">Turkish</a>
|
||||
</ul>
|
||||
</li>
|
||||
<li><div class="mid-line"></div></li>
|
||||
<li><a class="trn dots" data-target="help/about.about" href="#">About</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
`;
|
||||
const menuDefinition = [
|
||||
{
|
||||
name: 'File',
|
||||
children: [
|
||||
{
|
||||
name: 'New',
|
||||
target: 'file/new.new'
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'Open',
|
||||
children: [
|
||||
{
|
||||
name: 'Open File',
|
||||
shortcut: 'Drag&Drop',
|
||||
target: 'file/open.open_file'
|
||||
},
|
||||
{
|
||||
name: 'Open Directory',
|
||||
target: 'file/open.open_dir'
|
||||
},
|
||||
{
|
||||
name: 'Open from Webcam',
|
||||
target: 'file/open.open_webcam'
|
||||
},
|
||||
{
|
||||
name: 'Open URL',
|
||||
target: 'file/open.open_url'
|
||||
},
|
||||
{
|
||||
name: 'Open Data URL',
|
||||
target: 'file/open.open_data_url'
|
||||
},
|
||||
{
|
||||
name: 'Open Test Template',
|
||||
target: 'file/open.open_template_test'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Search Images',
|
||||
ellipsis: true,
|
||||
target: 'file/search.search'
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'Save As',
|
||||
ellipsis: true,
|
||||
shortcut: 'S',
|
||||
target: 'file/save.save'
|
||||
},
|
||||
{
|
||||
name: 'Save As Data URL',
|
||||
ellipsis: true,
|
||||
target: 'file/save.save_data_url'
|
||||
},
|
||||
{
|
||||
name: 'Print',
|
||||
ellipsis: true,
|
||||
shortcut: 'Ctrl-P',
|
||||
target: 'file/print.print'
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'Quick Save',
|
||||
shortcut: 'F9',
|
||||
target: 'file/quicksave.quicksave'
|
||||
},
|
||||
{
|
||||
name: 'Quick Load',
|
||||
shortcut: 'F10',
|
||||
target: 'file/quickload.quickload'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Edit',
|
||||
children: [
|
||||
{
|
||||
name: 'Undo',
|
||||
target: 'edit/undo.undo'
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'Delete Selection',
|
||||
shortcut: 'Del',
|
||||
target: 'edit/selection.delete'
|
||||
},
|
||||
{
|
||||
name: 'Copy Selection',
|
||||
target: 'layer/new.new_selection'
|
||||
},
|
||||
{
|
||||
name: 'Paste',
|
||||
shortcut: 'Ctrl+V',
|
||||
target: 'edit/paste.paste'
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'Select All',
|
||||
target: 'edit/selection.select_all'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Image',
|
||||
children: [
|
||||
{
|
||||
name: 'Information',
|
||||
ellipsis: true,
|
||||
target: 'image/information.information'
|
||||
},
|
||||
{
|
||||
name: 'Size',
|
||||
ellipsis: true,
|
||||
target: 'image/size.size'
|
||||
},
|
||||
{
|
||||
name: 'Trim',
|
||||
ellipsis: true,
|
||||
shortcut: 'T',
|
||||
target: 'image/trim.trim'
|
||||
},
|
||||
{
|
||||
name: 'Zoom',
|
||||
children: [
|
||||
{
|
||||
name: 'Zoom In',
|
||||
target: 'image/zoom.in'
|
||||
},
|
||||
{
|
||||
name: 'Zoom Out',
|
||||
target: 'image/zoom.out'
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'Original Size',
|
||||
target: 'image/zoom.original'
|
||||
},
|
||||
{
|
||||
name: 'Fit Window',
|
||||
target: 'image/zoom.auto'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'Resize',
|
||||
ellipsis: true,
|
||||
target: 'image/resize.resize'
|
||||
},
|
||||
{
|
||||
name: 'Rotate',
|
||||
ellipsis: true,
|
||||
target: 'image/rotate.rotate'
|
||||
},
|
||||
{
|
||||
name: 'Flip',
|
||||
children: [
|
||||
{
|
||||
name: 'Vertical',
|
||||
target: 'image/flip.vertical'
|
||||
},
|
||||
{
|
||||
name: 'Horizontal',
|
||||
target: 'image/flip.horizontal'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Translate',
|
||||
ellipsis: true,
|
||||
target: 'image/translate.translate'
|
||||
},
|
||||
{
|
||||
name: 'Opacity',
|
||||
ellipsis: true,
|
||||
target: 'image/opacity.opacity'
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'Color Correction',
|
||||
ellipsis: true,
|
||||
target: 'image/color_corrections.color_corrections'
|
||||
},
|
||||
{
|
||||
name: 'Auto Adjust Colors',
|
||||
target: 'image/auto_adjust.auto_adjust'
|
||||
},
|
||||
{
|
||||
name: 'Decrease Color Depth',
|
||||
target: 'image/decrease_colors.decrease_colors'
|
||||
},
|
||||
{
|
||||
name: 'Color Palette',
|
||||
ellipsis: true,
|
||||
target: 'image/palette.palette'
|
||||
},
|
||||
{
|
||||
name: 'Grid',
|
||||
ellipsis: true,
|
||||
shortcut: 'G',
|
||||
target: 'image/grid.grid'
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'Histogram',
|
||||
ellipsis: true,
|
||||
shortcut: 'H',
|
||||
target: 'image/histogram.histogram'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Layers',
|
||||
children: [
|
||||
{
|
||||
name: 'New',
|
||||
shortcut: 'N',
|
||||
target: 'layer/new.new'
|
||||
},
|
||||
{
|
||||
name: 'New from Selection',
|
||||
target: 'layer/new.new_selection'
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'Duplicate',
|
||||
target: 'layer/duplicate.duplicate'
|
||||
},
|
||||
{
|
||||
name: 'Show / Hide',
|
||||
target: 'layer/visibility.toggle'
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
target: 'layer/delete.delete'
|
||||
},
|
||||
{
|
||||
name: 'Convert to Raster',
|
||||
target: 'layer/raster.raster'
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'Move',
|
||||
children: [
|
||||
{
|
||||
name: 'Up',
|
||||
target: 'layer/move.up'
|
||||
},
|
||||
{
|
||||
name: 'Down',
|
||||
target: 'layer/move.down'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Composition',
|
||||
ellipsis: true,
|
||||
target: 'layer/composition.composition'
|
||||
},
|
||||
{
|
||||
name: 'Rename',
|
||||
ellipsis: true,
|
||||
target: 'layer/rename.rename'
|
||||
},
|
||||
{
|
||||
name: 'Clear',
|
||||
target: 'layer/clear.clear'
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'Differences Down',
|
||||
target: 'layer/differences.differences'
|
||||
},
|
||||
{
|
||||
name: 'Merge Down',
|
||||
target: 'layer/merge.merge'
|
||||
},
|
||||
{
|
||||
name: 'Flatten Image',
|
||||
target: 'layer/flatten.flatten'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Effects',
|
||||
children: [
|
||||
{
|
||||
name: 'CSS Filters',
|
||||
children: [
|
||||
{
|
||||
name: 'Gaussian Blur',
|
||||
ellipsis: true,
|
||||
target: 'effects/blur.blur'
|
||||
},
|
||||
{
|
||||
name: 'Brightness',
|
||||
ellipsis: true,
|
||||
target: 'effects/brightness.brightness'
|
||||
},
|
||||
{
|
||||
name: 'Contrast',
|
||||
ellipsis: true,
|
||||
target: 'effects/contrast.contrast'
|
||||
},
|
||||
{
|
||||
name: 'Grayscale',
|
||||
ellipsis: true,
|
||||
target: 'effects/grayscale.grayscale'
|
||||
},
|
||||
{
|
||||
name: 'Hue Rotate',
|
||||
ellipsis: true,
|
||||
target: 'effects/hue_rotate.hue_rotate'
|
||||
},
|
||||
{
|
||||
name: 'Negative',
|
||||
ellipsis: true,
|
||||
target: 'effects/negative.negative'
|
||||
},
|
||||
{
|
||||
name: 'Saturate',
|
||||
ellipsis: true,
|
||||
target: 'effects/saturate.saturate'
|
||||
},
|
||||
{
|
||||
name: 'Sepia',
|
||||
ellipsis: true,
|
||||
target: 'effects/sepia.sepia'
|
||||
},
|
||||
{
|
||||
name: 'Shadow',
|
||||
ellipsis: true,
|
||||
target: 'effects/shadow.shadow'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Black and White',
|
||||
ellipsis: true,
|
||||
target: 'effects/black_and_white.black_and_white'
|
||||
},
|
||||
{
|
||||
name: 'Blueprint',
|
||||
ellipsis: true,
|
||||
target: 'effects/blueprint.blueprint'
|
||||
},
|
||||
{
|
||||
name: 'Box Blur',
|
||||
ellipsis: true,
|
||||
target: 'effects/box_blur.box_blur'
|
||||
},
|
||||
{
|
||||
name: 'Denoise',
|
||||
ellipsis: true,
|
||||
target: 'effects/denoise.denoise'
|
||||
},
|
||||
{
|
||||
name: 'Dither',
|
||||
ellipsis: true,
|
||||
target: 'effects/dither.dither'
|
||||
},
|
||||
{
|
||||
name: 'Dot Screen',
|
||||
ellipsis: true,
|
||||
target: 'effects/dot_screen.dot_screen'
|
||||
},
|
||||
{
|
||||
name: 'Edge',
|
||||
ellipsis: true,
|
||||
target: 'effects/edge.edge'
|
||||
},
|
||||
{
|
||||
name: 'Emboss',
|
||||
ellipsis: true,
|
||||
target: 'effects/emboss.emboss'
|
||||
},
|
||||
{
|
||||
name: 'Enrich',
|
||||
ellipsis: true,
|
||||
target: 'effects/enrich.enrich'
|
||||
},
|
||||
{
|
||||
name: 'Grains',
|
||||
ellipsis: true,
|
||||
target: 'effects/grains.grains'
|
||||
},
|
||||
{
|
||||
name: 'Heatmap',
|
||||
ellipsis: true,
|
||||
target: 'effects/heatmap.heatmap'
|
||||
},
|
||||
{
|
||||
name: 'Mosaic',
|
||||
ellipsis: true,
|
||||
target: 'effects/mosaic.mosaic'
|
||||
},
|
||||
{
|
||||
name: 'Night Vision',
|
||||
ellipsis: true,
|
||||
target: 'effects/night_vision.night_vision'
|
||||
},
|
||||
{
|
||||
name: 'Oil',
|
||||
ellipsis: true,
|
||||
target: 'effects/oil.oil'
|
||||
},
|
||||
{
|
||||
name: 'Pencil',
|
||||
ellipsis: true,
|
||||
target: 'effects/pencil.pencil'
|
||||
},
|
||||
{
|
||||
name: 'Sharpen',
|
||||
ellipsis: true,
|
||||
target: 'effects/sharpen.sharpen'
|
||||
},
|
||||
{
|
||||
name: 'Solarize',
|
||||
ellipsis: true,
|
||||
target: 'effects/solarize.solarize'
|
||||
},
|
||||
{
|
||||
name: 'Tilt Shift',
|
||||
ellipsis: true,
|
||||
target: 'effects/tilt_shift.tilt_shift'
|
||||
},
|
||||
{
|
||||
name: 'Vignette',
|
||||
ellipsis: true,
|
||||
target: 'effects/vignette.vignette'
|
||||
},
|
||||
{
|
||||
name: 'Vibrance',
|
||||
ellipsis: true,
|
||||
target: 'effects/vibrance.vibrance'
|
||||
},
|
||||
{
|
||||
name: 'Vintage',
|
||||
ellipsis: true,
|
||||
target: 'effects/vintage.vintage'
|
||||
},
|
||||
{
|
||||
name: 'Zoom Blur',
|
||||
ellipsis: true,
|
||||
target: 'effects/zoom_blur.zoom_blur'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Tools',
|
||||
children: [
|
||||
{
|
||||
name: 'Borders',
|
||||
ellipsis: true,
|
||||
target: 'tools/borders.borders'
|
||||
},
|
||||
{
|
||||
name: 'Sprites',
|
||||
target: 'tools/sprites.sprites'
|
||||
},
|
||||
{
|
||||
name: 'Key-Points',
|
||||
target: 'tools/keypoints.keypoints'
|
||||
},
|
||||
{
|
||||
name: 'Content Fill',
|
||||
ellipsis: true,
|
||||
target: 'tools/content_fill.content_fill'
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'Color to Alpha',
|
||||
ellipsis: true,
|
||||
target: 'tools/color_to_alpha.color_to_alpha'
|
||||
},
|
||||
{
|
||||
name: 'Color Zoom',
|
||||
ellipsis: true,
|
||||
target: 'tools/color_zoom.color_zoom'
|
||||
},
|
||||
{
|
||||
name: 'Replace Color',
|
||||
ellipsis: true,
|
||||
target: 'tools/replace_color.replace_color'
|
||||
},
|
||||
{
|
||||
name: 'Restore Alpha',
|
||||
ellipsis: true,
|
||||
target: 'tools/restore_alpha.restore_alpha'
|
||||
},
|
||||
{
|
||||
name: 'External',
|
||||
children: [
|
||||
{
|
||||
name: 'TINYPNG - Compress PNG and JPEG',
|
||||
href: 'https://tinypng.com'
|
||||
},
|
||||
{
|
||||
name: 'REMOVE.BG - Remove Image Background',
|
||||
href: 'https://www.remove.bg'
|
||||
},
|
||||
{
|
||||
name: 'PNGTOSVG - Convert Image to SVG',
|
||||
href: 'https://www.pngtosvg.com'
|
||||
},
|
||||
{
|
||||
name: 'SQUOOSH - Compress and Compare Images',
|
||||
href: 'https://squoosh.app'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'Settings',
|
||||
ellipsis: true,
|
||||
target: 'tools/settings.settings'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Help',
|
||||
children: [
|
||||
{
|
||||
name: 'Keyboard Shortcuts',
|
||||
ellipsis: true,
|
||||
target: 'help/shortcuts.shortcuts'
|
||||
},
|
||||
{
|
||||
name: 'Report Issues',
|
||||
href: 'https://github.com/viliusle/miniPaint/issues'
|
||||
},
|
||||
{
|
||||
name: 'Language',
|
||||
children: [
|
||||
{
|
||||
name: 'English',
|
||||
target: 'help/translate.translate.en'
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: '简体中文',
|
||||
target: 'help/translate.translate.zh'
|
||||
},
|
||||
{
|
||||
name: 'Español',
|
||||
target: 'help/translate.translate.es'
|
||||
},
|
||||
{
|
||||
name: 'Français',
|
||||
target: 'help/translate.translate.fr'
|
||||
},
|
||||
{
|
||||
name: 'Deutsch',
|
||||
target: 'help/translate.translate.de'
|
||||
},
|
||||
{
|
||||
name: 'Italiano',
|
||||
target: 'help/translate.translate.it'
|
||||
},
|
||||
{
|
||||
name: '日本語',
|
||||
target: 'help/translate.translate.ja'
|
||||
},
|
||||
{
|
||||
name: '한국어',
|
||||
target: 'help/translate.translate.ko'
|
||||
},
|
||||
{
|
||||
name: 'Lietuvių',
|
||||
target: 'help/translate.translate.lt'
|
||||
},
|
||||
{
|
||||
name: 'Português',
|
||||
target: 'help/translate.translate.pt'
|
||||
},
|
||||
{
|
||||
name: 'русский язык',
|
||||
target: 'help/translate.translate.ru'
|
||||
},
|
||||
{
|
||||
name: 'Türkçe',
|
||||
target: 'help/translate.translate.tr'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
},
|
||||
{
|
||||
name: 'About',
|
||||
target: 'help/about.about'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
export default menu_template;
|
||||
|
||||
export default menuDefinition;
|
||||
@ -124,34 +124,23 @@ class Base_gui_class {
|
||||
var _this = this;
|
||||
|
||||
//menu events
|
||||
var targets = document.querySelectorAll('#main_menu a');
|
||||
for (var i = 0; i < targets.length; i++) {
|
||||
if (targets[i].dataset.target == undefined)
|
||||
continue;
|
||||
targets[i].addEventListener('click', function (event) {
|
||||
var parts = this.dataset.target.split('.');
|
||||
var module = parts[0];
|
||||
var function_name = parts[1];
|
||||
var param = parts[2];
|
||||
this.GUI_menu.on('select_target', (target) => {
|
||||
var parts = target.split('.');
|
||||
var module = parts[0];
|
||||
var function_name = parts[1];
|
||||
var param = parts[2];
|
||||
|
||||
//close menu
|
||||
var menu = document.querySelector('#main_menu .selected');
|
||||
if (menu != undefined) {
|
||||
menu.click();
|
||||
}
|
||||
|
||||
//call module
|
||||
if (_this.modules[module] == undefined) {
|
||||
alertify.error('Modules class not found: ' + module);
|
||||
return;
|
||||
}
|
||||
if (_this.modules[module][function_name] == undefined) {
|
||||
alertify.error('Module function not found. ' + module + '.' + function_name);
|
||||
return;
|
||||
}
|
||||
_this.modules[module][function_name](param);
|
||||
});
|
||||
}
|
||||
//call module
|
||||
if (this.modules[module] == undefined) {
|
||||
alertify.error('Modules class not found: ' + module);
|
||||
return;
|
||||
}
|
||||
if (this.modules[module][function_name] == undefined) {
|
||||
alertify.error('Module function not found. ' + module + '.' + function_name);
|
||||
return;
|
||||
}
|
||||
this.modules[module][function_name](param);
|
||||
});
|
||||
|
||||
//registerToggleAbility
|
||||
var targets = document.querySelectorAll('.toggle');
|
||||
|
||||
@ -4,37 +4,369 @@
|
||||
*/
|
||||
|
||||
import config from './../../config.js';
|
||||
import menu_template from './../../config-menu.js';
|
||||
import ddsmoothmenu from './../../libs/menu.js';
|
||||
import menuDefinition from './../../config-menu.js';
|
||||
|
||||
/**
|
||||
* class responsible for rendering main menu
|
||||
*/
|
||||
class GUI_menu_class {
|
||||
|
||||
constructor() {
|
||||
this.eventSubscriptions = {};
|
||||
this.dropdownMaxHeightMargin = 15;
|
||||
this.menuContainer = null;
|
||||
this.menuBarNode = null;
|
||||
this.lastFocusedMenuBarLink = 0;
|
||||
this.dropdownStack = [];
|
||||
}
|
||||
|
||||
render_main() {
|
||||
document.getElementById('main_menu').innerHTML = menu_template;
|
||||
ddsmoothmenu.init({
|
||||
mainmenuid: "main_menu",
|
||||
method: 'toggle', //'hover' (default) or 'toggle'
|
||||
contentsource: "markup",
|
||||
this.menuContainer = document.getElementById('main_menu');
|
||||
|
||||
let menuTemplate = '<ul class="menu_bar" role="menubar" tabindex="0">';
|
||||
for (let i = 0; i < menuDefinition.length; i++) {
|
||||
const item = menuDefinition[i];
|
||||
menuTemplate += this.generate_menu_bar_item_template(item, i);
|
||||
}
|
||||
menuTemplate += '</ul>';
|
||||
|
||||
this.menuContainer.innerHTML = menuTemplate;
|
||||
this.menuBarNode = this.menuContainer.querySelector('[role="menubar"]');
|
||||
|
||||
this.menuContainer.addEventListener('click', (event) => { return this.on_click_menu(event); }, true);
|
||||
this.menuContainer.addEventListener('keydown', (event) => { return this.on_key_down_menu(event); }, true);
|
||||
this.menuBarNode.addEventListener('focus', (event) => { return this.on_focus_menu_bar(event); });
|
||||
this.menuBarNode.addEventListener('blur', (event) => { return this.on_blur_menu_bar(event); });
|
||||
this.menuBarNode.querySelectorAll('a').forEach((link) => {
|
||||
link.addEventListener('focus', (event) => { return this.on_focus_menu_bar_link(event); });
|
||||
});
|
||||
document.body.addEventListener('mousedown', (event) => { return this.on_mouse_down_body(event); }, true);
|
||||
document.body.addEventListener('touchstart', (event) => { return this.on_mouse_down_body(event); }, true);
|
||||
window.addEventListener('resize', (event) => { return this.on_resize_window(event); }, true)
|
||||
}
|
||||
|
||||
on(eventName, callback) {
|
||||
if (!this.eventSubscriptions[eventName]) {
|
||||
this.eventSubscriptions[eventName] = [];
|
||||
}
|
||||
if (!this.eventSubscriptions[eventName].includes(callback)) {
|
||||
this.eventSubscriptions[eventName].push(callback);
|
||||
}
|
||||
}
|
||||
|
||||
emit(eventName, payload) {
|
||||
if (this.eventSubscriptions[eventName]) {
|
||||
for (let callback of this.eventSubscriptions[eventName]) {
|
||||
callback(payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generate_menu_bar_item_template(definition, index) {
|
||||
return `
|
||||
<li>
|
||||
<a id="main_menu_0_${index}" role="menuitem" tabindex="-1" aria-haspopup="true" aria-expanded="false"
|
||||
href="javascript:void(0)" data-level="0" data-index="${ index }"><span class="name">${ definition.name }</span></a>
|
||||
</li>
|
||||
`.trim();
|
||||
}
|
||||
|
||||
generate_menu_dropdown_item_template(definition, level, index) {
|
||||
if (definition.divider) {
|
||||
return `
|
||||
<li role="presentation">
|
||||
<hr>
|
||||
</li>
|
||||
`.trim();
|
||||
} else {
|
||||
return `
|
||||
<li>
|
||||
<a id="main_menu_${ level }_${ index }" role="menuitem" aria-haspopup="${ (!!definition.children) + '' }"
|
||||
href="${ definition.href ? definition.href : 'javascript:void(0)' }"
|
||||
target="${ definition.href ? '_blank' : '_self' }"
|
||||
data-level="${ level }" data-index="${ index }">
|
||||
<span class="name">${ definition.name }${ definition.ellipsis ? ' ...' : '' }</span>
|
||||
${ !!definition.shortcut ? `
|
||||
<span class="shortcut"><span class="sr_only">Shortcut Key:</span> ${ definition.shortcut }</span>
|
||||
` : `` }
|
||||
</a>
|
||||
</li>
|
||||
`.trim();
|
||||
}
|
||||
}
|
||||
|
||||
on_mouse_down_body(event) {
|
||||
const target = event.touches ? event.touches[0].target : event.target;
|
||||
|
||||
// Clicked outside of menu; close dropdowns.
|
||||
if (target && !this.menuContainer.contains(target)) {
|
||||
this.close_child_dropdowns(0);
|
||||
}
|
||||
}
|
||||
|
||||
on_focus_menu_bar(event) {
|
||||
if (document.activeElement === this.menuBarNode) {
|
||||
let lastFocusedLink = this.menuBarNode.querySelector(`[data-index="${ this.lastFocusedMenuBarLink }"]`);
|
||||
if (!lastFocusedLink) {
|
||||
lastFocusedLink = this.menuBarNode.querySelector('a');
|
||||
}
|
||||
lastFocusedLink.focus();
|
||||
}
|
||||
}
|
||||
|
||||
on_focus_menu_bar_link(event) {
|
||||
this.lastFocusedMenuBarLink = parseInt(event.target.getAttribute('data-index'), 10) || 0;
|
||||
}
|
||||
|
||||
on_blur_menu_bar(event) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
on_key_down_menu(event) {
|
||||
const key = event.key;
|
||||
const activeElement = document.activeElement;
|
||||
|
||||
if (activeElement && activeElement.tagName === 'A') {
|
||||
const linkLevel = parseInt(activeElement.getAttribute('data-level'), 10) || 0;
|
||||
const linkIndex = parseInt(activeElement.getAttribute('data-index'), 10) || 0;
|
||||
const menuParent = activeElement.closest('ul');
|
||||
if (linkLevel === 0) {
|
||||
if (['Right', 'ArrowRight'].includes(event.key)) {
|
||||
let nextLink = menuParent.querySelector(`[data-index="${ linkIndex + 1 }"]`);
|
||||
if (!nextLink) {
|
||||
nextLink = menuParent.querySelector(`[data-index="0"]`);
|
||||
}
|
||||
nextLink.focus();
|
||||
}
|
||||
else if (['Left', 'ArrowLeft'].includes(event.key)) {
|
||||
let previousLink = menuParent.querySelector(`[data-index="${ linkIndex - 1 }"]`);
|
||||
if (!previousLink) {
|
||||
previousLink = menuParent.querySelector(`[data-index="${ menuParent.querySelectorAll('[data-index]').length - 1 }"]`);
|
||||
}
|
||||
previousLink.focus();
|
||||
}
|
||||
else if (['Down', 'ArrowDown'].includes(event.key)) {
|
||||
if (activeElement.getAttribute('aria-haspopup') === 'true') {
|
||||
event.preventDefault();
|
||||
activeElement.click();
|
||||
}
|
||||
}
|
||||
else if ([' ', 'Enter'].includes(event.key)) {
|
||||
event.preventDefault();
|
||||
activeElement.click();
|
||||
}
|
||||
} else {
|
||||
if (['Up', 'ArrowUp'].includes(event.key)) {
|
||||
event.preventDefault();
|
||||
let previousLink = menuParent.querySelector(`[data-index="${ linkIndex - 1 }"]`);
|
||||
if (!previousLink) {
|
||||
previousLink = menuParent.querySelector(`[data-index="${ linkIndex - 2 }"]`); // Skip dividers
|
||||
}
|
||||
if (!previousLink) {
|
||||
previousLink = menuParent.querySelector(`[data-index="${ this.dropdownStack[linkLevel - 1].children.length - 1 }"]`);
|
||||
}
|
||||
previousLink.focus();
|
||||
}
|
||||
else if (['Down', 'ArrowDown'].includes(event.key)) {
|
||||
event.preventDefault();
|
||||
let nextLink = menuParent.querySelector(`[data-index="${ linkIndex + 1 }"]`);
|
||||
if (!nextLink) {
|
||||
nextLink = menuParent.querySelector(`[data-index="${ linkIndex + 2 }"]`); // Skip dividers
|
||||
}
|
||||
if (!nextLink) {
|
||||
nextLink = menuParent.querySelector(`[data-index="0"]`);
|
||||
}
|
||||
nextLink.focus();
|
||||
}
|
||||
else if (['Right', 'ArrowRight'].includes(event.key)) {
|
||||
const menuBarLinkIndex = parseInt(this.dropdownStack[0].opener.getAttribute('data-index'), 10) || 0;
|
||||
let nextLink = this.menuBarNode.querySelector(`[data-index="${ menuBarLinkIndex + 1 }"]`);
|
||||
if (!nextLink) {
|
||||
nextLink = this.menuBarNode.querySelector(`[data-index="0"]`);
|
||||
}
|
||||
nextLink.click();
|
||||
}
|
||||
else if (['Left', 'ArrowLeft'].includes(event.key)) {
|
||||
const menuBarLinkIndex = parseInt(this.dropdownStack[0].opener.getAttribute('data-index'), 10) || 0;
|
||||
let previousLink = this.menuBarNode.querySelector(`[data-index="${ menuBarLinkIndex - 1 }"]`);
|
||||
if (!previousLink) {
|
||||
previousLink = this.menuBarNode.querySelector(`[data-index="${ this.menuBarNode.querySelectorAll('[data-index]').length - 1 }"]`);
|
||||
}
|
||||
previousLink.click();
|
||||
}
|
||||
else if ([' ', 'Enter'].includes(event.key)) {
|
||||
event.preventDefault();
|
||||
activeElement.click();
|
||||
}
|
||||
else if (['Esc', 'Escape'].includes(event.key)) {
|
||||
const opener = this.dropdownStack[linkLevel - 1].opener;
|
||||
opener.click();
|
||||
opener.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
on_click_menu(event) {
|
||||
const target = event.target.closest('a');
|
||||
|
||||
// Any link in the menu is clicked.
|
||||
if (target && target.tagName === 'A') {
|
||||
const hasPopup = target.getAttribute('aria-haspopup') === 'true';
|
||||
if (hasPopup) {
|
||||
this.toggle_dropdown(target, event.isTrusted);
|
||||
} else {
|
||||
this.trigger_link(target);
|
||||
}
|
||||
} else {
|
||||
this.close_child_dropdowns(0);
|
||||
}
|
||||
}
|
||||
|
||||
on_resize_window(event) {
|
||||
if (this.dropdownStack.length > 0) {
|
||||
this.position_dropdowns();
|
||||
}
|
||||
}
|
||||
|
||||
toggle_dropdown(opener, isTrusted) {
|
||||
const linkLevel = parseInt(opener.getAttribute('data-level'), 10) || 0;
|
||||
const linkIndex = parseInt(opener.getAttribute('data-index'), 10) || 0;
|
||||
if (opener.getAttribute('aria-expanded') === 'true') {
|
||||
this.close_child_dropdowns(linkLevel);
|
||||
} else {
|
||||
const parentList = opener.closest('ul');
|
||||
parentList.querySelectorAll('a').forEach((item) => {
|
||||
item.setAttribute('aria-expanded', 'false');
|
||||
});
|
||||
opener.setAttribute('aria-expanded', true);
|
||||
this.create_dropdown(opener, linkLevel, linkIndex, !isTrusted);
|
||||
}
|
||||
}
|
||||
|
||||
trigger_link(link) {
|
||||
const level = parseInt(link.getAttribute('data-level'), 10) || 0;
|
||||
const index = parseInt(link.getAttribute('data-index'), 10) || 0;
|
||||
|
||||
// Find link definition
|
||||
let children = menuDefinition;
|
||||
for (let i = 0; i < level; i++) {
|
||||
const childIndex = this.dropdownStack[i] != null ? this.dropdownStack[i].index : index;
|
||||
children = children[childIndex].children;
|
||||
}
|
||||
let definition = children[index];
|
||||
|
||||
// Close the dropdown
|
||||
this.close_child_dropdowns(0);
|
||||
|
||||
// Emit callback events for triggered links
|
||||
if (definition.target) {
|
||||
this.emit('select_target', definition.target);
|
||||
}
|
||||
else if (definition.href) {
|
||||
this.emit('select_href', definition.href);
|
||||
}
|
||||
}
|
||||
|
||||
close_child_dropdowns(level) {
|
||||
for (let i = this.dropdownStack.length - 1; i >= 0; i--) {
|
||||
if (i >= level) {
|
||||
this.dropdownStack[i].element.parentNode.removeChild(this.dropdownStack[i].element);
|
||||
this.dropdownStack[i].opener.setAttribute('aria-expanded', false);
|
||||
}
|
||||
}
|
||||
this.dropdownStack = this.dropdownStack.slice(0, level);
|
||||
}
|
||||
|
||||
create_dropdown(opener, level, index, focusAfterCreation) {
|
||||
this.close_child_dropdowns(level);
|
||||
|
||||
// Find child list in the menu definition
|
||||
let children = menuDefinition;
|
||||
for (let i = 0; i <= level; i++) {
|
||||
const childIndex = this.dropdownStack[i] != null ? this.dropdownStack[i].index : index;
|
||||
children = children[childIndex].children;
|
||||
}
|
||||
|
||||
// Create the dropdown element, place it in DOM & position it
|
||||
let dropdownElement = document.createElement('ul');
|
||||
dropdownElement.className = 'menu_dropdown';
|
||||
dropdownElement.role = 'menu';
|
||||
dropdownElement.setAttribute('aria-labelledby', 'main_menu_' + level + '_' + index);
|
||||
let dropdownTemplate = '';
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
dropdownTemplate += this.generate_menu_dropdown_item_template(children[i], level + 1, i);
|
||||
}
|
||||
dropdownElement.innerHTML = dropdownTemplate;
|
||||
|
||||
this.menuContainer.appendChild(dropdownElement);
|
||||
|
||||
if (focusAfterCreation) {
|
||||
dropdownElement.querySelector('a').focus();
|
||||
}
|
||||
|
||||
this.dropdownStack.push({
|
||||
children,
|
||||
opener,
|
||||
index,
|
||||
element: dropdownElement
|
||||
});
|
||||
|
||||
// Additional logic for ddsmoothmenu library:
|
||||
// Add CSS class to primary dropdown to identify when to toggle scrolling for mobile.
|
||||
document.getElementById('main_menu').addEventListener('click', (e) => {
|
||||
const target = e.target;
|
||||
if (!target || !target.parentNode) return;
|
||||
if (target.parentNode.classList.contains('more')) {
|
||||
var parentList = target.closest('ul');
|
||||
var wasSelected = target.classList.contains('selected');
|
||||
setTimeout(() => {
|
||||
parentList.classList.toggle('expanded', !wasSelected);
|
||||
}, 1);
|
||||
} else if (target.tagName === 'A' && target.matches('#main_menu > ul > li > a')) {
|
||||
target.nextElementSibling.classList.remove('expanded');
|
||||
this.position_dropdowns();
|
||||
}
|
||||
|
||||
position_dropdowns() {
|
||||
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
|
||||
const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
|
||||
|
||||
let topNavHeight = 0;
|
||||
for (let level = 0; level < this.dropdownStack.length; level++) {
|
||||
const dropdownElement = this.dropdownStack[level].element;
|
||||
const openerRect = this.dropdownStack[level].opener.getBoundingClientRect();
|
||||
|
||||
topNavHeight = openerRect.height;
|
||||
const dropdownMaxHeight = vh - topNavHeight - this.dropdownMaxHeightMargin;
|
||||
dropdownElement.style.maxHeight = dropdownMaxHeight + 'px';
|
||||
const dropdownRect = dropdownElement.getBoundingClientRect();
|
||||
|
||||
if (level === 0) {
|
||||
dropdownElement.style.top = (openerRect.y + openerRect.height) + 'px';
|
||||
|
||||
let left = openerRect.x;
|
||||
if (left + dropdownRect.width > vw) {
|
||||
left = openerRect.x + openerRect.width - dropdownRect.width;
|
||||
}
|
||||
if (left + dropdownRect.width > vw) {
|
||||
left = vw - dropdownRect.width;
|
||||
}
|
||||
if (left < 0) {
|
||||
left = 0;
|
||||
}
|
||||
dropdownElement.style.left = left + 'px';
|
||||
} else {
|
||||
let top = openerRect.y;
|
||||
if (top + dropdownRect.height > vh - this.dropdownMaxHeightMargin) {
|
||||
top = vh - this.dropdownMaxHeightMargin - dropdownRect.height;
|
||||
}
|
||||
dropdownElement.style.top = top + 'px';
|
||||
|
||||
let left = openerRect.x + openerRect.width + 1;
|
||||
if (left + dropdownRect.width > vw) {
|
||||
left = openerRect.x - dropdownRect.width - 1;
|
||||
}
|
||||
if (left < 0) {
|
||||
if (openerRect.x + (openerRect.width / 2) > vw / 2) {
|
||||
left = 1;
|
||||
} else {
|
||||
left = vw - dropdownRect.width - 1;
|
||||
if (left < 0) {
|
||||
left = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
dropdownElement.style.left = left + 'px';
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user