mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-19 17:38:19 +08:00
ui-default: init
将ui-default合并至主存储库便于维护
This commit is contained in:
1 parent
6317c9057f
commit
5faa54c7ca
564 files changed
+23083
-14
No files matched your search
@@ -0,0 +1,151 @@
|
||||
import _ from 'lodash';
|
||||
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
|
||||
|
||||
const TAB_TRANSITION_DURATION = 300;
|
||||
|
||||
export default class Tab extends DOMAttachedObject {
|
||||
static DOMAttachKey = 'vjTabInstance';
|
||||
|
||||
static initAll() {
|
||||
$('.section__tabs').get().forEach((tab) => {
|
||||
Tab.getOrConstruct($(tab));
|
||||
});
|
||||
}
|
||||
|
||||
static initEventListeners() {
|
||||
$(document).on('click', '.section__tab-header-item', (ev) => {
|
||||
const targetIndex = $(ev.currentTarget).attr('data-tab-index');
|
||||
const $container = $(ev.currentTarget).closest('.section__tab-container');
|
||||
const tabInstance = Tab.get($container);
|
||||
tabInstance.switchToTab(parseInt(targetIndex, 10));
|
||||
});
|
||||
}
|
||||
|
||||
constructor($dom) {
|
||||
super($dom);
|
||||
this.attached = false;
|
||||
this.attach();
|
||||
}
|
||||
|
||||
async switchToTab(idx) {
|
||||
if (idx === this.currentIndex) {
|
||||
return;
|
||||
}
|
||||
if (this.isAnimating) {
|
||||
return;
|
||||
}
|
||||
|
||||
const $tabs = this.$content.children();
|
||||
const $currentTab = $tabs.eq(this.currentIndex);
|
||||
const $newTab = $tabs.eq(idx);
|
||||
|
||||
// 0. Change header
|
||||
this.$header
|
||||
.children()
|
||||
.removeClass('selected')
|
||||
.eq(idx)
|
||||
.addClass('selected');
|
||||
|
||||
// 1. Prepare for animating
|
||||
this.isAnimating = true;
|
||||
$newTab.addClass('active');
|
||||
const animateParameter = {};
|
||||
if (idx < this.currentIndex) {
|
||||
animateParameter.from = '-100%';
|
||||
animateParameter.to = '0%';
|
||||
} else {
|
||||
animateParameter.from = '0%';
|
||||
animateParameter.to = '-100%';
|
||||
}
|
||||
$newTab
|
||||
.css('opacity', 0);
|
||||
this.$content
|
||||
.css('x', animateParameter.from)
|
||||
.width();
|
||||
|
||||
// 2. Animate transition
|
||||
$currentTab
|
||||
.transition({
|
||||
opacity: 0,
|
||||
}, {
|
||||
duration: TAB_TRANSITION_DURATION,
|
||||
easing: 'linear',
|
||||
});
|
||||
$newTab
|
||||
.transition({
|
||||
opacity: 1,
|
||||
}, {
|
||||
duration: TAB_TRANSITION_DURATION,
|
||||
easing: 'linear',
|
||||
});
|
||||
await this.$content
|
||||
.transition({
|
||||
x: animateParameter.to,
|
||||
}, {
|
||||
duration: TAB_TRANSITION_DURATION,
|
||||
easing: 'easeOutCubic',
|
||||
})
|
||||
.promise();
|
||||
|
||||
// 3. Hide previous content
|
||||
this.$content
|
||||
.children()
|
||||
.eq(this.currentIndex)
|
||||
.removeClass('active');
|
||||
this.$content
|
||||
.css('x', '0');
|
||||
|
||||
// 4. Finalize
|
||||
this.currentIndex = idx;
|
||||
this.isAnimating = false;
|
||||
}
|
||||
|
||||
attach() {
|
||||
if (this.attached) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const $container = this.$dom
|
||||
.closest('.section__tab-container');
|
||||
const $headerWrapper = $(document.createElement('div'))
|
||||
.addClass('section__tab-header-wrapper')
|
||||
.appendTo($container);
|
||||
const $contentWrapper = $(document.createElement('div'))
|
||||
.addClass('section__tab-content-wrapper')
|
||||
.appendTo($container);
|
||||
this.$header = $(document.createElement('ul'))
|
||||
.addClass('section__tab-header')
|
||||
.attr('data-slideout-ignore', 'on')
|
||||
.appendTo($headerWrapper);
|
||||
this.$content = $(document.createElement('div'))
|
||||
.addClass('section__tab-content')
|
||||
.appendTo($contentWrapper);
|
||||
|
||||
this.$dom.find('.section__tab-title').get().forEach((element, idx) => {
|
||||
$(document.createElement('li')).text($(element).text())
|
||||
.addClass('section__tab-header-item')
|
||||
.attr('data-tab-index', idx)
|
||||
.appendTo(this.$header);
|
||||
});
|
||||
|
||||
this.$dom.find('.section__tab-main')
|
||||
.appendTo(this.$content);
|
||||
|
||||
this.$dom.remove();
|
||||
this.$dom = $container;
|
||||
|
||||
this.currentIndex = 0;
|
||||
this.$content
|
||||
.children()
|
||||
.eq(0)
|
||||
.addClass('active');
|
||||
this.$header
|
||||
.children()
|
||||
.eq(0)
|
||||
.addClass('selected');
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
_.assign(Tab, DOMAttachedObject);
|
||||
@@ -0,0 +1,9 @@
|
||||
import { AutoloadPage } from 'vj/misc/Page';
|
||||
import Tab from './Tab';
|
||||
|
||||
const tabPage = new AutoloadPage('tabPage', () => {
|
||||
Tab.initAll();
|
||||
Tab.initEventListeners();
|
||||
});
|
||||
|
||||
export default tabPage;
|
||||
@@ -0,0 +1,89 @@
|
||||
@import './var.inc.styl'
|
||||
|
||||
// No JavaScript
|
||||
.section__tab-item
|
||||
margin: rem(20px) 0
|
||||
border-bottom: 1px solid #DDD
|
||||
padding: 0 rem($section-gap-h) rem($section-gap-v)
|
||||
|
||||
.section__tab-title
|
||||
font-size: rem($font-size-title)
|
||||
color: #888
|
||||
margin-bottom: 0.8em
|
||||
|
||||
// Has JavaScript
|
||||
.section__tab-header-wrapper
|
||||
overflow: hidden
|
||||
|
||||
.section__tab-header
|
||||
padding: 0 rem($section-gap-h)
|
||||
padding-top: rem($tab-item-shadow-size)
|
||||
overflow-x: auto
|
||||
white-space: nowrap
|
||||
padding-bottom: 20px
|
||||
margin-bottom: -20px
|
||||
|
||||
+mobile()
|
||||
padding-top: 0
|
||||
padding-right: rem($section-gap-h + 50px)
|
||||
webkit-overflow-scrolling: touch
|
||||
mask-image: linear-gradient(to right, rgba(0,0,0,1) 80%, rgba(0,0,0,0));
|
||||
|
||||
.section__tab-header-item
|
||||
display: inline-block
|
||||
font-size: rem($font-size-secondary)
|
||||
line-height: rem($tab-item-height)
|
||||
height: rem($tab-item-height)
|
||||
padding: 0 rem(20px)
|
||||
margin-right: rem(10px)
|
||||
user-select: none
|
||||
position: relative
|
||||
|
||||
+mobile()
|
||||
line-height: rem($tab-item-height-mobile)
|
||||
height: rem($tab-item-height-mobile)
|
||||
|
||||
.section__tab-container.immersive
|
||||
.section__tab-header-item
|
||||
color: rgba(#FFF, 0.9)
|
||||
border-radius: 1px 1px 0 0
|
||||
cursor: pointer
|
||||
transition: background .2s ease-out-cubic
|
||||
|
||||
&:hover
|
||||
color: #FFF
|
||||
|
||||
&.selected
|
||||
background: #FFF
|
||||
color: #666
|
||||
box-shadow: 0 0 10px rgba(#000, 0.3)
|
||||
|
||||
+mobile()
|
||||
&.selected
|
||||
box-shadow: none
|
||||
background: transparent
|
||||
color: #FFF
|
||||
|
||||
&::after
|
||||
position: absolute
|
||||
left: 0
|
||||
width: 100%
|
||||
bottom: 0
|
||||
height: 3px
|
||||
background: $secondary-color
|
||||
content: ''
|
||||
|
||||
.section__tab-content-wrapper
|
||||
overflow: hidden
|
||||
|
||||
.section__tab-content
|
||||
position: relative
|
||||
white-space: nowrap
|
||||
|
||||
.section__tab-main
|
||||
display: none
|
||||
vertical-align: top
|
||||
width: 100%
|
||||
|
||||
&.active
|
||||
display: inline-block
|
||||
@@ -0,0 +1,3 @@
|
||||
$tab-item-height = 35px
|
||||
$tab-item-shadow-size = 10px
|
||||
$tab-item-height-mobile = 32px // 32 * (13 / 16) is an integer
|
||||
Reference in new issue
Block a user