mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from master
This commit is contained in:
@@ -2,27 +2,31 @@
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { TimeoutTimer } from 'vs/base/common/async';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import * as browser from 'vs/base/browser/browser';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { IMouseEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { TimeoutTimer } from 'vs/base/common/async';
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
|
||||
export function clearNode(node: HTMLElement) {
|
||||
export function clearNode(node: HTMLElement): void {
|
||||
while (node.firstChild) {
|
||||
node.removeChild(node.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
export function isInDOM(node: Node): boolean {
|
||||
export function removeNode(node: HTMLElement): void {
|
||||
if (node.parentNode) {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
export function isInDOM(node: Node | null): boolean {
|
||||
while (node) {
|
||||
if (node === document.body) {
|
||||
return true;
|
||||
@@ -153,7 +157,7 @@ const _manualClassList = new class implements IDomClassList {
|
||||
|
||||
const _nativeClassList = new class implements IDomClassList {
|
||||
hasClass(node: HTMLElement, className: string): boolean {
|
||||
return className && node.classList && node.classList.contains(className);
|
||||
return Boolean(className) && node.classList && node.classList.contains(className);
|
||||
}
|
||||
|
||||
addClasses(node: HTMLElement, ...classNames: string[]): void {
|
||||
@@ -200,7 +204,7 @@ class DomListener implements IDisposable {
|
||||
private readonly _type: string;
|
||||
private readonly _useCapture: boolean;
|
||||
|
||||
constructor(node: Element | Window | Document, type: string, handler: (e: any) => void, useCapture: boolean) {
|
||||
constructor(node: Element | Window | Document, type: string, handler: (e: any) => void, useCapture?: boolean) {
|
||||
this._node = node;
|
||||
this._type = type;
|
||||
this._handler = handler;
|
||||
@@ -217,11 +221,13 @@ class DomListener implements IDisposable {
|
||||
this._node.removeEventListener(this._type, this._handler, this._useCapture);
|
||||
|
||||
// Prevent leakers from holding on to the dom or handler func
|
||||
this._node = null;
|
||||
this._handler = null;
|
||||
this._node = null!;
|
||||
this._handler = null!;
|
||||
}
|
||||
}
|
||||
|
||||
export function addDisposableListener<K extends keyof GlobalEventHandlersEventMap>(node: Element | Window | Document, type: K, handler: (event: GlobalEventHandlersEventMap[K]) => void, useCapture?: boolean): IDisposable;
|
||||
export function addDisposableListener(node: Element | Window | Document, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable;
|
||||
export function addDisposableListener(node: Element | Window | Document, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable {
|
||||
return new DomListener(node, type, handler, useCapture);
|
||||
}
|
||||
@@ -259,7 +265,7 @@ export let addStandardDisposableListener: IAddStandardDisposableListenerSignatur
|
||||
export function addDisposableNonBubblingMouseOutListener(node: Element, handler: (event: MouseEvent) => void): IDisposable {
|
||||
return addDisposableListener(node, 'mouseout', (e: MouseEvent) => {
|
||||
// Mouse out bubbles, so this is an attempt to ignore faux mouse outs coming from children elements
|
||||
let toElement = <Node>(e.relatedTarget || e.toElement);
|
||||
let toElement: Node | null = <Node>(e.relatedTarget || e.toElement);
|
||||
while (toElement && toElement !== node) {
|
||||
toElement = toElement.parentNode;
|
||||
}
|
||||
@@ -274,10 +280,10 @@ export function addDisposableNonBubblingMouseOutListener(node: Element, handler:
|
||||
interface IRequestAnimationFrame {
|
||||
(callback: (time: number) => void): number;
|
||||
}
|
||||
let _animationFrame: IRequestAnimationFrame = null;
|
||||
let _animationFrame: IRequestAnimationFrame | null = null;
|
||||
function doRequestAnimationFrame(callback: (time: number) => void): number {
|
||||
if (!_animationFrame) {
|
||||
const emulatedRequestAnimationFrame = (callback: (time: number) => void): number => {
|
||||
const emulatedRequestAnimationFrame = (callback: (time: number) => void): any => {
|
||||
return setTimeout(() => callback(new Date().getTime()), 0);
|
||||
};
|
||||
_animationFrame = (
|
||||
@@ -313,7 +319,7 @@ class AnimationFrameQueueItem implements IDisposable {
|
||||
public priority: number;
|
||||
private _canceled: boolean;
|
||||
|
||||
constructor(runner: () => void, priority: number) {
|
||||
constructor(runner: () => void, priority: number = 0) {
|
||||
this._runner = runner;
|
||||
this.priority = priority;
|
||||
this._canceled = false;
|
||||
@@ -349,7 +355,7 @@ class AnimationFrameQueueItem implements IDisposable {
|
||||
/**
|
||||
* The runners scheduled at the current animation frame
|
||||
*/
|
||||
let CURRENT_QUEUE: AnimationFrameQueueItem[] = null;
|
||||
let CURRENT_QUEUE: AnimationFrameQueueItem[] | null = null;
|
||||
/**
|
||||
* A flag to keep track if the native requestAnimationFrame was already called
|
||||
*/
|
||||
@@ -368,7 +374,7 @@ class AnimationFrameQueueItem implements IDisposable {
|
||||
inAnimationFrameRunner = true;
|
||||
while (CURRENT_QUEUE.length > 0) {
|
||||
CURRENT_QUEUE.sort(AnimationFrameQueueItem.sort);
|
||||
let top = CURRENT_QUEUE.shift();
|
||||
let top = CURRENT_QUEUE.shift()!;
|
||||
top.execute();
|
||||
}
|
||||
inAnimationFrameRunner = false;
|
||||
@@ -389,7 +395,7 @@ class AnimationFrameQueueItem implements IDisposable {
|
||||
runAtThisOrScheduleAtNextAnimationFrame = (runner: () => void, priority?: number) => {
|
||||
if (inAnimationFrameRunner) {
|
||||
let item = new AnimationFrameQueueItem(runner, priority);
|
||||
CURRENT_QUEUE.push(item);
|
||||
CURRENT_QUEUE!.push(item);
|
||||
return item;
|
||||
} else {
|
||||
return scheduleAtNextAnimationFrame(runner, priority);
|
||||
@@ -397,11 +403,19 @@ class AnimationFrameQueueItem implements IDisposable {
|
||||
};
|
||||
})();
|
||||
|
||||
export function measure(callback: () => void): IDisposable {
|
||||
return scheduleAtNextAnimationFrame(callback, 10000 /* must be early */);
|
||||
}
|
||||
|
||||
export function modify(callback: () => void): IDisposable {
|
||||
return scheduleAtNextAnimationFrame(callback, -10000 /* must be late */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a throttled listener. `handler` is fired at most every 16ms or with the next animation frame (if browser supports it).
|
||||
*/
|
||||
export interface IEventMerger<R, E> {
|
||||
(lastEvent: R, currentEvent: E): R;
|
||||
(lastEvent: R | null, currentEvent: E): R;
|
||||
}
|
||||
|
||||
export interface DOMEvent {
|
||||
@@ -419,13 +433,13 @@ class TimeoutThrottledDomListener<R, E extends DOMEvent> extends Disposable {
|
||||
constructor(node: any, type: string, handler: (event: R) => void, eventMerger: IEventMerger<R, E> = <any>DEFAULT_EVENT_MERGER, minimumTimeMs: number = MINIMUM_TIME_MS) {
|
||||
super();
|
||||
|
||||
let lastEvent: R = null;
|
||||
let lastEvent: R | null = null;
|
||||
let lastHandlerTime = 0;
|
||||
let timeout = this._register(new TimeoutTimer());
|
||||
|
||||
let invokeHandler = () => {
|
||||
lastHandlerTime = (new Date()).getTime();
|
||||
handler(lastEvent);
|
||||
handler(<R>lastEvent);
|
||||
lastEvent = null;
|
||||
};
|
||||
|
||||
@@ -449,7 +463,7 @@ export function addDisposableThrottledListener<R, E extends DOMEvent = DOMEvent>
|
||||
}
|
||||
|
||||
export function getComputedStyle(el: HTMLElement): CSSStyleDeclaration {
|
||||
return document.defaultView.getComputedStyle(el, null);
|
||||
return document.defaultView!.getComputedStyle(el, null);
|
||||
}
|
||||
|
||||
// Adapted from WinJS
|
||||
@@ -486,8 +500,8 @@ export function getClientArea(element: HTMLElement): Dimension {
|
||||
return new Dimension(window.innerWidth, window.innerHeight);
|
||||
}
|
||||
|
||||
// Try with document.body.clientWidth / document.body.clientHeigh
|
||||
if (document.body && document.body.clientWidth && document.body.clientWidth) {
|
||||
// Try with document.body.clientWidth / document.body.clientHeight
|
||||
if (document.body && document.body.clientWidth && document.body.clientHeight) {
|
||||
return new Dimension(document.body.clientWidth, document.body.clientHeight);
|
||||
}
|
||||
|
||||
@@ -553,6 +567,16 @@ export class Dimension {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
static equals(a: Dimension | undefined, b: Dimension | undefined): boolean {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
return a.width === b.width && a.height === b.height;
|
||||
}
|
||||
}
|
||||
|
||||
export function getTopLeftOffset(element: HTMLElement): { left: number; top: number; } {
|
||||
@@ -644,7 +668,7 @@ export const StandardWindow: IStandardWindow = new class implements IStandardWin
|
||||
// modern browsers
|
||||
return window.scrollX;
|
||||
} else {
|
||||
return document.body.scrollLeft + document.documentElement.scrollLeft;
|
||||
return document.body.scrollLeft + document.documentElement!.scrollLeft;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -653,7 +677,7 @@ export const StandardWindow: IStandardWindow = new class implements IStandardWin
|
||||
// modern browsers
|
||||
return window.scrollY;
|
||||
} else {
|
||||
return document.body.scrollTop + document.documentElement.scrollTop;
|
||||
return document.body.scrollTop + document.documentElement!.scrollTop;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -712,7 +736,7 @@ export function getLargestChildWidth(parent: HTMLElement, children: HTMLElement[
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
export function isAncestor(testChild: Node, testAncestor: Node): boolean {
|
||||
export function isAncestor(testChild: Node | null, testAncestor: Node | null): boolean {
|
||||
while (testChild) {
|
||||
if (testChild === testAncestor) {
|
||||
return true;
|
||||
@@ -723,7 +747,7 @@ export function isAncestor(testChild: Node, testAncestor: Node): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function findParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): HTMLElement {
|
||||
export function findParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): HTMLElement | null {
|
||||
while (node) {
|
||||
if (hasClass(node, clazz)) {
|
||||
return node;
|
||||
@@ -755,7 +779,7 @@ export function createStyleSheet(container: HTMLElement = document.getElementsBy
|
||||
return style;
|
||||
}
|
||||
|
||||
let _sharedStyleSheet: HTMLStyleElement = null;
|
||||
let _sharedStyleSheet: HTMLStyleElement | null = null;
|
||||
function getSharedStyleSheet(): HTMLStyleElement {
|
||||
if (!_sharedStyleSheet) {
|
||||
_sharedStyleSheet = createStyleSheet();
|
||||
@@ -811,49 +835,48 @@ export function isHTMLElement(o: any): o is HTMLElement {
|
||||
|
||||
export const EventType = {
|
||||
// Mouse
|
||||
CLICK: 'click',
|
||||
AUXCLICK: 'auxclick', // >= Chrome 56
|
||||
DBLCLICK: 'dblclick',
|
||||
MOUSE_UP: 'mouseup',
|
||||
MOUSE_DOWN: 'mousedown',
|
||||
MOUSE_OVER: 'mouseover',
|
||||
MOUSE_MOVE: 'mousemove',
|
||||
MOUSE_OUT: 'mouseout',
|
||||
MOUSE_ENTER: 'mouseenter',
|
||||
MOUSE_LEAVE: 'mouseleave',
|
||||
CONTEXT_MENU: 'contextmenu',
|
||||
WHEEL: 'wheel',
|
||||
CLICK: 'click' as 'click',
|
||||
DBLCLICK: 'dblclick' as 'dblclick',
|
||||
MOUSE_UP: 'mouseup' as 'mouseup',
|
||||
MOUSE_DOWN: 'mousedown' as 'mousedown',
|
||||
MOUSE_OVER: 'mouseover' as 'mouseover',
|
||||
MOUSE_MOVE: 'mousemove' as 'mousemove',
|
||||
MOUSE_OUT: 'mouseout' as 'mouseout',
|
||||
MOUSE_ENTER: 'mouseenter' as 'mouseenter',
|
||||
MOUSE_LEAVE: 'mouseleave' as 'mouseleave',
|
||||
CONTEXT_MENU: 'contextmenu' as 'contextmenu',
|
||||
WHEEL: 'wheel' as 'wheel',
|
||||
// Keyboard
|
||||
KEY_DOWN: 'keydown',
|
||||
KEY_PRESS: 'keypress',
|
||||
KEY_UP: 'keyup',
|
||||
KEY_DOWN: 'keydown' as 'keydown',
|
||||
KEY_PRESS: 'keypress' as 'keypress',
|
||||
KEY_UP: 'keyup' as 'keyup',
|
||||
// HTML Document
|
||||
LOAD: 'load',
|
||||
UNLOAD: 'unload',
|
||||
ABORT: 'abort',
|
||||
ERROR: 'error',
|
||||
RESIZE: 'resize',
|
||||
SCROLL: 'scroll',
|
||||
LOAD: 'load' as 'load',
|
||||
UNLOAD: 'unload' as 'unload',
|
||||
ABORT: 'abort' as 'abort',
|
||||
ERROR: 'error' as 'error',
|
||||
RESIZE: 'resize' as 'resize',
|
||||
SCROLL: 'scroll' as 'scroll',
|
||||
// Form
|
||||
SELECT: 'select',
|
||||
CHANGE: 'change',
|
||||
SUBMIT: 'submit',
|
||||
RESET: 'reset',
|
||||
FOCUS: 'focus',
|
||||
FOCUS_IN: 'focusin',
|
||||
FOCUS_OUT: 'focusout',
|
||||
BLUR: 'blur',
|
||||
INPUT: 'input',
|
||||
SELECT: 'select' as 'select',
|
||||
CHANGE: 'change' as 'change',
|
||||
SUBMIT: 'submit' as 'submit',
|
||||
RESET: 'reset' as 'reset',
|
||||
FOCUS: 'focus' as 'focus',
|
||||
FOCUS_IN: 'focusin' as 'focusin',
|
||||
FOCUS_OUT: 'focusout' as 'focusout',
|
||||
BLUR: 'blur' as 'blur',
|
||||
INPUT: 'input' as 'input',
|
||||
// Local Storage
|
||||
STORAGE: 'storage',
|
||||
STORAGE: 'storage' as 'storage',
|
||||
// Drag
|
||||
DRAG_START: 'dragstart',
|
||||
DRAG: 'drag',
|
||||
DRAG_ENTER: 'dragenter',
|
||||
DRAG_LEAVE: 'dragleave',
|
||||
DRAG_OVER: 'dragover',
|
||||
DROP: 'drop',
|
||||
DRAG_END: 'dragend',
|
||||
DRAG_START: 'dragstart' as 'dragstart',
|
||||
DRAG: 'drag' as 'drag',
|
||||
DRAG_ENTER: 'dragenter' as 'dragenter',
|
||||
DRAG_LEAVE: 'dragleave' as 'dragleave',
|
||||
DRAG_OVER: 'dragover' as 'dragover',
|
||||
DROP: 'drop' as 'drop',
|
||||
DRAG_END: 'dragend' as 'dragend',
|
||||
// Animation
|
||||
ANIMATION_START: browser.isWebKit ? 'webkitAnimationStart' : 'animationstart',
|
||||
ANIMATION_END: browser.isWebKit ? 'webkitAnimationEnd' : 'animationend',
|
||||
@@ -920,7 +943,7 @@ class FocusTracker implements IFocusTracker {
|
||||
private disposables: IDisposable[] = [];
|
||||
|
||||
constructor(element: HTMLElement | Window) {
|
||||
let hasFocus = false;
|
||||
let hasFocus = isAncestor(document.activeElement, <HTMLElement>element);
|
||||
let loosingFocus = false;
|
||||
|
||||
let onFocus = () => {
|
||||
@@ -971,7 +994,6 @@ export function prepend<T extends Node>(parent: HTMLElement, child: T): T {
|
||||
|
||||
const SELECTOR_REGEX = /([\w\-]+)?(#([\w\-]+))?((.([\w\-]+))*)/;
|
||||
|
||||
// Similar to builder, but much more lightweight
|
||||
export function $<T extends HTMLElement>(description: string, attrs?: { [key: string]: any; }, ...children: (Node | string)[]): T {
|
||||
let match = SELECTOR_REGEX.exec(description);
|
||||
|
||||
@@ -988,17 +1010,18 @@ export function $<T extends HTMLElement>(description: string, attrs?: { [key: st
|
||||
result.className = match[4].replace(/\./g, ' ').trim();
|
||||
}
|
||||
|
||||
Object.keys(attrs || {}).forEach(name => {
|
||||
attrs = attrs || {};
|
||||
Object.keys(attrs).forEach(name => {
|
||||
const value = attrs![name];
|
||||
if (/^on\w+$/.test(name)) {
|
||||
(<any>result)[name] = attrs[name];
|
||||
(<any>result)[name] = value;
|
||||
} else if (name === 'selected') {
|
||||
const value = attrs[name];
|
||||
if (value) {
|
||||
result.setAttribute(name, 'true');
|
||||
}
|
||||
|
||||
} else {
|
||||
result.setAttribute(name, attrs[name]);
|
||||
result.setAttribute(name, value);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1047,7 +1070,7 @@ export function hide(...elements: HTMLElement[]): void {
|
||||
}
|
||||
}
|
||||
|
||||
function findParentWithAttribute(node: Node, attribute: string): HTMLElement {
|
||||
function findParentWithAttribute(node: Node | null, attribute: string): HTMLElement | null {
|
||||
while (node) {
|
||||
if (node instanceof HTMLElement && node.hasAttribute(attribute)) {
|
||||
return node;
|
||||
@@ -1090,13 +1113,13 @@ export function finalHandler<T extends DOMEvent>(fn: (event: T) => any): (event:
|
||||
};
|
||||
}
|
||||
|
||||
export function domContentLoaded(): TPromise<any> {
|
||||
return new TPromise<any>((c, e) => {
|
||||
export function domContentLoaded(): Promise<any> {
|
||||
return new Promise<any>(resolve => {
|
||||
const readyState = document.readyState;
|
||||
if (readyState === 'complete' || (document && document.body !== null)) {
|
||||
platform.setImmediate(c);
|
||||
platform.setImmediate(resolve);
|
||||
} else {
|
||||
window.addEventListener('DOMContentLoaded', c, false);
|
||||
window.addEventListener('DOMContentLoaded', resolve, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user