Skip to content

Commit

Permalink
Пагинация
Browse files Browse the repository at this point in the history
  • Loading branch information
xaota committed Nov 12, 2020
1 parent a34d457 commit a9b2e7e
Show file tree
Hide file tree
Showing 13 changed files with 454 additions and 50 deletions.
52 changes: 52 additions & 0 deletions components/blur.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import Component, {html, css} from '../script/Component.js';

const attributes = {};
const properties = {};

const style = css`
slot {
display: inline;
filter: blur(5px);
user-select: none;
}
:host([block]) slot {
display: block;
}
:host([disabled]) slot {
filter: none;
user-select: initial;
}`;

/** Blur {UIBlur} @class @ui @component <ui-blur />
* Размытие текстовых или блочных данных
*/
export default class UIBlur extends Component {
static template = html`
<template>
<style>${style}</style>
<slot></slot>
</template>`;

/** Создание компонента {UIBlur} @constructor
* @param {type} store type
*/
constructor(store) {
super();
this.store({store});
}

/** Создание элемента в DOM (DOM доступен) / mount @lifecycle
* @param {ShadowRoot} node корневой узел элемента
* @return {UIBlur} @this текущий компонент
*/
mount(node) {
super.mount(node, attributes, properties);

const {store} = this.store();
return this;
}


}

Component.init(UIBlur, 'ui-blur', {attributes, properties});
13 changes: 9 additions & 4 deletions components/button.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,10 @@ const style = css`
margin-right: -1.2em;
}`;

const attributes = {}
const attributes = {
mode() {},
text() {}
}
const properties = {
disabled() {}
}
Expand All @@ -143,9 +146,11 @@ const properties = {
super();
if (content === undefined) return;
if (typeof content !== 'object') content = {label: content};
if ('label' in content) this.innerHTML = content.label;
if ('mode' in content) this.mode = content.mode;
if ('text' in content) this.text = content.text;

if ('label' in content) this.innerText = content.label;
if ('mode' in content && content.mode) this.mode = content.mode;
if ('text' in content && content.text) this.text = content.text;
if ('disabled' in content && content.disabled === true) this.disabled = true;
}

/** Создание элемента в DOM (DOM доступен) / mount @lifecycle
Expand Down
22 changes: 19 additions & 3 deletions components/checkbox.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Component, {html, css} from '../script/Component.js';
import {updateChildrenProperty, updateChildrenElement} from '../script/DOM.js';
import UIIcon from './icon.js';

const style = css`
:host {
Expand All @@ -9,6 +10,7 @@ const style = css`
label {
display: flex;
position: relative;
}
slot {
Expand Down Expand Up @@ -42,8 +44,19 @@ const style = css`
border-color: #d5d5d5;
}
#checkbox:checked + label:before {
background: #6fbeb5 url('../../icons/light/check.svg') center center;
#checkbox + label > ui-icon {
position: absolute;
left: 0;
transform: scale(0.8);
opacity: 0;
transition: ease opacity 0.3s;
}
:host([right]) #checkbox + label > ui-icon {
left: auto;
right: -2px;
}
#checkbox:checked + label > ui-icon {
opacity: 1;
}
#checkbox:disabled + label:before {
Expand Down Expand Up @@ -75,7 +88,10 @@ const properties = {
<template>
<style>${style}</style>
<input type="checkbox" id="checkbox" hidden />
<label for="checkbox"><slot></slot></label>
<label for="checkbox">
<ui-icon>check</ui-icon>
<slot></slot>
</label>
</template>`;

/** Создание компонента {UICheckbox} @constructor
Expand Down
2 changes: 1 addition & 1 deletion components/drop-root.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ const properties = {}

// root.addEventListener('click', _ => drop.forEach(e => e.style.display = 'block'), {once: true});
slot.addEventListener('click', _ => {
console.log('slot click');
// console.log('slot click');
drop.visible = !drop.visible;
// setTimeout(() => drop.visible = false, 400);
});
Expand Down
45 changes: 24 additions & 21 deletions components/input.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Component, {html, css, url} from '../script/Component.js';
import {updateChildrenElement, pointerOffset} from '../script/DOM.js';
import {updateChildrenElement, pointerOffset, updateChildrenText} from '../script/DOM.js';
import {drawRipple} from '../script/Material.js';
import UIIcon from './icon.js';

const style = css`
@import "${url('../style/color.css', import.meta.url)}";
Expand All @@ -18,7 +19,7 @@ const style = css`
div.root {
user-select: none;
font: normal 1em / normal Tahoma, sans-serif;
font: var(--font);
transition: 0.3s all ease;
position: relative;
overflow: hidden;
Expand All @@ -45,7 +46,7 @@ const style = css`
padding: 1.2em 0.6em 1.2em var(--left);
background: none;
border: none;
font: normal 1em / normal Tahoma, sans-serif;
font: var(--font);
transition: 0.2s all ease;
}
Expand All @@ -60,14 +61,13 @@ const style = css`
pointer-events: none;
transition: 0.2s all ease;
top: 1.5em;
font: normal 1em / normal Tahoma, sans-serif;
font: var(--font);
white-space: nowrap;
}
div.root > input:focus + label, div.root > input:valid + label {
font-size: .8em;
color: var(--stroke-active);
/* left: 0.6em; */
top: .2em;
}
Expand All @@ -84,8 +84,17 @@ const style = css`
/* ::-moz-placeholder { color: blue; } // Firefox 19+
:-ms-input-placeholder { color: blue; } */
:host([icon]:not([right])) div.root {
background-position: left 0.3em top 1.4em;
:host(:not([icon])) ui-icon { /* , ui-icon:empty */
display: none;
}
:host([icon]) ui-icon {
display: block;
position: absolute;
pointer-events: none;
}
:host([icon]:not([right])) div.root > ui-icon {
left: 0.3em;
top: 1.4em;
}
:host([icon]:not([right])) div.root > input {
padding-left: 2em;
Expand All @@ -94,8 +103,9 @@ const style = css`
left: 2.3em;
}
:host([icon][right]) div.root {
background-position: right 0.3em top 1.4em;
:host([icon][right]) div.root > ui-icon {
right: 0.3em;
top: 1.4em;
}
:host([icon][right]) div.root > input {
padding-right: 2em;
Expand Down Expand Up @@ -156,7 +166,7 @@ const style = css`
const attributes = {
value(root, value) { updateChildrenElement(root, 'input', 'value', value) },
placeholder(root, value) { updateChildrenElement(root, 'input', 'placeholder', value) },
icon(root, value) { setIcon(value, root) }
icon(root, value) { updateChildrenText(root, 'ui-icon', value) }
}
const properties = {}

Expand All @@ -170,6 +180,7 @@ const properties = {}
<div class="root">
<input required />
<label><slot></slot></label>
<ui-icon></ui-icon>
</div>
</template>`;

Expand All @@ -187,14 +198,15 @@ const properties = {}
*/
mount(node) {
super.mount(node, attributes, properties);
const input = node.querySelector('input');

const root = node.querySelector('div.root');
root.addEventListener('click', event => {
const position = pointerOffset(root, event);
root.style.setProperty('--position', position.x + 'px');
drawRipple.call(root, position);
});

const input = node.querySelector('input');
input.addEventListener('blur', _ => {
root.style.setProperty('--position', '50%');
});
Expand All @@ -203,18 +215,9 @@ const properties = {}
input.addEventListener('change', _ => this.event('change'));
input.addEventListener('keydown', e => { if (e.key === 'Enter') return this.event('enter') });
this.addEventListener('focus', _ => input.focus());

return this;
}
}

Component.init(UIInput, 'ui-input', {attributes, properties});

// #region [Private]
/** */
function setIcon(icon, root) {
if (!root || !root.style) return;
if (!icon) return root.style.backgroundImage = 'none';
// const href = UIIcon.src(icon);
// root.style.backgroundImage = `url(${href.toString()})`;
}
// #endregion
132 changes: 132 additions & 0 deletions components/pagination.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import Component, {html, css} from '../script/Component.js';
import {clear} from '../script/DOM.js';
import UIButton from './button.js';
import UIIcon from './icon.js';

const attributes = {
pages(node, value) {
const pages = parseInt(value) || 0;
createContent.call(this, node, pages, this.current);
},
current(node, value) {
const pages = parseInt(this.pages) || 0;
const current = parseInt(value) || 1;
createContent.call(this, node, pages, value);
}
};

const properties = {};

const style = css`
:host {
display: block;
}
#root {
text-align: center;
}
#root > ui-icon {
position: relative;
bottom: -0.5em;
margin-left: 0.2em;
margin-right: 0.2em;
}
#root > ui-button {
transform: scale(0.8);
margin-left: 0.05em;
margin-right: 0.05em;
}`;

/** Pagination {UIPagination} @class @ui @component <ui-pagination />
* Пагинация по страничным данным
*/
export default class UIPagination extends Component {
static template = html`
<template>
<style>${style}</style>
<div id="root"></div>
</template>`;

/** Создание компонента {UIPagination} @constructor
* @param {number} pages общее количество страниц
* @param {number} [current] текущая страница
* @attention нумерация страниц начинается с 1
*/
constructor(pages, current) {
super();
if (pages) this.pages = pages;
if (current) this.current = current;
}

/** Создание элемента в DOM (DOM доступен) / mount @lifecycle
* @param {ShadowRoot} node корневой узел элемента
* @return {UIPagination} @this текущий компонент
*/
mount(node) {
return super.mount(node, attributes, properties);
}
}

Component.init(UIPagination, 'ui-pagination', {attributes, properties});

// #region [Private]
function createContent(node, pages, current) {
if (pages < 2) return; // всего одна страница -> пагинация не нужна

const root = node.getElementById('root');
if (!root) return;

current = getCurrent(current);
const buttons = createButtons(pages, current, page => this.event('change', {page}));

clear(root);
buttons.forEach(b => root.appendChild(b));
}

function createButtons(length, current, callback) {
// выбираем страницы, кнопки которых будут показаны
const creating = length < 10 ? () => true : () => false;
const pages = Array.from({ length }, creating); // если страниц больше 10 -> сначала все скрыты
pages[0] = true; // показ первой страницы
pages[length - 1] = true; // показ последней страницы
pages[current] = true; // показ текущей страницы
if (current < length - 1) pages[current + 1] = true; // показ следующей страницы
if (current > 0) pages[current - 1] = true; // показ предыдущей страницы

// создание кнопок для рендеринга
const buttons = new Array();
let skip = 0;
pages.forEach((show, index) => {
if (!show) {
++skip;
return;
}
if (skip > 0) {
if (skip > 2) {
buttons.push(new UIIcon('more_horiz'));
} else {
// если пропущено не более 2х страниц - покажем их
while (skip--) {
const label = index - skip;
const button = new UIButton({text: 'outline', label});
button.addEventListener('click', () => callback(label));
buttons.push(button);
}
}
}

skip = 0;
const mode = index === current ? "primary" : "";
const disabled = index === current;
const label = index + 1;
const button = new UIButton({text: 'outline', label, mode, disabled});
if (!disabled) button.addEventListener('click', () => callback(label));
buttons.push(button);
});

return buttons;
}

function getCurrent(value) {
return (value || 1) - 1;
}
// #endregion
Loading

0 comments on commit a9b2e7e

Please sign in to comment.