PNG  IHDRxsBIT|d pHYs+tEXtSoftwarewww.inkscape.org<,tEXtComment File Manager

File Manager

Path: /home/u491334613/domains/web-default.net/public_html/node_modules/rxjs/src/internal/ajax/

Viewing File: ajax.ts

import { map } from '../operators/map';
import { Observable } from '../Observable';
import { AjaxConfig, AjaxRequest, AjaxDirection, ProgressEventType } from './types';
import { AjaxResponse } from './AjaxResponse';
import { AjaxTimeoutError, AjaxError } from './errors';

export interface AjaxCreationMethod {
  /**
   * Creates an observable that will perform an AJAX request using the
   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in
   * global scope by default.
   *
   * This is the most configurable option, and the basis for all other AJAX calls in the library.
   *
   * ## Example
   *
   * ```ts
   * import { ajax } from 'rxjs/ajax';
   * import { map, catchError, of } from 'rxjs';
   *
   * const obs$ = ajax({
   *   method: 'GET',
   *   url: 'https://api.github.com/users?per_page=5',
   *   responseType: 'json'
   * }).pipe(
   *   map(userResponse => console.log('users: ', userResponse)),
   *   catchError(error => {
   *     console.log('error: ', error);
   *     return of(error);
   *   })
   * );
   * ```
   */
  <T>(config: AjaxConfig): Observable<AjaxResponse<T>>;

  /**
   * Perform an HTTP GET using the
   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in
   * global scope. Defaults to a `responseType` of `"json"`.
   *
   * ## Example
   *
   * ```ts
   * import { ajax } from 'rxjs/ajax';
   * import { map, catchError, of } from 'rxjs';
   *
   * const obs$ = ajax('https://api.github.com/users?per_page=5').pipe(
   *   map(userResponse => console.log('users: ', userResponse)),
   *   catchError(error => {
   *     console.log('error: ', error);
   *     return of(error);
   *   })
   * );
   * ```
   */
  <T>(url: string): Observable<AjaxResponse<T>>;

  /**
   * Performs an HTTP GET using the
   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in
   * global scope by default, and a `responseType` of `"json"`.
   *
   * @param url The URL to get the resource from
   * @param headers Optional headers. Case-Insensitive.
   */
  get<T>(url: string, headers?: Record<string, string>): Observable<AjaxResponse<T>>;

  /**
   * Performs an HTTP POST using the
   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in
   * global scope by default, and a `responseType` of `"json"`.
   *
   * Before sending the value passed to the `body` argument, it is automatically serialized
   * based on the specified `responseType`. By default, a JavaScript object will be serialized
   * to JSON. A `responseType` of `application/x-www-form-urlencoded` will flatten any provided
   * dictionary object to a url-encoded string.
   *
   * @param url The URL to get the resource from
   * @param body The content to send. The body is automatically serialized.
   * @param headers Optional headers. Case-Insensitive.
   */
  post<T>(url: string, body?: any, headers?: Record<string, string>): Observable<AjaxResponse<T>>;

  /**
   * Performs an HTTP PUT using the
   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in
   * global scope by default, and a `responseType` of `"json"`.
   *
   * Before sending the value passed to the `body` argument, it is automatically serialized
   * based on the specified `responseType`. By default, a JavaScript object will be serialized
   * to JSON. A `responseType` of `application/x-www-form-urlencoded` will flatten any provided
   * dictionary object to a url-encoded string.
   *
   * @param url The URL to get the resource from
   * @param body The content to send. The body is automatically serialized.
   * @param headers Optional headers. Case-Insensitive.
   */
  put<T>(url: string, body?: any, headers?: Record<string, string>): Observable<AjaxResponse<T>>;

  /**
   * Performs an HTTP PATCH using the
   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in
   * global scope by default, and a `responseType` of `"json"`.
   *
   * Before sending the value passed to the `body` argument, it is automatically serialized
   * based on the specified `responseType`. By default, a JavaScript object will be serialized
   * to JSON. A `responseType` of `application/x-www-form-urlencoded` will flatten any provided
   * dictionary object to a url-encoded string.
   *
   * @param url The URL to get the resource from
   * @param body The content to send. The body is automatically serialized.
   * @param headers Optional headers. Case-Insensitive.
   */
  patch<T>(url: string, body?: any, headers?: Record<string, string>): Observable<AjaxResponse<T>>;

  /**
   * Performs an HTTP DELETE using the
   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in
   * global scope by default, and a `responseType` of `"json"`.
   *
   * @param url The URL to get the resource from
   * @param headers Optional headers. Case-Insensitive.
   */
  delete<T>(url: string, headers?: Record<string, string>): Observable<AjaxResponse<T>>;

  /**
   * Performs an HTTP GET using the
   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in
   * global scope by default, and returns the hydrated JavaScript object from the
   * response.
   *
   * @param url The URL to get the resource from
   * @param headers Optional headers. Case-Insensitive.
   */
  getJSON<T>(url: string, headers?: Record<string, string>): Observable<T>;
}

function ajaxGet<T>(url: string, headers?: Record<string, string>): Observable<AjaxResponse<T>> {
  return ajax({ method: 'GET', url, headers });
}

function ajaxPost<T>(url: string, body?: any, headers?: Record<string, string>): Observable<AjaxResponse<T>> {
  return ajax({ method: 'POST', url, body, headers });
}

function ajaxDelete<T>(url: string, headers?: Record<string, string>): Observable<AjaxResponse<T>> {
  return ajax({ method: 'DELETE', url, headers });
}

function ajaxPut<T>(url: string, body?: any, headers?: Record<string, string>): Observable<AjaxResponse<T>> {
  return ajax({ method: 'PUT', url, body, headers });
}

function ajaxPatch<T>(url: string, body?: any, headers?: Record<string, string>): Observable<AjaxResponse<T>> {
  return ajax({ method: 'PATCH', url, body, headers });
}

const mapResponse = map((x: AjaxResponse<any>) => x.response);

function ajaxGetJSON<T>(url: string, headers?: Record<string, string>): Observable<T> {
  return mapResponse(
    ajax<T>({
      method: 'GET',
      url,
      headers,
    })
  );
}

/**
 * There is an ajax operator on the Rx object.
 *
 * It creates an observable for an Ajax request with either a request object with
 * url, headers, etc or a string for a URL.
 *
 * ## Examples
 *
 * Using `ajax()` to fetch the response object that is being returned from API
 *
 * ```ts
 * import { ajax } from 'rxjs/ajax';
 * import { map, catchError, of } from 'rxjs';
 *
 * const obs$ = ajax('https://api.github.com/users?per_page=5').pipe(
 *   map(userResponse => console.log('users: ', userResponse)),
 *   catchError(error => {
 *     console.log('error: ', error);
 *     return of(error);
 *   })
 * );
 *
 * obs$.subscribe({
 *   next: value => console.log(value),
 *   error: err => console.log(err)
 * });
 * ```
 *
 * Using `ajax.getJSON()` to fetch data from API
 *
 * ```ts
 * import { ajax } from 'rxjs/ajax';
 * import { map, catchError, of } from 'rxjs';
 *
 * const obs$ = ajax.getJSON('https://api.github.com/users?per_page=5').pipe(
 *   map(userResponse => console.log('users: ', userResponse)),
 *   catchError(error => {
 *     console.log('error: ', error);
 *     return of(error);
 *   })
 * );
 *
 * obs$.subscribe({
 *   next: value => console.log(value),
 *   error: err => console.log(err)
 * });
 * ```
 *
 * Using `ajax()` with object as argument and method POST with a two seconds delay
 *
 * ```ts
 * import { ajax } from 'rxjs/ajax';
 * import { map, catchError, of } from 'rxjs';
 *
 * const users = ajax({
 *   url: 'https://httpbin.org/delay/2',
 *   method: 'POST',
 *   headers: {
 *     'Content-Type': 'application/json',
 *     'rxjs-custom-header': 'Rxjs'
 *   },
 *   body: {
 *     rxjs: 'Hello World!'
 *   }
 * }).pipe(
 *   map(response => console.log('response: ', response)),
 *   catchError(error => {
 *     console.log('error: ', error);
 *     return of(error);
 *   })
 * );
 *
 * users.subscribe({
 *   next: value => console.log(value),
 *   error: err => console.log(err)
 * });
 * ```
 *
 * Using `ajax()` to fetch. An error object that is being returned from the request
 *
 * ```ts
 * import { ajax } from 'rxjs/ajax';
 * import { map, catchError, of } from 'rxjs';
 *
 * const obs$ = ajax('https://api.github.com/404').pipe(
 *   map(userResponse => console.log('users: ', userResponse)),
 *   catchError(error => {
 *     console.log('error: ', error);
 *     return of(error);
 *   })
 * );
 *
 * obs$.subscribe({
 *   next: value => console.log(value),
 *   error: err => console.log(err)
 * });
 * ```
 */
export const ajax: AjaxCreationMethod = (() => {
  const create = <T>(urlOrConfig: string | AjaxConfig) => {
    const config: AjaxConfig =
      typeof urlOrConfig === 'string'
        ? {
            url: urlOrConfig,
          }
        : urlOrConfig;
    return fromAjax<T>(config);
  };

  create.get = ajaxGet;
  create.post = ajaxPost;
  create.delete = ajaxDelete;
  create.put = ajaxPut;
  create.patch = ajaxPatch;
  create.getJSON = ajaxGetJSON;

  return create;
})();

const UPLOAD = 'upload';
const DOWNLOAD = 'download';
const LOADSTART = 'loadstart';
const PROGRESS = 'progress';
const LOAD = 'load';

export function fromAjax<T>(init: AjaxConfig): Observable<AjaxResponse<T>> {
  return new Observable((destination) => {
    const config = {
      // Defaults
      async: true,
      crossDomain: false,
      withCredentials: false,
      method: 'GET',
      timeout: 0,
      responseType: 'json' as XMLHttpRequestResponseType,

      ...init,
    };

    const { queryParams, body: configuredBody, headers: configuredHeaders } = config;

    let url = config.url;
    if (!url) {
      throw new TypeError('url is required');
    }

    if (queryParams) {
      let searchParams: URLSearchParams;
      if (url.includes('?')) {
        // If the user has passed a URL with a querystring already in it,
        // we need to combine them. So we're going to split it. There
        // should only be one `?` in a valid URL.
        const parts = url.split('?');
        if (2 < parts.length) {
          throw new TypeError('invalid url');
        }
        // Add the passed queryParams to the params already in the url provided.
        searchParams = new URLSearchParams(parts[1]);
        // queryParams is converted to any because the runtime is *much* more permissive than
        // the types are.
        new URLSearchParams(queryParams as any).forEach((value, key) => searchParams.set(key, value));
        // We have to do string concatenation here, because `new URL(url)` does
        // not like relative URLs like `/this` without a base url, which we can't
        // specify, nor can we assume `location` will exist, because of node.
        url = parts[0] + '?' + searchParams;
      } else {
        // There is no preexisting querystring, so we can just use URLSearchParams
        // to convert the passed queryParams into the proper format and encodings.
        // queryParams is converted to any because the runtime is *much* more permissive than
        // the types are.
        searchParams = new URLSearchParams(queryParams as any);
        url = url + '?' + searchParams;
      }
    }

    // Normalize the headers. We're going to make them all lowercase, since
    // Headers are case insensitive by design. This makes it easier to verify
    // that we aren't setting or sending duplicates.
    const headers: Record<string, any> = {};
    if (configuredHeaders) {
      for (const key in configuredHeaders) {
        if (configuredHeaders.hasOwnProperty(key)) {
          headers[key.toLowerCase()] = configuredHeaders[key];
        }
      }
    }

    const crossDomain = config.crossDomain;

    // Set the x-requested-with header. This is a non-standard header that has
    // come to be a de facto standard for HTTP requests sent by libraries and frameworks
    // using XHR. However, we DO NOT want to set this if it is a CORS request. This is
    // because sometimes this header can cause issues with CORS. To be clear,
    // None of this is necessary, it's only being set because it's "the thing libraries do"
    // Starting back as far as JQuery, and continuing with other libraries such as Angular 1,
    // Axios, et al.
    if (!crossDomain && !('x-requested-with' in headers)) {
      headers['x-requested-with'] = 'XMLHttpRequest';
    }

    // Allow users to provide their XSRF cookie name and the name of a custom header to use to
    // send the cookie.
    const { withCredentials, xsrfCookieName, xsrfHeaderName } = config;
    if ((withCredentials || !crossDomain) && xsrfCookieName && xsrfHeaderName) {
      const xsrfCookie = document?.cookie.match(new RegExp(`(^|;\\s*)(${xsrfCookieName})=([^;]*)`))?.pop() ?? '';
      if (xsrfCookie) {
        headers[xsrfHeaderName] = xsrfCookie;
      }
    }

    // Examine the body and determine whether or not to serialize it
    // and set the content-type in `headers`, if we're able.
    const body = extractContentTypeAndMaybeSerializeBody(configuredBody, headers);

    // The final request settings.
    const _request: Readonly<AjaxRequest> = {
      ...config,

      // Set values we ensured above
      url,
      headers,
      body,
    };

    let xhr: XMLHttpRequest;

    // Create our XHR so we can get started.
    xhr = init.createXHR ? init.createXHR() : new XMLHttpRequest();

    {
      ///////////////////////////////////////////////////
      // set up the events before open XHR
      // https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
      // You need to add the event listeners before calling open() on the request.
      // Otherwise the progress events will not fire.
      ///////////////////////////////////////////////////

      const { progressSubscriber, includeDownloadProgress = false, includeUploadProgress = false } = init;

      /**
       * Wires up an event handler that will emit an error when fired. Used
       * for timeout and abort events.
       * @param type The type of event we're treating as an error
       * @param errorFactory A function that creates the type of error to emit.
       */
      const addErrorEvent = (type: string, errorFactory: () => any) => {
        xhr.addEventListener(type, () => {
          const error = errorFactory();
          progressSubscriber?.error?.(error);
          destination.error(error);
        });
      };

      // If the request times out, handle errors appropriately.
      addErrorEvent('timeout', () => new AjaxTimeoutError(xhr, _request));

      // If the request aborts (due to a network disconnection or the like), handle
      // it as an error.
      addErrorEvent('abort', () => new AjaxError('aborted', xhr, _request));

      /**
       * Creates a response object to emit to the consumer.
       * @param direction the direction related to the event. Prefixes the event `type` in the
       * `AjaxResponse` object with "upload_" for events related to uploading and "download_"
       * for events related to downloading.
       * @param event the actual event object.
       */
      const createResponse = (direction: AjaxDirection, event: ProgressEvent) =>
        new AjaxResponse<T>(event, xhr, _request, `${direction}_${event.type as ProgressEventType}` as const);

      /**
       * Wires up an event handler that emits a Response object to the consumer, used for
       * all events that emit responses, loadstart, progress, and load.
       * Note that download load handling is a bit different below, because it has
       * more logic it needs to run.
       * @param target The target, either the XHR itself or the Upload object.
       * @param type The type of event to wire up
       * @param direction The "direction", used to prefix the response object that is
       * emitted to the consumer. (e.g. "upload_" or "download_")
       */
      const addProgressEvent = (target: any, type: string, direction: AjaxDirection) => {
        target.addEventListener(type, (event: ProgressEvent) => {
          destination.next(createResponse(direction, event));
        });
      };

      if (includeUploadProgress) {
        [LOADSTART, PROGRESS, LOAD].forEach((type) => addProgressEvent(xhr.upload, type, UPLOAD));
      }

      if (progressSubscriber) {
        [LOADSTART, PROGRESS].forEach((type) => xhr.upload.addEventListener(type, (e: any) => progressSubscriber?.next?.(e)));
      }

      if (includeDownloadProgress) {
        [LOADSTART, PROGRESS].forEach((type) => addProgressEvent(xhr, type, DOWNLOAD));
      }

      const emitError = (status?: number) => {
        const msg = 'ajax error' + (status ? ' ' + status : '');
        destination.error(new AjaxError(msg, xhr, _request));
      };

      xhr.addEventListener('error', (e) => {
        progressSubscriber?.error?.(e);
        emitError();
      });

      xhr.addEventListener(LOAD, (event) => {
        const { status } = xhr;
        // 4xx and 5xx should error (https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
        if (status < 400) {
          progressSubscriber?.complete?.();

          let response: AjaxResponse<T>;
          try {
            // This can throw in IE, because we end up needing to do a JSON.parse
            // of the response in some cases to produce object we'd expect from
            // modern browsers.
            response = createResponse(DOWNLOAD, event);
          } catch (err) {
            destination.error(err);
            return;
          }

          destination.next(response);
          destination.complete();
        } else {
          progressSubscriber?.error?.(event);
          emitError(status);
        }
      });
    }

    const { user, method, async } = _request;
    // open XHR
    if (user) {
      xhr.open(method, url, async, user, _request.password);
    } else {
      xhr.open(method, url, async);
    }

    // timeout, responseType and withCredentials can be set once the XHR is open
    if (async) {
      xhr.timeout = _request.timeout;
      xhr.responseType = _request.responseType;
    }

    if ('withCredentials' in xhr) {
      xhr.withCredentials = _request.withCredentials;
    }

    // set headers
    for (const key in headers) {
      if (headers.hasOwnProperty(key)) {
        xhr.setRequestHeader(key, headers[key]);
      }
    }

    // finally send the request
    if (body) {
      xhr.send(body);
    } else {
      xhr.send();
    }

    return () => {
      if (xhr && xhr.readyState !== 4 /*XHR done*/) {
        xhr.abort();
      }
    };
  });
}

/**
 * Examines the body to determine if we need to serialize it for them or not.
 * If the body is a type that XHR handles natively, we just allow it through,
 * otherwise, if the body is something that *we* can serialize for the user,
 * we will serialize it, and attempt to set the `content-type` header, if it's
 * not already set.
 * @param body The body passed in by the user
 * @param headers The normalized headers
 */
function extractContentTypeAndMaybeSerializeBody(body: any, headers: Record<string, string>) {
  if (
    !body ||
    typeof body === 'string' ||
    isFormData(body) ||
    isURLSearchParams(body) ||
    isArrayBuffer(body) ||
    isFile(body) ||
    isBlob(body) ||
    isReadableStream(body)
  ) {
    // The XHR instance itself can handle serializing these, and set the content-type for us
    // so we don't need to do that. https://xhr.spec.whatwg.org/#the-send()-method
    return body;
  }

  if (isArrayBufferView(body)) {
    // This is a typed array (e.g. Float32Array or Uint8Array), or a DataView.
    // XHR can handle this one too: https://fetch.spec.whatwg.org/#concept-bodyinit-extract
    return body.buffer;
  }

  if (typeof body === 'object') {
    // If we have made it here, this is an object, probably a POJO, and we'll try
    // to serialize it for them. If this doesn't work, it will throw, obviously, which
    // is okay. The workaround for users would be to manually set the body to their own
    // serialized string (accounting for circular references or whatever), then set
    // the content-type manually as well.
    headers['content-type'] = headers['content-type'] ?? 'application/json;charset=utf-8';
    return JSON.stringify(body);
  }

  // If we've gotten past everything above, this is something we don't quite know how to
  // handle. Throw an error. This will be caught and emitted from the observable.
  throw new TypeError('Unknown body type');
}

const _toString = Object.prototype.toString;

function toStringCheck(obj: any, name: string): boolean {
  return _toString.call(obj) === `[object ${name}]`;
}

function isArrayBuffer(body: any): body is ArrayBuffer {
  return toStringCheck(body, 'ArrayBuffer');
}

function isFile(body: any): body is File {
  return toStringCheck(body, 'File');
}

function isBlob(body: any): body is Blob {
  return toStringCheck(body, 'Blob');
}

function isArrayBufferView(body: any): body is ArrayBufferView {
  return typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView(body);
}

function isFormData(body: any): body is FormData {
  return typeof FormData !== 'undefined' && body instanceof FormData;
}

function isURLSearchParams(body: any): body is URLSearchParams {
  return typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams;
}

function isReadableStream(body: any): body is ReadableStream {
  return typeof ReadableStream !== 'undefined' && body instanceof ReadableStream;
}
b IDATxytVսϓ22 A@IR :hCiZ[v*E:WũZA ^dQeQ @ !jZ'>gsV仿$|?g)&x-EIENT ;@xT.i%-X}SvS5.r/UHz^_$-W"w)Ɗ/@Z &IoX P$K}JzX:;` &, ŋui,e6mX ԵrKb1ԗ)DADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADA݀!I*]R;I2$eZ#ORZSrr6mteffu*((Pu'v{DIߔ4^pIm'77WEEE;vƎ4-$]'RI{\I&G :IHJ DWBB=\WR޽m o$K(V9ABB.}jѢv`^?IOȅ} ڶmG}T#FJ`56$-ھ}FI&v;0(h;Б38CӧOWf!;A i:F_m9s&|q%=#wZprrrla A &P\\СC[A#! {olF} `E2}MK/vV)i{4BffV\|ۭX`b@kɶ@%i$K z5zhmX[IXZ` 'b%$r5M4º/l ԃߖxhʔ)[@=} K6IM}^5k㏷݆z ΗÿO:gdGBmyT/@+Vɶ纽z񕏵l.y޴it뭷zV0[Y^>Wsqs}\/@$(T7f.InݺiR$푔n.~?H))\ZRW'Mo~v Ov6oԃxz! S,&xm/yɞԟ?'uaSѽb,8GלKboi&3t7Y,)JJ c[nzӳdE&KsZLӄ I?@&%ӟ۶mSMMњ0iؐSZ,|J+N ~,0A0!5%Q-YQQa3}$_vVrf9f?S8`zDADADADADADADADADAdqP,تmMmg1V?rSI꒟]u|l RCyEf٢9 jURbztѰ!m5~tGj2DhG*{H9)꒟ר3:(+3\?/;TUݭʴ~S6lڧUJ*i$d(#=Yݺd{,p|3B))q:vN0Y.jkק6;SɶVzHJJЀ-utѹսk>QUU\޲~]fFnK?&ߡ5b=z9)^|u_k-[y%ZNU6 7Mi:]ۦtk[n X(e6Bb."8cۭ|~teuuw|ήI-5"~Uk;ZicEmN/:]M> cQ^uiƞ??Ңpc#TUU3UakNwA`:Y_V-8.KKfRitv޲* 9S6ֿj,ՃNOMߤ]z^fOh|<>@Å5 _/Iu?{SY4hK/2]4%it5q]GGe2%iR| W&f*^]??vq[LgE_3f}Fxu~}qd-ږFxu~I N>\;͗O֊:̗WJ@BhW=y|GgwܷH_NY?)Tdi'?խwhlmQi !SUUsw4kӺe4rfxu-[nHtMFj}H_u~w>)oV}(T'ebʒv3_[+vn@Ȭ\S}ot}w=kHFnxg S 0eޢm~l}uqZfFoZuuEg `zt~? b;t%>WTkķh[2eG8LIWx,^\thrl^Ϊ{=dž<}qV@ ⠨Wy^LF_>0UkDuʫuCs$)Iv:IK;6ֲ4{^6եm+l3>݆uM 9u?>Zc }g~qhKwڭeFMM~pМuqǿz6Tb@8@Y|jx](^]gf}M"tG -w.@vOqh~/HII`S[l.6nØXL9vUcOoB\xoǤ'T&IǍQw_wpv[kmO{w~>#=P1Pɞa-we:iǏlHo׈꒟f9SzH?+shk%Fs:qVhqY`jvO'ρ?PyX3lх]˾uV{ݞ]1,MzYNW~̈́ joYn}ȚF߾׮mS]F z+EDxm/d{F{-W-4wY듏:??_gPf ^3ecg ҵs8R2מz@TANGj)}CNi/R~}c:5{!ZHӋӾ6}T]G]7W6^n 9*,YqOZj:P?Q DFL|?-^.Ɵ7}fFh׶xe2Pscz1&5\cn[=Vn[ĶE鎀uˌd3GII k;lNmشOuuRVfBE]ۣeӶu :X-[(er4~LHi6:Ѻ@ԅrST0trk%$Č0ez" *z"T/X9|8.C5Feg}CQ%͞ˣJvL/?j^h&9xF`њZ(&yF&Iݻfg#W;3^{Wo^4'vV[[K';+mӍִ]AC@W?1^{එyh +^]fm~iԵ]AB@WTk̏t uR?l.OIHiYyԶ]Aˀ7c:q}ힽaf6Z~қm(+sK4{^6}T*UUu]n.:kx{:2 _m=sAߤU@?Z-Vކеz왍Nэ{|5 pڶn b p-@sPg]0G7fy-M{GCF'%{4`=$-Ge\ eU:m+Zt'WjO!OAF@ik&t݆ϥ_ e}=]"Wz_.͜E3leWFih|t-wZۍ-uw=6YN{6|} |*={Ѽn.S.z1zjۻTH]흾 DuDvmvK.`V]yY~sI@t?/ϓ. m&["+P?MzovVЫG3-GRR[(!!\_,^%?v@ҵő m`Y)tem8GMx.))A]Y i`ViW`?^~!S#^+ѽGZj?Vģ0.))A꨷lzL*]OXrY`DBBLOj{-MH'ii-ϰ ok7^ )쭡b]UXSְmռY|5*cֽk0B7镹%ڽP#8nȎq}mJr23_>lE5$iwui+ H~F`IjƵ@q \ @#qG0".0" l`„.0! ,AQHN6qzkKJ#o;`Xv2>,tێJJ7Z/*A .@fفjMzkg @TvZH3Zxu6Ra'%O?/dQ5xYkU]Rֽkق@DaS^RSּ5|BeHNN͘p HvcYcC5:y #`οb;z2.!kr}gUWkyZn=f Pvsn3p~;4p˚=ē~NmI] ¾ 0lH[_L hsh_ғߤc_њec)g7VIZ5yrgk̞W#IjӪv>՞y睝M8[|]\շ8M6%|@PZڨI-m>=k='aiRo-x?>Q.}`Ȏ:Wsmu u > .@,&;+!!˱tﭧDQwRW\vF\~Q7>spYw$%A~;~}6¾ g&if_=j,v+UL1(tWake:@Ș>j$Gq2t7S?vL|]u/ .(0E6Mk6hiۺzښOrifޱxm/Gx> Lal%%~{lBsR4*}{0Z/tNIɚpV^#Lf:u@k#RSu =S^ZyuR/.@n&΃z~B=0eg뺆#,Þ[B/?H uUf7y Wy}Bwegל`Wh(||`l`.;Ws?V@"c:iɍL֯PGv6zctM̠':wuW;d=;EveD}9J@B(0iհ bvP1{\P&G7D޴Iy_$-Qjm~Yrr&]CDv%bh|Yzni_ˆR;kg}nJOIIwyuL}{ЌNj}:+3Y?:WJ/N+Rzd=hb;dj͒suݔ@NKMԄ jqzC5@y°hL m;*5ezᕏ=ep XL n?מ:r`۵tŤZ|1v`V뽧_csج'ߤ%oTuumk%%%h)uy]Nk[n 'b2 l.=͜E%gf$[c;s:V-͞WߤWh-j7]4=F-X]>ZLSi[Y*We;Zan(ӇW|e(HNNP5[= r4tP &0<pc#`vTNV GFqvTi*Tyam$ߏWyE*VJKMTfFw>'$-ؽ.Ho.8c"@DADADADADADADADADA~j*֘,N;Pi3599h=goضLgiJ5փy~}&Zd9p֚ e:|hL``b/d9p? fgg+%%hMgXosج, ΩOl0Zh=xdjLmhݻoO[g_l,8a]٭+ӧ0$I]c]:粹:Teꢢ"5a^Kgh,&= =՟^߶“ߢE ܹS J}I%:8 IDAT~,9/ʃPW'Mo}zNƍ쨓zPbNZ~^z=4mswg;5 Y~SVMRXUյڱRf?s:w ;6H:ºi5-maM&O3;1IKeamZh͛7+##v+c ~u~ca]GnF'ټL~PPPbn voC4R,ӟgg %hq}@#M4IÇ Oy^xMZx ) yOw@HkN˖-Sǎmb]X@n+i͖!++K3gd\$mt$^YfJ\8PRF)77Wא!Cl$i:@@_oG I{$# 8磌ŋ91A (Im7֭>}ߴJq7ޗt^ -[ԩSj*}%]&' -ɓ'ꫯVzzvB#;a 7@GxI{j޼ƌ.LÇWBB7`O"I$/@R @eee@۷>}0,ɒ2$53Xs|cS~rpTYYY} kHc %&k.], @ADADADADADADADADA@lT<%''*Lo^={رc5h %$+CnܸQ3fҥK}vUVVs9G R,_{xˇ3o߾;TTTd}馛]uuuG~iԩ@4bnvmvfϞ /Peeeq}}za I~,誫{UWW뮻}_~YƍSMMMYχ֝waw\ďcxꩧtEƍկ_?۷5@u?1kNׯWzz/wy>}zj3 k(ٺuq_Zvf̘:~ ABQ&r|!%KҥKgԞ={<_X-z !CyFUUz~ ABQIIIjݺW$UXXDٳZ~ ABQƍecW$<(~<RSSvZujjjԧOZQu@4 8m&&&jԩg$ď1h ͟?_{768@g =@`)))5o6m3)ѣƌJ;wҿUTT /KZR{~a=@0o<*狔iFɶ[ˎ;T]]OX@?K.ۈxN pppppppppppppppppPfl߾] ,{ァk۶mڿo5BTӦMӴiӴ|r DB2e|An!Dy'tkΝ[A $***t5' "!駟oaDnΝ:t֭[gDШQ06qD;@ x M6v(PiizmZ4ew"@̴ixf [~-Fٱc&IZ2|n!?$@{[HTɏ#@hȎI# _m(F /6Z3z'\r,r!;w2Z3j=~GY7"I$iI.p_"?pN`y DD?: _  Gÿab7J !Bx@0 Bo cG@`1C[@0G @`0C_u V1 aCX>W ` | `!<S `"<. `#c`?cAC4 ?c p#~@0?:08&_MQ1J h#?/`7;I  q 7a wQ A 1 Hp !#<8/#@1Ul7=S=K.4Z?E_$i@!1!E4?`P_  @Bă10#: "aU,xbFY1 [n|n #'vEH:`xb #vD4Y hi.i&EΖv#O H4IŶ}:Ikh @tZRF#(tXҙzZ ?I3l7q@õ|ۍ1,GpuY Ꮿ@hJv#xxk$ v#9 5 }_$c S#=+"K{F*m7`#%H:NRSp6I?sIՖ{Ap$I$I:QRv2$Z @UJ*$]<FO4IENDB`