デモ
See the Pen Side-Menu-1 by YugetaKoji (@geta1972) on CodePen.
ソースコード
<html lang="en">
<head>
<meta charset="utf-8">
<title>HTML-parts SideMenu</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="side-menu.css">
<script src="side-menu.js"></script>
</head>
<body>
<div class="side-menu">
<ul>
<li>
<a>Menu-1</a>
<ul>
<li><a href="#menu-1-1">Menu-1-1</a></li>
<li><a href="#menu-1-2">Menu-1-2</a></li>
</ul>
</li>
<li>
<a href="#menu-2">Menu-2</a>
</li>
</ul>
<ul>
<li>
<a>Menu-3</a>
<ul>
<li><a href="#menu-3-1">Menu-3-1</a></li>
<li>
<a href="#menu-3-2">Menu-3-2</a>
</li>
</ul>
</li>
</ul>
</div>
</body>
</html>
html,body{
margin : 0;
padding : 0;
border : 0;
width : 100%;
height : 100%;
}
*, *:before, *:after {
-webkit-box-sizing : border-box;
-moz-box-sizing : border-box;
-o-box-sizing : border-box;
-ms-box-sizing : border-box;
box-sizing : border-box;
}
/* Side-menu */
.side-menu{
width : 200px;
background-color:white;
border-right:1px solid #ccc;
}
.side-menu ul{
padding:0;
margin:0;
border:0;
}
.side-menu li{
padding:0;
margin:0;
border:0;
list-style:none;
min-height:60px;
line-height:60px;
}
.side-menu a{
display:block;
border-bottom:1px solid #ccc;
}
.side-menu > ul > li > a{
padding-left:10px;
}
.side-menu > ul > li > ul > li > a{
padding-left:20px;
}
.side-menu li[data-dropdown="1"] > a:after{
content: "";
display: inline-block;
width: 0;
height: 0;
vertical-align: middle;
border-top: 6px dashed;
border-right: 4px solid transparent;
border-left: 4px solid transparent;
box-sizing: border-box;
margin-left:4px;
}
.side-menu a:hover{
background-color:#eee;
}
/* expand-default */
.side-menu > ul li > ul{
display:none;
}
/* ecpand-open */
.side-menu li[data-view="1"] > ul{
display:block;
}
/* expand-close */
.side-menu li[data-view="0"] > ul{
display:none;
}
@keyframes menu-noactive{
0%{
background-color:#eee;
}
100%{
background-color:rgba(255,255,255,0.0);
}
}
@keyframes menu-close{
0%{
opacity:1.0;
visibility:visible;
}
100%{
opacity:0.0;
visibility:hidden;
}
}
@keyframes menu-list-open{
0%{
transform : scaleY(0);
}
100%{
transform : scaleY(1);
}
}
@keyframes menu-list-close{
0%{
transform : scaleY(1);
}
100%{
transform : scaleY(0);
}
}
;(function(){
// ページ内にjsライブラリの読み込み
var $$addScript = function(file){
var s = document.createElement("script");
s.src = file;
document.body.appendChild(s);
}
// イベントライブラリ
var $$event = function(target, mode, func){
//other Browser
if (typeof target.addEventListener !== "undefined"){
target.addEventListener(mode, func, false);
}
else if(typeof target.attachEvent !== "undefined"){
target.attachEvent('on' + mode, function(){func.call(target , window.event)});
}
};
var $$ = function(){
var state = document.readyState;
if(state === "complete"){
this.start();
}
else if(state === "interactive"){
$$event(window , "DOMContentLoaded" , (function(e){this.start(e)}).bind(this));
}
else{
$$event(window , "load" , (function(e){this.start(e)}).bind(this));
}
};
$$.prototype.start = function(){
// dropdown-set
this.set_dropdown();
// dropdown-click
this.set_dropdown_click();
// top-menu
var links = document.querySelectorAll(".side-menu ul > li > a");
for(var i=0; i<links.length; i++){
$$event(links[i] , "click" , (function(e){this.set_top_menu_toggle(e)}).bind(this));
}
// other-click
$$event(window , "click" , (function(e){this.checkClick(e)}).bind(this));
};
$$.prototype.set_top_menu_toggle = function(e){
var currentTarget = e.currentTarget;
if(!currentTarget || currentTarget.parentNode.getAttribute("data-dropdown") !== "1"){
this.set_top_menu_hidden();
}
var top_menus = document.querySelectorAll(".side-menu ul > li");
for(var i=0; i<top_menus.length; i++){
// 対象リンククリック
if(top_menus[i] === currentTarget.parentNode){
if(top_menus[i].getAttribute("data-view") !== "1"){
this.set_top_menu_view(top_menus[i] , true);
}
else{
this.set_top_menu_view(top_menus[i] , false);
}
}
// 対象の親階層は処理しない
else if(this.checkHierarchy(currentTarget , top_menus[i])){
continue;
}
// 対象外リンククリック
else{
this.set_top_menu_view(top_menus[i] , false);
}
}
};
$$.prototype.checkHierarchy = function(currentTarget , menuElement){
while(!currentTarget.matches(".side-menu")){
if(currentTarget === menuElement){
return true;
}
currentTarget = currentTarget.parentNode;
}
return false;
};
// bool @ [true:active , false:unactive]
$$.prototype.set_top_menu_view = function(linkElm , bool){
if(!linkElm){return;}
if(bool === true){
linkElm.setAttribute("data-view" , "1");
}
else{
linkElm.setAttribute("data-view" , "0");
}
};
// all-link-hidden
$$.prototype.set_top_menu_hidden = function(){
var listElm = document.querySelectorAll(".side-menu ul > li");
for(var i=0; i<listElm.length; i++){
if(listElm[i].getAttribute("data-dropdown") !== "1"){continue;}
listElm[i].setAttribute("data-view" , "0");
}
};
// bool @ [true:view , false:hidden]
$$.prototype.set_top_menu_active = function(dropdowns , currentTarget){
if(!dropdowns || !dropdowns.length){return;}
for(var i=0; i<dropdowns.length; i++){
if(!currentTarget || dropdowns[i].getAttribute("data-active") === "1"){
dropdowns[i].setAttribute("data-active" , "0");
}
else{
dropdowns[i].setAttribute("data-active" , "1");
}
}
};
// window-event
$$.prototype.checkClick = function(e){
var target = e.target;
if(target && target.matches(".side-menu ul > li *")){
return;
}
if(!target || !target.matches(".side-menu ul > li > a")){
this.set_top_menu_hidden();
}
};
$$.prototype.set_dropdown = function(){
var top_menus = document.querySelectorAll(".side-menu ul > li");
for(var i=0; i<top_menus.length; i++){
var listsElm = top_menus[i].querySelectorAll(":scope > ul");
if(!listsElm.length){continue;}
top_menus[i].setAttribute("data-dropdown" , "1");
}
};
$$.prototype.set_dropdown_click = function(){
var dropdowns = document.querySelectorAll(".side-menu ul li[data-dropdown='1']");
for(var i=0; i<dropdowns.length; i++){
var a = dropdowns[i].querySelector(":scope > a");
a.href = "javascript:void(0)";
}
};
new $$;
})();
0 件のコメント:
コメントを投稿