[jquery] Add preDispatch and postDispatch methods. Fix weak type issues. (#29750)

* [jquery] Add `preDispatch` and `postDispatch` methods.

See https://github.com/jquery/api.jquery.com/issues/752.

* [jquery] Fix weak type issue for `SpecialEventHook`.

* [jquery] Fix weak type issue for `FixHook`.

* [jquery] Add interface for `jQuery.valHooks`.

* [jquery] Fix weak type issue for `ValHook`.

* [jquery] Add interface for `jQuery.cssHooks`.

* [jquery] Properties on `CSSHook` are optional.

* [jquery] Use polymorphic `this` for `settings` parameter.

* [jquery] Wrap `StatusCodeCallbacks` in a region.

* [jquery] Split `@since` tag for consistency.
This commit is contained in:
Leonard Thieu
2018-10-16 14:42:42 -07:00
committed by Sheetal Nandi
parent 5037781c9a
commit bbf1adeeac
3 changed files with 265 additions and 49 deletions
+90 -46
View File
@@ -60,8 +60,7 @@ interface JQueryStatic {
* @see \`{@link https://api.jquery.com/jQuery.cssHooks/ }\`
* @since 1.4.3
*/
// Set to HTMLElement to minimize breaks but should probably be Element.
cssHooks: JQuery.PlainObject<JQuery.CSSHook<HTMLElement>>;
cssHooks: JQuery.CSSHooks;
/**
* An object containing all CSS properties that may be used without a unit. The .css() method uses this
* object to see if it may append px to unitless values.
@@ -118,8 +117,7 @@ $.when(
support: JQuery.PlainObject;
timers: Array<JQuery.TickFunction<any>>;
Tween: JQuery.TweenStatic;
// Set to HTMLElement to minimize breaks but should probably be Element.
valHooks: JQuery.PlainObject<JQuery.ValHook<HTMLElement>>;
valHooks: JQuery.ValHooks;
// HACK: This is the factory function returned when importing jQuery without a DOM. Declaring it separately breaks using the type parameter on JQueryStatic.
// HACK: The discriminator parameter handles the edge case of passing a Window object to JQueryStatic. It doesn't actually exist on the factory function.
(window: Window, discriminator: boolean): JQueryStatic;
@@ -2021,7 +2019,8 @@ $.getScript( "myplugin.js", function() {
*
* @param html The HTML string on which to operate.
* @see \`{@link https://api.jquery.com/jQuery.htmlPrefilter/ }\`
* @since 1.12/2.2
* @since 1.12
* @since 2.2
*/
htmlPrefilter(html: JQuery.htmlString): JQuery.htmlString;
/**
@@ -26376,14 +26375,6 @@ declare namespace JQuery {
* A string containing the URL to which the request is sent.
*/
url?: string;
/**
* A pre-request callback function that can be used to modify the jqXHR (in jQuery 1.4.x,
* XMLHTTPRequest) object before it is sent. Use this to set custom headers, etc. The jqXHR and
* settings objects are passed as arguments. This is an Ajax Event. Returning false in the beforeSend
* function will cancel the request. As of jQuery 1.5, the beforeSend option will be called regardless
* of the type of request.
*/
beforeSend?(this: TContext, jqXHR: jqXHR, settings: AjaxSettings<TContext>): false | void;
}
interface UrlAjaxSettings<TContext = any> extends Ajax.AjaxSettingsBase<TContext> {
@@ -26391,14 +26382,6 @@ declare namespace JQuery {
* A string containing the URL to which the request is sent.
*/
url: string;
/**
* A pre-request callback function that can be used to modify the jqXHR (in jQuery 1.4.x,
* XMLHTTPRequest) object before it is sent. Use this to set custom headers, etc. The jqXHR and
* settings objects are passed as arguments. This is an Ajax Event. Returning false in the beforeSend
* function will cancel the request. As of jQuery 1.5, the beforeSend option will be called regardless
* of the type of request.
*/
beforeSend?(this: TContext, jqXHR: jqXHR, settings: UrlAjaxSettings<TContext>): false | void;
}
namespace Ajax {
@@ -26443,7 +26426,7 @@ declare namespace JQuery {
* function will cancel the request. As of jQuery 1.5, the beforeSend option will be called regardless
* of the type of request.
*/
beforeSend?(this: TContext, jqXHR: jqXHR, settings: AjaxSettingsBase<TContext>): false | void;
beforeSend?(this: TContext, jqXHR: jqXHR, settings: this): false | void;
/**
* If set to false, it will force requested pages not to be cached by the browser. Note: Setting cache
* to false will only work correctly with HEAD and GET requests. It works by appending "_={timestamp}"
@@ -26673,6 +26656,9 @@ declare namespace JQuery {
xhrFields?: XHRFields;
}
// region StatusCodeCallbacks
// #region StatusCodeCallbacks
type StatusCodeCallbacks<TContext> = {
// region Success Status Codes
// #region Success Status Codes
@@ -27092,6 +27078,8 @@ declare namespace JQuery {
[index: number]: SuccessCallback<TContext> | ErrorCallback<TContext>;
};
// #endregion
// Writable properties on XMLHttpRequest
interface XHRFields extends Partial<Pick<XMLHttpRequest, 'onreadystatechange' | 'responseType' | 'timeout' | 'withCredentials'>> {
msCaching?: string;
@@ -27575,12 +27563,24 @@ callbacks.fire( "world" );
// #endregion
// region CSS
// #region CSS
// region CSS hooks
// #region CSS hooks
interface CSSHook<TElement> {
get(this: this, elem: TElement, computed: any, extra: any): any;
set(this: this, elem: TElement, value: any): void;
// Workaround for TypeScript 2.3 which does not have support for weak types handling.
type CSSHook<TElement> =
Partial<_CSSHook<TElement>> & (
Pick<_CSSHook<TElement>, 'get'> |
Pick<_CSSHook<TElement>, 'set'>
);
interface _CSSHook<TElement> {
get(elem: TElement, computed: any, extra: any): any;
set(elem: TElement, value: any): void;
}
interface CSSHooks {
// Set to HTMLElement to minimize breaks but should probably be Element.
[propertyName: string]: CSSHook<HTMLElement>;
}
// #endregion
@@ -31342,13 +31342,18 @@ $( "ul" ).click( handler ).find( "ul" ).hide();
special: SpecialEventHooks;
}
interface FixHook {
// region Fix hooks
// #region Fix hooks
// Workaround for TypeScript 2.3 which does not have support for weak types handling.
type FixHook = {
/**
* Strings representing properties that should be copied from the browser's event object to the jQuery
* event object. If omitted, no additional properties are copied beyond the standard ones that jQuery
* copies and normalizes (e.g. `event.target` and `event.relatedTarget`).
*/
props?: string[];
props: string[];
} | {
/**
* jQuery calls this function after it constructs the `jQuery.Event` object, copies standard properties
* from `jQuery.event.props`, and copies the `fixHooks`-specific props (if any) specified above. The
@@ -31399,8 +31404,10 @@ if ( !existingHook ) {
}
```
*/
filter?(event: Event, originalEvent: _Event): void;
}
filter(event: Event, originalEvent: _Event): void;
} | {
[key: string]: never;
};
/**
* The `fixHooks` interface provides a per-event-type way to extend or normalize the event object that
@@ -31412,6 +31419,8 @@ if ( !existingHook ) {
[event: string]: FixHook;
}
// #endregion
// region Special event hooks
// #region Special event hooks
@@ -31428,7 +31437,8 @@ if ( !existingHook ) {
*
* @see \`{@link https://learn.jquery.com/events/event-extensions/#special-event-hooks }\`
*/
interface SpecialEventHook<TTarget, TData> {
// Workaround for TypeScript 2.3 which does not have support for weak types handling.
type SpecialEventHook<TTarget, TData> = {
/**
* Indicates whether this event type should be bubbled when the `.trigger()` method is called; by
* default it is `false`, meaning that a triggered event will bubble to the element's parents up to the
@@ -31437,7 +31447,8 @@ if ( !existingHook ) {
*
* @see \`{@link https://learn.jquery.com/events/event-extensions/#nobubble-boolean }\`
*/
noBubble?: boolean;
noBubble: boolean;
} | {
/**
* When defined, these string properties specify that a special event should be handled like another
* event type until the event is delivered. The `bindType` is used if the event is attached directly,
@@ -31446,7 +31457,8 @@ if ( !existingHook ) {
*
* @see \`{@link https://learn.jquery.com/events/event-extensions/#bindtype-string-delegatetype-string }\`
*/
bindType?: string;
bindType: string;
} | {
/**
* When defined, these string properties specify that a special event should be handled like another
* event type until the event is delivered. The `bindType` is used if the event is attached directly,
@@ -31455,7 +31467,8 @@ if ( !existingHook ) {
*
* @see \`{@link https://learn.jquery.com/events/event-extensions/#bindtype-string-delegatetype-string }\`
*/
delegateType?: string;
delegateType: string;
} | {
/**
* The setup hook is called the first time an event of a particular type is attached to an element;
* this provides the hook an opportunity to do processing that will apply to all events of this type on
@@ -31474,7 +31487,8 @@ if ( !existingHook ) {
*
* @see \`{@link https://learn.jquery.com/events/event-extensions/#setup-function-data-object-namespaces-eventhandle-function }\`
*/
setup?(this: TTarget, data: TData, namespaces: string, eventHandle: EventHandler<TTarget, TData>): void | false;
setup(this: TTarget, data: TData, namespaces: string, eventHandle: EventHandler<TTarget, TData>): void | false;
} | {
/**
* The teardown hook is called when the final event of a particular type is removed from an element.
* The `this` keyword will be a reference to the element where the event is being cleaned up. This hook
@@ -31489,7 +31503,8 @@ if ( !existingHook ) {
*
* @see \`{@link https://learn.jquery.com/events/event-extensions/#teardown-function }\`
*/
teardown?(this: TTarget): void | false;
teardown(this: TTarget): void | false;
} | {
/**
* Each time an event handler is added to an element through an API such as `.on()`, jQuery calls this
* hook. The `this` keyword will be the element to which the event handler is being added, and the
@@ -31497,7 +31512,8 @@ if ( !existingHook ) {
*
* @see \`{@link https://learn.jquery.com/events/event-extensions/#add-function-handleobj }\`
*/
add?(this: TTarget, handleObj: HandleObject<TTarget, TData>): void;
add(this: TTarget, handleObj: HandleObject<TTarget, TData>): void;
} | {
/**
* When an event handler is removed from an element using an API such as `.off()`, this hook is called.
* The `this` keyword will be the element where the handler is being removed, and the `handleObj`
@@ -31505,7 +31521,8 @@ if ( !existingHook ) {
*
* @see \`{@link https://learn.jquery.com/events/event-extensions/#remove-function-handleobj }\`
*/
remove?(this: TTarget, handleObj: HandleObject<TTarget, TData>): void;
remove(this: TTarget, handleObj: HandleObject<TTarget, TData>): void;
} | {
/**
* Called when the `.trigger()` or `.triggerHandler()` methods are used to trigger an event for the
* special type from code, as opposed to events that originate from within the browser. The `this`
@@ -31524,7 +31541,8 @@ if ( !existingHook ) {
*
* @see \`{@link https://learn.jquery.com/events/event-extensions/#trigger-function-event-jquery-event-data-object }\`
*/
trigger?(this: TTarget, event: Event<TTarget, TData>, data: TData): void | false;
trigger(this: TTarget, event: Event<TTarget, TData>, data: TData): void | false;
} | {
/**
* When the `.trigger()` method finishes running all the event handlers for an event, it also looks for
* and runs any method on the target object by the same name unless of the handlers called `event.preventDefault()`.
@@ -31535,7 +31553,8 @@ if ( !existingHook ) {
*
* @see \`{@link https://learn.jquery.com/events/event-extensions/#_default-function-event-jquery-event-data-object }\`
*/
_default?(event: Event<TTarget, TData>, data: TData): void | false;
_default(event: Event<TTarget, TData>, data: TData): void | false;
} | {
/**
* jQuery calls a handle hook when the event has occurred and jQuery would normally call the user's event
* handler specified by `.on()` or another event binding method. If the hook exists, jQuery calls it
@@ -31555,8 +31574,14 @@ if ( !existingHook ) {
*
* @see \`{@link https://learn.jquery.com/events/event-extensions/#handle-function-event-jquery-event-data-object }\`
*/
handle?(this: TTarget, event: Event<TTarget, TData> & { handleObj: HandleObject<TTarget, TData>; }, ...data: TData[]): void;
}
handle(this: TTarget, event: Event<TTarget, TData> & { handleObj: HandleObject<TTarget, TData>; }, ...data: TData[]): void;
} | {
preDispatch(this: TTarget, event: Event<TTarget, TData>): false | void;
} | {
postDispatch(this: TTarget, event: Event<TTarget, TData>): void;
} | {
[key: string]: never;
};
interface SpecialEventHooks {
[event: string]: SpecialEventHook<EventTarget, any>;
@@ -31615,6 +31640,9 @@ if ( !existingHook ) {
value: string;
}
// region Coordinates
// #region Coordinates
interface Coordinates {
left: number;
top: number;
@@ -31626,11 +31654,27 @@ if ( !existingHook ) {
Pick<Coordinates, 'top'> |
{ [key: string]: never; };
interface ValHook<TElement> {
get?(elem: TElement): any;
set?(elem: TElement, value: any): any;
// #endregion
// region Val hooks
// #region Val hooks
// Workaround for TypeScript 2.3 which does not have support for weak types handling.
type ValHook<TElement> = {
get(elem: TElement): any;
} | {
set(elem: TElement, value: any): any;
} | {
[key: string]: never;
};
interface ValHooks {
// Set to HTMLElement to minimize breaks but should probably be Element.
[nodeName: string]: ValHook<HTMLElement>;
}
// #endregion
type _Falsy = false | null | undefined | 0 | '' | typeof document.all;
}
+174 -2
View File
@@ -19,7 +19,7 @@ function JQueryStatic() {
}
function cssHooks() {
// $ExpectType PlainObject<CSSHook<HTMLElement>>
// $ExpectType CSSHooks
$.cssHooks;
}
@@ -84,7 +84,7 @@ function JQueryStatic() {
}
function valHooks() {
// $ExpectType PlainObject<ValHook<HTMLElement>>
// $ExpectType ValHooks
$.valHooks;
}
@@ -7119,6 +7119,51 @@ function JQuery_Callbacks() {
}
}
function JQuery_CSSHooks() {
$.cssHooks.borderRadius = {
get(elem, computed, extra) {
// $ExpectedType HTMLElement
elem;
// $ExpectedType any
computed;
// $ExpectedType any
extra;
},
set(elem, value) {
// $ExpectedType HTMLElement
elem;
// $ExpectedType any
value;
}
};
$.cssHooks.borderRadius = {
get(elem, computed, extra) {
// $ExpectedType HTMLElement
elem;
// $ExpectedType any
computed;
// $ExpectedType any
extra;
}
};
$.cssHooks.borderRadius = {
set(elem, value) {
// $ExpectedType HTMLElement
elem;
// $ExpectedType any
value;
}
};
// Weak type test. This may be removed if the TypeScript requirement is increased to 2.4+.
// $ExpectError
$.cssHooks.borderRadius = function get(elem: HTMLElement, computed: any, extra: any) {
return 1;
};
}
function JQuery_Promise3() {
interface I1 { kind: 'I1'; }
interface I2 { kind: 'I2'; }
@@ -8143,3 +8188,130 @@ function JQuery_Event() {
$(window).trigger(event);
}
}
function JQuery_EventExtensions() {
function fixHooks() {
jQuery.event.fixHooks.drop = {
props: ['dataTransfer'],
filter(event, originalEvent) {
// $ExpectType Event<EventTarget, null>
event;
// $ExpectType Event
originalEvent;
},
};
// Weak type test. This may be removed if the TypeScript requirement is increased to 2.4+.
// $ExpectError
jQuery.event.fixHooks.drop = ['dataTransfer'];
}
function special() {
jQuery.event.special.multiclick = {
noBubble: true,
bindType: 'click',
delegateType: 'click',
setup(data, namespaces, eventHandle) {
// $ExpectType EventTarget
this;
// $ExpectType any
data;
// $ExpectType string
namespaces;
// $ExpectType EventHandler<EventTarget, any>
eventHandle;
return false;
},
teardown() {
// $ExpectType EventTarget
this;
return false;
},
add(handleObj) {
// $ExpectType EventTarget
this;
// $ExpectType HandleObject<EventTarget, any>
handleObj;
},
remove(handleObj) {
// $ExpectType EventTarget
this;
// $ExpectType HandleObject<EventTarget, any>
handleObj;
},
trigger(event, data) {
// $ExpectType EventTarget
this;
// $ExpectType Event<EventTarget, any>
event;
// $ExpectType any
data;
return false;
},
_default(event, data) {
// $ExpectType Event<EventTarget, any>
event;
// $ExpectType any
data;
return false;
},
handle(event, data) {
// $ExpectType Event<EventTarget, any> & { handleObj: HandleObject<EventTarget, any>; }
event;
// $ExpectType any
data;
},
preDispatch(event) {
// $ExpectType EventTarget
this;
// $ExpectType Event<EventTarget, any>
event;
return false;
},
postDispatch(event) {
// $ExpectType EventTarget
this;
// $ExpectType Event<EventTarget, any>
event;
}
};
// Weak type test. This may be removed if the TypeScript requirement is increased to 2.4+.
// $ExpectError
jQuery.event.special.multiclick = 1;
}
}
declare namespace JQuery {
interface ValHooks {
textarea: ValHook<HTMLTextAreaElement>;
}
}
function JQuery_ValHooks() {
jQuery.valHooks.textarea = {
get(elem) {
// $ExpectType HTMLTextAreaElement
elem;
return elem.value.replace(/\r?\n/g, "\r\n");
},
set(elem) {
// $ExpectType HTMLTextAreaElement
elem;
return elem.value;
}
};
// Weak type test. This may be removed if the TypeScript requirement is increased to 2.4+.
// $ExpectError
jQuery.valHooks.textarea = function get(elem: HTMLTextAreaElement) {
return elem.value.replace(/\r?\n/g, "\r\n");
};
}
+1 -1
View File
@@ -1341,7 +1341,7 @@ function longdesc() {
function jquery_css_hooks_6() {
$.fx.step.someCSSProp = function(fx) {
$.cssHooks.someCSSProp.set(fx.elem as HTMLElement, fx.now + fx.unit);
$.cssHooks.someCSSProp.set!(fx.elem as HTMLElement, fx.now + fx.unit);
};
}