diff --git a/docs/mithril.render.md b/docs/mithril.render.md index 0b4c6beb..39b0a808 100644 --- a/docs/mithril.render.md +++ b/docs/mithril.render.md @@ -122,4 +122,4 @@ where: - **Boolean forceRecreation** - If set to true, rendering a new virtual tree will completely overwrite an existing one without attempting to diff against it \ No newline at end of file + If set to true, rendering a new virtual tree will completely overwrite an existing one without attempting to diff against it diff --git a/docs/web-services.md b/docs/web-services.md index 469bfb4b..ebc3d2e5 100644 --- a/docs/web-services.md +++ b/docs/web-services.md @@ -1,8 +1,8 @@ ## Web Services -Mithril provides a high-level utility for working with web services, which allows writing asynchronous code relatively procedurally. +Mithril allows writing asynchronous code in a procedural way through a high-level utility for working with web services. -It provides a number of useful features out of the box: +This utility provides a number of useful features out of the box: - The ability to get an early reference to a container that will hold the asynchronous response - The ability to queue operations to be performed after the asynchronous request completes diff --git a/mithril.d.ts b/mithril.d.ts index c9763a96..3db03036 100644 --- a/mithril.d.ts +++ b/mithril.d.ts @@ -1,166 +1,884 @@ -//Mithril type definitions for Typescript +// Mithril type definitions for Typescript + +/** +* This is the module containing all the types/declarations/etc. for Mithril +*/ declare module _mithril { interface MithrilStatic { + /** + * Creates a virtual element for use with m.render, m.mount, etc. + * + * @param selector A simple CSS selector. May include SVG tags. Nested + * selectors are not supported. + * @param attributes Attributes to add. Any DOM attribute may be used + * as an attribute, although innerHTML and the like may be overwritten + * silently. + * @param children Child elements, components, and text to add. + * @return A virtual element. + * + * @see m.render + * @see m.mount + * @see m.component + */ + ( + selector: string, + attributes: MithrilAttributes, + ...children: Array | + MithrilComponent> + ): MithrilVirtualElement; - (selector: string, attributes: MithrilAttributes, ...children: Array>): MithrilVirtualElement; - (selector: string, ...children: Array>): MithrilVirtualElement; + /** + * Creates a virtual element for use with m.render, m.mount, etc. + * + * @param selector A simple CSS selector. Nested selectors are not + * supported. + * @param children Child elements, components, and text to add. + * @return A virtual element. + * + * @see m.render + * @see m.mount + * @see m.component + */ + ( + selector: string, + ...children: Array | + MithrilComponent> + ): MithrilVirtualElement; - prop(promise: MithrilPromise) : MithrilPromiseProperty; - prop(value: T): MithrilProperty; - prop(): MithrilProperty; // might be that this should be Property + /** + * Initializes a component for use with m.render, m.mount, etc. + * Shorthand for m.component. + * + * @param selector A component. + * @param args Arguments to optionally pass to the component. + * @return A component. + * + * @see m.render + * @see m.mount + * @see m.component + */ + ( + component: MithrilComponent, + ...args: any[] + ): MithrilComponent; - withAttr(property: string, callback: (value: any) => void): (e: MithrilEvent) => any; + /** + * Creates a getter-setter function that wraps a Mithril promise. Useful + * for uniform data access, m.withAttr, etc. + * + * @param promise A thennable to initialize the property with. It may + * optionally be a Mithril promise. + * @return A getter-setter function wrapping the promise. + * + * @see m.withAttr + */ + prop(promise: Thennable) : MithrilPromiseProperty; - module(rootElement: Node, component: MithrilComponent): T; - module(rootElement: Node): T; - mount(rootElement: Node, component: MithrilComponent): T; - mount(rootElement: Node): T; + /** + * Creates a getter-setter function that wraps a simple value. Useful + * for uniform data access, m.withAttr, etc. + * + * @param value A value to initialize the property with + * @return A getter-setter function wrapping the value. + * + * @see m.withAttr + */ + prop(value: T): MithrilBasicProperty; - component(component: MithrilComponent, ...args: Array): MithrilComponent - - trust(html: string): string; + /** + * Creates a getter-setter function that wraps a simple value. Useful + * for uniform data access, m.withAttr, etc. + * + * @return A getter-setter function wrapping the value. + * + * @see m.withAttr + */ + prop(): MithrilBasicProperty; - render(rootElement: Element|HTMLDocument): void; - render(rootElement: Element|HTMLDocument, children: MithrilVirtualElement, forceRecreation?: boolean): void; - render(rootElement: Element|HTMLDocument, children: MithrilVirtualElement[], forceRecreation?: boolean): void; + /** + * Returns a event handler that can be bound to an element, firing with + * the specified property. + * + * @param property The property to get from the event. + * @param callback The handler to use the value from the event. + * @return A function suitable for listening to an event. + */ + withAttr( + property: string, + callback: (value: any) => void + ): (e: Event) => any; + + /** + * @deprecated Use m.mount instead + */ + module( + rootElement: Node, + component: MithrilComponent + ): T; + + /** + * Mounts a component to a base DOM node. + * + * @param rootElement The base node. + * @param component The component to mount. + * @return An instance of the top-level component's controller + */ + mount( + rootElement: Node, + component: MithrilComponent + ): T; + + /** + * Initializes a component for use with m.render, m.mount, etc. + * + * @param selector A component. + * @param args Arguments to optionally pass to the component. + * @return A component. + * + * @see m.render + * @see m.mount + * @see m + */ + component( + component: MithrilComponent, + ...args: any[] + ): MithrilComponent; + + /** + * Trust this string of HTML. + * + * @param html The HTML to trust + * @return A String object instance with an added internal flag to mark + * it as trusted. + */ + trust(html: string): MithrilTrustedString; + + /** + * Render a virtual DOM tree. + * + * @param rootElement The base element/node to render the tree from. + * @param children One or more child nodes to add to the tree. + * @param forceRecreation If true, overwrite the entire tree without + * diffing against it. + */ + render( + rootElement: Element, + children: MithrilVirtualElement|MithrilVirtualElement[], + forceRecreation?: boolean + ): void; redraw: { + /** + * Force a redraw the active component. It redraws asynchronously by + * default to allow for simultaneous events to run before redrawing, + * such as the event combination keypress + input frequently used for + * input. + * + * @param force If true, redraw synchronously. + */ (force?: boolean): void; - strategy: MithrilProperty; + + strategy: { + /** + * Gets the current redraw strategy, which returns one of the + * following: + * + * "all" - recreates the DOM tree from scratch + * "diff" - recreates the DOM tree from scratch + * "none" - leaves the DOM tree intact + * + * This is useful for event handlers, which may want to cancel + * the next redraw if the event doesn't update the UI. + * + * @return The current strategy + */ + (): string; + + /** + * Sets the current redraw strategy. The parameter must be one of + * the following values: + * + * "all" - recreates the DOM tree from scratch + * "diff" - recreates the DOM tree from scratch + * "none" - leaves the DOM tree intact + * + * This is useful for event handlers, which may want to cancel + * the next redraw if the event doesn't update the UI. + * + * @param value The value to set + * @return The new strategy + */ + (value: string): string; + + /** + * @private + * Implementation detail - it's a MithrilBasicProperty instance + */ + toJSON(): string; + } } route: { - (rootElement: HTMLDocument, defaultRoute: string, routes: MithrilRoutes): void; - (rootElement: Element, defaultRoute: string, routes: MithrilRoutes): void; + /** + * Enable routing, mounting a controller based on the route. It + * automatically mounts the components for you, starting with the one + * specified by the default route. + * + * @param rootElement The element to mount the active controller to. + * @param defaultRoute The route to start with. + * @param routes A key-value mapping of pathname to controller. + */ + ( + rootElement: Element, + defaultRoute: string, + routes: MithrilRoutes + ): void; - (element: Element, isInitialized: boolean, context: Object, vdom: Object): void; + /** + * This allows m.route to be used as the `config` attribute for a + * virtual element, particularly useful for cases like this: + * + * ```ts + * // Note that the '#' is not required in `href`, thanks to the + * `config` setting. + * m("a[href='/dashboard/alicesmith']", {config: m.route}); + * ``` + */ + ( + element: Element, + isInitialized: boolean, + context?: MithrilContext, + vdom?: MithrilVirtualElement + ): void; + + /** + * Programmatically redirect to another route. + * + * @param path The route to go to. + * @param params Parameters to pass as a query string. + * @param shouldReplaceHistory Whether to replace the current history + * instead of adding a new one. + */ (path: string, params?: any, shouldReplaceHistory?: boolean): void; + + /** + * Gets the current route. + * + * @return The current route. + */ (): string; + /** + * Gets a route parameter. + * + * @param key The key to get. + * @return The value associated with the parameter key. + */ param(key: string): string; + + /** + * The current routing mode. This may be changed before calling + * m.route to change the part of the URL used to perform the routing. + * + * The value can be set to one of the following, defaulting to + * "hash": + * + * "search" - Uses the query string. This allows for named anchors to + * work on the page, but changes cause IE8 and lower to refresh the + * page. + * + * "hash" - Uses the hash. This is the only routing mode that does + * not cause page refreshes on any browser, but it does not support + * named anchors. + * + * "pathname" - Uses the URL pathname. This requires server-side + * setup to support bookmarking and page refreshes. It always causes + * page refreshes on IE8 and lower. Note that this requires that the + * application to be run from the root of the URL. + */ mode: string; + + /** + * Serialize an object into a query string. + * + * @param data The data to serialize. + * @return The serialized string. + */ buildQueryString(data: Object): String + + /** + * Parse a query string into an object. + * + * @param data The data to parse. + * @return The parsed object data. + */ parseQueryString(data: String): Object } - request(options: MithrilXHROptions): MithrilPromise; + /** + * Send a request to a server to server. Note that the `url` option is + * required. + * + * @param options The options to use + * @return A promise to the returned data for "GET" requests, or a void + * promise for any other request type. + * + * @see MithrilXHROptions for the available options. + */ + request(options: MithrilXHROptions): MithrilPromise; deferred: { - onerror(e: Error): void; + /** + * Create a Mithril deferred object. It behaves synchronously if + * possible, an intentional deviation from Promises/A+. Note that + * deferreds are completely separate from the redrawing system, and + * never trigger a redraw on their own. + * + * @return A new Mithril deferred instance. + * + * @see m.deferred.onerror for the error callback called for Error + * subclasses + */ (): MithrilDeferred; + + /** + * A callback for all uncaught native Error subclasses in deferreds. + * This defaults to synchronously rethrowing all errors, a deviation + * from Promises/A+, but the behavior is configurable. To restore + * Promises/A+-compatible behavior. simply set this to a no-op. + */ + onerror(e: Error): void; } - sync(promises: MithrilPromise[]): MithrilPromise; + /** + * Takes a list of promises or thennables and returns a Mithril promise + * that resolves once all in the list are resolved, or rejects if any of + * them reject. + * + * @param promises A list of promises to try to resolve. + * @return A promise that resolves to all the promises if all resolve, or + * rejects with the error contained in the first rejection. + */ + sync(promises: Thennable[]): MithrilPromise; + /** + * Use this and endComputation if your views aren't redrawing after + * calls to third-party libraries. For integrating asynchronous code, + * this should be called before any asynchronous work is done. For + * synchronous code, this should be called at the beginning of the + * problematic segment. Note that these calls must be balanced, much like + * braces and parentheses. This is mostly used internally. Prefer + * m.redraw where possible, especially when making repeated calls. + * + * @see endComputation + * @see m.render + */ startComputation(): void; + + /** + * Use startComputation and this if your views aren't redrawing after + * calls to third-party libraries. For integrating asynchronous code, + * this should be called after all asynchronous work completes. For + * synchronous code, this should be called at the end of the problematic + * segment. Note that these calls must be balanced, much like braces and + * parentheses. This is mostly used internally. Prefer m.redraw where + * possible, especially when making repeated calls. + * + * @see startComputation + * @see m.render + */ endComputation(): void; - // For test suite - deps: { - (mockWindow: Window): Window; - factory: Object; - } - + /** + * This overwrites the internal version of window used by Mithril. + * It's mostly useful for testing, and is also used internally by + * Mithril to test itself. By default Mithril uses `window` for the + * dependency. + * + * @param mockWindow The mock to use for the window. + * @return The mock that was passed in. + */ + deps(mockWindow: Window): Window; } - interface MithrilVirtualElement { + interface MithrilTrustedString extends String { + /** @private Implementation detail. Don't depend on it. */ + $trusted: boolean; + } + + /** + * The interface for a virtual element. It's best to consider this immutable + * for most use cases. + * + * @see m + */ + interface MithrilVirtualElement { + /** + * A key to optionally associate with this element. + */ key?: number; + + /** + * The tag name of this element. + */ tag?: string; + + /** + * The attributes of this element. + */ attrs?: MithrilAttributes; - children?: any[]; + + /** + * The children of this element. + */ + children?: Array|MithrilComponent>; } - // Configuration function for an element + /** + * An event passed by Mithril to unload event handlers. + */ + interface MithrilEvent { + /** + * Prevent the default behavior of scrolling the page and updating the + * URL on next route change. + */ + preventDefault(): void; + } + + /** + * A context object for configuration functions. + * + * @see MithrilElementConfig + */ + interface MithrilContext { + /** + * A function to call when the node is unloaded. Useful for cleanup. + */ + onunload?(): any; + + /** + * Set true if the backing DOM node needs to be retained between route + * changes if possible. Set false if this node needs to be recreated + * every single time, regardless of how "different" it is. + */ + retain?: boolean; + } + + /** + * This represents a callback function for a virtual element's config + * attribute. It's a low-level function useful for extra cleanup after + * removal from the tree, storing instances of third-party classes that + * need to be associated with the DOM, etc. + * + * @see MithrilAttributes + * @see MithrilContext + */ interface MithrilElementConfig { - (element: Element, isInitialized: boolean, context?: any, vdom?: MithrilVirtualElement): void; + /** + * A callback function for a virtual element's config attribute. + * + * @param element The associated DOM element. + * @param isInitialized Whether this is the first call for the virtual + * element or not. + * @param context The associated context for this element. + * @param vdom The associated virtual element. + */ + ( + element: Element, + isInitialized: boolean, + context: MithrilContext, + vdom: MithrilVirtualElement + ): void; } - // Attributes on a virtual element + /** + * This represents the attributes available for configuring virtual elements, + * beyond the applicable DOM attributes. + * + * @see m + */ interface MithrilAttributes { - title?: string; + /** + * The class name(s) for this virtual element, as a space-separated list. + */ className?: string; + + /** + * The class name(s) for this virtual element, as a space-separated list. + */ class?: string; + + /** + * A custom, low-level configuration in case this element needs special + * cleanup after removal from the tree. + * + * @see MithrilElementConfig + */ config?: MithrilElementConfig; } - // Defines the subset of Event that Mithril needs - interface MithrilEvent { - currentTarget: Element; - } - + /** + * The basis of a Mithril controller instance. + */ interface MithrilController { - onunload?(evt: Event): any; + /** + * An optional handler to call when the associated virtual element is + * destroyed. + * + * @param evt An associated event. + */ + onunload?(evt: MithrilEvent): any; } - interface MithrilControllerFunction extends MithrilController { - (): any; + /** + * This represents a controller function. + * + * @see MithrilControllerConstructor + */ + interface MithrilControllerFunction { + (): T; } + /** + * This represents a controller constructor. + * + * @see MithrilControllerFunction + */ + interface MithrilControllerConstructor { + new(): T; + } + + /** + * This represents a view factory. + */ interface MithrilView { - (ctrl: T): string|MithrilVirtualElement; + /** + * Creates a view out of virtual elements. + */ + (ctrl: T): MithrilVirtualElement; } + /** + * This represents a Mithril component. + * + * @see m + * @see m.component + */ interface MithrilComponent { - controller: MithrilControllerFunction|{ new(): T }; - view: MithrilView; + /** + * The component's controller. + * + * @see m.component + */ + controller: MithrilControllerFunction | + MithrilControllerConstructor; + + /** + * Creates a view out of virtual elements. + * + * @see m.component + */ + view(ctrl: T): MithrilVirtualElement; } + /** + * This is the base interface for property getter-setters + * + * @see m.prop + */ interface MithrilProperty { + /** + * Gets the contained value. + * + * @return The contained value. + */ (): T; + + /** + * Sets the contained value. + * + * @param value The new value to set. + * @return The newly set value. + */ (value: T): T; + } + + /** + * This represents a non-promise getter-setter functions. + * + * @see m.prop which returns objects that implement this interface. + */ + interface MithrilBasicProperty extends MithrilProperty { + /** + * Makes this serializable to JSON. + */ toJSON(): T; } - interface MithrilPromiseProperty extends MithrilPromise { - (): T; - (value: T): T; - toJSON(): T; + /** + * This represents a promise getter-setter function. + * + * @see m.prop which returns objects that implement this interface. + */ + interface MithrilPromiseProperty extends MithrilPromise, + MithrilProperty> { + /** + * Gets the contained promise. + * + * @return The contained value. + */ + (): MithrilPromise; + + /** + * Sets the contained promise. + * + * @param value The new value to set. + * @return The newly set value. + */ + (value: MithrilPromise): MithrilPromise; + + /** + * Sets the contained wrapped value. + * + * @param value The new value to set. + * @return The newly set value. + */ + (value: T): MithrilPromise; } + /** + * This represents a key-value mapping linking routes to components. + */ interface MithrilRoutes { + /** + * The key represents the route. The value represents the corresponding + * component. + */ [key: string]: MithrilComponent; } - + /** + * This represents a Mithril deferred object. + */ interface MithrilDeferred { + /** + * Resolve this deferred's promise with a value. + * + * @param value The value to resolve the promise with. + */ resolve(value?: T): void; - reject(value?: any): void; + + /** + * Reject this deferred with an error. + * + * @param value The reason for rejecting the promise. + */ + reject(reason?: any): void; + + /** + * The backing promise. + * + * @see MithrilPromise + */ promise: MithrilPromise; } + /** + * This represents a thennable success callback. + */ interface MithrilSuccessCallback { - (value: T): U; - (value: T): MithrilPromise; + (value: T): U | Thennable; } - interface MithrilErrorCallback { - (value: Error): U; - (value: string): U; + /** + * This represents a thennable error callback. + */ + interface MithrilErrorCallback { + (value: Error): T | Thennable; } - interface MithrilPromise { - (): T; - (value: T): T; - then(success: (value: T) => U): MithrilPromise; - then(success: (value: T) => MithrilPromise): MithrilPromise; - then(success: (value: T) => U, error: (value: Error) => V): MithrilPromise|MithrilPromise; - then(success: (value: T) => MithrilPromise, error: (value: Error) => V): MithrilPromise|MithrilPromise; + /** + * This represents a thennable. + */ + interface Thennable { + then(success: (value: T) => U): Thennable; + then(success: (value: T) => U, error: (value: Error) => V): Thennable|Thennable; + catch?: (error: (value: Error) => U) => Thennable; } - interface MithrilXHROptions { + + /** + * This represents a Mithril promise object. + */ + interface MithrilPromise extends Thennable, MithrilProperty> { + /** + * Chain this promise with a simple success callback, propogating + * rejections. + * + * @param success The callback to call when the promise is resolved. + * @return The chained promise. + */ + then(success: MithrilSuccessCallback): MithrilPromise; + + /** + * Chain this promise with a success callback and error callback, without + * propogating rejections. + * + * @param success The callback to call when the promise is resolved. + * @param error The callback to call when the promise is rejected. + * @return The chained promise. + */ + then( + success: MithrilSuccessCallback, + error: MithrilErrorCallback + ): MithrilPromise | MithrilPromise; + + /** + * Chain this promise with a single error callback, without propogating + * rejections. + * + * @param error The callback to call when the promise is rejected. + * @return The chained promise. + */ + catch(error: MithrilErrorCallback): MithrilPromise | + MithrilPromise; + } + + /** + * This represents the available options for configuring m.request. + * + * @see m.request + */ + interface MithrilXHROptions { + /** + * This represents the HTTP method used, one of the following: + * + * - "GET" (default) + * - "POST" + * - "PUT" + * - "DELETE" + * - "HEAD" + * - "OPTIONS" + */ method?: string; + + /** + * The URL to send the request to. + */ url: string; + + /** + * The username for HTTP authentication. + */ user?: string; + + /** + * The password for HTTP authentication. + */ password?: string; + + /** + * The data to be sent. It's automatically serialized in the right format + * depending on the method (with exception of HTML5 FormData), and put in + * the appropriate section of the request. + */ data?: any; + + /** + * Whether to run it in the background, i.e. true if it doesn't affect + * template rendering. + */ background?: boolean; - unwrapSuccess?(data: any): any; - unwrapError?(data: any): any; + + /** + * Set an initial value while the request is working, to populate the + * promise getter-setter. + */ + initialValue?: T; + + /** + * An optional preprocessor function to unwrap a successful response, in + * case the response contains metadata wrapping the data. + * + * @param data The data to unwrap. + * @return The unwrapped result. + */ + unwrapSuccess?(data: any): T; + + /** + * An optional preprocessor function to unwrap an unsuccessful response, + * in case the response contains metadata wrapping the data. + * + * @param data The data to unwrap. + * @return The unwrapped result. + */ + unwrapError?(data: any): T; + + /** + * An optional function to serialize the data. This defaults to + * `JSON.stringify`. + * + * @param dataToSerialize The data to serialize. + * @return The serialized form as a string. + */ serialize?(dataToSerialize: any): string; + + /** + * An optional function to deserialize the data. This defaults to + * `JSON.parse`. + * + * @param dataToSerialize The data to parse. + * @return The parsed form. + */ deserialize?(dataToDeserialize: string): any; - extract?(xhr: XMLHttpRequest, options: MithrilXHROptions): string; - type?(data: Object): void; - config?(xhr: XMLHttpRequest, options: MithrilXHROptions): XMLHttpRequest; + + /** + * An optional function to extract the data from a raw XMLHttpRequest, + * useful if the relevant data is in a response header or the status + * field. + * + * @param xhr The associated XMLHttpRequest. + * @param options The options passed to this request. + * @return string The serialized format. + */ + extract?(xhr: XMLHttpRequest, options: MithrilXHROptions): string; + + /** + * The parsed data, or its children if it's an array, will be passed to + * this class constructor if it's given, to parse it into classes. + * + * @param data The data to parse. + * @return The new instance for the list. + */ + type?: new (data: Object) => any; + + /** + * An optional function to run between `open` and `send`, useful for + * adding request headers or using XHR2 features such as the `upload` + * property. It is even possible to override the XHR altogether with a + * similar object, such as an XDomainRequest instance. + * + * @param xhr The associated XMLHttpRequest. + * @param options The options passed to this request. + * @return The new XMLHttpRequest, or nothing if the same one is kept. + */ + config?(xhr: XMLHttpRequest, options: MithrilXHROptions): any; + + /** + * For JSONP requests, this must be the string "jsonp". Otherwise, it's + * ignored. + */ dataType?: string; + + /** + * For JSONP requests, this is the query string key for the JSONP + * request. This is useful for APIs that don't use common conventions, + * such as `www.example.com/?jsonpCallback=doSomething`. It defaults to + * `callback` for JSONP requests, and is ignored for any other kind of + * request. + */ + callbackKey?: string; } } diff --git a/mithril.js b/mithril.js index 06e10307..e0b1c0a6 100644 --- a/mithril.js +++ b/mithril.js @@ -1197,6 +1197,9 @@ var m = (function app(window, undefined) { var controller = function() { return (component.controller || noop).apply(this, args) || this } + if (component.controller) { + controller.prototype = component.controller.prototype + } var view = function(ctrl) { for (var i = 1; i < arguments.length; i++) { args.push(arguments[i]) diff --git a/mithril.min.js b/mithril.min.js index 47f19c51..d60ff391 100644 --- a/mithril.min.js +++ b/mithril.min.js @@ -4,5 +4,5 @@ http://github.com/lhorie/mithril.js (c) Leo Horie License: MIT */ -var m=function a(b,c){function d(a){return"function"==typeof a}function e(a){return"[object Object]"===P.call(a)}function f(a){return"[object String]"===P.call(a)}function g(a){K=a.document,L=a.location,N=a.cancelAnimationFrame||a.clearTimeout,M=a.requestAnimationFrame||a.setTimeout}function h(a,b){for(var c=[],d=1;d\s*[^<]/g)||[0]).length:O(e)?e.length:1,t[X++]=e)}),F||(i(s,function(a,b){null!=t[b]&&E.push.apply(E,t[b].nodes)}),i(t.nodes,function(a,b){null!=a.parentNode&&E.indexOf(a)<0&&p([a],[t[b]])}),s.length-1?t.controllers[_]:new(s.controller||T),ba=s&&s.attrs&&s.attrs.key;if(s=0==ia||ha||t&&t.controllers&&t.controllers.indexOf(aa)>-1?s.view(aa):{tag:"placeholder"},"retain"===s.subtree)return t;null!=ba&&(s.attrs||(s.attrs={}),s.attrs.key=ba),aa.onunload&&ea.push({controller:aa,handler:aa.onunload}),Y.push($),Z.push(aa)}if(!s.tag&&Z.length)throw new Error("Component template must return a virtual element, not an array, string, etc.");s.attrs||(s.attrs={}),t.attrs||(t.attrs={});var ca=Object.keys(s.attrs),da=ca.length>("key"in s.attrs?1:0);if((s.tag!=t.tag||ca.sort().join()!=Object.keys(t.attrs).sort().join()||s.attrs.id!=t.attrs.id||s.attrs.key!=t.attrs.key||"all"==h.redraw.strategy()&&(!t.configContext||t.configContext.retain!==!0)||"diff"==h.redraw.strategy()&&t.configContext&&t.configContext.retain===!1)&&(t.nodes.length&&p(t.nodes),t.configContext&&d(t.configContext.onunload)&&t.configContext.onunload(),t.controllers))for(var aa,D=0;aa=t.controllers[D];D++)d(aa.onunload)&&aa.onunload({preventDefault:T});if(!f(s.tag))return;var fa,ga=0===t.nodes.length;if(s.attrs.xmlns?x=s.attrs.xmlns:"svg"===s.tag?x="http://www.w3.org/2000/svg":"math"===s.tag&&(x="http://www.w3.org/1998/Math/MathML"),ga){if(fa=s.attrs.is?x===c?K.createElement(s.tag,s.attrs.is):K.createElementNS(x,s.tag,s.attrs.is):x===c?K.createElement(s.tag):K.createElementNS(x,s.tag),t={tag:s.tag,attrs:da?o(fa,s.tag,s.attrs,{},x):s.attrs,children:null!=s.children&&s.children.length>0?m(fa,s.tag,c,c,s.children,t.children,!0,0,s.attrs.contenteditable?fa:w,x,y):s.children,nodes:[fa]},Z.length){t.views=Y,t.controllers=Z;for(var aa,D=0;aa=Z[D];D++)if(aa.onunload&&aa.onunload.$old&&(aa.onunload=aa.onunload.$old),ia&&aa.onunload){var ja=aa.onunload;aa.onunload=T,aa.onunload.$old=ja}}t.children&&!t.children.nodes&&(t.children.nodes=[]),"select"===s.tag&&"value"in s.attrs&&o(fa,s.tag,{value:s.attrs.value},{},x),a.insertBefore(fa,a.childNodes[v]||null)}else fa=t.nodes[0],da&&o(fa,s.tag,s.attrs,t.attrs,x),t.children=m(fa,s.tag,c,c,s.children,t.children,!1,0,s.attrs.contenteditable?fa:w,x,y),t.nodes.intact=!0,Z.length&&(t.views=Y,t.controllers=Z),u===!0&&null!=fa&&a.insertBefore(fa,a.childNodes[v]||null);if(d(s.attrs.config)){var ka=t.configContext=t.configContext||{},la=function(a,b){return function(){return a.attrs.config.apply(a,b)}};y.push(la(s,[fa,!ga,ka,t]))}}else if(!d(s)){var E;0===t.nodes.length?(s.$trusted?E=r(a,v,s):(E=[K.createTextNode(s)],a.nodeName.match(S)||a.insertBefore(E[0],a.childNodes[v]||null)),t="string number boolean".indexOf(typeof s)>-1?new s.constructor(s):s,t.nodes=E):t.valueOf()!==s.valueOf()||u===!0?(E=t.nodes,w&&w===K.activeElement||(s.$trusted?(p(E,t),E=r(a,v,s)):"textarea"===b?a.value=s:w?w.innerHTML=s:((1===E[0].nodeType||E.length>1)&&(p(t.nodes,t),E=[K.createTextNode(s)]),l(a,E[0],v,s))),t=new s.constructor(s),t.nodes=E):t.nodes.intact=!0}return t}function n(a,b){return a.action-b.action||a.index-b.index}function o(a,b,c,f,g){for(var h in c){var i=c[h],j=f[h];if(h in f&&j===i)"value"===h&&"input"===b&&a.value!=i&&(a.value=i);else{f[h]=i;try{if("config"===h||"key"==h)continue;if(d(i)&&0===h.indexOf("on"))a[h]=s(i,a);else if("style"===h&&null!=i&&e(i)){for(var k in i)(null==j||j[k]!==i[k])&&(a.style[k]=i[k]);for(var k in j)k in i||(a.style[k]="")}else null!=g?"href"===h?a.setAttributeNS("http://www.w3.org/1999/xlink","href",i):"className"===h?a.setAttribute("class",i):a.setAttribute(h,i):h in a&&"list"!==h&&"style"!==h&&"form"!==h&&"type"!==h&&"width"!==h&&"height"!==h?("input"!==b||a[h]!==i)&&(a[h]=i):a.setAttribute(h,i)}catch(l){if(l.message.indexOf("Invalid argument")<0)throw l}}}return f}function p(a,b){for(var c=a.length-1;c>-1;c--)if(a[c]&&a[c].parentNode){try{a[c].parentNode.removeChild(a[c])}catch(d){}b=[].concat(b),b[c]&&q(b[c])}0!=a.length&&(a.length=0)}function q(a){if(a.configContext&&d(a.configContext.onunload)&&(a.configContext.onunload(),a.configContext.onunload=null),a.controllers)for(var b,c=0;b=a.controllers[c];c++)d(b.onunload)&&b.onunload({preventDefault:T});if(a.children)if(O(a.children))for(var e,c=0;e=a.children[c];c++)q(e);else a.children.tag&&q(a.children)}function r(a,b,c){var d=a.childNodes[b];if(d){var e=1!=d.nodeType,f=K.createElement("span");e?(a.insertBefore(f,d||null),f.insertAdjacentHTML("beforebegin",c),a.removeChild(f)):d.insertAdjacentHTML("beforebegin",c)}else a.insertAdjacentHTML("beforeend",c);for(var g=[];a.childNodes[b]!==d;)g.push(a.childNodes[b]),b++;return g}function s(a,b){return function(c){c=c||event,h.redraw.strategy("diff"),h.startComputation();try{return a.call(b,c)}finally{ja()}}}function t(a){var b=W.indexOf(a);return 0>b?W.push(a)-1:b}function u(a){var b=function(){return arguments.length&&(a=arguments[0]),a};return b.toJSON=function(){return a},b}function v(a,b){var c=function(){return(a.controller||T).apply(this,b)||this},d=function(c){for(var d=1;de;e++)ka[c[e].replace(/:|\./g,"")]=decodeURIComponent(d[e]);h.mount(a,b[g])}),!0}}function z(a){if(a=a||event,!a.ctrlKey&&!a.metaKey&&2!==a.which){a.preventDefault?a.preventDefault():a.returnValue=!1;for(var b=a.currentTarget||a.srcElement,c="pathname"===h.route.mode&&b.search?C(b.search.slice(1)):{};b&&"A"!=b.nodeName.toUpperCase();)b=b.parentNode;h.route(b[h.route.mode].slice(ma[h.route.mode].length),c)}}function A(){"hash"!=h.route.mode&&L.hash?L.hash=L.hash:b.scrollTo(0,0)}function B(a,b){var d={},f=[];for(var g in a){var h=b?b+"["+g+"]":g,i=a[g],j=(P.call(i),null===i?encodeURIComponent(h):e(i)?B(i,h):O(i)?i.reduce(function(a,b){return d[h]||(d[h]={}),d[h][b]?a:(d[h][b]=!0,a.concat(encodeURIComponent(h)+"="+encodeURIComponent(b)))},[]).join("&"):encodeURIComponent(h)+"="+encodeURIComponent(i));i!==c&&f.push(j)}return f.join("&")}function C(a){"?"===a.charAt(0)&&(a=a.substring(1));for(var b=a.split("&"),c={},d=0,e=b.length;e>d;d++){var f=b[d].split("="),g=decodeURIComponent(f[0]),h=2==f.length?decodeURIComponent(f[1]):null;null!=c[g]?(O(c[g])||(c[g]=[c[g]]),c[g].push(h)):c[g]=h}return c}function D(a){var b=t(a);p(a.childNodes,X[b]),X[b]=c}function E(a,b){var c=h.prop(b);return a.then(c),c.then=function(c,d){return E(a.then(c,d),b)},c["catch"]=c.then.bind(null,null),c}function F(a,b){function c(a){n=a||l,p.map(function(a){n===k&&a.resolve(o)||a.reject(o)})}function f(a,b,c,f){if((null!=o&&e(o)||d(o))&&d(a))try{var g=0;a.call(o,function(a){g++||(o=a,b())},function(a){g++||(o=a,c())})}catch(i){h.deferred.onerror(i),o=i,c()}else f()}function g(){var e;try{e=o&&o.then}catch(l){return h.deferred.onerror(l),o=l,n=j,g()}f(e,function(){n=i,g()},function(){n=j,g()},function(){try{n===i&&d(a)?o=a(o):n===j&&d(b)&&(o=b(o),n=i)}catch(g){return h.deferred.onerror(g),o=g,c()}o===m?(o=TypeError(),c()):f(e,function(){c(k)},c,function(){c(n===i&&k)})})}var i=1,j=2,k=3,l=4,m=this,n=0,o=0,p=[];m.promise={},m.resolve=function(a){return n||(o=a,n=i,g()),this},m.reject=function(a){return n||(o=a,n=j,g()),this},m.promise.then=function(a,b){var c=new F(a,b);return n===k?c.resolve(o):n===l?c.reject(o):p.push(c),c.promise}}function G(a){return a}function H(a){if(!a.dataType||"jsonp"!==a.dataType.toLowerCase()){var e=new b.XMLHttpRequest;if(e.open(a.method,a.url,!0,a.user,a.password),e.onreadystatechange=function(){4===e.readyState&&(e.status>=200&&e.status<300?a.onload({type:"load",target:e}):a.onerror({type:"error",target:e}))},a.serialize===JSON.stringify&&a.data&&"GET"!==a.method&&e.setRequestHeader("Content-Type","application/json; charset=utf-8"),a.deserialize===JSON.parse&&e.setRequestHeader("Accept","application/json, text/*"),d(a.config)){var g=a.config(e,a);null!=g&&(e=g)}var h="GET"!==a.method&&a.data?a.data:"";if(h&&!f(h)&&h.constructor!=b.FormData)throw"Request data should be either be a string or FormData. Check the `serialize` option in `m.request`";return e.send(h),e}var i="mithril_callback_"+(new Date).getTime()+"_"+Math.round(1e16*Math.random()).toString(36),j=K.createElement("script");b[i]=function(d){j.parentNode.removeChild(j),a.onload({type:"load",target:{responseText:d}}),b[i]=c},j.onerror=function(d){return j.parentNode.removeChild(j),a.onerror({type:"error",target:{status:500,responseText:JSON.stringify({error:"Error making jsonp request"})}}),b[i]=c,!1},j.onload=function(a){return!1},j.src=a.url+(a.url.indexOf("?")>0?"&":"?")+(a.callbackKey?a.callbackKey:"callback")+"="+i+"&"+B(a.data||{}),K.body.appendChild(j)}function I(a,b,c){if("GET"===a.method&&"jsonp"!=a.dataType){var d=a.url.indexOf("?")<0?"?":"&",e=B(b);a.url=a.url+(e?d+e:"")}else a.data=c(b);return a}function J(a,b){var c=a.match(/:[a-z]\w+/gi);if(c&&b)for(var d=0;di;i++)e[i]()},h.trust=function(a){return a=new String(a),a.$trusted=!0,a},h.prop=function(a){return(null!=a&&e(a)||d(a))&&d(a.then)?E(a):u(a)};var Y,Z=[],$=[],_=[],aa=null,ba=0,ca=null,da=null,ea=[],fa=16;h.component=function(a){for(var b=[],c=1;cc&&(c=Z.length);for(var e,f=!1,g={preventDefault:function(){f=!0,ca=da=null}},i=0;e=ea[i];i++)e.handler.call(e.controller,g),e.controller.onunload=null;if(f)for(var e,i=0;e=ea[i];i++)e.controller.onunload=e.handler;else ea=[];if(_[c]&&d(_[c].onunload)&&_[c].onunload(g),!f){h.redraw.strategy("all"),h.startComputation(),Z[c]=a,arguments.length>2&&(b=subcomponent(b,[].slice.call(arguments,2)));var j=Y=b=b||{controller:T},k=b.controller||T,l=new k;return j===Y&&(_[c]=l,$[c]=b),ja(),_[c]}};var ga=!1,ha=!1;h.redraw=function(a){if(!ga){ga=!0,a&&(ha=!0);try{aa&&!a?(M===b.requestAnimationFrame||new Date-ba>fa)&&(aa>0&&N(aa),aa=M(w,fa)):(w(),aa=M(function(){aa=null},fa))}finally{ga=ha=!1}}},h.redraw.strategy=h.prop();var ia=0;h.startComputation=function(){ia++},h.endComputation=function(){ia=Math.max(ia-1,0),0===ia&&h.redraw()};var ja=function(){"none"==h.redraw.strategy()?(ia--,h.redraw.strategy("diff")):h.endComputation()};h.withAttr=function(a,b){return function(c){c=c||event;var d=c.currentTarget||this;b(a in d?d[a]:d.getAttribute(a))}};var ka,la,ma={pathname:"",hash:"#",search:"?"},na=T,oa=!1;return h.route=function(a,c,d,e){if(0===arguments.length)return la;if(3===arguments.length&&f(c)){na=function(b){var e=la=x(b);if(!y(a,d,e)){if(oa)throw new Error("Ensure the default route matches one of the routes defined in m.route");oa=!0,h.route(c,!0),oa=!1}};var g="hash"===h.route.mode?"onhashchange":"onpopstate";b[g]=function(){var a=L[h.route.mode];"pathname"===h.route.mode&&(a+=L.search),la!=x(a)&&na(a)},ca=A,b[g]()}else if(a.addEventListener||a.attachEvent)a.href=("pathname"!==h.route.mode?L.pathname:"")+ma[h.route.mode]+e.attrs.href,a.addEventListener?(a.removeEventListener("click",z),a.addEventListener("click",z)):(a.detachEvent("onclick",z),a.attachEvent("onclick",z));else if(f(a)){var i=la;la=a;var j=la.indexOf("?"),k=j>-1?C(la.slice(j+1)):{};for(var l in c)k[l]=c[l];var m=B(k),n=j>-1?la.slice(0,j):la;m&&(la=n+(-1===n.indexOf("?")?"?":"&")+m);var o=(3===arguments.length?d:c)===!0||i===a;b.history.pushState?(ca=A,da=function(){b.history[o?"replaceState":"pushState"](null,K.title,ma[h.route.mode]+la)},na(ma[h.route.mode]+la)):(L[h.route.mode]=la,na(ma[h.route.mode]+la))}},h.route.param=function(a){if(!ka)throw new Error("You must call m.route(element, defaultRoute, routes) before calling m.route.param()");return ka[a]},h.route.mode="search",h.route.buildQueryString=B,h.route.parseQueryString=C,h.deferred=function(){var a=new F;return a.promise=E(a.promise),a},h.deferred.onerror=function(a){if("[object Error]"===P.call(a)&&!a.constructor.toString().match(/ Error/))throw ia=0,a},h.sync=function(a){function b(a,b){return function(g){return f[a]=g,b||(c="reject"),0===--e&&(d.promise(f),d[c](f)),g}}var c="resolve",d=h.deferred(),e=a.length,f=new Array(e);if(a.length>0)for(var g=0;g\s*[^<]/g)||[0]).length:O(e)?e.length:1,t[V++]=e)}),D||(i(s,function(a,b){null!=t[b]&&C.push.apply(C,t[b].nodes)}),i(t.nodes,function(a,b){null!=a.parentNode&&C.indexOf(a)<0&&p([a],[t[b]])}),s.length-1?t.controllers[Z]:new(s.controller||T),_=s&&s.attrs&&s.attrs.key;if(s=0==ia||ha||t&&t.controllers&&t.controllers.indexOf($)>-1?s.view($):{tag:"placeholder"},"retain"===s.subtree)return t;null!=_&&(s.attrs||(s.attrs={}),s.attrs.key=_),$.onunload&&ea.push({controller:$,handler:$.onunload}),W.push(Y),X.push($)}if(!s.tag&&X.length)throw new Error("Component template must return a virtual element, not an array, string, etc.");s.attrs||(s.attrs={}),t.attrs||(t.attrs={});var aa=Object.keys(s.attrs),ba=aa.length>("key"in s.attrs?1:0);if((s.tag!=t.tag||aa.sort().join()!=Object.keys(t.attrs).sort().join()||s.attrs.id!=t.attrs.id||s.attrs.key!=t.attrs.key||"all"==h.redraw.strategy()&&(!t.configContext||t.configContext.retain!==!0)||"diff"==h.redraw.strategy()&&t.configContext&&t.configContext.retain===!1)&&(t.nodes.length&&p(t.nodes),t.configContext&&d(t.configContext.onunload)&&t.configContext.onunload(),t.controllers))for(var $,B=0;$=t.controllers[B];B++)d($.onunload)&&$.onunload({preventDefault:T});if(!f(s.tag))return;var ca,da=0===t.nodes.length;if(s.attrs.xmlns?x=s.attrs.xmlns:"svg"===s.tag?x="http://www.w3.org/2000/svg":"math"===s.tag&&(x="http://www.w3.org/1998/Math/MathML"),da){if(ca=s.attrs.is?x===c?K.createElement(s.tag,s.attrs.is):K.createElementNS(x,s.tag,s.attrs.is):x===c?K.createElement(s.tag):K.createElementNS(x,s.tag),t={tag:s.tag,attrs:ba?o(ca,s.tag,s.attrs,{},x):s.attrs,children:null!=s.children&&s.children.length>0?m(ca,s.tag,c,c,s.children,t.children,!0,0,s.attrs.contenteditable?ca:w,x,y):s.children,nodes:[ca]},X.length){t.views=W,t.controllers=X;for(var $,B=0;$=X[B];B++)if($.onunload&&$.onunload.$old&&($.onunload=$.onunload.$old),ia&&$.onunload){var fa=$.onunload;$.onunload=T,$.onunload.$old=fa}}t.children&&!t.children.nodes&&(t.children.nodes=[]),"select"===s.tag&&"value"in s.attrs&&o(ca,s.tag,{value:s.attrs.value},{},x),a.insertBefore(ca,a.childNodes[v]||null)}else ca=t.nodes[0],ba&&o(ca,s.tag,s.attrs,t.attrs,x),t.children=m(ca,s.tag,c,c,s.children,t.children,!1,0,s.attrs.contenteditable?ca:w,x,y),t.nodes.intact=!0,X.length&&(t.views=W,t.controllers=X),u===!0&&null!=ca&&a.insertBefore(ca,a.childNodes[v]||null);if(d(s.attrs.config)){var ga=t.configContext=t.configContext||{},ja=function(a,b){return function(){return a.attrs.config.apply(a,b)}};y.push(ja(s,[ca,!da,ga,t]))}}else if(!d(s)){var C;0===t.nodes.length?(s.$trusted?C=r(a,v,s):(C=[K.createTextNode(s)],a.nodeName.match(S)||a.insertBefore(C[0],a.childNodes[v]||null)),t="string number boolean".indexOf(typeof s)>-1?new s.constructor(s):s,t.nodes=C):t.valueOf()!==s.valueOf()||u===!0?(C=t.nodes,w&&w===K.activeElement||(s.$trusted?(p(C,t),C=r(a,v,s)):"textarea"===b?a.value=s:w?w.innerHTML=s:((1===C[0].nodeType||C.length>1)&&(p(t.nodes,t),C=[K.createTextNode(s)]),l(a,C[0],v,s))),t=new s.constructor(s),t.nodes=C):t.nodes.intact=!0}return t}function n(a,b){return a.action-b.action||a.index-b.index}function o(a,b,c,f,g){for(var h in c){var i=c[h],j=f[h];if(h in f&&j===i)"value"===h&&"input"===b&&a.value!=i&&(a.value=i);else{f[h]=i;try{if("config"===h||"key"==h)continue;if(d(i)&&0===h.indexOf("on"))a[h]=s(i,a);else if("style"===h&&null!=i&&e(i)){for(var k in i)(null==j||j[k]!==i[k])&&(a.style[k]=i[k]);for(var k in j)k in i||(a.style[k]="")}else null!=g?"href"===h?a.setAttributeNS("http://www.w3.org/1999/xlink","href",i):"className"===h?a.setAttribute("class",i):a.setAttribute(h,i):h in a&&"list"!==h&&"style"!==h&&"form"!==h&&"type"!==h&&"width"!==h&&"height"!==h?("input"!==b||a[h]!==i)&&(a[h]=i):a.setAttribute(h,i)}catch(l){if(l.message.indexOf("Invalid argument")<0)throw l}}}return f}function p(a,b){for(var c=a.length-1;c>-1;c--)if(a[c]&&a[c].parentNode){try{a[c].parentNode.removeChild(a[c])}catch(d){}b=[].concat(b),b[c]&&q(b[c])}0!=a.length&&(a.length=0)}function q(a){if(a.configContext&&d(a.configContext.onunload)&&(a.configContext.onunload(),a.configContext.onunload=null),a.controllers)for(var b,c=0;b=a.controllers[c];c++)d(b.onunload)&&b.onunload({preventDefault:T});if(a.children)if(O(a.children))for(var e,c=0;e=a.children[c];c++)q(e);else a.children.tag&&q(a.children)}function r(a,b,c){var d=a.childNodes[b];if(d){var e=1!=d.nodeType,f=K.createElement("span");e?(a.insertBefore(f,d||null),f.insertAdjacentHTML("beforebegin",c),a.removeChild(f)):d.insertAdjacentHTML("beforebegin",c)}else a.insertAdjacentHTML("beforeend",c);for(var g=[];a.childNodes[b]!==d;)g.push(a.childNodes[b]),b++;return g}function s(a,b){return function(c){c=c||event,h.redraw.strategy("diff"),h.startComputation();try{return a.call(b,c)}finally{ja()}}}function t(a){var b=W.indexOf(a);return 0>b?W.push(a)-1:b}function u(a){var b=function(){return arguments.length&&(a=arguments[0]),a};return b.toJSON=function(){return a},b}function v(a,b){var c=function(){return(a.controller||T).apply(this,b)||this},d=function(c){for(var d=1;de;e++)ka[c[e].replace(/:|\./g,"")]=decodeURIComponent(d[e]);h.mount(a,b[g])}),!0}}function z(a){if(a=a||event,!a.ctrlKey&&!a.metaKey&&2!==a.which){a.preventDefault?a.preventDefault():a.returnValue=!1;for(var b=a.currentTarget||a.srcElement,c="pathname"===h.route.mode&&b.search?C(b.search.slice(1)):{};b&&"A"!=b.nodeName.toUpperCase();)b=b.parentNode;h.route(b[h.route.mode].slice(ma[h.route.mode].length),c)}}function A(){"hash"!=h.route.mode&&L.hash?L.hash=L.hash:b.scrollTo(0,0)}function B(a,b){var d={},f=[];for(var g in a){var h=b?b+"["+g+"]":g,i=a[g],j=(P.call(i),null===i?encodeURIComponent(h):e(i)?B(i,h):O(i)?i.reduce(function(a,b){return d[h]||(d[h]={}),d[h][b]?a:(d[h][b]=!0,a.concat(encodeURIComponent(h)+"="+encodeURIComponent(b)))},[]).join("&"):encodeURIComponent(h)+"="+encodeURIComponent(i));i!==c&&f.push(j)}return f.join("&")}function C(a){"?"===a.charAt(0)&&(a=a.substring(1));for(var b=a.split("&"),c={},d=0,e=b.length;e>d;d++){var f=b[d].split("="),g=decodeURIComponent(f[0]),h=2==f.length?decodeURIComponent(f[1]):null;null!=c[g]?(O(c[g])||(c[g]=[c[g]]),c[g].push(h)):c[g]=h}return c}function D(a){var b=t(a);p(a.childNodes,X[b]),X[b]=c}function E(a,b){var c=h.prop(b);return a.then(c),c.then=function(c,d){return E(a.then(c,d),b)},c["catch"]=c.then.bind(null,null),c}function F(a,b){function c(a){n=a||l,p.map(function(a){n===k&&a.resolve(o)||a.reject(o)})}function f(a,b,c,f){if((null!=o&&e(o)||d(o))&&d(a))try{var g=0;a.call(o,function(a){g++||(o=a,b())},function(a){g++||(o=a,c())})}catch(i){h.deferred.onerror(i),o=i,c()}else f()}function g(){var e;try{e=o&&o.then}catch(l){return h.deferred.onerror(l),o=l,n=j,g()}f(e,function(){n=i,g()},function(){n=j,g()},function(){try{n===i&&d(a)?o=a(o):n===j&&d(b)&&(o=b(o),n=i)}catch(g){return h.deferred.onerror(g),o=g,c()}o===m?(o=TypeError(),c()):f(e,function(){c(k)},c,function(){c(n===i&&k)})})}var i=1,j=2,k=3,l=4,m=this,n=0,o=0,p=[];m.promise={},m.resolve=function(a){return n||(o=a,n=i,g()),this},m.reject=function(a){return n||(o=a,n=j,g()),this},m.promise.then=function(a,b){var c=new F(a,b);return n===k?c.resolve(o):n===l?c.reject(o):p.push(c),c.promise}}function G(a){return a}function H(a){if(!a.dataType||"jsonp"!==a.dataType.toLowerCase()){var e=new b.XMLHttpRequest;if(e.open(a.method,a.url,!0,a.user,a.password),e.onreadystatechange=function(){4===e.readyState&&(e.status>=200&&e.status<300?a.onload({type:"load",target:e}):a.onerror({type:"error",target:e}))},a.serialize===JSON.stringify&&a.data&&"GET"!==a.method&&e.setRequestHeader("Content-Type","application/json; charset=utf-8"),a.deserialize===JSON.parse&&e.setRequestHeader("Accept","application/json, text/*"),d(a.config)){var g=a.config(e,a);null!=g&&(e=g)}var h="GET"!==a.method&&a.data?a.data:"";if(h&&!f(h)&&h.constructor!=b.FormData)throw"Request data should be either be a string or FormData. Check the `serialize` option in `m.request`";return e.send(h),e}var i="mithril_callback_"+(new Date).getTime()+"_"+Math.round(1e16*Math.random()).toString(36),j=K.createElement("script");b[i]=function(d){j.parentNode.removeChild(j),a.onload({type:"load",target:{responseText:d}}),b[i]=c},j.onerror=function(d){return j.parentNode.removeChild(j),a.onerror({type:"error",target:{status:500,responseText:JSON.stringify({error:"Error making jsonp request"})}}),b[i]=c,!1},j.onload=function(a){return!1},j.src=a.url+(a.url.indexOf("?")>0?"&":"?")+(a.callbackKey?a.callbackKey:"callback")+"="+i+"&"+B(a.data||{}),K.body.appendChild(j)}function I(a,b,c){if("GET"===a.method&&"jsonp"!=a.dataType){var d=a.url.indexOf("?")<0?"?":"&",e=B(b);a.url=a.url+(e?d+e:"")}else a.data=c(b);return a}function J(a,b){var c=a.match(/:[a-z]\w+/gi);if(c&&b)for(var d=0;di;i++)e[i]()},h.trust=function(a){return a=new String(a),a.$trusted=!0,a},h.prop=function(a){return(null!=a&&e(a)||d(a))&&d(a.then)?E(a):u(a)};var Y,Z=[],$=[],_=[],aa=null,ba=0,ca=null,da=null,ea=[],fa=16;h.component=function(a){for(var b=[],c=1;cc&&(c=Z.length);for(var e,f=!1,g={preventDefault:function(){f=!0,ca=da=null}},i=0;e=ea[i];i++)e.handler.call(e.controller,g),e.controller.onunload=null;if(f)for(var e,i=0;e=ea[i];i++)e.controller.onunload=e.handler;else ea=[];if(_[c]&&d(_[c].onunload)&&_[c].onunload(g),!f){h.redraw.strategy("all"),h.startComputation(),Z[c]=a,arguments.length>2&&(b=subcomponent(b,[].slice.call(arguments,2)));var j=Y=b=b||{controller:T},k=b.controller||T,l=new k;return j===Y&&(_[c]=l,$[c]=b),ja(),_[c]}};var ga=!1,ha=!1;h.redraw=function(a){if(!ga){ga=!0,a&&(ha=!0);try{aa&&!a?(M===b.requestAnimationFrame||new Date-ba>fa)&&(aa>0&&N(aa),aa=M(w,fa)):(w(),aa=M(function(){aa=null},fa))}finally{ga=ha=!1}}},h.redraw.strategy=h.prop();var ia=0;h.startComputation=function(){ia++},h.endComputation=function(){ia=Math.max(ia-1,0),0===ia&&h.redraw()};var ja=function(){"none"==h.redraw.strategy()?(ia--,h.redraw.strategy("diff")):h.endComputation()};h.withAttr=function(a,b){return function(c){c=c||event;var d=c.currentTarget||this;b(a in d?d[a]:d.getAttribute(a))}};var ka,la,ma={pathname:"",hash:"#",search:"?"},na=T,oa=!1;return h.route=function(a,c,d,e){if(0===arguments.length)return la;if(3===arguments.length&&f(c)){na=function(b){var e=la=x(b);if(!y(a,d,e)){if(oa)throw new Error("Ensure the default route matches one of the routes defined in m.route");oa=!0,h.route(c,!0),oa=!1}};var g="hash"===h.route.mode?"onhashchange":"onpopstate";b[g]=function(){var a=L[h.route.mode];"pathname"===h.route.mode&&(a+=L.search),la!=x(a)&&na(a)},ca=A,b[g]()}else if(a.addEventListener||a.attachEvent)a.href=("pathname"!==h.route.mode?L.pathname:"")+ma[h.route.mode]+e.attrs.href,a.addEventListener?(a.removeEventListener("click",z),a.addEventListener("click",z)):(a.detachEvent("onclick",z),a.attachEvent("onclick",z));else if(f(a)){var i=la;la=a;var j=la.indexOf("?"),k=j>-1?C(la.slice(j+1)):{};for(var l in c)k[l]=c[l];var m=B(k),n=j>-1?la.slice(0,j):la;m&&(la=n+(-1===n.indexOf("?")?"?":"&")+m);var o=(3===arguments.length?d:c)===!0||i===a;b.history.pushState?(ca=A,da=function(){b.history[o?"replaceState":"pushState"](null,K.title,ma[h.route.mode]+la)},na(ma[h.route.mode]+la)):(L[h.route.mode]=la,na(ma[h.route.mode]+la))}},h.route.param=function(a){if(!ka)throw new Error("You must call m.route(element, defaultRoute, routes) before calling m.route.param()");return ka[a]},h.route.mode="search",h.route.buildQueryString=B,h.route.parseQueryString=C,h.deferred=function(){var a=new F;return a.promise=E(a.promise),a},h.deferred.onerror=function(a){if("[object Error]"===P.call(a)&&!a.constructor.toString().match(/ Error/))throw ia=0,a},h.sync=function(a){function b(a,b){return function(g){return f[a]=g,b||(c="reject"),0===--e&&(d.promise(f),d[c](f)),g}}var c="resolve",d=h.deferred(),e=a.length,f=new Array(e);if(a.length>0)for(var g=0;g -1; }, set : function( key, value ){ var index = map.has( key ) ? keys.indexOf( key ) : keys.length; - + keys[ index ] = key; values[ index ] = value; - + return map; }, clear : function(){ @@ -234,21 +234,21 @@ var mod = ( function initModulator(){ }, delete : function( key ){ var index = keys.indexOf( key ); - + if( index > -1 ){ keys.splice( index, 1 ); values.splice( index, 1 ); - + return true; } - + return false; } }; - + return map; } - + function noop(){} }() ); @@ -271,4 +271,4 @@ b.view = function(ctrl, count) { return m("li", count) } -m.module(document.body, a) \ No newline at end of file +m.module(document.body, a)