UNPKG

25 kBTypeScriptView Raw
1/// <reference types="jquery" />
2/// <reference types="underscore" />
3
4export = Backbone;
5export as namespace Backbone;
6
7declare namespace Backbone {
8 type _Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
9 type _Result<T> = T | (() => T);
10 type _StringKey<T> = keyof T & string;
11
12 interface AddOptions extends Silenceable {
13 at?: number | undefined;
14 merge?: boolean | undefined;
15 sort?: boolean | undefined;
16 }
17
18 interface CollectionSetOptions extends Parseable, Silenceable {
19 add?: boolean | undefined;
20 remove?: boolean | undefined;
21 merge?: boolean | undefined;
22 at?: number | undefined;
23 sort?: boolean | undefined;
24 }
25
26 interface HistoryOptions extends Silenceable {
27 pushState?: boolean | undefined;
28 root?: string | undefined;
29 hashChange?: boolean | undefined;
30 }
31
32 interface NavigateOptions {
33 trigger?: boolean | undefined;
34 replace?: boolean | undefined;
35 }
36
37 interface RouterOptions {
38 routes: _Result<RoutesHash>;
39 }
40
41 interface Silenceable {
42 silent?: boolean | undefined;
43 }
44
45 interface Validable {
46 validate?: boolean | undefined;
47 }
48
49 interface Waitable {
50 wait?: boolean | undefined;
51 }
52
53 interface Parseable {
54 parse?: boolean | undefined;
55 }
56
57 interface PersistenceOptions extends Partial<_Omit<JQueryAjaxSettings, "success" | "error">> {
58 // TODO: Generalize modelOrCollection
59 success?: ((modelOrCollection: any, response: any, options: any) => void) | undefined;
60 error?: ((modelOrCollection: any, response: any, options: any) => void) | undefined;
61 emulateJSON?: boolean | undefined;
62 emulateHTTP?: boolean | undefined;
63 }
64
65 interface ModelConstructorOptions<TModel extends Model = Model> extends ModelSetOptions, Parseable {
66 collection?: Collection<TModel> | undefined;
67 }
68
69 type CombinedModelConstructorOptions<E, M extends Model<any, any, E> = Model> = ModelConstructorOptions<M> & E;
70
71 interface ModelSetOptions extends Silenceable, Validable {}
72
73 interface ModelFetchOptions extends PersistenceOptions, ModelSetOptions, Parseable {}
74
75 interface ModelSaveOptions extends Silenceable, Waitable, Validable, Parseable, PersistenceOptions {
76 patch?: boolean | undefined;
77 }
78
79 interface ModelDestroyOptions extends Waitable, PersistenceOptions {}
80
81 interface CollectionFetchOptions extends PersistenceOptions, Parseable, CollectionSetOptions {
82 reset?: boolean | undefined;
83 }
84
85 type ObjectHash = Record<string, any>;
86
87 interface RoutesHash {
88 [routePattern: string]: string | { (...urlParts: string[]): void };
89 }
90
91 /**
92 * DOM events (used in the events property of a View)
93 */
94 interface EventsHash {
95 [selector: string]: string | { (eventObject: JQuery.TriggeredEvent): void };
96 }
97
98 /**
99 * JavaScript events (used in the methods of the Events interface)
100 */
101 interface EventHandler {
102 (...args: any[]): void;
103 }
104 interface EventMap {
105 [event: string]: EventHandler;
106 }
107
108 const Events: Events;
109 interface Events extends EventsMixin {}
110
111 /**
112 * Helper shorthands for classes that implement the Events interface.
113 * Define your class like this:
114 *
115 * import {
116 * Events,
117 * Events_On,
118 * Events_Off,
119 * Events_Trigger,
120 * Events_Listen,
121 * Events_Stop,
122 * } from 'backbone';
123 *
124 * class YourClass implements Events {
125 * on: Events_On<YourClass>;
126 * off: Events_Off<YourClass>;
127 * trigger: Events_Trigger<YourClass>;
128 * bind: Events_On<YourClass>;
129 * unbind: Events_Off<YourClass>;
130 *
131 * once: Events_On<YourClass>;
132 * listenTo: Events_Listen<YourClass>;
133 * listenToOnce: Events_Listen<YourClass>;
134 * stopListening: Events_Stop<YourClass>;
135 *
136 * // ... (other methods)
137 * }
138 *
139 * Object.assign(YourClass.prototype, Events); // can also use _.extend
140 *
141 * If you are just writing a class type declaration that doesn't already
142 * extend some other base class, you can use the EventsMixin instead;
143 * see below.
144 */
145 interface Events_On<BaseT> {
146 <T extends BaseT>(this: T, eventName: string, callback: EventHandler, context?: any): T;
147 <T extends BaseT>(this: T, eventMap: EventMap, context?: any): T;
148 }
149 interface Events_Off<BaseT> {
150 <T extends BaseT>(this: T, eventName?: string | null, callback?: EventHandler | null, context?: any): T;
151 }
152 interface Events_Trigger<BaseT> {
153 <T extends BaseT>(this: T, eventName: string, ...args: any[]): T;
154 }
155 interface Events_Listen<BaseT> {
156 <T extends BaseT>(this: T, object: any, events: string, callback: EventHandler): T;
157 <T extends BaseT>(this: T, object: any, eventMap: EventMap): T;
158 }
159 interface Events_Stop<BaseT> {
160 <T extends BaseT>(this: T, object?: any, events?: string, callback?: EventHandler): T;
161 }
162
163 /**
164 * Helper to avoid code repetition in type declarations.
165 * Backbone.Events cannot be extended, hence a separate abstract
166 * class with a different name. Both classes and interfaces can
167 * extend from this helper class to reuse the signatures.
168 *
169 * For class type declarations that already extend another base
170 * class, and for actual class definitions, please see the
171 * Events_* interfaces above.
172 */
173 abstract class EventsMixin implements Events {
174 on(eventName: string, callback: EventHandler, context?: any): this;
175 on(eventMap: EventMap, context?: any): this;
176 off(eventName?: string | null, callback?: EventHandler | null, context?: any): this;
177 trigger(eventName: string, ...args: any[]): this;
178 bind(eventName: string, callback: EventHandler, context?: any): this;
179 bind(eventMap: EventMap, context?: any): this;
180 unbind(eventName?: string, callback?: EventHandler, context?: any): this;
181
182 once(events: string, callback: EventHandler, context?: any): this;
183 once(eventMap: EventMap, context?: any): this;
184 listenTo(object: any, events: string, callback: EventHandler): this;
185 listenTo(object: any, eventMap: EventMap): this;
186 listenToOnce(object: any, events: string, callback: EventHandler): this;
187 listenToOnce(object: any, eventMap: EventMap): this;
188 stopListening(object?: any, events?: string, callback?: EventHandler): this;
189 }
190
191 class ModelBase extends EventsMixin {
192 parse(response: any, options?: any): any;
193 toJSON(options?: any): any;
194 sync(...arg: any[]): JQueryXHR;
195 }
196
197 /**
198 * E - Extensions to the model constructor options. You can accept additional constructor options
199 * by listing them in the E parameter.
200 */
201 class Model<T extends ObjectHash = any, S = ModelSetOptions, E = any> extends ModelBase implements Events {
202 /**
203 * Do not use, prefer TypeScript's extend functionality.
204 */
205 static extend(properties: any, classProperties?: any): any;
206
207 attributes: Partial<T>;
208 changed: Partial<T>;
209 cidPrefix: string;
210 cid: string;
211 collection: Collection<this>;
212
213 private _changing: boolean;
214 private _previousAttributes: Partial<T>;
215 private _pending: boolean;
216
217 /**
218 * Default attributes for the model. It can be an object hash or a method returning an object hash.
219 * For assigning an object hash, do it like this: this.defaults = <any>{ attribute: value, ... };
220 * That works only if you set it in the constructor or the initialize method.
221 */
222 defaults(): Partial<T>;
223 id: string | number;
224 idAttribute: string;
225 validationError: any;
226
227 /**
228 * Returns the relative URL where the model's resource would be located on the server.
229 */
230 url: () => string;
231
232 urlRoot: _Result<string>;
233
234 /**
235 * For use with models as ES classes. If you define a preinitialize
236 * method, it will be invoked when the Model is first created, before
237 * any instantiation logic is run for the Model.
238 * @see https://backbonejs.org/#Model-preinitialize
239 */
240 preinitialize(attributes?: T, options?: CombinedModelConstructorOptions<E, this>): void;
241
242 constructor(attributes?: T, options?: CombinedModelConstructorOptions<E>);
243 initialize(attributes?: T, options?: CombinedModelConstructorOptions<E, this>): void;
244
245 fetch(options?: ModelFetchOptions): JQueryXHR;
246
247 /**
248 * For strongly-typed access to attributes, use the `get` method only privately in public getter properties.
249 * @example
250 * get name(): string {
251 * return super.get("name");
252 * }
253 */
254 get<A extends _StringKey<T>>(attributeName: A): T[A] | undefined;
255
256 /**
257 * For strongly-typed assignment of attributes, use the `set` method only privately in public setter properties.
258 * @example
259 * set name(value: string) {
260 * super.set("name", value);
261 * }
262 */
263 set<A extends _StringKey<T>>(attributeName: A, value?: T[A], options?: S): this;
264 set(attributeName: Partial<T>, options?: S): this;
265 set<A extends _StringKey<T>>(attributeName: A | Partial<T>, value?: T[A] | S, options?: S): this;
266
267 /**
268 * Return an object containing all the attributes that have changed, or
269 * false if there are no changed attributes. Useful for determining what
270 * parts of a view need to be updated and/or what attributes need to be
271 * persisted to the server. Unset attributes will be set to undefined.
272 * You can also pass an attributes object to diff against the model,
273 * determining if there *would be* a change.
274 */
275 changedAttributes(attributes?: Partial<T>): Partial<T> | false;
276 clear(options?: Silenceable): this;
277 clone(): Model;
278 destroy(options?: ModelDestroyOptions): JQueryXHR | false;
279 escape(attribute: _StringKey<T>): string;
280 has(attribute: _StringKey<T>): boolean;
281 hasChanged(attribute?: _StringKey<T>): boolean;
282 isNew(): boolean;
283 isValid(options?: any): boolean;
284 previous<A extends _StringKey<T>>(attribute: A): T[A] | null | undefined;
285 previousAttributes(): Partial<T>;
286 save(attributes?: Partial<T> | null, options?: ModelSaveOptions): JQueryXHR;
287 unset(attribute: _StringKey<T>, options?: Silenceable): this;
288 validate(attributes: Partial<T>, options?: any): any;
289 private _validate(attributes: Partial<T>, options: any): boolean;
290
291 // mixins from underscore
292
293 keys(): string[];
294 values(): any[];
295 pairs(): any[];
296 invert(): any;
297 pick<A extends _StringKey<T>>(keys: A[]): Partial<Pick<T, A>>;
298 pick<A extends _StringKey<T>>(...keys: A[]): Partial<Pick<T, A>>;
299 pick(fn: (value: any, key: any, object: any) => any): Partial<T>;
300 omit<A extends _StringKey<T>>(keys: A[]): Partial<_Omit<T, A>>;
301 omit<A extends _StringKey<T>>(...keys: A[]): Partial<_Omit<T, A>>;
302 omit(fn: (value: any, key: any, object: any) => any): Partial<T>;
303 chain(): any;
304 isEmpty(): boolean;
305 matches(attrs: any): boolean;
306 }
307
308 class Collection<TModel extends Model = Model> extends ModelBase implements Events {
309 /**
310 * Do not use, prefer TypeScript's extend functionality.
311 */
312 static extend(properties: any, classProperties?: any): any;
313
314 model: new(...args: any[]) => TModel;
315 models: TModel[];
316 length: number;
317
318 /**
319 * For use with collections as ES classes. If you define a preinitialize
320 * method, it will be invoked when the Collection is first created and
321 * before any instantiation logic is run for the Collection.
322 * @see https://backbonejs.org/#Collection-preinitialize
323 */
324 preinitialize(models?: TModel[] | Array<Record<string, any>>, options?: any): void;
325
326 constructor(models?: TModel[] | Array<Record<string, any>>, options?: any);
327 initialize(models?: TModel[] | Array<Record<string, any>>, options?: any): void;
328
329 fetch(options?: CollectionFetchOptions): JQueryXHR;
330
331 /**
332 * Specify a model attribute name (string) or function that will be used to sort the collection.
333 */
334 comparator:
335 | string
336 | { bivarianceHack(element: TModel): number | string }["bivarianceHack"]
337 | { bivarianceHack(compare: TModel, to?: TModel): number }["bivarianceHack"];
338
339 add(model: {} | TModel, options?: AddOptions): TModel;
340 add(models: Array<{} | TModel>, options?: AddOptions): TModel[];
341 at(index: number): TModel;
342 /**
343 * Get a model from a collection, specified by an id, a cid, or by passing in a model.
344 */
345 get(id: number | string | Model): TModel;
346 has(key: number | string | Model): boolean;
347 clone(): this;
348 create(attributes: any, options?: ModelSaveOptions): TModel;
349 pluck(attribute: string): any[];
350 push(model: TModel, options?: AddOptions): TModel;
351 pop(options?: Silenceable): TModel;
352 remove(model: {} | TModel, options?: Silenceable): TModel;
353 remove(models: Array<{} | TModel>, options?: Silenceable): TModel[];
354 reset(models?: Array<{} | TModel>, options?: Silenceable): TModel[];
355
356 /**
357 * The set method performs a "smart" update of the collection with the passed list of models.
358 * If a model in the list isn't yet in the collection it will be added; if the model is already in the
359 * collection its attributes will be merged; and if the collection contains any models that aren't present
360 * in the list, they'll be removed. All of the appropriate "add", "remove", and "change" events are fired as
361 * this happens. Returns the touched models in the collection. If you'd like to customize the behavior, you can
362 * disable it with options: {add: false}, {remove: false}, or {merge: false}.
363 * @param models
364 * @param options
365 */
366 set(models?: Array<{} | TModel>, options?: CollectionSetOptions): TModel[];
367 shift(options?: Silenceable): TModel;
368 sort(options?: Silenceable): this;
369 unshift(model: TModel, options?: AddOptions): TModel;
370 where(properties: any): TModel[];
371 findWhere(properties: any): TModel;
372 modelId(attrs: any): any;
373
374 values(): Iterator<TModel>;
375 keys(): Iterator<any>;
376 entries(): Iterator<[any, TModel]>;
377 [Symbol.iterator](): Iterator<TModel>;
378
379 private _prepareModel(attributes?: any, options?: any): any;
380 private _removeReference(model: TModel): void;
381 private _onModelEvent(event: string, model: TModel, collection: Collection<TModel>, options: any): void;
382 private _isModel(obj: any): obj is Model;
383
384 /**
385 * Return a shallow copy of this collection's models, using the same options as native Array#slice.
386 */
387 slice(min?: number, max?: number): TModel[];
388
389 // mixins from underscore
390
391 all(iterator?: _.ListIterator<TModel, boolean>, context?: any): boolean;
392 any(iterator?: _.ListIterator<TModel, boolean>, context?: any): boolean;
393 chain(): any;
394 collect<TResult>(iterator: _.ListIterator<TModel, TResult>, context?: any): TResult[];
395 contains(value: TModel): boolean;
396 countBy(iterator?: _.ListIterator<TModel, any>): _.Dictionary<number>;
397 countBy(iterator: string): _.Dictionary<number>;
398 detect(iterator: _.ListIterator<TModel, boolean>, context?: any): TModel;
399 difference(others: TModel[]): TModel[];
400 drop(n?: number): TModel[];
401 each(iterator: _.ListIterator<TModel, void>, context?: any): TModel[];
402 every(iterator: _.ListIterator<TModel, boolean>, context?: any): boolean;
403 filter(iterator: _.ListIterator<TModel, boolean>, context?: any): TModel[];
404 find(iterator: _.ListIterator<TModel, boolean>, context?: any): TModel;
405 findIndex(predicate: _.ListIterator<TModel, boolean>, context?: any): number;
406 findLastIndex(predicate: _.ListIterator<TModel, boolean>, context?: any): number;
407 first(): TModel;
408 first(n: number): TModel[];
409 foldl<TResult>(iterator: _.MemoIterator<TModel, TResult>, memo?: TResult, context?: any): TResult;
410 foldr<TResult>(iterator: _.MemoIterator<TModel, TResult>, memo?: TResult, context?: any): TResult;
411 forEach(iterator: _.ListIterator<TModel, void>, context?: any): TModel[];
412 groupBy(iterator: _.ListIterator<TModel, any> | string, context?: any): _.Dictionary<TModel[]>;
413 head(): TModel;
414 head(n: number): TModel[];
415 include(value: TModel): boolean;
416 includes(value: TModel): boolean;
417 indexBy(iterator: _.ListIterator<TModel, any>, context?: any): _.Dictionary<TModel>;
418 indexBy(iterator: string, context?: any): _.Dictionary<TModel>;
419 indexOf(value: TModel, isSorted?: boolean): number;
420 initial(): TModel;
421 initial(n: number): TModel[];
422 inject<TResult>(iterator: _.MemoIterator<TModel, TResult>, memo?: TResult, context?: any): TResult;
423 invoke(methodName: string, ...args: any[]): any;
424 isEmpty(): boolean;
425 last(): TModel;
426 last(n: number): TModel[];
427 lastIndexOf(value: TModel, from?: number): number;
428 map<TResult>(iterator: _.ListIterator<TModel, TResult>, context?: any): TResult[];
429 max(iterator?: _.ListIterator<TModel, any>, context?: any): TModel;
430 min(iterator?: _.ListIterator<TModel, any>, context?: any): TModel;
431 partition(iterator: _.ListIterator<TModel, boolean>): TModel[][];
432 reduce<TResult>(iterator: _.MemoIterator<TModel, TResult>, memo?: TResult, context?: any): TResult;
433 reduceRight<TResult>(iterator: _.MemoIterator<TModel, TResult>, memo?: TResult, context?: any): TResult;
434 reject(iterator: _.ListIterator<TModel, boolean>, context?: any): TModel[];
435 rest(n?: number): TModel[];
436 sample(): TModel;
437 sample(n: number): TModel[];
438 select(iterator: _.ListIterator<TModel, boolean>, context?: any): TModel[];
439 shuffle(): TModel[];
440 size(): number;
441 some(iterator?: _.ListIterator<TModel, boolean>, context?: any): boolean;
442 sortBy(iterator?: _.ListIterator<TModel, any>, context?: any): TModel[];
443 sortBy(iterator: string, context?: any): TModel[];
444 tail(n?: number): TModel[];
445 take(): TModel;
446 take(n: number): TModel[];
447 toArray(): TModel[];
448
449 /**
450 * Sets the url property (or function) on a collection to reference its location on the server.
451 */
452 url: _Result<string>;
453
454 without(...values: TModel[]): TModel[];
455 }
456
457 type RouterCallback = (...args: string[]) => void;
458
459 class Router extends EventsMixin implements Events {
460 /**
461 * Do not use, prefer TypeScript's extend functionality.
462 */
463 static extend(properties: any, classProperties?: any): any;
464
465 /**
466 * Routes hash or a method returning the routes hash that maps URLs with parameters to methods on your Router.
467 * For assigning routes as object hash, do it like this: this.routes = <any>{ "route": callback, ... };
468 * That works only if you set it in the constructor or the initialize method.
469 */
470 routes: _Result<RoutesHash>;
471
472 /**
473 * For use with Router as ES classes. If you define a preinitialize method,
474 * it will be invoked when the Router is first created, before any
475 * instantiation logic is run for the Router.
476 * @see https://backbonejs.org/#Router-preinitialize
477 */
478 preinitialize(options?: RouterOptions): void;
479
480 constructor(options?: RouterOptions);
481 initialize(options?: RouterOptions): void;
482 route(route: string | RegExp, name: string, callback?: RouterCallback): this;
483 route(route: string | RegExp, callback: RouterCallback): this;
484 navigate(fragment: string, options?: NavigateOptions | boolean): this;
485
486 execute(callback: RouterCallback, args: string[], name: string): void;
487
488 protected _bindRoutes(): void;
489 protected _routeToRegExp(route: string): RegExp;
490 protected _extractParameters(route: RegExp, fragment: string): string[];
491 }
492
493 const history: History;
494
495 class History extends EventsMixin implements Events {
496 handlers: any[];
497 interval: number;
498
499 start(options?: HistoryOptions): boolean;
500
501 getHash(window?: Window): string;
502 getFragment(fragment?: string): string;
503 decodeFragment(fragment: string): string;
504 getSearch(): string;
505 stop(): void;
506 route(route: string | RegExp, callback: (fragment: string) => void): number;
507 checkUrl(e?: any): void;
508 getPath(): string;
509 matchRoot(): boolean;
510 atRoot(): boolean;
511 loadUrl(fragmentOverride?: string): boolean;
512 navigate(fragment: string, options?: any): boolean;
513 static started: boolean;
514 options: any;
515
516 private _updateHash(location: Location, fragment: string, replace: boolean): void;
517 }
518
519 interface ViewOptions<TModel extends (Model | undefined) = Model, TElement extends Element = HTMLElement> {
520 model?: TModel | undefined;
521 // TODO: quickfix, this can't be fixed easy. The collection does not need to have the same model as the parent view.
522 collection?: Collection<any> | undefined; // was: Collection<TModel>;
523 el?: TElement | JQuery | string | undefined;
524 id?: string | undefined;
525 attributes?: Record<string, any> | undefined;
526 className?: string | undefined;
527 tagName?: string | undefined;
528 events?: _Result<EventsHash> | undefined;
529 }
530
531 type ViewEventListener = (event: JQuery.Event) => void;
532
533 class View<TModel extends (Model | undefined) = Model, TElement extends Element = HTMLElement> extends EventsMixin
534 implements Events
535 {
536 /**
537 * Do not use, prefer TypeScript's extend functionality.
538 */
539 static extend(properties: any, classProperties?: any): any;
540
541 /**
542 * For use with views as ES classes. If you define a preinitialize
543 * method, it will be invoked when the view is first created, before any
544 * instantiation logic is run.
545 * @see https://backbonejs.org/#View-preinitialize
546 */
547 preinitialize(options?: ViewOptions<TModel, TElement>): void;
548
549 constructor(options?: ViewOptions<TModel, TElement>);
550 initialize(options?: ViewOptions<TModel, TElement>): void;
551
552 /**
553 * Events hash or a method returning the events hash that maps events/selectors to methods on your View.
554 * For assigning events as object hash, do it like this: this.events = <any>{ "event:selector": callback, ... };
555 * That works only if you set it in the constructor or the initialize method.
556 */
557 events(): EventsHash;
558
559 // A conditional type used here to prevent `TS2532: Object is possibly 'undefined'`
560 model: TModel extends Model ? TModel : undefined;
561 collection: Collection<any>;
562 setElement(element: TElement | JQuery): this;
563 id?: string | undefined;
564 cid: string;
565 className?: string | undefined;
566 tagName: string;
567
568 el: TElement;
569 $el: JQuery;
570 attributes: Record<string, any>;
571 $(selector: string): JQuery;
572 render(): this;
573 remove(): this;
574 delegateEvents(events?: _Result<EventsHash>): this;
575 delegate(eventName: string, selector: string, listener: ViewEventListener): this;
576 undelegateEvents(): this;
577 undelegate(eventName: string, selector?: string, listener?: ViewEventListener): this;
578
579 protected _removeElement(): void;
580 protected _setElement(el: TElement | JQuery): void;
581 protected _createElement(tagName: string): void;
582 protected _ensureElement(): void;
583 protected _setAttributes(attributes: Record<string, any>): void;
584 }
585
586 // SYNC
587 function sync(method: string, model: Model | Collection, options?: JQueryAjaxSettings): any;
588 function ajax(options?: JQueryAjaxSettings): JQueryXHR;
589 let emulateHTTP: boolean;
590 let emulateJSON: boolean;
591
592 // Utility
593 function noConflict(): typeof Backbone;
594 let $: JQueryStatic;
595}