<commit_before>/**
@license
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/
import './boot.js';

import { calculateSplices } from './array-splice.js';
import { microTask } from './async.js';

/**
 * Returns true if `node` is a slot element
 * @param {Node} node Node to test.
 * @return {boolean} Returns true if the given `node` is a slot
 * @private
 */
function isSlot(node) {
  return (node.localName === 'slot');
}

/**
 * Class that listens for changes (additions or removals) to
 * "flattened nodes" on a given `node`. The list of flattened nodes consists
 * of a node's children and, for any children that are `<slot>` elements,
 * the expanded flattened list of `assignedNodes`.
 * For example, if the observed node has children `<a></a><slot></slot><b></b>`
 * and the `<slot>` has one `<div>` assigned to it, then the flattened
 * nodes list is `<a></a><div></div><b></b>`. If the `<slot>` has other
 * `<slot>` elements assigned to it, these are flattened as well.
 *
 * The provided `callback` is called whenever any change to this list
 * of flattened nodes occurs, where an addition or removal of a node is
 * considered a change. The `callback` is called with one argument, an object
 * containing an array of any `addedNodes` and `removedNodes`.
 *
 * Note: the callback is called asynchronous to any changes
 * at a microtask checkpoint. This is because observation is performed using
 * `MutationObserver` and the `<slot>` element's `slotchange` event which
 * are asynchronous.
 *
 * An example:
 * ```js
 * class TestSelfObserve extends PolymerElement {
 *   static get is() { return 'test-self-observe';}
 *   connectedCallback() {
 *     super.connectedCallback();
 *     this._observer = new FlattenedNodesObserver(this, (info) => {
 *       this.info = info;
 *     });
 *   }
 *   disconnectedCallback() {
 *     super.disconnectedCallback();
 *     this._observer.disconnect();
 *   }
 * }
 * customElements.define(TestSelfObserve.is, TestSelfObserve);
 * ```
 *
 * @summary Class that listens for changes (additions or removals) to
 * "flattened nodes" on a given `node`.
 */
export class FlattenedNodesObserver {

  /**
   * Returns the list of flattened nodes for the given `node`.
   * This list consists of a node's children and, for any children
   * that are `<slot>` elements, the expanded flattened list of `assignedNodes`.
   * For example, if the observed node has children `<a></a><slot></slot><b></b>`
   * and the `<slot>` has one `<div>` assigned to it, then the flattened
   * nodes list is `<a></a><div></div><b></b>`. If the `<slot>` has other
   * `<slot>` elements assigned to it, these are flattened as well.
   *
   * @param {HTMLElement|HTMLSlotElement} node The node for which to return the list of flattened nodes.
   * @return {Array} The list of flattened nodes for the given `node`.
  */
  static getFlattenedNodes(node) {
    if (isSlot(node)) {
      node = /** @type {HTMLSlotElement} */(node); // eslint-disable-line no-self-assign
      return node.assignedNodes({flatten: true});
    } else {
      return Array.from(node.childNodes).map((node) => {
        if (isSlot(node)) {
          node = /** @type {HTMLSlotElement} */(node); // eslint-disable-line no-self-assign
          return node.assignedNodes({flatten: true});
        } else {
          return [node];
        }
      }).reduce((a, b) => a.concat(b), []);
    }
  }

  /**
   * @param {Element} target Node on which to listen for changes.
   * @param {?function(!Element, { target: !Element, addedNodes: !Array<!Element>, removedNodes: !Array<!Element> }):void} callback Function called when there are additions
   * or removals from the target's list of flattened nodes.
  */
  constructor(target, callback) {
    /**
     * @type {MutationObserver}
     * @private
     */
    this._shadyChildrenObserver = null;
    /**
     * @type {MutationObserver}
     * @private
     */
    this._nativeChildrenObserver = null;
    this._connected = false;
    /**
     * @type {Element}
     * @private
     */
    this._target = target;
    this.callback = callback;
    this._effectiveNodes = [];
    this._observer = null;
    this._scheduled = false;
    /**
     * @type {function()}
     * @private
     */
    this._boundSchedule = () => {
      this._schedule();
    };
    this.connect();
    this._schedule();
  }

  /**
   * Activates an observer. This method is automatically called when
   * a `FlattenedNodesObserver` is created. It should only be called to
   * re-activate an observer that has been deactivated via the `disconnect` method.
   *
   * @return {void}
   */
  connect() {
    if (isSlot(this._target)) {
      this._listenSlots([this._target]);
    } else if (this._target.children) {
      this._listenSlots(this._target.children);
      if (window.ShadyDOM) {
        this._shadyChildrenObserver =
          ShadyDOM.observeChildren(this._target, (mutations) => {
            this._processMutations(mutations);
          });
      } else {
        this._nativeChildrenObserver =
          new MutationObserver((mutations) => {
            this._processMutations(mutations);
          });
        this._nativeChildrenObserver.observe(this._target, {childList: true});
      }
    }
    this._connected = true;
  }

  /**
   * Deactivates the flattened nodes observer. After calling this method
   * the observer callback will not be called when changes to flattened nodes
   * occur. The `connect` method may be subsequently called to reactivate
   * the observer.
   *
   * @return {void}
   */
  disconnect() {
    if (isSlot(this._target)) {
      this._unlistenSlots([this._target]);
    } else if (this._target.children) {
      this._unlistenSlots(this._target.children);
      if (window.ShadyDOM && this._shadyChildrenObserver) {
        ShadyDOM.unobserveChildren(this._shadyChildrenObserver);
        this._shadyChildrenObserver = null;
      } else if (this._nativeChildrenObserver) {
        this._nativeChildrenObserver.disconnect();
        this._nativeChildrenObserver = null;
      }
    }
    this._connected = false;
  }

  /**
   * @return {void}
   * @private
   */
  _schedule() {
    if (!this._scheduled) {
      this._scheduled = true;
      microTask.run(() => this.flush());
    }
  }

  /**
   * @param {Array<MutationRecord>} mutations Mutations signaled by the mutation observer
   * @return {void}
   * @private
   */
  _processMutations(mutations) {
    this._processSlotMutations(mutations);
    this.flush();
  }

  /**
   * @param {Array<MutationRecord>} mutations Mutations signaled by the mutation observer
   * @return {void}
   * @private
   */
  _processSlotMutations(mutations) {
    if (mutations) {
      for (let i=0; i < mutations.length; i++) {
        let mutation = mutations[i];
        if (mutation.addedNodes) {
          this._listenSlots(mutation.addedNodes);
        }
        if (mutation.removedNodes) {
          this._unlistenSlots(mutation.removedNodes);
        }
      }
    }
  }

  /**
   * Flushes the observer causing any pending changes to be immediately
   * delivered the observer callback. By default these changes are delivered
   * asynchronously at the next microtask checkpoint.
   *
   * @return {boolean} Returns true if any pending changes caused the observer
   * callback to run.
   */
  flush() {
    if (!this._connected) {
      return false;
    }
    if (window.ShadyDOM) {
      ShadyDOM.flush();
    }
    if (this._nativeChildrenObserver) {
      this._processSlotMutations(this._nativeChildrenObserver.takeRecords());
    } else if (this._shadyChildrenObserver) {
      this._processSlotMutations(this._shadyChildrenObserver.takeRecords());
    }
    this._scheduled = false;
    let info = {
      target: this._target,
      addedNodes: [],
      removedNodes: []
    };
    let newNodes = this.constructor.getFlattenedNodes(this._target);
    let splices = calculateSplices(newNodes,
      this._effectiveNodes);
    // process removals
    for (let i=0, s; (i<splices.length) && (s=splices[i]); i++) {
      for (let j=0, n; (j < s.removed.length) && (n=s.removed[j]); j++) {
        info.removedNodes.push(n);
      }
    }
    // process adds
    for (let i=0, s; (i<splices.length) && (s=splices[i]); i++) {
      for (let j=s.index; j < s.index + s.addedCount; j++) {
        info.addedNodes.push(newNodes[j]);
      }
    }
    // update cache
    this._effectiveNodes = newNodes;
    let didFlush = false;
    if (info.addedNodes.length || info.removedNodes.length) {
      didFlush = true;
      this.callback.call(this._target, info);
    }
    return didFlush;
  }

  /**
   * @param {!Array<Element|Node>|!NodeList<Node>} nodeList Nodes that could change
   * @return {void}
   * @private
   */
  _listenSlots(nodeList) {
    for (let i=0; i < nodeList.length; i++) {
      let n = nodeList[i];
      if (isSlot(n)) {
        n.addEventListener('slotchange', this._boundSchedule);
      }
    }
  }

  /**
   * @param {!Array<Element|Node>|!NodeList<Node>} nodeList Nodes that could change
   * @return {void}
   * @private
   */
  _unlistenSlots(nodeList) {
    for (let i=0; i < nodeList.length; i++) {
      let n = nodeList[i];
      if (isSlot(n)) {
        n.removeEventListener('slotchange', this._boundSchedule);
      }
    }
  }

}
<commit_msg>Add @nocollapse for jscompiler<commit_after>/**
@license
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/
import './boot.js';

import { calculateSplices } from './array-splice.js';
import { microTask } from './async.js';

/**
 * Returns true if `node` is a slot element
 * @param {Node} node Node to test.
 * @return {boolean} Returns true if the given `node` is a slot
 * @private
 */
function isSlot(node) {
  return (node.localName === 'slot');
}

/**
 * Class that listens for changes (additions or removals) to
 * "flattened nodes" on a given `node`. The list of flattened nodes consists
 * of a node's children and, for any children that are `<slot>` elements,
 * the expanded flattened list of `assignedNodes`.
 * For example, if the observed node has children `<a></a><slot></slot><b></b>`
 * and the `<slot>` has one `<div>` assigned to it, then the flattened
 * nodes list is `<a></a><div></div><b></b>`. If the `<slot>` has other
 * `<slot>` elements assigned to it, these are flattened as well.
 *
 * The provided `callback` is called whenever any change to this list
 * of flattened nodes occurs, where an addition or removal of a node is
 * considered a change. The `callback` is called with one argument, an object
 * containing an array of any `addedNodes` and `removedNodes`.
 *
 * Note: the callback is called asynchronous to any changes
 * at a microtask checkpoint. This is because observation is performed using
 * `MutationObserver` and the `<slot>` element's `slotchange` event which
 * are asynchronous.
 *
 * An example:
 * ```js
 * class TestSelfObserve extends PolymerElement {
 *   static get is() { return 'test-self-observe';}
 *   connectedCallback() {
 *     super.connectedCallback();
 *     this._observer = new FlattenedNodesObserver(this, (info) => {
 *       this.info = info;
 *     });
 *   }
 *   disconnectedCallback() {
 *     super.disconnectedCallback();
 *     this._observer.disconnect();
 *   }
 * }
 * customElements.define(TestSelfObserve.is, TestSelfObserve);
 * ```
 *
 * @summary Class that listens for changes (additions or removals) to
 * "flattened nodes" on a given `node`.
 */
export class FlattenedNodesObserver {

  /**
   * Returns the list of flattened nodes for the given `node`.
   * This list consists of a node's children and, for any children
   * that are `<slot>` elements, the expanded flattened list of `assignedNodes`.
   * For example, if the observed node has children `<a></a><slot></slot><b></b>`
   * and the `<slot>` has one `<div>` assigned to it, then the flattened
   * nodes list is `<a></a><div></div><b></b>`. If the `<slot>` has other
   * `<slot>` elements assigned to it, these are flattened as well.
   *
   * @param {HTMLElement|HTMLSlotElement} node The node for which to return the list of flattened nodes.
   * @return {Array} The list of flattened nodes for the given `node`.
   * @nocollapse See https://github.com/google/closure-compiler/issues/2763
   */
  static getFlattenedNodes(node) {
    if (isSlot(node)) {
      node = /** @type {HTMLSlotElement} */(node); // eslint-disable-line no-self-assign
      return node.assignedNodes({flatten: true});
    } else {
      return Array.from(node.childNodes).map((node) => {
        if (isSlot(node)) {
          node = /** @type {HTMLSlotElement} */(node); // eslint-disable-line no-self-assign
          return node.assignedNodes({flatten: true});
        } else {
          return [node];
        }
      }).reduce((a, b) => a.concat(b), []);
    }
  }

  /**
   * @param {Element} target Node on which to listen for changes.
   * @param {?function(!Element, { target: !Element, addedNodes: !Array<!Element>, removedNodes: !Array<!Element> }):void} callback Function called when there are additions
   * or removals from the target's list of flattened nodes.
   */
  constructor(target, callback) {
    /**
     * @type {MutationObserver}
     * @private
     */
    this._shadyChildrenObserver = null;
    /**
     * @type {MutationObserver}
     * @private
     */
    this._nativeChildrenObserver = null;
    this._connected = false;
    /**
     * @type {Element}
     * @private
     */
    this._target = target;
    this.callback = callback;
    this._effectiveNodes = [];
    this._observer = null;
    this._scheduled = false;
    /**
     * @type {function()}
     * @private
     */
    this._boundSchedule = () => {
      this._schedule();
    };
    this.connect();
    this._schedule();
  }

  /**
   * Activates an observer. This method is automatically called when
   * a `FlattenedNodesObserver` is created. It should only be called to
   * re-activate an observer that has been deactivated via the `disconnect` method.
   *
   * @return {void}
   */
  connect() {
    if (isSlot(this._target)) {
      this._listenSlots([this._target]);
    } else if (this._target.children) {
      this._listenSlots(this._target.children);
      if (window.ShadyDOM) {
        this._shadyChildrenObserver =
          ShadyDOM.observeChildren(this._target, (mutations) => {
            this._processMutations(mutations);
          });
      } else {
        this._nativeChildrenObserver =
          new MutationObserver((mutations) => {
            this._processMutations(mutations);
          });
        this._nativeChildrenObserver.observe(this._target, {childList: true});
      }
    }
    this._connected = true;
  }

  /**
   * Deactivates the flattened nodes observer. After calling this method
   * the observer callback will not be called when changes to flattened nodes
   * occur. The `connect` method may be subsequently called to reactivate
   * the observer.
   *
   * @return {void}
   */
  disconnect() {
    if (isSlot(this._target)) {
      this._unlistenSlots([this._target]);
    } else if (this._target.children) {
      this._unlistenSlots(this._target.children);
      if (window.ShadyDOM && this._shadyChildrenObserver) {
        ShadyDOM.unobserveChildren(this._shadyChildrenObserver);
        this._shadyChildrenObserver = null;
      } else if (this._nativeChildrenObserver) {
        this._nativeChildrenObserver.disconnect();
        this._nativeChildrenObserver = null;
      }
    }
    this._connected = false;
  }

  /**
   * @return {void}
   * @private
   */
  _schedule() {
    if (!this._scheduled) {
      this._scheduled = true;
      microTask.run(() => this.flush());
    }
  }

  /**
   * @param {Array<MutationRecord>} mutations Mutations signaled by the mutation observer
   * @return {void}
   * @private
   */
  _processMutations(mutations) {
    this._processSlotMutations(mutations);
    this.flush();
  }

  /**
   * @param {Array<MutationRecord>} mutations Mutations signaled by the mutation observer
   * @return {void}
   * @private
   */
  _processSlotMutations(mutations) {
    if (mutations) {
      for (let i=0; i < mutations.length; i++) {
        let mutation = mutations[i];
        if (mutation.addedNodes) {
          this._listenSlots(mutation.addedNodes);
        }
        if (mutation.removedNodes) {
          this._unlistenSlots(mutation.removedNodes);
        }
      }
    }
  }

  /**
   * Flushes the observer causing any pending changes to be immediately
   * delivered the observer callback. By default these changes are delivered
   * asynchronously at the next microtask checkpoint.
   *
   * @return {boolean} Returns true if any pending changes caused the observer
   * callback to run.
   */
  flush() {
    if (!this._connected) {
      return false;
    }
    if (window.ShadyDOM) {
      ShadyDOM.flush();
    }
    if (this._nativeChildrenObserver) {
      this._processSlotMutations(this._nativeChildrenObserver.takeRecords());
    } else if (this._shadyChildrenObserver) {
      this._processSlotMutations(this._shadyChildrenObserver.takeRecords());
    }
    this._scheduled = false;
    let info = {
      target: this._target,
      addedNodes: [],
      removedNodes: []
    };
    let newNodes = this.constructor.getFlattenedNodes(this._target);
    let splices = calculateSplices(newNodes,
      this._effectiveNodes);
    // process removals
    for (let i=0, s; (i<splices.length) && (s=splices[i]); i++) {
      for (let j=0, n; (j < s.removed.length) && (n=s.removed[j]); j++) {
        info.removedNodes.push(n);
      }
    }
    // process adds
    for (let i=0, s; (i<splices.length) && (s=splices[i]); i++) {
      for (let j=s.index; j < s.index + s.addedCount; j++) {
        info.addedNodes.push(newNodes[j]);
      }
    }
    // update cache
    this._effectiveNodes = newNodes;
    let didFlush = false;
    if (info.addedNodes.length || info.removedNodes.length) {
      didFlush = true;
      this.callback.call(this._target, info);
    }
    return didFlush;
  }

  /**
   * @param {!Array<Element|Node>|!NodeList<Node>} nodeList Nodes that could change
   * @return {void}
   * @private
   */
  _listenSlots(nodeList) {
    for (let i=0; i < nodeList.length; i++) {
      let n = nodeList[i];
      if (isSlot(n)) {
        n.addEventListener('slotchange', this._boundSchedule);
      }
    }
  }

  /**
   * @param {!Array<Element|Node>|!NodeList<Node>} nodeList Nodes that could change
   * @return {void}
   * @private
   */
  _unlistenSlots(nodeList) {
    for (let i=0; i < nodeList.length; i++) {
      let n = nodeList[i];
      if (isSlot(n)) {
        n.removeEventListener('slotchange', this._boundSchedule);
      }
    }
  }

}
<|endoftext|>


<commit_before>/*
  AUTHORIZE USER

  Authorize and sign in the user.
*/

View.authorized = function() {
  return true;
};

var Authorize;

Authorize = {
  init: function(guid, default_state, params) {
    Debug.log("Authorize.init");
    params = params || {};
    if (Params.get("invitation")) {
      params["invitation"] = Params.get("invitation");
    }
    params["application"] = View.application;
    Authorize.url = YAHOO.constants.controller_url + "/authorize/" + guid;
    Authorize.locale = params.locale;
    Authorize.default_state = default_state;

    Authorize.params = params;
  },

  assignUrl: function(url) {
    url = url || Authorize.url;
    url = url + "?" + Object.toQueryString(Authorize.params);
    if ($('get_started_1')) {
      $('get_started_1').href = url;
      $('get_started_1').setAttribute("target", "_blank");
    }
    if ($('get_started_2')) {
      $('get_started_2').href = url;
      $('get_started_2').setAttribute("target", "_blank");
    }
    $$('a.get_started').each(function(element) {
      element = $(element);
      element.href = url;
      element.setAttribute("target", "_blank");
    });
  },

  authorize: function() {
    Debug.log("Authorize.authorize");
    YAHOO.oib.getUserState(function(response) {
      if (Authorize.authorized(response)) {
        Authorize.confirm();
      } else {
        Debug.log("About to startScanning");
        Authorize.startScanning();
      }
    });
  },

  startScanning: function() {
    Debug.log("Authorize.startScanning", Authorize.scanner);
    if (!Authorize.scanner) {
      Debug.log("Authorize.scanner doesnt exist", Authorize.scanner);
      Authorize.scanner = new PeriodicalExecuter(Authorize.scan, 5);
    } else {
      Debug.log("Authorize.scanner does exist", Authorize.scanner);
    }
  },

  authorized: function(response) {
    Debug.log("Authorize.authorized", response);
    return !!(response.state !== Authorize.default_state && View.authorized(response));
  },

  confirm: YAHOO.oib.confirm,

  scan: function(pe) {
    Debug.log("Authorize.scan", pe);
    if (Authorize.stop_scanning) {
      Debug.log("Authorize.stop_scanning is true", Authorize.stop_scanning);
      pe.stop();
    } else {
      Debug.log("Authorize.stop_scanning is not true", Authorize.stop_scanning);
    }

    Debug.log("About to getUserState");

    YAHOO.oib.getUserState(function(response) {
      Debug.log("inside Authorize.scan's getUserState callback", response);
      if (response.state !== Authorize.default_state) {
        Debug.log("not default state, about to Authorize.confirm()");

        Authorize.confirm();
        if (pe) {
          Debug.log("pe", pe);
          pe.stop();
        }
        Authorize.scanner = undefined;
        Debug.log("just set Authorize.scanner to undefined");
      }
    }, function(response) {
      // error function
      Debug.error("Error in Authorize.scan's getUserState", response);

      if (pe) {
        pe.stop();
      }
    });
  },

  addBehaviors: function() {
    Debug.log("Authorize.addBehaviors");
    if ($("get_started_1")) {
      Debug.log("get_started_1");
      $("get_started_1").observe("click", Authorize.authorize);
    }
    if ($("get_started_2")) {
      Debug.log("get_started_2");
      $("get_started_2").observe("click", Authorize.authorize);
    }
    $$(".get_started").each(function(element) {
      element.observe("click", Authorize.authorize);
    });
  },

  verify: function() {
		// call /ymdp/verify and return data about the user
		YAHOO.oib.verifyUser(function(user) {
      Debug.log("inside YAHOO.oib.verifyUser callback", user);

		  YAHOO.oib.login = user.login;
      YAHOO.init.switchOnState(user);
    }, function(response) {
      // call to ymdp/verify was not a 200 response, show error
      YAHOO.oib.showError({
        "method_name": "YAHOO.oib.verifyUser",
        "description": "error response"
      });
    });
  }
};

<commit_msg>Remove function from authorization js<commit_after>/*
  AUTHORIZE USER

  Authorize and sign in the user.
*/

var Authorize;

Authorize = {
  init: function(guid, default_state, params) {
    Debug.log("Authorize.init");
    params = params || {};
    if (Params.get("invitation")) {
      params["invitation"] = Params.get("invitation");
    }
    params["application"] = View.application;
    Authorize.url = YAHOO.constants.controller_url + "/authorize/" + guid;
    Authorize.locale = params.locale;
    Authorize.default_state = default_state;

    Authorize.params = params;
  },

  assignUrl: function(url) {
    url = url || Authorize.url;
    url = url + "?" + Object.toQueryString(Authorize.params);
    if ($('get_started_1')) {
      $('get_started_1').href = url;
      $('get_started_1').setAttribute("target", "_blank");
    }
    if ($('get_started_2')) {
      $('get_started_2').href = url;
      $('get_started_2').setAttribute("target", "_blank");
    }
    $$('a.get_started').each(function(element) {
      element = $(element);
      element.href = url;
      element.setAttribute("target", "_blank");
    });
  },

  authorize: function() {
    Debug.log("Authorize.authorize");
    YAHOO.oib.getUserState(function(response) {
      if (Authorize.authorized(response)) {
        Authorize.confirm();
      } else {
        Debug.log("About to startScanning");
        Authorize.startScanning();
      }
    });
  },

  startScanning: function() {
    Debug.log("Authorize.startScanning", Authorize.scanner);
    if (!Authorize.scanner) {
      Debug.log("Authorize.scanner doesnt exist", Authorize.scanner);
      Authorize.scanner = new PeriodicalExecuter(Authorize.scan, 5);
    } else {
      Debug.log("Authorize.scanner does exist", Authorize.scanner);
    }
  },

  authorized: function(response) {
    Debug.log("Authorize.authorized", response);
    return !!(response.state !== Authorize.default_state && View.authorized(response));
  },

  confirm: YAHOO.oib.confirm,

  scan: function(pe) {
    Debug.log("Authorize.scan", pe);
    if (Authorize.stop_scanning) {
      Debug.log("Authorize.stop_scanning is true", Authorize.stop_scanning);
      pe.stop();
    } else {
      Debug.log("Authorize.stop_scanning is not true", Authorize.stop_scanning);
    }

    Debug.log("About to getUserState");

    YAHOO.oib.getUserState(function(response) {
      Debug.log("inside Authorize.scan's getUserState callback", response);
      if (response.state !== Authorize.default_state) {
        Debug.log("not default state, about to Authorize.confirm()");

        Authorize.confirm();
        if (pe) {
          Debug.log("pe", pe);
          pe.stop();
        }
        Authorize.scanner = undefined;
        Debug.log("just set Authorize.scanner to undefined");
      }
    }, function(response) {
      // error function
      Debug.error("Error in Authorize.scan's getUserState", response);

      if (pe) {
        pe.stop();
      }
    });
  },

  addBehaviors: function() {
    Debug.log("Authorize.addBehaviors");
    if ($("get_started_1")) {
      Debug.log("get_started_1");
      $("get_started_1").observe("click", Authorize.authorize);
    }
    if ($("get_started_2")) {
      Debug.log("get_started_2");
      $("get_started_2").observe("click", Authorize.authorize);
    }
    $$(".get_started").each(function(element) {
      element.observe("click", Authorize.authorize);
    });
  },

  verify: function() {
		// call /ymdp/verify and return data about the user
		YAHOO.oib.verifyUser(function(user) {
      Debug.log("inside YAHOO.oib.verifyUser callback", user);

		  YAHOO.oib.login = user.login;
      YAHOO.init.switchOnState(user);
    }, function(response) {
      // call to ymdp/verify was not a 200 response, show error
      YAHOO.oib.showError({
        "method_name": "YAHOO.oib.verifyUser",
        "description": "error response"
      });
    });
  }
};

<|endoftext|>


<commit_before>/**
  @module solr
*/

import Ember from 'ember';
import DS from 'ember-data';
import {
  SolrSearchHandler,
  SolrRealTimeGetHandler,
  SolrUpdateHandler,
  SolrDeleteHandler
} from 'ember-solr/lib/handlers';

import SolrCommitType from 'ember-solr/lib/commit-type';
import SolrRequest from 'ember-solr/lib/request';
import SolrUpdateMode from 'ember-solr/lib/update-mode';
import bigNumberStringify from 'ember-solr/lib/big-number-stringify';
import ConcurrentModificationError from 'ember-solr/concurrent-modification-error';

const forEach = Ember.ArrayPolyfills.forEach,
      get = Ember.get,
      set = Ember.set;

/**
  Ember Data Adapter for Apache Solr.
  @class SolrAdapter
  @extends DS.Adapter
*/
export default DS.Adapter.extend({
  /**
    The base URL where the Solr instance is hosted.
    This property is typically configured by setting
    `ENV.solrBaseURL` in your `config/environment.js`
    file.
    @property baseURL
    @type {string}
    @default '/solr'
  */
  baseURL: '/solr',

  /**
    When enabled, sends a `commit` command to Solr in update
    requests to commit the index synchronously and
    block the request until commit has completed.

    There are many considerations when choosing to
    enable this feature. Consult the Solr
    [documentation](https://wiki.apache.org/solr/SolrConfigXml#Update_Handler_Section)
    on autoCommit, and softAutoCommit.

    See also {{#crossLink "SolrAdapter/commitWithinMilliseconds:property"}}{{/crossLink}}.

    @property commit
    @type {SolrCommitType}
    @default SolrCommitType.None
  */
  commit: SolrCommitType.None,

  /**
    When set, sends a `commitWithin` command to Solr
    in update requests to have the update committed
    within a time limit (in milliseconds). Solr will
    aggregate multiple pending writes into a single
    commit to reduce overhead and improve performance.

    This property, when set, takes precedence over
    {{#crossLink "SolrAdapter/commit:property"}}{{/crossLink}}.

    There are many considerations when choosing to
    enable this feature. Consult the Solr
    [documentation](https://wiki.apache.org/solr/SolrConfigXml#Update_Handler_Section)
    on autoCommit, and softAutoCommit.

    In Solr 4 and later, commitWithin is handled by default
    as a soft commit. See [UpdateHandlers in SolrConfig](https://cwiki.apache.org/confluence/display/solr/UpdateHandlers+in+SolrConfig#UpdateHandlersinSolrConfig-commitWithin).

    See also {{#crossLink "SolrAdapter/commit:property"}}{{/crossLink}}.

    @property commitWithinMilliseconds
    @type {number} milliseconds
    @default undefined
  */
  commitWithinMilliseconds: undefined,

  /**
    Specifies a default Solr Core to send requests
    to. If no default core is configured, this adapter
    will not include a core in the request URI path
    and the Solr server will use its own default.
    @property defaultCore
    @type {string}
    @default null
  */
  defaultCore: null,

  /**
    Sets the default serializer for this adapter.
    Uses {{#crossLink "SolrSerializer"}}{{/crossLink}} by default.
    @property defaultSerializer
    @type {string}
    @default '-solr'
  */
  defaultSerializer: '-solr',

  /**
    Sets the data type for jQuery ajax requests.
    Either `json` or `jsonp` are supported.
    `jsonp` is provided as the default to allow cross-origin
    requests to succeed without needing special customization
    of the Solr server.
    @property dataType
    @type {string}
    @default 'jsonp'
  */
  dataType: 'jsonp',

  /**
    Enables or disables sending requests to Solr's
    Real Time Get handler. Note that this handler is
    disabled by default on many Solr servers.

    Real Time Get allows retrieval of documents that
    have not yet been committed by retrieving them from
    the update log.

    If you are using SolrCloud, it is generally safe to
    enable this feature.

    @property enableRealTimeGet
    @type {boolean}
    @default false
  */
  enableRealTimeGet: false,

  /**
    Sets the concurrency mode for how updates are sent
    to Solr.

    @property updateMode
    @type {SolrUpdateMode}
    @default SolrUpdateType.OptimisticConcurrency
  */
  updateMode: SolrUpdateMode.OptimisticConcurrency,

  /**
    Find a record by its unique ID.

    @method find
  */
  find: function(store, type, id) {
    var request = this.buildRequest(store, type, 'find', id);

    return this.executeRequest(request);
  },

  /**
    Find all documents of a type.

    @method findAll
  */
  findAll: function(store, type, sinceToken) {
    console.log('findAll since', sinceToken);
    var request = this.buildRequest(store, type, 'findAll');

    return this.executeRequest(request);
  },

  /**
    Find multiple documents in a single request.

    @method findMany
  */
  findMany: function(store, type, ids) {
    var request = this.buildRequest(store, type, 'findMany', ids);

    return this.executeRequest(request);
  },

  /**
    Find one or more records by arbitrary query

    The query hash should include the key `q` with
    an appropriate Solr query to execute. If this key
    is not specified, `*:*` will be used to match all
    documents.

    The query hash may include the keys `limit` and/or
    `offset` to override the Solr request handler's
    page size and retrieve rows from a given offset.

    @method findQuery
  */
  findQuery: function(store, type, query) {
    var request = this.buildRequest(store, type, 'findQuery', query);

    return this.executeRequest(request);
  },

  createRecord: function(store, type, snapshot) {
    return this.update(store, type, snapshot, 'createRecord');
  },

  updateRecord: function(store, type, snapshot) {
    return this.update(store, type, snapshot, 'updateRecord');
  },

  deleteRecord: function(store, type, snapshot) {
    return this.update(store, type, snapshot, 'deleteRecord');
  },

  update: function(store, type, snapshot, operation) {
    var options = {
      includeId: true,
      updateMode: get(this, 'updateMode')
    };

    var doc = this.serialize(snapshot, options);

    var request = this.buildRequest(store, type, operation, doc);

    var promise = this.executeRequest(request);

    if (operation === 'deleteRecord') {
      return promise;
    }

    var self = this;

    return promise.then(function() {
      return self.find(store, type, snapshot.id);
    });
  },

  serialize: function(snapshot, options) {
    var store = snapshot.record.store;
    var serializer = store.serializerFor(snapshot.typeKey);
    return serializer.serialize(snapshot, options);
  },

  /**
    Builds a request to send to Solr.

    @method buildRequest
    @param {instance of DS.Store} store
    @param {subclass of DS.Model} type the model type
    @param {string} operation one of `find`, `findQuery`, etc.
    @param {data} data to be sent in the request
    @return {SolrRequest} request
    @protected
  */
  buildRequest: function(store, type, operation, data) {
    var handler = this.handlerForType(type, operation);

    handler.prepare(this, store, type, operation, data);

    return SolrRequest.create({
      core: this.coreForType(type, operation),
      handler: handler,
      data: get(handler, 'data')
    });
  },

  /**
    Determines which Solr Core should handle queries for
    a given type and oepration. By default,
    {{#crossLink "SolrAdapter/defaultCore:property"}}{{/crossLink}}
    is used.
    @method coreForType
    @param {subclass of DS.Model} type
    @param {String} operation
    @return {String} core name
    @protected
  */
  coreForType: function() {
    return get(this, 'defaultCore');
  },

  /**
    Determines the [unique key](https://wiki.apache.org/solr/UniqueKey)
    for a given type. Default Solr schemas use the canonical field `id`
    and this method defaults to the same field.
    @method uniqueKeyForType
    @param {subclass of DS.Model} type
    @return {String}
    @protected
  */
  uniqueKeyForType: function() {
    return 'id';
  },

  /**
    Determines which Solr Core should handle queries for
    a given type and operation.

    When
    {{#crossLink "SolrAdapter/enableRealTimeGet:property"}}{{/crossLink}}
    is set to `true`, this method will choose RealTimeGet
    for `find` and `findMany` operations.

    Override this method to customize the path and type
    of handler that should be used for given operations.

    @method handlerForType
    @param {subclass of DS.Model} type
    @param {String} operation
    @return {SolrRequestHandler} handler instance
    @protected
  */
  handlerForType: function(type, operation) {
    var enableRealTimeGet = get(this, 'enableRealTimeGet');

    if (enableRealTimeGet &&
        (operation === 'find' || operation === 'findMany')) {
      return SolrRealTimeGetHandler.create();
    }

    if (operation === 'updateRecord' || operation === 'createRecord') {
      return SolrUpdateHandler.create();
    }

    if (operation === 'deleteRecord') {
      return SolrDeleteHandler.create();
    }

    return SolrSearchHandler.create();
  },

  /**
    Builds an optional filter query (`fq`) to include in search requests.
    If multiple models are stored in the same Solr Core, applying
    an appropriate filter query will ensure only the documents of
    the appropriate type are included.
    Example
    ```javascript
    App.ApplicationAdapter = SolrAdapter.extend({
      filterQueryForType: function(type) {
        return 'doc_type:' + type;
      }
    });
    ```
    See [CommonQueryParameters](https://wiki.apache.org/solr/CommonQueryParameters#fq).
    @method filterQueryForType
    @param {String} type
    @param {String} operation
    @return {String} a filter query or `null`
    @protected
  */

  /**
    Builds a complete URL and initiates
    an AJAX request to Solr.

    @method executeRequest
    @param {SolrRequest} request
    @return {Promise} promise
    @protected
  */
  executeRequest: function(request) {
    var URL = this.combinePath(
      get(this, 'baseURL'),
      get(request, 'core'),
      get(request, 'handler.path'));

    return this.ajax(URL, get(request, 'method'), get(request, 'options'));
  },

  /**
    Joins two or more strings into a path delimited
    by forward slashes without adding redundant slashes.
    Any number of arguments can be passed into this method.
    @method combinePath
    @param {string} path1
    @param {string} path2
    @return {string}
    @protected
  */
  combinePath: function(path1) {
    var s = path1;

    for (var i = 1; i < arguments.length; i++) {
      var part = arguments[i];
      if (!part) {
        continue;
      }

      if (s[s.length - 1] !== '/' && part[0] !== '/') {
        s += '/';
      } else if (s[s.length - 1] === '/' && part[0] === '/') {
        part = part.substring(1);
      }

      s += part;
    }

    return s;
  },

  /**
    Takes a URL, an HTTP method and a hash of data, and makes an
    HTTP request.
    When the server responds with a payload, Ember Data will call into `extractSingle`
    or `extractArray` (depending on whether the original query was for one record or
    many records).
    By default, `ajax` method has the following behavior:
    * It sets the response `dataType` to `"json"`
    * If the HTTP method is not `"GET"`, it sets the `Content-Type` to be
      `application/json; charset=utf-8`
    * If the HTTP method is not `"GET"`, it stringifies the data passed in. The
      data is the serialized record in the case of a save.
    * Registers success and failure handlers.
    @method ajax
    @private
    @param {String} url
    @param {String} type The request type GET, POST, PUT, DELETE etc.
    @param {Object} options
    @return {Promise} promise
    @protected
  */
  ajax: function(url, type, options) {
    var adapter = this;

    return new Ember.RSVP.Promise(function(resolve, reject) {
      var hash = adapter.ajaxOptions(url, type, options);

      hash.converters = {
        'text json': function(text) {
          return BigNumberJSON.parse(text);
        }
      };

      hash.success = function(json, textStatus, jqXHR) {
        json = adapter.ajaxSuccess(jqXHR, json);
        if (json instanceof DS.InvalidError) {
          Ember.run(null, reject, json);
        } else {
          Ember.run(null, resolve, json);
        }
      };

      hash.error = function(jqXHR, textStatus, errorThrown) {
        Ember.run(null, reject, adapter.ajaxError(jqXHR, jqXHR.responseText, errorThrown));
      };

      Ember.$.ajax(hash);
    }, 'Solr: SolrAdapter#ajax ' + type + ' to ' + url);
  },

  /**
    @method ajaxOptions
    @private
    @param {String} url
    @param {String} type The request type GET, POST, PUT, DELETE etc.
    @param {Object} options
    @return {Object}
    @protected
  */
  ajaxOptions: function(url, type, options) {
    var hash = options || {};
    hash.url = url;
    hash.type = type;
    hash.dataType = get(this, 'dataType') || 'json';
    hash.context = this;
    hash.traditional = true;

    if (hash.dataType.indexOf('jsonp') === 0) {
      hash.jsonp = 'json.wrf';
      if (type !== 'GET') {
        set(hash, 'data', {'stream.body': bigNumberStringify(hash.data)});
        hash.type = 'GET'; // JSON-P can only use GET
      }
    }

    if (hash.data && hash.type !== 'GET') {
      hash.contentType = 'application/json; charset=utf-8';
      set(hash, 'data', bigNumberStringify(hash.data));
    }

    var headers = get(this, 'headers');
    if (headers !== undefined) {
      hash.beforeSend = function (xhr) {
        forEach.call(Ember.keys(headers), function(key) {
          xhr.setRequestHeader(key, headers[key]);
        });
      };
    }

    return hash;
  },

  /**
    Takes an ajax response, and returns the json payload.
    By default this hook just returns the jsonPayload passed to it.
    You might want to override it in two cases:
    1. Your API might return useful results in the request headers.
    If you need to access these, you can override this hook to copy them
    from jqXHR to the payload object so they can be processed in you serializer.
    2. Your API might return errors as successful responses with status code
    200 and an Errors text or object. You can return a DS.InvalidError from
    this hook and it will automatically reject the promise and put your record
    into the invalid state.
    @method ajaxSuccess
    @param  {Object} jqXHR
    @param  {Object} jsonPayload
    @return {Object} jsonPayload
    @protected
  */
  ajaxSuccess: function(jqXHR, jsonPayload) {
    return jsonPayload;
  },

  /**
    Takes an ajax response, and returns an error payload.
    Returning a `DS.InvalidError` from this method will cause the
    record to transition into the `invalid` state and make the
    `errors` object available on the record.
    This function should return the entire payload as received from the
    server.  Error object extraction and normalization of model errors
    should be performed by `extractErrors` on the serializer.
    Example
    ```javascript
    App.ApplicationAdapter = DS.RESTAdapter.extend({
      ajaxError: function(jqXHR) {
        var error = this._super(jqXHR);
        if (jqXHR && jqXHR.status === 422) {
          var jsonErrors = Ember.$.parseJSON(jqXHR.responseText);
          return new DS.InvalidError(jsonErrors);
        } else {
          return error;
        }
      }
    });
    ```
    Note: As a correctness optimization, the default implementation of
    the `ajaxError` method strips out the `then` method from jquery's
    ajax response (jqXHR). This is important because the jqXHR's
    `then` method fulfills the promise with itself resulting in a
    circular "thenable" chain which may cause problems for some
    promise libraries.
    @method ajaxError
    @param  {Object} jqXHR
    @param  {Object} responseText
    @return {Object} jqXHR
    @protected
  */
  ajaxError: function(jqXHR, responseText, errorThrown) {
    var isObject = jqXHR !== null && typeof jqXHR === 'object';

    if (!isObject) {
      return jqXHR;
    }

    if (jqXHR.status === 409) {
      var message = 'version conflict';
      if (jqXHR.responseJSON && jqXHR.responseJSON.error && jqXHR.responseJSON.error.msg) {
        message = jqXHR.responseJSON.error.msg;
      }
      return new ConcurrentModificationError(message);
    }

    jqXHR.then = null;
    if (!jqXHR.errorThrown) {
      if (typeof errorThrown === 'string') {
        jqXHR.errorThrown = new Error(errorThrown);
      } else {
        jqXHR.errorThrown = errorThrown;
      }
    }

    return jqXHR;
  }
});
<commit_msg>Use SolrUpdateMode.None by default for JSON-P compatibility.<commit_after>/**
  @module solr
*/

import Ember from 'ember';
import DS from 'ember-data';
import {
  SolrSearchHandler,
  SolrRealTimeGetHandler,
  SolrUpdateHandler,
  SolrDeleteHandler
} from 'ember-solr/lib/handlers';

import SolrCommitType from 'ember-solr/lib/commit-type';
import SolrRequest from 'ember-solr/lib/request';
import SolrUpdateMode from 'ember-solr/lib/update-mode';
import bigNumberStringify from 'ember-solr/lib/big-number-stringify';
import ConcurrentModificationError from 'ember-solr/concurrent-modification-error';

const forEach = Ember.ArrayPolyfills.forEach,
      get = Ember.get,
      set = Ember.set;

/**
  Ember Data Adapter for Apache Solr.
  @class SolrAdapter
  @extends DS.Adapter
*/
export default DS.Adapter.extend({
  /**
    The base URL where the Solr instance is hosted.
    This property is typically configured by setting
    `ENV.solrBaseURL` in your `config/environment.js`
    file.
    @property baseURL
    @type {string}
    @default '/solr'
  */
  baseURL: '/solr',

  /**
    When enabled, sends a `commit` command to Solr in update
    requests to commit the index synchronously and
    block the request until commit has completed.

    There are many considerations when choosing to
    enable this feature. Consult the Solr
    [documentation](https://wiki.apache.org/solr/SolrConfigXml#Update_Handler_Section)
    on autoCommit, and softAutoCommit.

    See also {{#crossLink "SolrAdapter/commitWithinMilliseconds:property"}}{{/crossLink}}.

    @property commit
    @type {SolrCommitType}
    @default SolrCommitType.None
  */
  commit: SolrCommitType.None,

  /**
    When set, sends a `commitWithin` command to Solr
    in update requests to have the update committed
    within a time limit (in milliseconds). Solr will
    aggregate multiple pending writes into a single
    commit to reduce overhead and improve performance.

    This property, when set, takes precedence over
    {{#crossLink "SolrAdapter/commit:property"}}{{/crossLink}}.

    There are many considerations when choosing to
    enable this feature. Consult the Solr
    [documentation](https://wiki.apache.org/solr/SolrConfigXml#Update_Handler_Section)
    on autoCommit, and softAutoCommit.

    In Solr 4 and later, commitWithin is handled by default
    as a soft commit. See [UpdateHandlers in SolrConfig](https://cwiki.apache.org/confluence/display/solr/UpdateHandlers+in+SolrConfig#UpdateHandlersinSolrConfig-commitWithin).

    See also {{#crossLink "SolrAdapter/commit:property"}}{{/crossLink}}.

    @property commitWithinMilliseconds
    @type {number} milliseconds
    @default undefined
  */
  commitWithinMilliseconds: undefined,

  /**
    Specifies a default Solr Core to send requests
    to. If no default core is configured, this adapter
    will not include a core in the request URI path
    and the Solr server will use its own default.
    @property defaultCore
    @type {string}
    @default null
  */
  defaultCore: null,

  /**
    Sets the default serializer for this adapter.
    Uses {{#crossLink "SolrSerializer"}}{{/crossLink}} by default.
    @property defaultSerializer
    @type {string}
    @default '-solr'
  */
  defaultSerializer: '-solr',

  /**
    Sets the data type for jQuery ajax requests.
    Either `json` or `jsonp` are supported.
    `jsonp` is provided as the default to allow cross-origin
    requests to succeed without needing special customization
    of the Solr server.
    @property dataType
    @type {string}
    @default 'jsonp'
  */
  dataType: 'jsonp',

  /**
    Enables or disables sending requests to Solr's
    Real Time Get handler. Note that this handler is
    disabled by default on many Solr servers.

    Real Time Get allows retrieval of documents that
    have not yet been committed by retrieving them from
    the update log.

    If you are using SolrCloud, it is generally safe to
    enable this feature.

    @property enableRealTimeGet
    @type {boolean}
    @default false
  */
  enableRealTimeGet: false,

  /**
    Sets the concurrency mode for how updates are sent
    to Solr.

    @property updateMode
    @type {SolrUpdateMode}
    @default SolrUpdateType.None
  */
  updateMode: SolrUpdateMode.None,

  /**
    Find a record by its unique ID.

    @method find
  */
  find: function(store, type, id) {
    var request = this.buildRequest(store, type, 'find', id);

    return this.executeRequest(request);
  },

  /**
    Find all documents of a type.

    @method findAll
  */
  findAll: function(store, type, sinceToken) {
    console.log('findAll since', sinceToken);
    var request = this.buildRequest(store, type, 'findAll');

    return this.executeRequest(request);
  },

  /**
    Find multiple documents in a single request.

    @method findMany
  */
  findMany: function(store, type, ids) {
    var request = this.buildRequest(store, type, 'findMany', ids);

    return this.executeRequest(request);
  },

  /**
    Find one or more records by arbitrary query

    The query hash should include the key `q` with
    an appropriate Solr query to execute. If this key
    is not specified, `*:*` will be used to match all
    documents.

    The query hash may include the keys `limit` and/or
    `offset` to override the Solr request handler's
    page size and retrieve rows from a given offset.

    @method findQuery
  */
  findQuery: function(store, type, query) {
    var request = this.buildRequest(store, type, 'findQuery', query);

    return this.executeRequest(request);
  },

  createRecord: function(store, type, snapshot) {
    return this.update(store, type, snapshot, 'createRecord');
  },

  updateRecord: function(store, type, snapshot) {
    return this.update(store, type, snapshot, 'updateRecord');
  },

  deleteRecord: function(store, type, snapshot) {
    return this.update(store, type, snapshot, 'deleteRecord');
  },

  update: function(store, type, snapshot, operation) {
    var options = {
      includeId: true,
      updateMode: get(this, 'updateMode')
    };

    var doc = this.serialize(snapshot, options);

    var request = this.buildRequest(store, type, operation, doc);

    var promise = this.executeRequest(request);

    if (operation === 'deleteRecord') {
      return promise;
    }

    var self = this;

    return promise.then(function() {
      return self.find(store, type, snapshot.id);
    });
  },

  serialize: function(snapshot, options) {
    var store = snapshot.record.store;
    var serializer = store.serializerFor(snapshot.typeKey);
    return serializer.serialize(snapshot, options);
  },

  /**
    Builds a request to send to Solr.

    @method buildRequest
    @param {instance of DS.Store} store
    @param {subclass of DS.Model} type the model type
    @param {string} operation one of `find`, `findQuery`, etc.
    @param {data} data to be sent in the request
    @return {SolrRequest} request
    @protected
  */
  buildRequest: function(store, type, operation, data) {
    var handler = this.handlerForType(type, operation);

    handler.prepare(this, store, type, operation, data);

    return SolrRequest.create({
      core: this.coreForType(type, operation),
      handler: handler,
      data: get(handler, 'data')
    });
  },

  /**
    Determines which Solr Core should handle queries for
    a given type and oepration. By default,
    {{#crossLink "SolrAdapter/defaultCore:property"}}{{/crossLink}}
    is used.
    @method coreForType
    @param {subclass of DS.Model} type
    @param {String} operation
    @return {String} core name
    @protected
  */
  coreForType: function() {
    return get(this, 'defaultCore');
  },

  /**
    Determines the [unique key](https://wiki.apache.org/solr/UniqueKey)
    for a given type. Default Solr schemas use the canonical field `id`
    and this method defaults to the same field.
    @method uniqueKeyForType
    @param {subclass of DS.Model} type
    @return {String}
    @protected
  */
  uniqueKeyForType: function() {
    return 'id';
  },

  /**
    Determines which Solr Core should handle queries for
    a given type and operation.

    When
    {{#crossLink "SolrAdapter/enableRealTimeGet:property"}}{{/crossLink}}
    is set to `true`, this method will choose RealTimeGet
    for `find` and `findMany` operations.

    Override this method to customize the path and type
    of handler that should be used for given operations.

    @method handlerForType
    @param {subclass of DS.Model} type
    @param {String} operation
    @return {SolrRequestHandler} handler instance
    @protected
  */
  handlerForType: function(type, operation) {
    var enableRealTimeGet = get(this, 'enableRealTimeGet');

    if (enableRealTimeGet &&
        (operation === 'find' || operation === 'findMany')) {
      return SolrRealTimeGetHandler.create();
    }

    if (operation === 'updateRecord' || operation === 'createRecord') {
      return SolrUpdateHandler.create();
    }

    if (operation === 'deleteRecord') {
      return SolrDeleteHandler.create();
    }

    return SolrSearchHandler.create();
  },

  /**
    Builds an optional filter query (`fq`) to include in search requests.
    If multiple models are stored in the same Solr Core, applying
    an appropriate filter query will ensure only the documents of
    the appropriate type are included.
    Example
    ```javascript
    App.ApplicationAdapter = SolrAdapter.extend({
      filterQueryForType: function(type) {
        return 'doc_type:' + type;
      }
    });
    ```
    See [CommonQueryParameters](https://wiki.apache.org/solr/CommonQueryParameters#fq).
    @method filterQueryForType
    @param {String} type
    @param {String} operation
    @return {String} a filter query or `null`
    @protected
  */

  /**
    Builds a complete URL and initiates
    an AJAX request to Solr.

    @method executeRequest
    @param {SolrRequest} request
    @return {Promise} promise
    @protected
  */
  executeRequest: function(request) {
    var URL = this.combinePath(
      get(this, 'baseURL'),
      get(request, 'core'),
      get(request, 'handler.path'));

    return this.ajax(URL, get(request, 'method'), get(request, 'options'));
  },

  /**
    Joins two or more strings into a path delimited
    by forward slashes without adding redundant slashes.
    Any number of arguments can be passed into this method.
    @method combinePath
    @param {string} path1
    @param {string} path2
    @return {string}
    @protected
  */
  combinePath: function(path1) {
    var s = path1;

    for (var i = 1; i < arguments.length; i++) {
      var part = arguments[i];
      if (!part) {
        continue;
      }

      if (s[s.length - 1] !== '/' && part[0] !== '/') {
        s += '/';
      } else if (s[s.length - 1] === '/' && part[0] === '/') {
        part = part.substring(1);
      }

      s += part;
    }

    return s;
  },

  /**
    Takes a URL, an HTTP method and a hash of data, and makes an
    HTTP request.
    When the server responds with a payload, Ember Data will call into `extractSingle`
    or `extractArray` (depending on whether the original query was for one record or
    many records).
    By default, `ajax` method has the following behavior:
    * It sets the response `dataType` to `"json"`
    * If the HTTP method is not `"GET"`, it sets the `Content-Type` to be
      `application/json; charset=utf-8`
    * If the HTTP method is not `"GET"`, it stringifies the data passed in. The
      data is the serialized record in the case of a save.
    * Registers success and failure handlers.
    @method ajax
    @private
    @param {String} url
    @param {String} type The request type GET, POST, PUT, DELETE etc.
    @param {Object} options
    @return {Promise} promise
    @protected
  */
  ajax: function(url, type, options) {
    var adapter = this;

    return new Ember.RSVP.Promise(function(resolve, reject) {
      var hash = adapter.ajaxOptions(url, type, options);

      hash.converters = {
        'text json': function(text) {
          return BigNumberJSON.parse(text);
        }
      };

      hash.success = function(json, textStatus, jqXHR) {
        json = adapter.ajaxSuccess(jqXHR, json);
        if (json instanceof DS.InvalidError) {
          Ember.run(null, reject, json);
        } else {
          Ember.run(null, resolve, json);
        }
      };

      hash.error = function(jqXHR, textStatus, errorThrown) {
        Ember.run(null, reject, adapter.ajaxError(jqXHR, jqXHR.responseText, errorThrown));
      };

      Ember.$.ajax(hash);
    }, 'Solr: SolrAdapter#ajax ' + type + ' to ' + url);
  },

  /**
    @method ajaxOptions
    @private
    @param {String} url
    @param {String} type The request type GET, POST, PUT, DELETE etc.
    @param {Object} options
    @return {Object}
    @protected
  */
  ajaxOptions: function(url, type, options) {
    var hash = options || {};
    hash.url = url;
    hash.type = type;
    hash.dataType = get(this, 'dataType') || 'json';
    hash.context = this;
    hash.traditional = true;

    if (hash.dataType.indexOf('jsonp') === 0) {
      hash.jsonp = 'json.wrf';
      if (type !== 'GET') {
        set(hash, 'data', {'stream.body': bigNumberStringify(hash.data)});
        hash.type = 'GET'; // JSON-P can only use GET
      }
    }

    if (hash.data && hash.type !== 'GET') {
      hash.contentType = 'application/json; charset=utf-8';
      set(hash, 'data', bigNumberStringify(hash.data));
    }

    var headers = get(this, 'headers');
    if (headers !== undefined) {
      hash.beforeSend = function (xhr) {
        forEach.call(Ember.keys(headers), function(key) {
          xhr.setRequestHeader(key, headers[key]);
        });
      };
    }

    return hash;
  },

  /**
    Takes an ajax response, and returns the json payload.
    By default this hook just returns the jsonPayload passed to it.
    You might want to override it in two cases:
    1. Your API might return useful results in the request headers.
    If you need to access these, you can override this hook to copy them
    from jqXHR to the payload object so they can be processed in you serializer.
    2. Your API might return errors as successful responses with status code
    200 and an Errors text or object. You can return a DS.InvalidError from
    this hook and it will automatically reject the promise and put your record
    into the invalid state.
    @method ajaxSuccess
    @param  {Object} jqXHR
    @param  {Object} jsonPayload
    @return {Object} jsonPayload
    @protected
  */
  ajaxSuccess: function(jqXHR, jsonPayload) {
    return jsonPayload;
  },

  /**
    Takes an ajax response, and returns an error payload.
    Returning a `DS.InvalidError` from this method will cause the
    record to transition into the `invalid` state and make the
    `errors` object available on the record.
    This function should return the entire payload as received from the
    server.  Error object extraction and normalization of model errors
    should be performed by `extractErrors` on the serializer.
    Example
    ```javascript
    App.ApplicationAdapter = DS.RESTAdapter.extend({
      ajaxError: function(jqXHR) {
        var error = this._super(jqXHR);
        if (jqXHR && jqXHR.status === 422) {
          var jsonErrors = Ember.$.parseJSON(jqXHR.responseText);
          return new DS.InvalidError(jsonErrors);
        } else {
          return error;
        }
      }
    });
    ```
    Note: As a correctness optimization, the default implementation of
    the `ajaxError` method strips out the `then` method from jquery's
    ajax response (jqXHR). This is important because the jqXHR's
    `then` method fulfills the promise with itself resulting in a
    circular "thenable" chain which may cause problems for some
    promise libraries.
    @method ajaxError
    @param  {Object} jqXHR
    @param  {Object} responseText
    @return {Object} jqXHR
    @protected
  */
  ajaxError: function(jqXHR, responseText, errorThrown) {
    var isObject = jqXHR !== null && typeof jqXHR === 'object';

    if (!isObject) {
      return jqXHR;
    }

    if (jqXHR.status === 409) {
      var message = 'version conflict';
      if (jqXHR.responseJSON && jqXHR.responseJSON.error && jqXHR.responseJSON.error.msg) {
        message = jqXHR.responseJSON.error.msg;
      }
      return new ConcurrentModificationError(message);
    }

    jqXHR.then = null;
    if (!jqXHR.errorThrown) {
      if (typeof errorThrown === 'string') {
        jqXHR.errorThrown = new Error(errorThrown);
      } else {
        jqXHR.errorThrown = errorThrown;
      }
    }

    return jqXHR;
  }
});
<|endoftext|>


<commit_before>// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE

(function(mod) {
  if (typeof exports == "object" && typeof module == "object") // CommonJS
    mod(require("../../lib/codemirror"));
  else if (typeof define == "function" && define.amd) // AMD
    define(["../../lib/codemirror"], mod);
  else // Plain browser env
    mod(CodeMirror);
})(function(CodeMirror) {
  "use strict";

  function doFold(cm, pos, options, force) {
    if (options && options.call) {
      var finder = options;
      options = null;
    } else {
      var finder = getOption(cm, options, "rangeFinder");
    }
    if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0);
    var minSize = getOption(cm, options, "minFoldSize");

    function getRange(allowFolded) {
      var range = finder(cm, pos);
      if (!range || range.to.line - range.from.line < minSize) return null;
      var marks = cm.findMarksAt(range.from);
      for (var i = 0; i < marks.length; ++i) {
        if (marks[i].__isFold && force !== "fold") {
          if (!allowFolded) return null;
          range.cleared = true;
          marks[i].clear();
        }
      }
      return range;
    }

    var range = getRange(true);
    if (getOption(cm, options, "scanUp")) while (!range && pos.line > cm.firstLine()) {
      pos = CodeMirror.Pos(pos.line - 1, 0);
      range = getRange(false);
    }
    if (!range || range.cleared || force === "unfold") return;

    var myWidget = makeWidget(cm, options);
    CodeMirror.on(myWidget, "mousedown", function(e) {
      myRange.clear();
      CodeMirror.e_preventDefault(e);
    });
    var myRange = cm.markText(range.from, range.to, {
      replacedWith: myWidget,
      clearOnEnter: getOption(cm, options, "clearOnEnter"),
      __isFold: true
    });
    myRange.on("clear", function(from, to) {
      CodeMirror.signal(cm, "unfold", cm, from, to);
    });
    CodeMirror.signal(cm, "fold", cm, range.from, range.to);
  }

  function makeWidget(cm, options) {
    var widget = getOption(cm, options, "widget");
    if (typeof widget == "string") {
      var text = document.createTextNode(widget);
      widget = document.createElement("span");
      widget.appendChild(text);
      widget.className = "CodeMirror-foldmarker";
    } else if (widget) {
      widget = widget.cloneNode(true)
    }
    return widget;
  }

  // Clumsy backwards-compatible interface
  CodeMirror.newFoldFunction = function(rangeFinder, widget) {
    return function(cm, pos) { doFold(cm, pos, {rangeFinder: rangeFinder, widget: widget}); };
  };

  // New-style interface
  CodeMirror.defineExtension("foldCode", function(pos, options, force) {
    doFold(this, pos, options, force);
  });

  CodeMirror.defineExtension("isFolded", function(pos) {
    var marks = this.findMarksAt(pos);
    for (var i = 0; i < marks.length; ++i)
      if (marks[i].__isFold) return true;
  });

  CodeMirror.commands.toggleFold = function(cm) {
    cm.foldCode(cm.getCursor());
  };
  CodeMirror.commands.fold = function(cm) {
    cm.foldCode(cm.getCursor(), null, "fold");
  };
  CodeMirror.commands.unfold = function(cm) {
    cm.foldCode(cm.getCursor(), null, "unfold");
  };
  CodeMirror.commands.foldAll = function(cm) {
    cm.operation(function() {
      for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
        cm.foldCode(CodeMirror.Pos(i, 0), null, "fold");
    });
  };
  CodeMirror.commands.unfoldAll = function(cm) {
    cm.operation(function() {
      for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
        cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold");
    });
  };

  CodeMirror.registerHelper("fold", "combine", function() {
    var funcs = Array.prototype.slice.call(arguments, 0);
    return function(cm, start) {
      for (var i = 0; i < funcs.length; ++i) {
        var found = funcs[i](cm, start);
        if (found) return found;
      }
    };
  });

  CodeMirror.registerHelper("fold", "auto", function(cm, start) {
    var helpers = cm.getHelpers(start, "fold");
    for (var i = 0; i < helpers.length; i++) {
      var cur = helpers[i](cm, start);
      if (cur) return cur;
    }
  });

  var defaultOptions = {
    rangeFinder: CodeMirror.fold.auto,
    widget: "\u2194",
    minFoldSize: 0,
    scanUp: false,
    clearOnEnter: true
  };

  CodeMirror.defineOption("foldOptions", null);

  function getOption(cm, options, name) {
    if (options && options[name] !== undefined)
      return options[name];
    var editorOptions = cm.options.foldOptions;
    if (editorOptions && editorOptions[name] !== undefined)
      return editorOptions[name];
    return defaultOptions[name];
  }

  CodeMirror.defineExtension("foldOption", function(options, name) {
    return getOption(this, options, name);
  });
});
<commit_msg>Be able to pass a custom code folding widget<commit_after>// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE

(function(mod) {
  if (typeof exports == "object" && typeof module == "object") // CommonJS
    mod(require("../../lib/codemirror"));
  else if (typeof define == "function" && define.amd) // AMD
    define(["../../lib/codemirror"], mod);
  else // Plain browser env
    mod(CodeMirror);
})(function(CodeMirror) {
  "use strict";

  function doFold(cm, pos, options, force) {
    if (options && options.call) {
      var finder = options;
      options = null;
    } else {
      var finder = getOption(cm, options, "rangeFinder");
    }
    if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0);
    var minSize = getOption(cm, options, "minFoldSize");

    function getRange(allowFolded) {
      var range = finder(cm, pos);
      if (!range || range.to.line - range.from.line < minSize) return null;
      var marks = cm.findMarksAt(range.from);
      for (var i = 0; i < marks.length; ++i) {
        if (marks[i].__isFold && force !== "fold") {
          if (!allowFolded) return null;
          range.cleared = true;
          marks[i].clear();
        }
      }
      return range;
    }

    var range = getRange(true);
    if (getOption(cm, options, "scanUp")) while (!range && pos.line > cm.firstLine()) {
      pos = CodeMirror.Pos(pos.line - 1, 0);
      range = getRange(false);
    }
    if (!range || range.cleared || force === "unfold") return;

    var myWidget = makeWidget(cm, options);
    CodeMirror.on(myWidget, "mousedown", function(e) {
      myRange.clear();
      CodeMirror.e_preventDefault(e);
    });
    var myRange = cm.markText(range.from, range.to, {
      replacedWith: myWidget,
      clearOnEnter: getOption(cm, options, "clearOnEnter"),
      __isFold: true
    });
    myRange.on("clear", function(from, to) {
      CodeMirror.signal(cm, "unfold", cm, from, to);
    });
    CodeMirror.signal(cm, "fold", cm, range.from, range.to);
  }

  function makeWidget(cm, options) {
    var widget = getOption(cm, options, "widget");
    if (typeof widget == "string") {
      var text = document.createTextNode(widget);
      widget = document.createElement("span");
      widget.appendChild(text);
      widget.className = "CodeMirror-foldmarker";
    } else if (widget) {
      widget = widget.cloneNode(true)
    }
    return widget;
  }

  // Clumsy backwards-compatible interface
  CodeMirror.newFoldFunction = function(rangeFinder, widget) {
    return function(cm, pos) { doFold(cm, pos, {rangeFinder: rangeFinder, widget: widget}); };
  };

  // New-style interface
  CodeMirror.defineExtension("foldCode", function(pos, options, force) {
    // Give subscribers a chance to provide a custom widget
    options = options || {};
    var ret = {};
    CodeMirror.signal(this, "getFoldWidget", pos, ret);
    if (ret.widget) options.widget = ret.widget;

    doFold(this, pos, options, force);
  });

  CodeMirror.defineExtension("isFolded", function(pos) {
    var marks = this.findMarksAt(pos);
    for (var i = 0; i < marks.length; ++i)
      if (marks[i].__isFold) return true;
  });

  CodeMirror.commands.toggleFold = function(cm) {
    cm.foldCode(cm.getCursor());
  };
  CodeMirror.commands.fold = function(cm) {
    cm.foldCode(cm.getCursor(), null, "fold");
  };
  CodeMirror.commands.unfold = function(cm) {
    cm.foldCode(cm.getCursor(), null, "unfold");
  };
  CodeMirror.commands.foldAll = function(cm) {
    cm.operation(function() {
      for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
        cm.foldCode(CodeMirror.Pos(i, 0), null, "fold");
    });
  };
  CodeMirror.commands.unfoldAll = function(cm) {
    cm.operation(function() {
      for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
        cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold");
    });
  };

  CodeMirror.registerHelper("fold", "combine", function() {
    var funcs = Array.prototype.slice.call(arguments, 0);
    return function(cm, start) {
      for (var i = 0; i < funcs.length; ++i) {
        var found = funcs[i](cm, start);
        if (found) return found;
      }
    };
  });

  CodeMirror.registerHelper("fold", "auto", function(cm, start) {
    var helpers = cm.getHelpers(start, "fold");
    for (var i = 0; i < helpers.length; i++) {
      var cur = helpers[i](cm, start);
      if (cur) return cur;
    }
  });

  var defaultOptions = {
    rangeFinder: CodeMirror.fold.auto,
    widget: "\u2194",
    minFoldSize: 0,
    scanUp: false,
    clearOnEnter: true
  };

  CodeMirror.defineOption("foldOptions", null);

  function getOption(cm, options, name) {
    if (options && options[name] !== undefined)
      return options[name];
    var editorOptions = cm.options.foldOptions;
    if (editorOptions && editorOptions[name] !== undefined)
      return editorOptions[name];
    return defaultOptions[name];
  }

  CodeMirror.defineExtension("foldOption", function(options, name) {
    return getOption(this, options, name);
  });
});
<|endoftext|>


<commit_before>import Helper from '@ember/component/helper';
import { inject as service } from '@ember/service';
import { get } from '@ember/object';

export default Helper.extend({
  init() {
    this._super(...arguments);
    this.media.on('mediaChanged', () => {
      this.recompute();
    });
  },

  media: service(),

  compute([prop]) {
    return get(this, `media.${prop}`);
  }
});
<commit_msg>Convert class based helper<commit_after>import Helper from '@ember/component/helper';
import { inject as service } from '@ember/service';
import { get } from '@ember/object';

export default class MediaHelper extends Helper {
  @service() media;

  init() {
    super.init(...arguments);

    this.media.on('mediaChanged', () => {
      this.recompute();
    });
  }

  compute([prop]) {
    return get(this, `media.${prop}`);
  }
}
<|endoftext|>