1// Copyright 2015 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5export function anyToString(x: any): string { 6 return "" + x; 7} 8 9function computeScrollTop(container, element) { 10 const height = container.offsetHeight; 11 const margin = Math.floor(height / 4); 12 const pos = element.offsetTop; 13 const currentScrollTop = container.scrollTop; 14 if (pos < currentScrollTop + margin) { 15 return Math.max(0, pos - margin); 16 } else if (pos > (currentScrollTop + 3 * margin)) { 17 return Math.max(0, pos - 3 * margin); 18 } 19 return pos; 20} 21 22export class ViewElements { 23 container: HTMLElement; 24 scrollTop: number; 25 26 constructor(container: HTMLElement) { 27 this.container = container; 28 this.scrollTop = undefined; 29 } 30 31 consider(element, doConsider) { 32 if (!doConsider) return; 33 const newScrollTop = computeScrollTop(this.container, element); 34 if (isNaN(newScrollTop)) { 35 console.log("NOO") 36 } 37 if (this.scrollTop === undefined) { 38 this.scrollTop = newScrollTop; 39 } else { 40 this.scrollTop = Math.min(this.scrollTop, newScrollTop); 41 } 42 } 43 44 apply(doApply) { 45 if (!doApply || this.scrollTop === undefined) return; 46 this.container.scrollTop = this.scrollTop; 47 } 48} 49 50 51function lowerBound(a, value, compare, lookup) { 52 let first = 0; 53 let count = a.length; 54 while (count > 0) { 55 let step = Math.floor(count / 2); 56 let middle = first + step; 57 let middle_value = (lookup === undefined) ? a[middle] : lookup(a, middle); 58 let result = (compare === undefined) ? (middle_value < value) : compare(middle_value, value); 59 if (result) { 60 first = middle + 1; 61 count -= step + 1; 62 } else { 63 count = step; 64 } 65 } 66 return first; 67} 68 69 70function upperBound(a, value, compare, lookup) { 71 let first = 0; 72 let count = a.length; 73 while (count > 0) { 74 let step = Math.floor(count / 2); 75 let middle = first + step; 76 let middle_value = (lookup === undefined) ? a[middle] : lookup(a, middle); 77 let result = (compare === undefined) ? (value < middle_value) : compare(value, middle_value); 78 if (!result) { 79 first = middle + 1; 80 count -= step + 1; 81 } else { 82 count = step; 83 } 84 } 85 return first; 86} 87 88 89export function sortUnique<T>(arr: Array<T>, f: (a: T, b: T) => number, equal: (a: T, b: T) => boolean) { 90 if (arr.length == 0) return arr; 91 arr = arr.sort(f); 92 let ret = [arr[0]]; 93 for (var i = 1; i < arr.length; i++) { 94 if (!equal(arr[i - 1], arr[i])) { 95 ret.push(arr[i]); 96 } 97 } 98 return ret; 99} 100 101// Partial application without binding the receiver 102export function partial(f, ...arguments1) { 103 return function (...arguments2) { 104 var arguments2 = Array.from(arguments); 105 f.apply(this, [...arguments1, ...arguments2]); 106 } 107} 108 109export function isIterable(obj: any): obj is Iterable<any> { 110 return obj != null && obj != undefined 111 && typeof obj != 'string' && typeof obj[Symbol.iterator] === 'function'; 112} 113 114export function alignUp(raw:number, multiple:number):number { 115 return Math.floor((raw + multiple - 1) / multiple) * multiple; 116} 117