init
This commit is contained in:
parent
06f61d8ce8
commit
f301cb744d
2271 changed files with 103162 additions and 0 deletions
|
@ -0,0 +1 @@
|
|||
[edit src="solution"/]
|
1
02-ui/05-widgets/06-widget-tasks/09-hover-menu-onclick/solution/.plnkr
Executable file
1
02-ui/05-widgets/06-widget-tasks/09-hover-menu-onclick/solution/.plnkr
Executable file
|
@ -0,0 +1 @@
|
|||
{"name":"menu-nested","plunk":"Y2FobU7onTBDYA3s4CTG"}
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Taken from jQuery UI accordion and fixed, special hoverintent event
|
||||
* http://benalman.com/news/2010/03/jquery-special-events/
|
||||
*/
|
||||
!function($) {
|
||||
|
||||
|
||||
var cfg = {
|
||||
sensitivity: 9,
|
||||
interval: 50
|
||||
};
|
||||
|
||||
|
||||
$.event.special.hoverintent = {
|
||||
setup: function() {
|
||||
$(this).on("mouseover", handler);
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
$(this).on("mouseover", handler);
|
||||
},
|
||||
|
||||
cfg: cfg
|
||||
};
|
||||
|
||||
function handler(event) {
|
||||
|
||||
var self = this,
|
||||
args = arguments,
|
||||
target = $(event.target),
|
||||
cX, cY, pX, pY;
|
||||
|
||||
function track(event) {
|
||||
cX = event.pageX;
|
||||
cY = event.pageY;
|
||||
};
|
||||
pX = event.pageX;
|
||||
pY = event.pageY;
|
||||
|
||||
function clear() {
|
||||
target.off("mousemove", track).off("mouseout", clear);
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
|
||||
function handler() {
|
||||
if((Math.abs(pX - cX) + Math.abs(pY - cY)) < cfg.sensitivity) {
|
||||
clear();
|
||||
event.type = "hoverintent";
|
||||
jQuery.event.simulate("hoverintent", event.target, $.event.fix(event), true);
|
||||
} else {
|
||||
pX = cX;
|
||||
pY = cY;
|
||||
timeout = setTimeout(handler, cfg.interval);
|
||||
}
|
||||
}
|
||||
var timeout = setTimeout(handler, cfg.interval);
|
||||
target.mousemove(track).mouseout(clear);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}(jQuery);
|
61
02-ui/05-widgets/06-widget-tasks/09-hover-menu-onclick/solution/index.html
Executable file
61
02-ui/05-widgets/06-widget-tasks/09-hover-menu-onclick/solution/index.html
Executable file
|
@ -0,0 +1,61 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="menu.css">
|
||||
<script src="http://code.jquery.com/jquery-latest.js"></script>
|
||||
<script src="hoverintent.js"></script>
|
||||
<script src="menu.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Разрешить вложенные меню -->
|
||||
<div class="menu" id="menu">
|
||||
<a href="#" class="title">Моё меню</a>
|
||||
<ol>
|
||||
<li class="has-children">
|
||||
<a href="#a1">Элемент 1</a>
|
||||
<ol>
|
||||
<li><a href="#a1.1">Элемент 1.1</a></li>
|
||||
<li class="has-children">
|
||||
<a href="#a1.2">Элемент 1.2</a>
|
||||
<ol>
|
||||
<li><a href="#a1.2.1">Элемент 1.2.1</a></li>
|
||||
<li><a href="#a1.2.2">Элемент 1.2.2</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#a1.3">Элемент 1.3</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#a2">Элемент 2</a></li>
|
||||
<li class="has-children">
|
||||
<a href="#a3">Элемент 3</a>
|
||||
<ol>
|
||||
<li><a href="#a3.1">Элемент 3.1</a></li>
|
||||
<li><a href="#a3.2">Элемент 3.2</a></li>
|
||||
<li><a href="#a3.3">Элемент 3.3</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#a4">Элемент 4</a></li>
|
||||
<li><a href="#a5">Элемент 5</a></li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor eos.
|
||||
|
||||
<script>
|
||||
|
||||
var menu = new Menu({
|
||||
elem: $('#menu')
|
||||
});
|
||||
|
||||
$(menu).on("select", function(e) {
|
||||
if (!e.value) return;
|
||||
alert(e.value);
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
{"name":"menu-nested","plunk":"Y2FobU7onTBDYA3s4CTG"}
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Taken from jQuery UI accordion and fixed, special hoverintent event
|
||||
* http://benalman.com/news/2010/03/jquery-special-events/
|
||||
*/
|
||||
!function($) {
|
||||
|
||||
|
||||
var cfg = {
|
||||
sensitivity: 9,
|
||||
interval: 50
|
||||
};
|
||||
|
||||
|
||||
$.event.special.hoverintent = {
|
||||
setup: function() {
|
||||
$(this).on("mouseover", handler);
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
$(this).on("mouseover", handler);
|
||||
},
|
||||
|
||||
cfg: cfg
|
||||
};
|
||||
|
||||
function handler(event) {
|
||||
|
||||
var self = this,
|
||||
args = arguments,
|
||||
target = $(event.target),
|
||||
cX, cY, pX, pY;
|
||||
|
||||
function track(event) {
|
||||
cX = event.pageX;
|
||||
cY = event.pageY;
|
||||
};
|
||||
pX = event.pageX;
|
||||
pY = event.pageY;
|
||||
|
||||
function clear() {
|
||||
target.off("mousemove", track).off("mouseout", clear);
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
|
||||
function handler() {
|
||||
if((Math.abs(pX - cX) + Math.abs(pY - cY)) < cfg.sensitivity) {
|
||||
clear();
|
||||
event.type = "hoverintent";
|
||||
jQuery.event.simulate("hoverintent", event.target, $.event.fix(event), true);
|
||||
} else {
|
||||
pX = cX;
|
||||
pY = cY;
|
||||
timeout = setTimeout(handler, cfg.interval);
|
||||
}
|
||||
}
|
||||
var timeout = setTimeout(handler, cfg.interval);
|
||||
target.mousemove(track).mouseout(clear);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}(jQuery);
|
|
@ -0,0 +1,61 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="menu.css">
|
||||
<script src="http://code.jquery.com/jquery-latest.js"></script>
|
||||
<script src="hoverintent.js"></script>
|
||||
<script src="menu.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Разрешить вложенные меню -->
|
||||
<div class="menu" id="menu">
|
||||
<a href="#" class="title">Моё меню</a>
|
||||
<ol>
|
||||
<li class="has-children">
|
||||
<a href="#a1">Элемент 1</a>
|
||||
<ol>
|
||||
<li><a href="#a1.1">Элемент 1.1</a></li>
|
||||
<li class="has-children">
|
||||
<a href="#a1.2">Элемент 1.2</a>
|
||||
<ol>
|
||||
<li><a href="#a1.2.1">Элемент 1.2.1</a></li>
|
||||
<li><a href="#a1.2.2">Элемент 1.2.2</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#a1.3">Элемент 1.3</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#a2">Элемент 2</a></li>
|
||||
<li class="has-children">
|
||||
<a href="#a3">Элемент 3</a>
|
||||
<ol>
|
||||
<li><a href="#a3.1">Элемент 3.1</a></li>
|
||||
<li><a href="#a3.2">Элемент 3.2</a></li>
|
||||
<li><a href="#a3.3">Элемент 3.3</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#a4">Элемент 4</a></li>
|
||||
<li><a href="#a5">Элемент 5</a></li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor eos.
|
||||
|
||||
<script>
|
||||
|
||||
var menu = new Menu({
|
||||
elem: $('#menu')
|
||||
});
|
||||
|
||||
$(menu).on("select", function(e) {
|
||||
if (!e.value) return;
|
||||
alert(e.value);
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,54 @@
|
|||
|
||||
.menu::before {
|
||||
content: '☞';
|
||||
font-size: 16px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
||||
.menu.open::before {
|
||||
content: '☟';
|
||||
}
|
||||
|
||||
.menu a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.menu > a {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.menu a {
|
||||
padding: 3px 5px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
li.active > a {
|
||||
background: blue;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.menu ol {
|
||||
margin: 0;
|
||||
padding: 3px 0;
|
||||
list-style: none;
|
||||
display: none;
|
||||
background: #eee;
|
||||
border: 1px solid black;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.menu.open > ol {
|
||||
display: block;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.menu li.has-children > a::after {
|
||||
content: ' >';
|
||||
}
|
||||
|
||||
.menu li.active > ol {
|
||||
display: block;
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
function Menu(options) {
|
||||
var elem = options.elem;
|
||||
var self = this;
|
||||
|
||||
var activeLi;
|
||||
|
||||
elem.on('click', 'a.title', onTitleClick);
|
||||
|
||||
// item clicks are all inside ol
|
||||
elem.on('click', 'ol a', onLiClick);
|
||||
|
||||
// I use "a" here instead of LI, because hover on LI also works if going over it's child container OL
|
||||
// child container may have paddings etc, so the click may happen on that OL, outside of this item
|
||||
elem.on('hoverintent', 'ol a', onLiHoverIntent);
|
||||
|
||||
// ----------------------
|
||||
|
||||
function onLiClick(e) {
|
||||
|
||||
close();
|
||||
|
||||
var li = $(e.currentTarget).closest('li');
|
||||
|
||||
$(self).triggerHandler({
|
||||
type: 'select',
|
||||
value: getLiValue(li)
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function onTitleClick() {
|
||||
if (elem.hasClass('open')) {
|
||||
close();
|
||||
} else {
|
||||
open();
|
||||
}
|
||||
}
|
||||
|
||||
function onLiHoverIntent(e) {
|
||||
var li = $(this).closest('li');
|
||||
|
||||
if (isActiveLi(li)) return;
|
||||
|
||||
activateLi(li);
|
||||
openChildren();
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
|
||||
function isActiveLi(li) {
|
||||
if (activeLi && activeLi[0] == li[0]) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function close(argument) {
|
||||
|
||||
elem.removeClass('open');
|
||||
|
||||
if (activeLi) {
|
||||
activeLi.parentsUntil(elem).andSelf().removeClass('active');
|
||||
activeLi = null;
|
||||
}
|
||||
|
||||
$(document).off('.menu-nested');
|
||||
}
|
||||
|
||||
function getLiValue(li) {
|
||||
if (!li.length) return null;
|
||||
return li.children('a').attr('href').slice(2);
|
||||
}
|
||||
|
||||
function open() {
|
||||
|
||||
elem.addClass('open');
|
||||
|
||||
// TODO: close menu on document click outside of it
|
||||
$(document).on('click.menu-nested', function(e) {
|
||||
if ( $(e.target).closest(elem).length ) return;
|
||||
close();
|
||||
});
|
||||
}
|
||||
|
||||
function getParentLi(li) {
|
||||
return li.parent().parent();
|
||||
}
|
||||
|
||||
function activateLi(li) {
|
||||
|
||||
if (activeLi && getParentLi(li)[0] != activeLi[0]) { // if (new li is not child of activeLi)
|
||||
// not a child item, then need to close currently active ones
|
||||
// collapse parents of last active until container of new element
|
||||
collapseActiveUntil(li);
|
||||
}
|
||||
|
||||
activeLi = li;
|
||||
activeLi.addClass("active");
|
||||
}
|
||||
|
||||
function collapseActiveUntil(li) {
|
||||
|
||||
var el = activeLi;
|
||||
for(;;) {
|
||||
el.removeClass('active');
|
||||
if (el[0].parentNode == li[0].parentNode) break;
|
||||
el = getParentLi(el);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function openChildren() {
|
||||
var subcontainer = activeLi.children('ol');
|
||||
if (!subcontainer.length) return;
|
||||
|
||||
// show children
|
||||
|
||||
var left = activeLi.width(); // to the right of the parent
|
||||
var top = activeLi.position().top; // at same height as current parent
|
||||
|
||||
// lift it up, so that first subchild will be aligned with the parent
|
||||
top -= subcontainer.children('li').position().top;
|
||||
top -= subcontainer.prop('clientTop')
|
||||
|
||||
subcontainer.css({
|
||||
left: left,
|
||||
top: top
|
||||
})
|
||||
}
|
||||
|
||||
}
|
54
02-ui/05-widgets/06-widget-tasks/09-hover-menu-onclick/solution/menu.css
Executable file
54
02-ui/05-widgets/06-widget-tasks/09-hover-menu-onclick/solution/menu.css
Executable file
|
@ -0,0 +1,54 @@
|
|||
|
||||
.menu::before {
|
||||
content: '☞';
|
||||
font-size: 16px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
||||
.menu.open::before {
|
||||
content: '☟';
|
||||
}
|
||||
|
||||
.menu a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.menu > a {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.menu a {
|
||||
padding: 3px 5px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
li.active > a {
|
||||
background: blue;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.menu ol {
|
||||
margin: 0;
|
||||
padding: 3px 0;
|
||||
list-style: none;
|
||||
display: none;
|
||||
background: #eee;
|
||||
border: 1px solid black;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.menu.open > ol {
|
||||
display: block;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.menu li.has-children > a::after {
|
||||
content: ' >';
|
||||
}
|
||||
|
||||
.menu li.active > ol {
|
||||
display: block;
|
||||
}
|
131
02-ui/05-widgets/06-widget-tasks/09-hover-menu-onclick/solution/menu.js
Executable file
131
02-ui/05-widgets/06-widget-tasks/09-hover-menu-onclick/solution/menu.js
Executable file
|
@ -0,0 +1,131 @@
|
|||
function Menu(options) {
|
||||
var elem = options.elem;
|
||||
var self = this;
|
||||
|
||||
var activeLi;
|
||||
|
||||
elem.on('click', 'a.title', onTitleClick);
|
||||
|
||||
// item clicks are all inside ol
|
||||
elem.on('click', 'ol a', onLiClick);
|
||||
|
||||
// I use "a" here instead of LI, because hover on LI also works if going over it's child container OL
|
||||
// child container may have paddings etc, so the click may happen on that OL, outside of this item
|
||||
elem.on('hoverintent', 'ol a', onLiHoverIntent);
|
||||
|
||||
// ----------------------
|
||||
|
||||
function onLiClick(e) {
|
||||
|
||||
close();
|
||||
|
||||
var li = $(e.currentTarget).closest('li');
|
||||
|
||||
$(self).triggerHandler({
|
||||
type: 'select',
|
||||
value: getLiValue(li)
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function onTitleClick() {
|
||||
if (elem.hasClass('open')) {
|
||||
close();
|
||||
} else {
|
||||
open();
|
||||
}
|
||||
}
|
||||
|
||||
function onLiHoverIntent(e) {
|
||||
var li = $(this).closest('li');
|
||||
|
||||
if (isActiveLi(li)) return;
|
||||
|
||||
activateLi(li);
|
||||
openChildren();
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
|
||||
function isActiveLi(li) {
|
||||
if (activeLi && activeLi[0] == li[0]) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function close(argument) {
|
||||
|
||||
elem.removeClass('open');
|
||||
|
||||
if (activeLi) {
|
||||
activeLi.parentsUntil(elem).andSelf().removeClass('active');
|
||||
activeLi = null;
|
||||
}
|
||||
|
||||
$(document).off('.menu-nested');
|
||||
}
|
||||
|
||||
function getLiValue(li) {
|
||||
if (!li.length) return null;
|
||||
return li.children('a').attr('href').slice(2);
|
||||
}
|
||||
|
||||
function open() {
|
||||
|
||||
elem.addClass('open');
|
||||
|
||||
// TODO: close menu on document click outside of it
|
||||
$(document).on('click.menu-nested', function(e) {
|
||||
if ( $(e.target).closest(elem).length ) return;
|
||||
close();
|
||||
});
|
||||
}
|
||||
|
||||
function getParentLi(li) {
|
||||
return li.parent().parent();
|
||||
}
|
||||
|
||||
function activateLi(li) {
|
||||
|
||||
if (activeLi && getParentLi(li)[0] != activeLi[0]) { // if (new li is not child of activeLi)
|
||||
// not a child item, then need to close currently active ones
|
||||
// collapse parents of last active until container of new element
|
||||
collapseActiveUntil(li);
|
||||
}
|
||||
|
||||
activeLi = li;
|
||||
activeLi.addClass("active");
|
||||
}
|
||||
|
||||
function collapseActiveUntil(li) {
|
||||
|
||||
var el = activeLi;
|
||||
for(;;) {
|
||||
el.removeClass('active');
|
||||
if (el[0].parentNode == li[0].parentNode) break;
|
||||
el = getParentLi(el);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function openChildren() {
|
||||
var subcontainer = activeLi.children('ol');
|
||||
if (!subcontainer.length) return;
|
||||
|
||||
// show children
|
||||
|
||||
var left = activeLi.width(); // to the right of the parent
|
||||
var top = activeLi.position().top; // at same height as current parent
|
||||
|
||||
// lift it up, so that first subchild will be aligned with the parent
|
||||
top -= subcontainer.children('li').position().top;
|
||||
top -= subcontainer.prop('clientTop')
|
||||
|
||||
subcontainer.css({
|
||||
left: left,
|
||||
top: top
|
||||
})
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
# Вложенное меню с выпаданием по клику
|
||||
|
||||
[importance 4]
|
||||
|
||||
Создайте меню с выпаданием по клику и раскрытием внутренних пунктов при наведении.
|
||||
|
||||
Демо:
|
||||
[iframe src="solution" height=200 border=1]
|
||||
|
||||
При выборе -- событие `select` с выбранным значением.
|
||||
|
||||
HTML/CSS -- на ваш вкус.
|
Loading…
Add table
Add a link
Reference in a new issue