UNPKG

5.04 kBPlain TextView Raw
1import {window} from "./browser";
2import { ObjectInterface } from "./types";
3
4declare var jQuery: any;
5
6export function toArray(nodes: NodeList): HTMLElement[] {
7 // const el = Array.prototype.slice.call(nodes);
8 // for IE8
9 const el = [];
10 for (let i = 0, len = nodes.length;
11 i < len; i++) {
12 el.push(nodes[i]);
13 }
14 return el;
15}
16
17export function $(param, multi = false) {
18 let el;
19
20 if (typeof param === "string") { // String (HTML, Selector)
21 // check if string is HTML tag format
22 const match = param.match(/^<([a-z]+)\s*([^>]*)>/);
23
24 // creating element
25 if (match) { // HTML
26 const dummy = document.createElement("div");
27
28 dummy.innerHTML = param;
29 el = toArray(dummy.childNodes);
30 } else { // Selector
31 el = toArray(document.querySelectorAll(param));
32 }
33 if (!multi) {
34 el = el.length >= 1 ? el[0] : undefined;
35 }
36 } else if (param === window) { // window
37 el = param;
38 } else if (param.nodeName &&
39 (param.nodeType === 1 || param.nodeType === 9)) { // HTMLElement, Document
40 el = param;
41 } else if (("jQuery" in window && param instanceof jQuery) ||
42 param.constructor.prototype.jquery) { // jQuery
43 el = multi ? param.toArray() : param.get(0);
44 } else if (Array.isArray(param)) {
45 el = param.map(v => $(v));
46 if (!multi) {
47 el = el.length >= 1 ? el[0] : undefined;
48 }
49 }
50 return el;
51}
52
53let raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame;
54let caf = window.cancelAnimationFrame || window.webkitCancelAnimationFrame;
55if (raf && !caf) {
56 const keyInfo = {};
57 const oldraf = raf;
58 raf = (callback: FrameRequestCallback) => {
59 function wrapCallback(timestamp) {
60 if (keyInfo[key]) {
61 callback(timestamp);
62 }
63 }
64 const key = oldraf(wrapCallback);
65 keyInfo[key] = true;
66 return key;
67 };
68 caf = (key: number) => {
69 delete keyInfo[key];
70 };
71} else if (!(raf && caf)) {
72 raf = (callback: FrameRequestCallback) => {
73 return window.setTimeout(() => {
74 callback(window.performance && window.performance.now && window.performance.now() || new Date().getTime());
75 }, 16);
76 };
77 caf = window.clearTimeout;
78}
79
80/**
81 * A polyfill for the window.requestAnimationFrame() method.
82 * @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
83 * @private
84 */
85export function requestAnimationFrame(fp) {
86 return raf(fp);
87}
88/**
89* A polyfill for the window.cancelAnimationFrame() method. It cancels an animation executed through a call to the requestAnimationFrame() method.
90* @param {Number} key − The ID value returned through a call to the requestAnimationFrame() method. <ko>requestAnimationFrame() 메서드가 반환한 아이디 값</ko>
91* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/cancelAnimationFrame
92* @private
93*/
94export function cancelAnimationFrame(key) {
95 caf(key);
96}
97
98export function map<T, U>(obj: ObjectInterface<T>, callback: (value: T, key: string) => U): ObjectInterface<U> {
99 const tranformed: ObjectInterface<U> = {};
100
101 for (const k in obj) {
102 k && (tranformed[k] = callback(obj[k], k));
103 }
104 return tranformed;
105}
106
107export function filter<T>(obj: ObjectInterface<T>, callback: (value: T, key: string) => boolean): ObjectInterface<T> {
108 const filtered: ObjectInterface<T> = {};
109
110 for (const k in obj) {
111 k && callback(obj[k], k) && (filtered[k] = obj[k]);
112 }
113 return filtered;
114}
115export function every<T>(obj: ObjectInterface<T>, callback: (value: T, key: string) => boolean) {
116 for (const k in obj) {
117 if (k && !callback(obj[k], k)) {
118 return false;
119 }
120 }
121 return true;
122}
123export function equal(target: ObjectInterface, base: ObjectInterface): boolean {
124 return every(target, (v, k) => v === base[k]);
125}
126
127const roundNumFunc = {};
128
129export function roundNumber(num: number, roundUnit: number) {
130 // Cache for performance
131 if (!roundNumFunc[roundUnit]) {
132 roundNumFunc[roundUnit] = getRoundFunc(roundUnit);
133 }
134
135 return roundNumFunc[roundUnit](num);
136}
137
138export function roundNumbers(num: ObjectInterface<number>, roundUnit: ObjectInterface<number> | number) {
139 if (!num || !roundUnit) {
140 return num;
141 }
142 const isNumber = typeof roundUnit === "number";
143 return map(num, (value, key) => roundNumber(value, isNumber ? roundUnit : roundUnit[key]));
144}
145
146export function getDecimalPlace(val: number): number {
147 if (!isFinite(val)) {
148 return 0;
149 }
150
151 const v = (val + "");
152
153 if (v.indexOf("e") >= 0) {
154 // Exponential Format
155 // 1e-10, 1e-12
156 let p = 0;
157 let e = 1;
158
159 while (Math.round(val * e) / e !== val) {
160 e *= 10;
161 p++;
162 }
163
164 return p;
165 }
166
167 // In general, following has performance benefit.
168 // https://jsperf.com/precision-calculation
169 return v.indexOf(".") >= 0 ? (v.length - v.indexOf(".") - 1) : 0;
170}
171
172export function inversePow(n: number) {
173 // replace Math.pow(10, -n) to solve floating point issue.
174 // eg. Math.pow(10, -4) => 0.00009999999999999999
175 return 1 / Math.pow(10, n);
176}
177
178export function getRoundFunc(v: number) {
179 const p = v < 1 ? Math.pow(10, getDecimalPlace(v)) : 1;
180
181 return (n: number) => {
182 if (v === 0) {
183 return 0;
184 }
185
186 return Math.round(Math.round(n / v) * v * p) / p;
187 };
188}