UNPKG

66.4 kBJavaScriptView Raw
1/************************************
2
3 RADIX
4 - Version : 4.0.1
5
6 Copyright 2021 shoalwave and other contributors.
7 Released under the MIT License.
8 https://github.com/7304sk/RADIX/blob/main/LICENSE.txt
9
10************************************/
11/**
12 * 本体クラス
13 * @typedef radix
14 * @type class
15 * @property {object} option オプション値を格納
16 * @property {object} modalParts モーダルウィンドウ機能で生成しているエレメントノードたち
17 * @property {object} events 各操作に対して発火しているイベントフックたち
18 * @property {object} icons SVGアイコンの全ノード
19 * @property {boolean} isMobile モバイル端末(タッチ操作可能)か否か
20 * @property {boolean} navState ナビゲーションの開閉状態
21 * @property {boolean} modalState モーダルウィンドウの開閉状態
22 * @property {boolean} initialized init() 関数の実行が完了したか
23 * @property {function} init radixの初期化を行う関数
24 * @property {function} toggleNav ナビゲーション開閉を実行する関数
25 * @property {function} smoothScroll スムーススクロールを実行する関数
26 * @property {function} replaceIcon SVGアイコンにエレメントを置換する関数
27 * @property {function} dragDown ドラッグスクロールのマウスダウン
28 * @property {function} dragMove ドラッグスクロールのマウスムーブ
29 * @property {function} dragUp ドラッグスクロールのマウスアップ
30 * @property {function} modalOpen モーダルウィンドウを開く関数
31 * @property {function} modalClose モーダルウィンドウを閉じる関数
32 * @property {function} modalResize モーダルウィンドウの拡縮をする関数
33 * @property {function} floatRound 浮動小数点数の文字列変換関数
34 * @property {function} floatCeil 浮動小数点数の文字列変換関数
35 * @property {function} floatFloor 浮動小数点数の文字列変換関数
36 * @property {function} preventScroll ページ全体の縦方向スクロール禁止を操作する関数
37 * @property {function} getEasing イージング関数を取得する関数
38 */
39let DOMLoaded = false;
40let windowLoaded = false;
41window.addEventListener('DOMContentLoaded',() => {DOMLoaded = true});
42window.addEventListener('load',() => {windowLoaded = true});
43class Radix {
44 /**
45 * コンストラクタ
46 * @constructor
47 */
48 constructor(option, mode) {
49 const defOption = {
50 timeFrame: 10,
51 preload: {
52 active: false,
53 selector: '',
54 class: 'hide',
55 delay: 200,
56 preventScroll: false
57 },
58 smoothScroll: {
59 active: true,
60 duration: 600,
61 easing: 'easeInOutExpo'
62 },
63 autoTargetBlank: {
64 active: true
65 },
66 toggleNav: {
67 active: false,
68 trigger: '',
69 target: '',
70 class: 'opened',
71 preventScroll: false
72 },
73 icons: {
74 active: true,
75 selector: '.radix-icon'
76 },
77 dragScroll: {
78 active: true,
79 selector: '.radix-drag',
80 hint: true
81 },
82 flexFix: {
83 active: true,
84 selector: '.radix-flexfix',
85 inherit: true,
86 min: 0
87 },
88 modal: {
89 active: true,
90 selector: '.radix-modal',
91 class: 'white',
92 resizeDuration: 300,
93 resizeEasing: 'easeInOutBack',
94 scaleStep: [0.2, 0.4, 0.6, 0.8, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5],
95 fit: true,
96 drag: true,
97 magnify: true,
98 wrap: false
99 },
100 scrollAppear: {
101 active: true,
102 selector: '.radix-appear',
103 delay: 200,
104 reset: true,
105 class: 'active'
106 }
107 }
108 const argFlg = this.typeJudge(option) == 'object' ? true : false;
109 Object.keys(defOption).forEach(key => {
110 if (mode === false && key != 'timeFrame') {
111 defOption[key].active = false;
112 }
113 if (argFlg) {
114 Object.assign(defOption[key], option[key]);
115 }
116 });
117 this.option = defOption;
118 // インスタンス変数
119 this.navState = false;
120 this.modalState = false;
121 this.initialized = false;
122 this.isMobile = typeof window.ontouchstart === "undefined" ? false : true;
123 }
124 events = {
125 beforeInitialize: new CustomEvent('_radixInit'),
126 afterInitialize: new CustomEvent('radixInit_'),
127 beforeScroll: new CustomEvent('_radixScroll'),
128 afterScroll: new CustomEvent('radixScroll_'),
129 beforeNavOpen: new CustomEvent('_radixNavOpen'),
130 afterNavOpen: new CustomEvent('radixNavOpen_'),
131 beforeNavClose: new CustomEvent('_radixNavClose'),
132 afterNavClose: new CustomEvent('radixNavClose_'),
133 beforeModalOpen: new CustomEvent('_radixModalOpen'),
134 afterModalOpen: new CustomEvent('radixModalOpen_'),
135 beforeModalClose: new CustomEvent('_radixModalClose'),
136 afterModalClose: new CustomEvent('radixModalClose_'),
137 }
138 /**
139 * DOMロード時に実行し初期化する関数
140 */
141 init() {
142 const self = this;
143 new Promise(resolve => {
144 // Speed 0
145 document.dispatchEvent(self.events.beforeInitialize);
146 if (DOMLoaded) {
147 resolve();
148 } else {
149 window.addEventListener('DOMContentLoaded', resolve);
150 }
151 }).then(() => {
152 // Speed 1
153 return new Promise(resolve => {
154 self.DOM_ROOTS = document.querySelectorAll('html,body');
155 // preload display
156 if (self.option.preload.preventScroll) self.preventScroll(true);
157 let preloader = self.option.preload.selector.length > 0 ? document.querySelectorAll(self.option.preload.selector) : [];
158 window.addEventListener('load', () => {
159 if (self.option.preload.active && preloader && self.initialized) {
160 setTimeout(() => {
161 if (self.option.preload.preventScroll) self.preventScroll(false);
162 preloader.forEach(pl => {
163 pl.classList.add(self.option.preload.class);
164 });
165 }, self.option.preload.delay);
166 }
167 });
168 document.addEventListener('radixInit_', () => {
169 self.initialized = true;
170 if (self.option.preload.active && preloader.length > 0 && windowLoaded) {
171 setTimeout(() => {
172 if (self.option.preload.preventScroll) self.preventScroll(false);
173 preloader.forEach(pl => {
174 pl.classList.add(self.option.preload.class);
175 });
176 }, self.option.preload.delay);
177 }
178 });
179 // SVG insert
180 if (self.option.icons.active) {
181 const iconSources = {
182 cross: {
183 viewbox: '0 0 100 100',
184 path: 'M 2 17 L 17 2 L 50 35 L 83 2 L 98 17 L 65 50 L 98 83 L 83 98 L 50 65 L 17 98 L 2 83 L 35 50 L 2 17 Z',
185 fill: true,
186 stroke: 0,
187 linejoin: 'miter',
188 linecap: 'butt'
189 },
190 angle_top: {
191 viewbox: '0 0 100 100',
192 path: 'M 50 19 L 97 66 L 84 79 L 50 45 L 16 79 L 3 66 L 50 19 Z',
193 fill: true,
194 stroke: 0
195 },
196 angle_right: {
197 viewbox: '0 0 100 100',
198 path: 'M 81 50 L 34 97 L 21 84 L 55 50 L 21 16 L 34 3 L 81 50 Z',
199 fill: true,
200 stroke: 0
201 },
202 angle_bottom: {
203 viewbox: '0 0 100 100',
204 path: 'M 50 81 L 97 34 L 84 21 L 50 55 L 16 21 L 3 34 L 50 81 Z',
205 fill: true,
206 stroke: 0
207 },
208 angle_left: {
209 viewbox: '0 0 100 100',
210 path: 'M 19 50 L 66 3 L 79 16 L 45 50 L 79 84 L 66 97 L 19 50 Z',
211 fill: true,
212 stroke: 0
213 },
214 arrow_lr: {
215 viewbox: '0 0 100 100',
216 path: 'M 10 50 L 35 20 L 35 42 L 65 42 L 65 20 L 90 50 L 65 80 L 65 58 L 35 58 L 35 80 L 10 50 Z',
217 fill: true,
218 stroke: 0
219 },
220 arrow_tb: {
221 viewbox: '0 0 100 100',
222 path: 'M 50 10 L 80 35 L 58 35 L 58 65 L 80 65 L 50 90 L 20 65 L 42 65 L 42 35 L 20 35 L 50 10 Z',
223 fill: true,
224 stroke: 0
225 },
226 magnifying_glass: {
227 viewbox: '0 0 500 500',
228 path: 'M 120 195 C 120 92.896 202.896 10 305 10 C 407.104 10 490 92.896 490 195 C 490 297.104 407.104 380 305 380 C 202.896 380 120 297.104 120 195 Z M 180 195 C 179.99 186.52 180.85 178.06 182.55 169.75 C 184.18 161.76 186.61 153.94 189.8 146.42 C 196.1 131.55 205.21 118.05 216.64 106.64 C 228.05 95.21 241.55 86.1 256.42 79.8 C 263.94 76.61 271.76 74.18 279.76 72.54 C 288.07 70.85 296.52 69.99 305 70 C 313.48 69.99 321.93 70.85 330.24 72.54 C 338.24 74.18 346.06 76.61 353.58 79.8 C 368.45 86.1 381.95 95.21 393.36 106.64 C 404.79 118.05 413.9 131.55 420.2 146.42 C 423.39 153.94 425.82 161.76 427.46 169.76 C 429.15 178.07 430.01 186.52 430 195 C 430.01 203.48 429.15 211.93 427.46 220.24 C 425.82 228.24 423.39 236.06 420.2 243.58 C 413.9 258.45 404.79 271.95 393.36 283.36 C 381.95 294.79 368.45 303.9 353.58 310.2 C 346.06 313.39 338.24 315.82 330.24 317.46 C 321.93 319.15 313.48 320.01 305 320 C 296.52 320.01 288.07 319.15 279.76 317.46 C 271.76 315.82 263.94 313.39 256.42 310.2 C 241.55 303.9 228.05 294.79 216.64 283.36 C 205.21 271.95 196.1 258.45 189.8 243.58 C 186.61 236.06 184.18 228.24 182.54 220.24 C 180.85 211.93 179.99 203.48 180 195 Z M 13 490 L 13 413.148 L 126.148 300 L 203 376.852 L 89.852 490 L 13 490 Z',
229 fill: true,
230 fillRule: "evenodd",
231 stroke: 0
232 },
233 zoom_in: {
234 viewbox: '0 0 500 500',
235 path: 'M 120 195 C 120 92.896 202.896 10 305 10 C 407.104 10 490 92.896 490 195 C 490 297.104 407.104 380 305 380 C 202.896 380 120 297.104 120 195 Z M 180 195 C 179.99 186.52 180.85 178.06 182.55 169.75 C 184.18 161.76 186.61 153.94 189.8 146.42 C 196.1 131.55 205.21 118.05 216.64 106.64 C 228.05 95.21 241.55 86.1 256.42 79.8 C 263.94 76.61 271.76 74.18 279.76 72.54 C 288.07 70.85 296.52 69.99 305 70 C 313.48 69.99 321.93 70.85 330.24 72.54 C 338.24 74.18 346.06 76.61 353.58 79.8 C 368.45 86.1 381.95 95.21 393.36 106.64 C 404.79 118.05 413.9 131.55 420.2 146.42 C 423.39 153.94 425.82 161.76 427.46 169.76 C 429.15 178.07 430.01 186.52 430 195 C 430.01 203.48 429.15 211.93 427.46 220.24 C 425.82 228.24 423.39 236.06 420.2 243.58 C 413.9 258.45 404.79 271.95 393.36 283.36 C 381.95 294.79 368.45 303.9 353.58 310.2 C 346.06 313.39 338.24 315.82 330.24 317.46 C 321.93 319.15 313.48 320.01 305 320 C 296.52 320.01 288.07 319.15 279.76 317.46 C 271.76 315.82 263.94 313.39 256.42 310.2 C 241.55 303.9 228.05 294.79 216.64 283.36 C 205.21 271.95 196.1 258.45 189.8 243.58 C 186.61 236.06 184.18 228.24 182.54 220.24 C 180.85 211.93 179.99 203.48 180 195 Z M 13 490 L 13 413.148 L 126.148 300 L 203 376.852 L 89.852 490 L 13 490 Z M 205 160 L 270 160 L 270 95 L 340 95 L 340 160 L 405 160 L 405 230 L 340 230 L 340 295 L 270 295 L 270 230 L 205 230 L 205 160 Z',
236 fill: true,
237 fillRule: "evenodd",
238 stroke: 0
239 },
240 zoom_out: {
241 viewbox: '0 0 500 500',
242 path: 'M 120 195 C 120 92.896 202.896 10 305 10 C 407.104 10 490 92.896 490 195 C 490 297.104 407.104 380 305 380 C 202.896 380 120 297.104 120 195 Z M 180 195 C 179.99 186.52 180.85 178.06 182.55 169.75 C 184.18 161.76 186.61 153.94 189.8 146.42 C 196.1 131.55 205.21 118.05 216.64 106.64 C 228.05 95.21 241.55 86.1 256.42 79.8 C 263.94 76.61 271.76 74.18 279.76 72.54 C 288.07 70.85 296.52 69.99 305 70 C 313.48 69.99 321.93 70.85 330.24 72.54 C 338.24 74.18 346.06 76.61 353.58 79.8 C 368.45 86.1 381.95 95.21 393.36 106.64 C 404.79 118.05 413.9 131.55 420.2 146.42 C 423.39 153.94 425.82 161.76 427.46 169.76 C 429.15 178.07 430.01 186.52 430 195 C 430.01 203.48 429.15 211.93 427.46 220.24 C 425.82 228.24 423.39 236.06 420.2 243.58 C 413.9 258.45 404.79 271.95 393.36 283.36 C 381.95 294.79 368.45 303.9 353.58 310.2 C 346.06 313.39 338.24 315.82 330.24 317.46 C 321.93 319.15 313.48 320.01 305 320 C 296.52 320.01 288.07 319.15 279.76 317.46 C 271.76 315.82 263.94 313.39 256.42 310.2 C 241.55 303.9 228.05 294.79 216.64 283.36 C 205.21 271.95 196.1 258.45 189.8 243.58 C 186.61 236.06 184.18 228.24 182.54 220.24 C 180.85 211.93 179.99 203.48 180 195 Z M 13 490 L 13 413.148 L 126.148 300 L 203 376.852 L 89.852 490 L 13 490 Z M 205 160 L 405 160 L 405 230 L 205 230 L 205 160 Z',
243 fill: true,
244 fillRule: "evenodd",
245 stroke: 0
246 }
247 };
248 self.icons = {};
249 Object.keys(iconSources).forEach(iconName => {
250 let iconData = iconSources[iconName];
251 let svgIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
252 svgIcon.setAttribute('viewBox', iconData.viewbox);
253 svgIcon.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
254 svgIcon.classList.add('radix-icon');
255 svgIcon.classList.add('rdx-icon-'+iconName);
256 let iconPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
257 iconPath.setAttribute('d', iconData.path);
258 if (iconData.fill) {
259 iconPath.setAttribute('fill', 'currentColor');
260 if (iconData.fillRule !== undefined) iconPath.setAttribute('fill-rule', iconData.fillRule);
261 } else {
262 iconPath.setAttribute('fill', 'none');
263 }
264 if (iconData.stroke === 0) {
265 iconPath.setAttribute('stroke', 'none');
266 } else {
267 iconPath.setAttribute('stroke', 'currentColor');
268 iconPath.setAttribute('stroke-linejoin', iconData.linejoin);
269 iconPath.setAttribute('stroke-linecap', iconData.linecap);
270 }
271 iconPath.setAttribute('stroke', 'none');
272 svgIcon.appendChild(iconPath);
273 self.icons[iconName] = svgIcon;
274 });
275 // hamburger Menu
276 let hmbgr = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
277 let hmbgrLine1 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
278 let hmbgrLine2 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
279 let hmbgrLine3 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
280 hmbgr.setAttribute('viewBox', '0 0 50 50');
281 hmbgr.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
282 hmbgr.classList.add('radix-icon');
283 hmbgr.classList.add('rdx-icon-hamburger');
284 hmbgrLine1.setAttribute('x1', 5);
285 hmbgrLine1.setAttribute('y1', 13);
286 hmbgrLine1.setAttribute('x2', 45);
287 hmbgrLine1.setAttribute('y2', 13);
288 hmbgrLine1.classList.add('bar1');
289 hmbgrLine2.setAttribute('x1', 5);
290 hmbgrLine2.setAttribute('y1', 25);
291 hmbgrLine2.setAttribute('x2', 45);
292 hmbgrLine2.setAttribute('y2', 25);
293 hmbgrLine2.classList.add('bar2');
294 hmbgrLine3.setAttribute('x1', 5);
295 hmbgrLine3.setAttribute('y1', 37);
296 hmbgrLine3.setAttribute('x2', 45);
297 hmbgrLine3.setAttribute('y2', 37);
298 hmbgrLine3.classList.add('bar3');
299 hmbgr.appendChild(hmbgrLine1);
300 hmbgr.appendChild(hmbgrLine2);
301 hmbgr.appendChild(hmbgrLine3);
302 self.icons.hamburger = hmbgr;
303 // svg insert
304 let iconCalls = document.querySelectorAll(self.option.icons.selector);
305 if (iconCalls) {
306 iconCalls.forEach(iconCall => {
307 let innerText = iconCall.textContent;
308 self.replaceIcon(iconCall, innerText);
309 });
310 }
311 }
312 resolve();
313 });
314 }).then(() => {
315 // Speed 2
316 return new Promise(resolve => {
317 // Smooth scroll and Auto fill target blank
318 if (self.option.smoothScroll.active || self.option.autoTargetBlank.active) {
319 const links = document.querySelectorAll('a');
320 let scrollFrom = null;
321 let scrollTo = null;
322 links.forEach(link => {
323 if (!link.hasAttribute('href') || link.getAttribute('href').length == 0) {
324 link.setAttribute('href', '#');
325 }
326 let linkHref = link.getAttribute('href');
327 // Smooth scroll
328 if (self.option.smoothScroll.active) {
329 let firstLetter = linkHref.substring(0, 1);
330 let hrefTarget = linkHref.substring(1);
331 if (firstLetter === '#') {
332 link.addEventListener('click', event => {
333 event.preventDefault();
334 const target = hrefTarget.length > 0 ? document.getElementById(hrefTarget) : document.body;
335 const uniqueEasing = link.dataset.scrollEasing;
336 const uniqueDuration = link.dataset.scrollDuration;
337 scrollFrom = window.scrollY;
338 scrollTo = window.scrollY + target.getBoundingClientRect().top;
339 self.smoothScroll(scrollFrom, scrollTo, uniqueDuration, uniqueEasing);
340 });
341 }
342 }
343 // Auto fill target blank
344 if (self.option.autoTargetBlank.active) {
345 let host = null;
346 if (linkHref.match(/.+\.pdf$/)) {
347 link.setAttribute('target', '_blank');
348 link.classList.add('rdx-pdf');
349 } else if (linkHref.match(/^http/)) {
350 host = window.location.hostname;
351 if (host === '' || linkHref.indexOf(host) < 0) {
352 link.setAttribute('target', '_blank');
353 link.classList.add('rdx-extlink');
354 }
355 }
356 }
357 });
358 }
359 // Toggle menu
360 if (self.option.toggleNav.active && self.option.toggleNav.trigger !== '' && self.option.toggleNav.target !== '') {
361 self.navState = false;
362 let toggleTrigger = document.querySelectorAll(self.option.toggleNav.trigger);
363 toggleTrigger.forEach(t => {
364 t.addEventListener('click', () => { self.toggleNav(); });
365 });
366 }
367 // drag scroll
368 if (self.option.dragScroll.active && self.option.dragScroll.selector !== '') {
369 let dragScrollWrapper = Array.from(document.querySelectorAll(self.option.dragScroll.selector));
370 let toggleHint = () => {
371 let target = document.querySelector('[rdx-drag-on="true"]');
372 if (target !== null) {
373 let thisHint = target.querySelector('.rdx-drag-hint');
374 if (thisHint !== null && (target.scrollLeft > 0 || target.scrollWidth === target.clientWidth)) {
375 thisHint.classList.add('hide');
376 }
377 }
378 };
379 let scrollHint = document.createElement('div');
380 scrollHint.classList.add('rdx-drag-hint');
381 let scrollHintInner = document.createElement('div');
382 scrollHintInner.classList.add('rdx-drag-hint-inner');
383 scrollHint.appendChild(scrollHintInner);
384 scrollHintInner.innerHTML = '<div class="rdx-drag-hint-text">DRAG</div>';
385 scrollHintInner.prepend(self.icons.arrow_lr.cloneNode(true));
386
387 if (dragScrollWrapper.length > 0) {
388 dragScrollWrapper.forEach(e => {
389 e.style.overflow = 'auto';
390 e.style.position = 'relative';
391 e.addEventListener('mousedown', v => { self.dragDown(e, v) }, false);
392 if (e.scrollWidth > e.clientWidth && self.option.dragScroll.hint) e.appendChild(scrollHint.cloneNode(true));
393 });
394 }
395 document.addEventListener('touchmove', toggleHint, false);
396 document.addEventListener('mousemove', v => { toggleHint; self.dragMove(v) }, false);
397 document.addEventListener('mouseup', v => { self.dragUp(v) }, false);
398 }
399 // flex fix
400 if (self.option.flexFix.active) {
401 let flexFix = document.querySelectorAll(self.option.flexFix.selector);
402 if (flexFix.length > 0) {
403 let inherit = self.option.flexFix.inherit;
404 flexFix.forEach(e => {
405 let childArr = Array.from(e.children);
406 let dummyChild = childArr[0].cloneNode(inherit);
407 dummyChild.classList.add('rdx-dummy-item');
408 let count = self.option.flexFix.min > childArr.length ? self.option.flexFix.min: childArr.length;
409 for (let i = 0; i < count; i++) {
410 let dummyClone = dummyChild.cloneNode(inherit);
411 e.appendChild(dummyClone);
412 }
413 });
414 }
415 }
416 // scroll appear
417 if (self.option.scrollAppear.active) {
418 const appearItems = document.querySelectorAll(self.option.scrollAppear.selector);
419 if (appearItems.length > 0) {
420 appearItems.forEach(item => {
421 item.classList.add('rdx-scroll-appear');
422 });
423 window.addEventListener('scroll', () => {
424 let windowHeight = window.innerHeight;
425 appearItems.forEach(appearItem => {
426 let resetFlg = appearItem.hasAttribute('data-appear-reset') ? appearItem.dataset.appearReset : self.option.scrollAppear.reset;
427 let activeClass = appearItem.hasAttribute('data-appear-class') ? appearItem.dataset.appearClass : self.option.scrollAppear.class;
428 let delay = appearItem.hasAttribute('data-appear-delay') ? appearItem.dataset.appearDelay : self.option.scrollAppear.delay;
429 let modeNum = appearItem.hasAttribute('data-appear-fixed') ? appearItem.dataset.appearFixed : null;
430
431 if (modeNum === null) {
432 let itemRect = appearItem.getBoundingClientRect();
433 let itemHeight = appearItem.offsetHeight;
434 if (itemRect.top < windowHeight * .9 && itemRect.top + itemHeight > windowHeight * .1) {
435 setTimeout(() => {
436 appearItem.classList.add(activeClass);
437 }, delay);
438 } else if (resetFlg) {
439 setTimeout(() => {
440 appearItem.classList.remove(activeClass);
441 }, delay);
442 }
443 } else {
444 if (window.pageYOffset > modeNum) {
445 setTimeout(() => {
446 appearItem.classList.add(activeClass);
447 }, delay);
448 } else if (resetFlg) {
449 setTimeout(() => {
450 appearItem.classList.remove(activeClass);
451 }, delay);
452 }
453 }
454 });
455 });
456 }
457 }
458 resolve();
459 });
460 }).then(() => {
461 // Speed 3
462 return new Promise(resolve => {
463 // modal
464 if (self.option.modal.active) {
465 let modals = document.querySelectorAll(self.option.modal.selector);
466 if (modals.length > 0) {
467 self.modalParts = {
468 viewport: document.createElement('div'),
469 area: document.createElement('div'),
470 wrapper: document.createElement('div'),
471 frame: document.createElement('div'),
472 content: document.createElement('div'),
473 closeButton: self.icons.cross.cloneNode(true),
474 toggles: document.createElement('div'),
475 magnifier: document.createElement('div'),
476 magnify: self.option.modal.magnify,
477 enlarge: self.icons.zoom_in.cloneNode(true),
478 shrink: self.icons.zoom_out.cloneNode(true),
479 scaleDisp: document.createElement('div'),
480 scaleSelector: document.createElement('ul'),
481 scale: self.option.modal.defaultScale,
482 size: {
483 width: 0,
484 height: 0
485 },
486 class: self.option.modal.class,
487 drag: self.option.modal.drag,
488 fit: self.option.modal.fit,
489 duration: self.option.modal.resizeDuration,
490 easing: self.option.modal.resizeEasing
491 }
492 self.modalParts.viewport.classList.add('rdx-modal-viewport');
493 self.modalParts.area.classList.add('rdx-modal-area');
494 self.modalParts.wrapper.classList.add('rdx-modal-wrapper');
495 self.modalParts.content.classList.add('rdx-modal-content');
496 self.modalParts.frame.classList.add('rdx-modal-frame');
497 self.modalParts.toggles.classList.add('rdx-modal-toggles');
498 self.modalParts.viewport.appendChild(self.modalParts.toggles);
499 self.modalParts.viewport.appendChild(self.modalParts.area);
500 self.modalParts.area.appendChild(self.modalParts.wrapper);
501 self.modalParts.wrapper.appendChild(self.modalParts.frame);
502 self.modalParts.frame.appendChild(self.modalParts.content);
503 self.modalParts.magnifier.classList.add('rdx-modal-magnifier');
504 self.modalParts.enlarge.classList.add('rdx-modal-enlarge');
505 self.modalParts.shrink.classList.add('rdx-modal-shrink');
506 self.modalParts.scaleDisp.classList.add('rdx-modal-scale');
507 self.modalParts.toggles.appendChild(self.modalParts.magnifier);
508 self.modalParts.magnifier.appendChild(self.modalParts.scaleDisp);
509 self.modalParts.magnifier.appendChild(self.modalParts.enlarge);
510 self.modalParts.magnifier.appendChild(self.modalParts.shrink);
511 self.modalParts.closeButton.classList.add('rdx-modal-close');
512 self.modalParts.toggles.appendChild(self.modalParts.closeButton);
513 self.modalParts.scaleSelector.classList.add('rdx-modal-scaler');
514 self.modalParts.magnifier.appendChild(self.modalParts.scaleSelector);
515 document.body.appendChild(self.modalParts.viewport);
516
517 self.modalParts.scaleDisp.addEventListener('click', event => {
518 event.preventDefault();
519 let i = self.option.modal.scaleStep.indexOf(self.modalParts.scale);
520 self.modalParts.scaleSelector.scrollTop = 40 * i;
521 self.modalParts.scaleSelector.classList.add('active');
522 });
523 self.option.modal.scaleStep.forEach(scale => {
524 let scaleItem = document.createElement('li');
525 scaleItem.innerHTML = self.floatRound(scale, 1) + 'x';
526 scaleItem.dataset.scale = scale;
527 self.modalParts.scaleSelector.appendChild(scaleItem);
528 scaleItem.addEventListener('click', event => {
529 event.preventDefault();
530 self.modalResize(scaleItem.dataset.scale);
531 self.modalParts.scale = scale;
532 });
533 });
534 self.modalParts.enlarge.addEventListener('click', event => {
535 event.preventDefault();
536 let i = self.option.modal.scaleStep.indexOf(self.modalParts.scale);
537 let aftScale = i < self.option.modal.scaleStep.length - 1 ? self.option.modal.scaleStep[i+1] : self.option.modal.scaleStep[i];
538 self.modalResize(aftScale);
539 self.modalParts.scale = aftScale;
540 });
541 self.modalParts.shrink.addEventListener('click', event => {
542 event.preventDefault();
543 let i = self.option.modal.scaleStep.indexOf(self.modalParts.scale);
544 let aftScale = i > 0 ? self.option.modal.scaleStep[i-1] : self.option.modal.scaleStep[i];
545 self.modalResize(aftScale);
546 self.modalParts.scale = aftScale;
547 });
548 modals.forEach(modal => {
549 let targets = [];
550 if (modal.hasAttribute('data-modal-target')) {
551 targets = document.querySelectorAll(modal.dataset.modalTarget);
552 if (targets) {
553 targets.forEach(target => {
554 target.classList.add('rdx-modal-source');
555 });
556 }
557 } else {
558 targets = [modal];
559 modal.classList.add('rdx-modal-source');
560 }
561 modal.addEventListener('click', event => {
562 event.preventDefault();
563 let duration = modal.hasAttribute('data-modal-duration') ? modal.dataset.modalDuration : null;
564 let easing = modal.hasAttribute('data-modal-easing') ? modal.dataset.modalEasing : null;
565 let scale = modal.hasAttribute('data-modal-scale') ? modal.dataset.modalScale : null;
566 let drag = modal.hasAttribute('data-modal-drag') ? modal.dataset.modalDrag : null;
567 let magnify = modal.hasAttribute('data-modal-magnify') ? modal.dataset.modalMagnify : null;
568 let fit = modal.hasAttribute('data-modal-fit') ? modal.dataset.modalFit : null;
569 let Class = modal.hasAttribute('data-modal-class') ? modal.dataset.modalClass : null;
570 let wrap = modal.hasAttribute('data-modal-wrap') ? modal.dataset.modalWrap : null;
571 self.modalOpen(targets, Class, duration, easing, scale, drag, magnify, fit, wrap);
572 });
573 });
574 self.modalParts.viewport.addEventListener('mouseup', event => {
575 let clicked = event.target;
576 if (!clicked.classList.contains('rdx-modal-item')) {
577 if (clicked.closest('.rdx-modal-content') === null && clicked.closest('.rdx-modal-toggles') === null) {
578 self.modalClose();
579 }
580 }
581 }, false);
582 self.modalParts.closeButton.addEventListener('click', () => {self.modalClose()}, false);
583 }
584 }
585 resolve();
586 });
587 }).then(() => {
588 // Speed 4
589 document.dispatchEvent(self.events.afterInitialize);
590 });
591 };
592 /**
593 * スムーススクロール
594 * @param {float} scrollFrom スクロールの始点
595 * @param {float} scrollTo スクロールの終点
596 * @param {int} duration スクロールにかける時間(ミリ秒)
597 * @param {string} easingName スクロールアニメーションのイージング
598 */
599 smoothScroll(scrollFrom, scrollTo, duration, easingName) {
600 const self = this;
601 scrollTo = scrollTo < 0 ? 0 : scrollTo;
602 const changeVal = scrollTo - scrollFrom;
603 duration = duration === undefined ? self.option.smoothScroll.duration : duration;
604 easingName = easingName === undefined ? self.option.smoothScroll.easing : easingName;
605 let easing = self.getEasing(easingName);
606 let cnt = 0;
607 let timer = null;
608
609 document.dispatchEvent(self.events.beforeScroll);
610
611 let moveAnimate = () => {
612 cnt++;
613 let elapsedTime = cnt * self.option.timeFrame;
614 let pos = easing(elapsedTime, scrollFrom, changeVal, duration);
615 window.scrollTo(0, pos);
616 if (elapsedTime > duration) {
617 window.scrollTo(0, scrollTo);
618 clearInterval(timer);
619 document.dispatchEvent(self.events.afterScroll);
620 }
621 }
622 timer = setInterval(moveAnimate, self.option.timeFrame);
623 };
624 /**
625 * ページスクロールのオンオフ
626 * @param {boolean} mode 禁止する(true)、禁止しない(false)
627 */
628 preventScroll(mode) {
629 this.DOM_ROOTS.forEach(e => {
630 if (mode) {
631 e.style.overflowY = 'hidden';
632 } else {
633 e.style.overflowY = 'auto';
634 }
635 });
636 };
637 /**
638 * ナビゲーション開閉
639 * @param {boolean | string} mode 開ける(false)か閉じる(true)か
640 */
641 toggleNav(mode) {
642 const self = this;
643 let toggleTrigger = document.querySelectorAll(self.option.toggleNav.trigger);
644 let toggleTarget = document.querySelectorAll(self.option.toggleNav.target);
645
646 if (mode === undefined) {
647 if (self.navState) {
648 document.dispatchEvent(self.events.beforeNavClose);
649 if (self.option.toggleNav.preventScroll) {
650 self.preventScroll(false);
651 }
652 self.navState = false;
653 toggleTrigger.forEach(t => {
654 t.classList.remove(self.option.toggleNav.class);
655 });
656 toggleTarget.forEach(t => {
657 t.classList.remove(self.option.toggleNav.class);
658 });
659 document.dispatchEvent(self.events.afterNavClose);
660 } else {
661 document.dispatchEvent(self.events.beforeNavOpen);
662 if (self.option.toggleNav.preventScroll) {
663 self.preventScroll(true);
664 }
665 self.navState = true;
666 toggleTrigger.forEach(t => {
667 t.classList.add(self.option.toggleNav.class);
668 });
669 toggleTarget.forEach(t => {
670 t.classList.add(self.option.toggleNav.class);
671 });
672 document.dispatchEvent(self.events.afterNavOpen);
673 }
674 } else {
675 if (mode === true || mode === 'close') {
676 document.dispatchEvent(self.events.beforeNavClose);
677 if (self.option.toggleNav.preventScroll) {
678 self.preventScroll(false);
679 }
680 self.navState = false;
681 toggleTrigger.forEach(t => {
682 t.classList.remove(self.option.toggleNav.class);
683 });
684 toggleTarget.forEach(t => {
685 t.classList.remove(self.option.toggleNav.class);
686 });
687 document.dispatchEvent(self.events.afterNavClose);
688 } else if (mode === false || mode === 'open') {
689 document.dispatchEvent(self.events.beforeNavOpen);
690 if (self.option.toggleNav.preventScroll) {
691 self.preventScroll(true);
692 }
693 self.navState = true;
694 toggleTrigger.forEach(t => {
695 t.classList.add(self.option.toggleNav.class);
696 });
697 toggleTarget.forEach(t => {
698 t.classList.add(self.option.toggleNav.class);
699 });
700 document.dispatchEvent(self.events.afterNavOpen);
701 }
702 }
703 };
704 /**
705 * SVG iconに置き換える
706 * @param {element} icon SVGに置き換える対象
707 */
708 replaceIcon(target, icon) {
709 const self = this;
710 icon = icon === undefined ? target.innerText : icon;
711 if (Object.keys(self.icons).includes(icon)) {
712 target.replaceWith(self.icons[icon].cloneNode(true));
713 } else {
714 console.log('' + icon + ' is not icon name.');
715 }
716 };
717 /**
718 * ドラッグスクロールのマウスダウンイベント
719 * @param {elemnt} e スクロール領域のエレメント
720 * @param {event} v マウスダウンイベント
721 */
722 dragDown(e, v) {
723 if(!self.isMobile) {
724 e.style.cursor = 'move';
725 e.setAttribute('rdx-drag-on', true);
726 e.setAttribute('rdx-drag-scrolled-x', e.scrollLeft);
727 e.setAttribute('rdx-drag-scrolled-y', e.scrollTop);
728 e.setAttribute('rdx-drag-click-x', v.clientX);
729 e.setAttribute('rdx-drag-click-y', v.clientY);
730 }
731 };
732 /**
733 * ドラッグスクロールのマウスムーブイベント
734 * @param {event} v マウスムーブイベント
735 */
736 dragMove(v) {
737 let target = document.querySelector('[rdx-drag-on="true"]');
738 if (target !== null) {
739 v.preventDefault();
740 target.scrollLeft = Number(target.getAttribute('rdx-drag-scrolled-x')) + Number(target.getAttribute('rdx-drag-click-x')) - v.clientX;
741 target.scrollTop = Number(target.getAttribute('rdx-drag-scrolled-y')) + Number(target.getAttribute('rdx-drag-click-y')) - v.clientY;
742 }
743 };
744 /**
745 * ドラッグスクロールのマウスアップイベント
746 * @param {event} v マウスアップイベント
747 */
748 dragUp(v) {
749 v.preventDefault();
750 v.stopImmediatePropagation();
751 let target = document.querySelector('[rdx-drag-on="true"]');
752 if (target) {
753 target.style.cursor = '';
754 target.setAttribute('rdx-drag-on', false);
755 }
756 };
757 /**
758 * モーダルを開く
759 * @param {array} targets 開く対象のエレメントの配列
760 * @param {string} Class viewport に追加するCSSクラス
761 * @param {int} duration 拡縮にかける時間
762 * @param {string} easing 拡縮アニメーションのイージング
763 * @param {float} scale 開いたときの拡大率
764 * @param {boolean} drag ドラッグスクロールを可能にするか
765 * @param {boolean} magnify 拡縮ボタンを表示するか
766 * @param {boolean} fit 展開時にスケールを自動調整するか
767 * @param {boolean} wrap 折り返しモードで開くか
768 */
769 modalOpen(targets, Class, duration, easing, scale, drag, magnify, fit, wrap) {
770 const self = this;
771 if (self.modalState) return;
772 new Promise(resolve => {
773 document.dispatchEvent(self.events.beforeModalOpen);
774 resolve();
775 }).then(() => {
776 return new Promise(resolve => {
777 self.modalParts.content.innerHTML = '';
778 self.modalParts.magnify = magnify !== null ? magnify : self.option.modal.magnify;
779 self.modalParts.drag = drag !== null ? drag : self.option.modal.drag;
780 self.modalParts.fit = fit !== null ? fit : self.option.modal.fit;
781 self.modalParts.duration = duration === undefined ? self.option.modal.resizeDuration : duration;
782 self.modalParts.easing = easing === undefined ? self.option.modal.resizeEasing : easing;
783 self.modalParts.wrap = wrap === undefined ? self.option.modal.wrap : wrap;
784 let classArr = Class !== null ? Class : self.option.modal.class;
785 classArr = String(classArr).split(' ');
786 self.modalParts.class = classArr;
787 self.preventScroll(true);
788 resolve();
789 });
790 }).then(() => {
791 return new Promise(resolve => {
792 targets.forEach(target => {
793 let modalClone = target.cloneNode(true);
794 modalClone.classList.remove('rdx-modal-source');
795 modalClone.classList.add('rdx-modal-item');
796 self.modalParts.content.appendChild(modalClone);
797 });
798 resolve();
799 });
800 }).then(() => {
801 return new Promise(resolve => {
802 self.modalParts.magnifier.style.display = self.str2bool(self.modalParts.magnify) && !self.str2bool(self.modalParts.wrap) ? 'flex' : 'none';
803 self.modalParts.size = {
804 width: self.modalParts.content.offsetWidth,
805 height: self.modalParts.content.offsetHeight
806 };
807 resolve();
808 });
809 }).then(() => {
810 return new Promise(resolve => {
811 self.modalParts.scale = 1;
812 if (scale !== null) {
813 self.modalParts.scale = self.floatRound(scale, 1);
814 } else if (self.str2bool(self.modalParts.fit)) {
815 let areaHeight = self.modalParts.area.clientHeight;
816 let areaWidth = self.modalParts.area.clientWidth;
817 self.modalParts.scale = self.option.modal.scaleStep[0];
818 for (let i = 0; i < self.option.modal.scaleStep.length; i++) {
819 if (self.modalParts.size.width * self.option.modal.scaleStep[i] > areaWidth || self.modalParts.size.height * self.option.modal.scaleStep[i] > areaHeight) break;
820 self.modalParts.scale = self.option.modal.scaleStep[i];
821 }
822 }
823 const modalDrag = v => { self.dragDown(self.modalParts.wrapper, v) };
824 if (self.str2bool(self.modalParts.drag) && !self.str2bool(self.modalParts.wrap)) {
825 self.modalParts.wrapper.addEventListener('mousedown', modalDrag, false);
826 } else {
827 self.modalParts.wrapper.removeEventListener('mousedown', modalDrag, false);
828 }
829 resolve();
830 });
831 }).then(() => {
832 return new Promise(resolve => {
833 if (self.str2bool(self.modalParts.wrap)) {
834 self.modalParts.content.style.maxHeight = '100%';
835 self.modalParts.content.style.maxWidth = '100%';
836 } else {
837 self.modalParts.content.style.transform = 'scale(' + self.modalParts.scale + ')';
838 self.modalParts.wrapper.style.height = 'min(' + self.floatCeil(self.modalParts.size.height * self.modalParts.scale, 0) + 'px, 100%)';
839 self.modalParts.wrapper.style.width = 'min(' + self.floatCeil(self.modalParts.size.width * self.modalParts.scale, 0) + 'px, 100%)';
840 self.modalParts.scaleDisp.innerHTML = self.floatRound(self.modalParts.scale, 1) + 'x';
841 self.modalParts.frame.style.height = self.floatCeil(self.modalParts.size.height * self.modalParts.scale, 0) + 'px';
842 self.modalParts.frame.style.width = self.floatCeil(self.modalParts.size.width * self.modalParts.scale, 0) + 'px';
843 }
844 self.modalParts.class.forEach(c => {
845 self.modalParts.viewport.classList.add(c);
846 });
847 self.modalParts.viewport.classList.add('active');
848 self.modalState = true;
849 resolve();
850 });
851 }).then(() => {
852 document.dispatchEvent(self.events.afterModalOpen);
853 });
854 };
855 /**
856 * モーダルを閉じる
857 */
858 modalClose() {
859 const self = this;
860 if (!self.modalState) return;
861 if (self.modalParts.wrapper.getAttribute('rdx-drag-on') === 'true') return;
862 new Promise(resolve => {
863 document.dispatchEvent(self.events.beforeModalClose);
864 resolve();
865 }).then(() => {
866 return new Promise(resolve => {
867 self.modalParts.scaleSelector.classList.remove('active');
868 self.modalParts.content.innerHTML = '';
869 self.preventScroll(false);
870 self.modalParts.content.style = '';
871 self.modalParts.frame.style = '';
872 self.modalParts.wrapper.style = '';
873 self.modalParts.viewport.classList.remove('active');
874 setTimeout(() => {
875 self.modalParts.class.forEach(c => {
876 self.modalParts.viewport.classList.remove(c);
877 });
878 }, 250);
879 self.modalState = false;
880 resolve();
881 });
882 }).then(() => {
883 document.dispatchEvent(self.events.afterModalClose);
884 });
885 };
886 /**
887 * モーダルウィンドウの拡縮
888 * @param {float} aftScale 操作後の倍率
889 */
890 modalResize(aftScale) {
891 const self = this;
892 if (!self.modalState) return;
893 let duration = self.option.modal.resizeDuration;
894 let frame = self.option.timeFrame;
895 let cnt = 0;
896 let timer = null;
897 let easing = self.getEasing(self.option.modal.resizeEasing);
898 let befScale = self.modalParts.scale;
899 let befWidth = self.modalParts.size.width * befScale;
900 let befHeight = self.modalParts.size.height * befScale;
901 aftScale = self.floatRound(aftScale, 1);
902 let aftWidth = self.modalParts.size.width * aftScale;
903 let aftHeight = self.modalParts.size.height * aftScale;
904 let difScale = aftScale - befScale;
905 let difWidth = self.modalParts.size.width * difScale;
906 let difHeight = self.modalParts.size.height * difScale;
907
908 self.modalParts.scaleDisp.innerHTML = self.floatRound(aftScale, 1) + 'x';
909 self.modalParts.scaleSelector.classList.remove('active');
910
911 let resizeAnimate = () => {
912 cnt++;
913 let elapsedTime = cnt * frame;
914 let nowWidth = easing(elapsedTime, befWidth, difWidth, duration);
915 let nowHeight = easing(elapsedTime, befHeight, difHeight, duration);
916 let nowScale = easing(elapsedTime, befScale, difScale, duration);
917 self.modalParts.content.style.transform = 'scale(' + nowScale + ')';
918 self.modalParts.wrapper.style.width = 'min(' + nowWidth + 'px, 100%)';
919 self.modalParts.wrapper.style.height = 'min(' + nowHeight + 'px, 100%)';
920 self.modalParts.frame.style.height = nowHeight + 'px';
921 self.modalParts.frame.style.width = nowWidth + 'px';
922 if (elapsedTime > duration) {
923 self.modalParts.content.style.transform = 'scale(' + self.floatRound(aftScale, 1) + ')';
924 self.modalParts.wrapper.style.height = 'min(' + self.floatCeil(aftHeight, 0) + 'px, 100%)';
925 self.modalParts.wrapper.style.width = 'min(' + self.floatCeil(aftWidth, 0) + 'px, 100%)';
926 self.modalParts.frame.style.height = self.floatCeil(aftHeight, 0) + 'px';
927 self.modalParts.frame.style.width = self.floatCeil(aftWidth, 0) + 'px';
928 clearInterval(timer);
929 }
930 }
931 if (difScale != 0) {
932 timer = setInterval(resizeAnimate, frame);
933 }
934 };
935 /**
936 * 型の判定
937 * @param {operand} obj 判定したいもの
938 * @return {string} 型名
939 */
940 typeJudge(obj) {
941 return toString.call(obj).slice(8, -1).toLowerCase();
942 };
943 /**
944 * 文字列のTF判定
945 * @param {string} str 判定したいもの
946 * @return {boolean}
947 */
948 str2bool(str) {
949 const trues = ['true', 'on', '1'];
950 if (str === true) return true;
951 if (trues.includes(String(str).toLocaleLowerCase())) return true;
952 return false;
953 };
954 /**
955 * 少数の桁変換
956 * @param {float} x 対象となる少数
957 * @param {int} digit 切り上げる小数点
958 * @return {string} フィックスされた少数文字列
959 */
960 floatRound(num, digit) {
961 digit = digit === undefined ? 2 : Number.parseInt(digit);
962 let fix = 10 ** digit;
963 let res = Math.round(num * fix) / fix;
964 return res.toFixed(digit);
965 };
966 floatCeil(num, digit) {
967 digit = digit === undefined ? 2 : Number.parseInt(digit);
968 let fix = 10 ** digit;
969 let res = Math.ceil(num * fix) / fix;
970 return res.toFixed(digit);
971 };
972 floatFloor(num, digit) {
973 digit = digit === undefined ? 2 : Number.parseInt(digit);
974 let fix = 10 ** digit;
975 let res = Math.floor(num * fix) / fix;
976 return res.toFixed(digit);
977 };
978 /**
979 * イージング関数を取得する関数
980 * @param {string} easingName イージング関数の名称
981 * @return {function} イージング関数
982 */
983 getEasing(easingName) {
984 let ease;
985 if (easingName == 'ease') {
986 easingName = 'easeInOutCirc';
987 } else if (easingName == 'ease-in' || easingName == 'easeIn') {
988 easingName = 'easeInQuad';
989 } else if (easingName == 'ease-out' || easingName == 'easeOut') {
990 easingName = 'easeOutQuad';
991 } else if (easingName == 'ease-in-out' || easingName == 'easeInOut') {
992 easingName = 'easeInOutQuad';
993 }
994 switch (easingName) {
995 case 'linear':
996 ease = function (t, b, c, d) {
997 return c * t / d + b;
998 };
999 break;
1000 case 'easeInSine':
1001 ease = function (t, b, c, d) {
1002 return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
1003 };
1004 break;
1005 case 'easeOutSine':
1006 ease = function (t, b, c, d) {
1007 return c * Math.sin(t / d * (Math.PI / 2)) + b;
1008 };
1009 break;
1010 case 'easeInOutSine':
1011 ease = function (t, b, c, d) {
1012 return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
1013 };
1014 break;
1015 case 'easeInQuad':
1016 ease = function (t, b, c, d) {
1017 return c * (t /= d) * t + b;
1018 };
1019 break;
1020 case 'easeOutQuad':
1021 ease = function (t, b, c, d) {
1022 return -c * (t /= d) * (t - 2) + b;
1023 };
1024 break;
1025 case 'easeInOutQuad':
1026 ease = function (t, b, c, d) {
1027 if ((t /= d / 2) < 1) return c / 2 * t * t + b;
1028 return -c / 2 * ((--t) * (t - 2) - 1) + b;
1029 };
1030 break;
1031 case 'easeInCubic':
1032 ease = function (t, b, c, d) {
1033 return c * (t /= d) * t * t + b;
1034 };
1035 break;
1036 case 'easeOutCubic':
1037 ease = function (t, b, c, d) {
1038 return c * ((t = t / d - 1) * t * t + 1) + b;
1039 };
1040 break;
1041 case 'easeInOutCubic':
1042 ease = function (t, b, c, d) {
1043 if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
1044 return c / 2 * ((t -= 2) * t * t + 2) + b;
1045 };
1046 break;
1047 case 'easeInQuart':
1048 ease = function (t, b, c, d) {
1049 return c * (t /= d) * t * t * t + b;
1050 };
1051 break;
1052 case 'easeOutQuart':
1053 ease = function (t, b, c, d) {
1054 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
1055 };
1056 break;
1057 case 'easeInOutQuart':
1058 ease = function (t, b, c, d) {
1059 if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
1060 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
1061 };
1062 break;
1063 case 'easeInQuint':
1064 ease = function (t, b, c, d) {
1065 return c * (t /= d) * t * t * t * t + b;
1066 };
1067 break;
1068 case 'easeOutQuint':
1069 ease = function (t, b, c, d) {
1070 return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
1071 };
1072 break;
1073 case 'easeInOutQuint':
1074 ease = function (t, b, c, d) {
1075 if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
1076 return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
1077 };
1078 break;
1079 case 'easeInExpo':
1080 ease = function (t, b, c, d) {
1081 return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
1082 };
1083 break;
1084 case 'easeOutExpo':
1085 ease = function (t, b, c, d) {
1086 return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
1087 };
1088 break;
1089 case 'easeInOutExpo':
1090 ease = function (t, b, c, d) {
1091 if (t == 0) return b;
1092 if (t == d) return b + c;
1093 if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
1094 return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
1095 };
1096 break;
1097 case 'easeInCirc':
1098 ease = function (t, b, c, d) {
1099 return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
1100 };
1101 break;
1102 case 'easeOutCirc':
1103 ease = function (t, b, c, d) {
1104 return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
1105 };
1106 break;
1107 case 'easeInOutCirc':
1108 ease = function (t, b, c, d) {
1109 if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
1110 return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
1111 };
1112 break;
1113 case 'easeInElastic':
1114 ease = function (t, b, c, d) {
1115 var s = 1.70158;
1116 var p = 0;
1117 var a = c;
1118 if (t == 0) return b;
1119 if ((t /= d) == 1) return b + c;
1120 if (!p) p = d * .3;
1121 if (a < Math.abs(c)) {
1122 a = c;
1123 var s = p / 4;
1124 } else var s = p / (2 * Math.PI) * Math.asin(c / a);
1125 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
1126 };
1127 break;
1128 case 'easeOutElastic':
1129 ease = function (t, b, c, d) {
1130 var s = 1.70158;
1131 var p = 0;
1132 var a = c;
1133 if (t == 0) return b;
1134 if ((t /= d) == 1) return b + c;
1135 if (!p) p = d * .3;
1136 if (a < Math.abs(c)) {
1137 a = c;
1138 var s = p / 4;
1139 } else var s = p / (2 * Math.PI) * Math.asin(c / a);
1140 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
1141 };
1142 break;
1143 case 'easeInOutElastic':
1144 ease = function (t, b, c, d) {
1145 var s = 1.70158;
1146 var p = 0;
1147 var a = c;
1148 if (t == 0) return b;
1149 if ((t /= d / 2) == 2) return b + c;
1150 if (!p) p = d * (.3 * 1.5);
1151 if (a < Math.abs(c)) {
1152 a = c;
1153 var s = p / 4;
1154 } else var s = p / (2 * Math.PI) * Math.asin(c / a);
1155 if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
1156 return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
1157 };
1158 break;
1159 case 'easeInBack':
1160 ease = function (t, b, c, d, s) {
1161 if (s == undefined) s = 1.70158;
1162 return c * (t /= d) * t * ((s + 1) * t - s) + b;
1163 };
1164 break;
1165 case 'easeOutBack':
1166 ease = function (t, b, c, d, s) {
1167 if (s == undefined) s = 1.70158;
1168 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
1169 };
1170 break;
1171 case 'easeInOutBack':
1172 ease = function (t, b, c, d, s) {
1173 if (s == undefined) s = 1.70158;
1174 if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
1175 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
1176 };
1177 break;
1178 case 'easeInBounce':
1179 ease = function (t, b, c, d) {
1180 t = d - t;
1181 if ((t /= d) < (1 / 2.75)) {
1182 return c - c * (7.5625 * t * t) + b;
1183 } else if (t < (2 / 2.75)) {
1184 return c - c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
1185 } else if (t < (2.5 / 2.75)) {
1186 return c - c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
1187 } else {
1188 return c - c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
1189 }
1190 };
1191 break;
1192 case 'easeOutBounce':
1193 ease = function (t, b, c, d) {
1194 if ((t /= d) < (1 / 2.75)) {
1195 return c * (7.5625 * t * t) + b;
1196 } else if (t < (2 / 2.75)) {
1197 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
1198 } else if (t < (2.5 / 2.75)) {
1199 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
1200 } else {
1201 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
1202 }
1203 };
1204 break;
1205 case 'easeInOutBounce':
1206 ease = function (t, b, c, d) {
1207 if (t < d / 2) {
1208 t = d - t * 2;
1209 if ((t /= d) < (1 / 2.75)) {
1210 return c * .5 - c * (7.5625 * t * t) * .5 + b;
1211 } else if (t < (2 / 2.75)) {
1212 return c * .5 - c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) * .5 + b;
1213 } else if (t < (2.5 / 2.75)) {
1214 return c * .5 - c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) * .5 + b;
1215 } else {
1216 return c * .5 - c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) * .5 + b;
1217 }
1218 } else {
1219 t = t * 2 - d;
1220 if ((t /= d) < (1 / 2.75)) {
1221 return c * (7.5625 * t * t) * .5 + c * .5 + b;
1222 } else if (t < (2 / 2.75)) {
1223 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) * .5 + c * .5 + b;
1224 } else if (t < (2.5 / 2.75)) {
1225 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) * .5 + c * .5 + b;
1226 } else {
1227 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) * .5 + c * .5 + b;
1228 }
1229 }
1230 };
1231 break;
1232 }
1233 return ease;
1234 };
1235}
\No newline at end of file