UNPKG

6.13 kBJavaScriptView Raw
1/*
2Copyright 2013-2015 ASIAL CORPORATION
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15
16*/
17
18import onsElements from '../ons/elements.js';
19import util from '../ons/util.js';
20import ModifierUtil from '../ons/internal/modifier-util.js';
21import AnimatorFactory from '../ons/internal/animator-factory.js';
22import OverlaySplitterAnimator from './ons-splitter/overlay-animator.js';
23import PushSplitterAnimator from './ons-splitter/push-animator.js';
24import RevealSplitterAnimator from './ons-splitter/reveal-animator.js';
25import BaseElement from './base/base-element.js';
26import deviceBackButtonDispatcher from '../ons/internal/device-back-button-dispatcher.js';
27import contentReady from '../ons/content-ready.js';
28
29const _animatorDict = {
30 default: OverlaySplitterAnimator,
31 overlay: OverlaySplitterAnimator,
32 push: PushSplitterAnimator,
33 reveal: RevealSplitterAnimator
34};
35
36/**
37 * @element ons-splitter
38 * @category menu
39 * @description
40 * [en]
41 * A component that enables responsive layout by implementing both a two-column layout and a sliding menu layout.
42 *
43 * It can be configured to automatically expand into a column layout on large screens and collapse the menu on smaller screens. When the menu is collapsed the user can open it by swiping.
44 * [/en]
45 * [ja][/ja]
46 * @codepen rOQOML
47 * @tutorial vanilla/Reference/splitter
48 * @guide fundamentals.html#managing-pages
49 * [en]Managing multiple pages.[/en]
50 * [ja]複数のページを管理する[/ja]
51 * @seealso ons-splitter-content
52 * [en]The `<ons-splitter-content>` component contains the main content of the page.[/en]
53 * [ja]ons-splitter-contentコンポーネント[/ja]
54 * @seealso ons-splitter-side
55 * [en]The `<ons-splitter-side>` component contains the menu.[/en]
56 * [ja]ons-splitter-sideコンポーネント[/ja]
57 * @example
58 * <ons-splitter id="splitter">
59 * <ons-splitter-content>
60 * ...
61 * </ons-splitter-content>
62 *
63 * <ons-splitter-side side="left" width="80%" collapse swipeable>
64 * ...
65 * </ons-splitter-side>
66 * </ons-splitter>
67 *
68 * <script>
69 * var splitter = document.getElementById('splitter');
70 * splitter.left.open();
71 * </script>
72 */
73export default class SplitterElement extends BaseElement {
74
75 _getSide(side) {
76 const element = util.findChild(this, e => {
77 return util.match(e, 'ons-splitter-side') && e.getAttribute('side') === side;
78 });
79 return element;
80 }
81
82 /**
83 * @property left
84 * @readonly
85 * @type {HTMLElement}
86 * @description
87 * [en]Left `<ons-splitter-side>` element.[/en]
88 * [ja][/ja]
89 */
90 get left() {
91 return this._getSide('left');
92 }
93 /**
94 * @property right
95 * @readonly
96 * @type {HTMLElement}
97 * @description
98 * [en]Right `<ons-splitter-side>` element.[/en]
99 * [ja][/ja]
100 */
101 get right() {
102 return this._getSide('right');
103 }
104
105 /**
106 * @property side
107 * @readonly
108 * @type {HTMLElement}
109 * @description
110 * [en]First `<ons-splitter-side>` element regardless the actual side.[/en]
111 * [ja][/ja]
112 */
113 get side() {
114 return util.findChild(this, 'ons-splitter-side');
115 }
116
117 get _sides() {
118 return [this.left, this.right].filter(e => e);
119 }
120 /**
121 * @property content
122 * @readonly
123 * @type {HTMLElement}
124 * @description
125 * [en]The `<ons-splitter-content>` element.[/en]
126 * [ja][/ja]
127 */
128 get content() {
129 return util.findChild(this, 'ons-splitter-content');
130 }
131
132 get topPage() {
133 return this.content._content;
134 }
135
136 get mask() {
137 return util.findChild(this, 'ons-splitter-mask');
138 }
139
140 /**
141 * @property onDeviceBackButton
142 * @type {Object}
143 * @description
144 * [en]Back-button handler.[/en]
145 * [ja]バックボタンハンドラ。[/ja]
146 */
147 get onDeviceBackButton() {
148 return this._backButtonHandler;
149 }
150
151 set onDeviceBackButton(callback) {
152 if (this._backButtonHandler) {
153 this._backButtonHandler.destroy();
154 }
155
156 this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback);
157 }
158
159 _onDeviceBackButton(event) {
160 this._sides.some(s => s.isOpen ? s.close() : false) || event.callParentHandler();
161 }
162
163 _onModeChange(e) {
164 if (e.target.parentNode) {
165 contentReady(this, () => {
166 this._layout();
167 });
168 }
169 }
170
171 _layout() {
172 this._sides.forEach(side => {
173 if (this.content) {
174 this.content.style[side.side] = side.mode === 'split' ? side.style.width : 0;
175 }
176 });
177 }
178
179 constructor() {
180 super();
181
182 this._onModeChange = this._onModeChange.bind(this);
183
184 contentReady(this, () => {
185 !this.mask && this.appendChild(document.createElement('ons-splitter-mask'));
186 this._layout();
187 });
188 }
189
190 connectedCallback() {
191 this.onDeviceBackButton = this._onDeviceBackButton.bind(this);
192 this.addEventListener('modechange', this._onModeChange, false);
193 }
194
195 disconnectedCallback() {
196 this._backButtonHandler.destroy();
197 this._backButtonHandler = null;
198 this.removeEventListener('modechange', this._onModeChange, false);
199 }
200
201 attributeChangedCallback(name, last, current) {}
202
203 _show() {
204 util.propagateAction(this, '_show');
205 }
206
207 _hide() {
208 util.propagateAction(this, '_hide');
209 }
210
211 _destroy() {
212 util.propagateAction(this, '_destroy');
213 this.remove();
214 }
215
216 static registerAnimator(name, Animator) {
217 if (!(Animator instanceof SplitterAnimator)) {
218 util.throwAnimator('Splitter');
219 }
220 _animatorDict[name] = Animator;
221 }
222
223 static get SplitterAnimator() {
224 return SplitterAnimator;
225 }
226
227 static get animators() {
228 return _animatorDict;
229 }
230}
231
232onsElements.Splitter = SplitterElement;
233customElements.define('ons-splitter', SplitterElement);