<commit_before>/**
 * @fileoverview Type annotations for the React library.
 *
 * Will be automatically included as a source (not externs) file by
 * ReactCompilerPass. The contents of this file should be inert (i.e. interfaces
 * and typedefs only) such that it compiles down to nothing.
 *
 * Based on https://github.com/facebook/flow/blob/master/lib/react.js and
 * https://github.com/borisyankov/DefinitelyTyped/blob/master/react/react.d.ts.
 */

/**
 * @interface
 * @template T
 */
function ReactClass() {}

/**
 * @type {Object.<ReactPropsChainableTypeChecker>|undefined}
 */
ReactClass.prototype.propTypes;

/**
 * @type {Object.<ReactPropsChainableTypeChecker>|undefined}
 */
ReactClass.prototype.contextTypes;

/**
 * @type {string|undefined}
 */
ReactClass.prototype.displayName;

/**
 * @type {ReactProps|undefined}
 */
ReactClass.prototype.defaultProps;

/**
 * @return {ReactProps}
 */
ReactClass.prototype.getDefaultProps = function() {};

/**
 * @typedef {!Object|{children: (Object|undefined)}}
 */
var ReactProps;

/**
 * @dict
 * @constructor
 */
function ReactRefs() {}

/**
 * @interface
 * @template T
 */
function ReactElement() {}

/**
 * @type {ReactClass.<T>}
 */
ReactElement.prototype.type;

/**
 * @type {ReactProps}
 */
ReactElement.prototype.props;

/**
 * @type {string|number}
 */
ReactElement.prototype.key;

/**
 * @type {string}
 */
ReactElement.prototype.ref;

/**
 * @interface
 * @extends {ReactElement}
 */
function ReactDOMElement() {}

/**
 * @type {string}
 */
ReactDOMElement.prototype.type;

/**
 * @interface
 */
function ReactComponent() {}

/**
 * @type {ReactProps}
 * @const
 */
ReactComponent.prototype.props;

/**
 * @type {Object}
 * @const
 */
ReactComponent.prototype.state;

/**
 * @type {Object}
 * @const
 */
ReactComponent.prototype.context;

/**
 * @type {ReactRefs}
 */
ReactComponent.prototype.refs;

/**
 * @return {Object}
 */
ReactComponent.prototype.getInitialState = function() {};

/**
 * @param {Object} props
 * @param {function(): void=} callback
 * @return {void}
 */
ReactComponent.prototype.setProps = function(props, callback) {};

/**
 * @param {Object} props
 * @param {function(): void=} callback
 * @return {void}
 */
ReactComponent.prototype.replaceProps = function(props, callback) {};

/**
 * @param {Object} state
 * @param {function(): void=} callback
 * @return {void}
 */
ReactComponent.prototype.setState = function(state, callback) {};

/**
 * @param {Object} state
 * @param {function(): void=} callback
 * @return {void}
 */
ReactComponent.prototype.replaceState = function(state, callback) {};

/**
 * @return {ReactElement|boolean}
 */
ReactComponent.prototype.render = function() {};

/**
 * @param {function(): void=} callback
 * @return {void}
 */
ReactComponent.prototype.forceUpdate = function(callback) {};

/**
 * @return {Element}
 */
ReactComponent.prototype.getDOMNode = function() {};

/**
 * @return {boolean}
 */
ReactComponent.prototype.isMounted = function() {};

// Component lifecycle/delegate methods that may be implemented. Intentionally
// does not include the context parameter that is passed to some methods, since
// it's undocumented. Implementations can still add it (and it will not be
// flagged as an error).

/**
 * @return {void}
 */
ReactComponent.prototype.componentWillMount = function() {};

/**
 * @return {void}
 */
ReactComponent.prototype.componentDidMount = function() {};

/**
 * @param {Object} nextProps
 * @return {void}
 */
ReactComponent.prototype.componentWillReceiveProps = function(nextProps) {};

/**
 * @param {Object} nextProps
 * @param {Object} nextState
 * @return {boolean}
 */
ReactComponent.prototype.shouldComponentUpdate = function(nextProps, nextState) {};

/**
 * @param {Object} nextProps
 * @param {Object} nextState
 * @return {void}
 */
ReactComponent.prototype.componentWillUpdate = function(nextProps, nextState) {};

/**
 * @param {Object} prevProps
 * @param {Object} prevState
 * @return {void}
 */
ReactComponent.prototype.componentDidUpdate = function(prevProps, prevState) {};

/**
 * @return {void}
 */
ReactComponent.prototype.componentWillUnmount = function() {};

/**
 * @typedef {boolean|number|string|ReactElement}
 */
var ReactChild;

/**
 * @typedef {
 *   ReactChild|
 *   Array.<boolean>|Array.<number>|Array.<string>|Array.<ReactElement>|
 *   Object.<boolean>|Object.<number>|Object.<string>|Object.<ReactElement>
 * }
 */
var ReactChildrenArgument;

/**
 * @interface
 */
function ReactChildren() {};

/**
 * @param {Object|undefined} children
 * @param {function(*, number)} func
 * @param {*=} context
 * @return {Object|undefined}
 */
ReactChildren.prototype.map = function(children, func, context) {};

/**
 * @param {Object|undefined} children
 * @param {function(*, number)} func
 * @param {*=} context
 */
ReactChildren.prototype.forEach = function(children, func, context) {};

/**
 * @param {Object|undefined} children
 * @return {number}
 */
ReactChildren.prototype.count = function(children) {};

/**
 * @param {Object|undefined} children
 * @return {ReactChild}
 */
ReactChildren.prototype.only = function(children) {};

/**
 * Factory functions for each HTML and SVG tag are generated by
 * ReactCompilerPass.
 *
 * @interface
 */
function ReactDOM() {};

/**
 * Parameters are: props, propName, componentName, location.
 * @typedef {function(Object, string, string, string): Error}
 */
var ReactPropsChainableTypeChecker = function() {};

/**
 * @interface
 */
function ReactPropTypes() {};
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.array;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.array.isRequired;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.bool;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.bool.isRequired;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.func;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.func.isRequired;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.number;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.number.isRequired;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.object;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.object.isRequired;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.string;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.string.isRequired;

/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.any;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.any.isRequired;
/**
 * @param {ReactPropsChainableTypeChecker} typeChecker
 * @return {ReactPropsChainableTypeChecker}
 */
ReactPropTypes.prototype.arrayOf = function(typeChecker) {};
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.element;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.element.isRequired;
/**
 * @param {Function} expectedClass
 * @return {ReactPropsChainableTypeChecker}
 */
ReactPropTypes.prototype.instanceOf = function(expectedClass) {};
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.node;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.node.isRequired;
/**
 * @param {ReactPropsChainableTypeChecker} typeChecker
 * @return {ReactPropsChainableTypeChecker}
 */
ReactPropTypes.prototype.objectOf = function(typeChecker) {};
/**
 * @param {Array} expectedValues
 * @return {ReactPropsChainableTypeChecker}
 */
ReactPropTypes.prototype.oneOf = function(expectedValues) {};
/**
 * @param {Array.<ReactPropsChainableTypeChecker>} arrayOfTypeCheckers
 * @return {ReactPropsChainableTypeChecker}
 */
ReactPropTypes.prototype.oneOfType = function(arrayOfTypeCheckers) {};
/**
 * @param {Object.<ReactPropsChainableTypeChecker>} shapeTypes
 * @return {ReactPropsChainableTypeChecker}
 */
ReactPropTypes.prototype.shape = function(shapeTypes) {};

/**
 * @interface
 * @extends {ReactComponent}
 */
function ReactCSSTransitionGroup() {}

/**
 * @interface
 * @extends {ReactComponent}
 */
function ReactTransitionGroup() {}

/**
 * @interface
 */
function ReactAddonsPerf() {}

ReactAddonsPerf.prototype.start = function() {};

ReactAddonsPerf.prototype.stop = function() {};

/**
 * @return {Array.<ReactAddonsPerf.Measurement>}
 */
ReactAddonsPerf.prototype.getLastMeasurements = function() {};

/**
 * @param {ReactAddonsPerf.Measurement=} measurements
 */
ReactAddonsPerf.prototype.printExclusive = function(measurements) {};

/**
 * @param {ReactAddonsPerf.Measurement=} measurements
 */
ReactAddonsPerf.prototype.printInclusive = function(measurements) {};

/**
 * @param {ReactAddonsPerf.Measurement=} measurements
 */
ReactAddonsPerf.prototype.printWasted = function(measurements) {};

/**
 * @typedef {{
 *     exclusive: !Object.<string, number>,
 *     inclusive: !Object.<string, number>,
 *     render: !Object.<string, number>,
 *     counts: !Object.<string, number>,
 *     writes: !Object.<string, {type: string, time: number, args: Array}>,
 *     displayNames: !Object.<string, {current: string, owner: string}>,
 *     totalTime: number
 * }}
 */
ReactAddonsPerf.Measurement;

/**
 * @interface
 */
function ReactAddons() {}

/**
 * @type {ReactClass.<ReactCSSTransitionGroup>}
 */
ReactAddons.prototype.CSSTransitionGroup;

/**
 * @type {ReactClass.<ReactTransitionGroup>}
 */
ReactAddons.prototype.TransitionGroup;

/**
 * @type {ReactAddonsPerf}
 */
ReactAddons.prototype.Perf;

/**
 * @type {Object}
 */
ReactAddons.prototype.PureRenderMixin;

/**
 * @param {Function} callback
 * @param {*=} a
 * @param {*=} b
 * @param {*=} c
 * @param {*=} d
 */
ReactAddons.prototype.batchedUpdates = function(callback, a, b, c, d) {};

/**
 * @param {Object|string} objectOrClassName
 * @param {...string} classNames
 * @return {string}
 * @deprecated
 */
ReactAddons.prototype.classSet = function(objectOrClassName, classNames) {};

/**
 * @param {ReactElement.<T>} element
 * @param {Object=} extraProps
 * @return {ReactElement.<T>}
 * @template T
 */
ReactAddons.prototype.cloneWithProps = function(element, extraProps) {};

/**
 * @param {Object.<string, ReactElement>} object
 * @return {*}
 */
ReactAddons.prototype.createFragment = function(object) {};

/**
 * @typedef {{
 *     $push: (Array|undefined),
 *     $unshift: (Array|undefined),
 *     $splice: (Array.<Array>|undefined),
 *     $set: (Object|undefined),
 *     $merge: (Object|undefined),
 *     $apply: (function(Object): Object|undefined)
 * }}
 */
ReactAddons.UpdateSpec;

/**
 * @param {Object|Array} value
 * @param {ReactAddons.UpdateSpec} updateSpec
 * @return {Object|Array}
 */
ReactAddons.prototype.update = function(value, updateSpec) {};

/**
 * @interface
 */
function ReactModule() {}

/**
 * @type {ReactChildren}
 * @const
 */
ReactModule.prototype.Children;

/**
 * @typedef {ReactComponent}
 */
ReactModule.prototype.Component;

/**
 * @type {ReactDOM}
 * @const
 */
ReactModule.prototype.DOM;

/**
 * @type {ReactPropTypes}
 * @const
 */
ReactModule.prototype.PropTypes;

/**
 * @param {boolean} shouldUseTouch
 * @return {void}
 */
ReactModule.prototype.initializeTouchEvents = function(shouldUseTouch) {};

/**
 * "render()" implementations may be undefined (i.e. missing) if it is instead
 * provided by a mixin.
 *
 * @param {{
 *     render: ((function(): (ReactElement|boolean))|undefined),
 *     displayName: (string|undefined),
 *     propTypes: (Object.<ReactPropsChainableTypeChecker>|undefined),
 *     contextTypes: (Object.<ReactPropsChainableTypeChecker>|undefined),
 *     mixins: (Array.<Object>|undefined),
 *     statics: (Object|undefined)
 * }} specification
 * @return {ReactClass}
 */
ReactModule.prototype.createClass = function(specification) {};

/**
 * @param {T} mixin
 * @return {T}
 * @template T
 */
ReactModule.prototype.createMixin = function(mixin) {};

/**
 * @param {ReactClass.<T>|string} type
 * @param {Object=} props
 * @param {...ReactChildrenArgument} children
 * @return {ReactElement.<T>}
 * @template T
 */
ReactModule.prototype.createElement = function(type, props, children) {};

/**
 * @param {ReactElement.<T>} element
 * @param {Object=} props
 * @param {...ReactChildrenArgument} children
 * @return {ReactElement.<T>}
 * @template T
 */
ReactModule.prototype.cloneElement = function(element, props, children) {};

/**
 * @param {ReactClass.<T>|string} type
 * @return {function(Object=, ...ReactChildrenArgument): ReactElement.<T>}
 * @template T
 */
ReactModule.prototype.createFactory = function(type) {};

/**
 * @param {ReactElement|Element} componentOrElement
 * @return {Element}
 */
ReactModule.prototype.findDOMNode = function(componentOrElement) {};

/**
 * @param {ReactElement.<T>} element
 * @param {Element} container
 * @param {function()=} callback
 * @return {T}
 * @template T
 */
ReactModule.prototype.render = function(element, container, callback) {};

/**
 * @param {ReactElement} element
 * @return {string}
 */
ReactModule.prototype.renderToString = function(element) {};

/**
 * @param {ReactElement} element
 * @return {string}
 */
ReactModule.prototype.renderToStaticMarkup = function(element) {};

/**
 * @param {Element} container
 * @return {boolean}
 */
ReactModule.prototype.unmountComponentAtNode = function(container) {};

/**
 * @param {Object} element
 * @return {boolean}
 */
ReactModule.prototype.isValidElement = function(element) {};

/**
 * @type {ReactAddons}
 * @const
 */
ReactModule.prototype.addons;

/**
 * @param {Object} target
 * @param {...Object} sources
 * @return {Object}
 */
ReactModule.prototype.__spread = function(target, sources) {};

/**
 * @param {Object} newContext
 * @param {function():ReactComponent|Array.<ReactComponent>} scopedCallback
 * @return {ReactComponent|Array.<ReactComponent>}
 */
ReactModule.prototype.withContext = function(newContext, scopedCallback) {};
<commit_msg>A few more contex type definitions.<commit_after>/**
 * @fileoverview Type annotations for the React library.
 *
 * Will be automatically included as a source (not externs) file by
 * ReactCompilerPass. The contents of this file should be inert (i.e. interfaces
 * and typedefs only) such that it compiles down to nothing.
 *
 * Based on https://github.com/facebook/flow/blob/master/lib/react.js and
 * https://github.com/borisyankov/DefinitelyTyped/blob/master/react/react.d.ts.
 */

/**
 * @interface
 * @template T
 */
function ReactClass() {}

/**
 * @type {Object.<ReactPropsChainableTypeChecker>|undefined}
 */
ReactClass.prototype.propTypes;

/**
 * @type {Object.<ReactPropsChainableTypeChecker>|undefined}
 */
ReactClass.prototype.contextTypes;

/**
 * @type {Object.<ReactPropsChainableTypeChecker>|undefined}
 */
ReactClass.prototype.childContextTypes;

/**
 * @type {string|undefined}
 */
ReactClass.prototype.displayName;

/**
 * @type {ReactProps|undefined}
 */
ReactClass.prototype.defaultProps;

/**
 * @return {ReactProps}
 */
ReactClass.prototype.getDefaultProps = function() {};

/**
 * @typedef {!Object|{children: (Object|undefined)}}
 */
var ReactProps;

/**
 * @dict
 * @constructor
 */
function ReactRefs() {}

/**
 * @interface
 * @template T
 */
function ReactElement() {}

/**
 * @type {ReactClass.<T>}
 */
ReactElement.prototype.type;

/**
 * @type {ReactProps}
 */
ReactElement.prototype.props;

/**
 * @type {string|number}
 */
ReactElement.prototype.key;

/**
 * @type {string}
 */
ReactElement.prototype.ref;

/**
 * @interface
 * @extends {ReactElement}
 */
function ReactDOMElement() {}

/**
 * @type {string}
 */
ReactDOMElement.prototype.type;

/**
 * @interface
 */
function ReactComponent() {}

/**
 * @type {ReactProps}
 * @const
 */
ReactComponent.prototype.props;

/**
 * @type {Object}
 * @const
 */
ReactComponent.prototype.state;

/**
 * @type {Object}
 * @const
 */
ReactComponent.prototype.context;

/**
 * @type {ReactRefs}
 */
ReactComponent.prototype.refs;

/**
 * @return {Object}
 */
ReactComponent.prototype.getInitialState = function() {};

/**
 * @return {Object}
 */
ReactComponent.prototype.getChildContext = function() {};

/**
 * @param {Object} props
 * @param {function(): void=} callback
 * @return {void}
 */
ReactComponent.prototype.setProps = function(props, callback) {};

/**
 * @param {Object} props
 * @param {function(): void=} callback
 * @return {void}
 */
ReactComponent.prototype.replaceProps = function(props, callback) {};

/**
 * @param {Object} state
 * @param {function(): void=} callback
 * @return {void}
 */
ReactComponent.prototype.setState = function(state, callback) {};

/**
 * @param {Object} state
 * @param {function(): void=} callback
 * @return {void}
 */
ReactComponent.prototype.replaceState = function(state, callback) {};

/**
 * @return {ReactElement|boolean}
 */
ReactComponent.prototype.render = function() {};

/**
 * @param {function(): void=} callback
 * @return {void}
 */
ReactComponent.prototype.forceUpdate = function(callback) {};

/**
 * @return {Element}
 */
ReactComponent.prototype.getDOMNode = function() {};

/**
 * @return {boolean}
 */
ReactComponent.prototype.isMounted = function() {};

// Component lifecycle/delegate methods that may be implemented. Intentionally
// does not include the context parameter that is passed to some methods, since
// it's undocumented. Implementations can still add it (and it will not be
// flagged as an error).

/**
 * @return {void}
 */
ReactComponent.prototype.componentWillMount = function() {};

/**
 * @return {void}
 */
ReactComponent.prototype.componentDidMount = function() {};

/**
 * @param {Object} nextProps
 * @return {void}
 */
ReactComponent.prototype.componentWillReceiveProps = function(nextProps) {};

/**
 * @param {Object} nextProps
 * @param {Object} nextState
 * @return {boolean}
 */
ReactComponent.prototype.shouldComponentUpdate = function(nextProps, nextState) {};

/**
 * @param {Object} nextProps
 * @param {Object} nextState
 * @return {void}
 */
ReactComponent.prototype.componentWillUpdate = function(nextProps, nextState) {};

/**
 * @param {Object} prevProps
 * @param {Object} prevState
 * @return {void}
 */
ReactComponent.prototype.componentDidUpdate = function(prevProps, prevState) {};

/**
 * @return {void}
 */
ReactComponent.prototype.componentWillUnmount = function() {};

/**
 * @typedef {boolean|number|string|ReactElement}
 */
var ReactChild;

/**
 * @typedef {
 *   ReactChild|
 *   Array.<boolean>|Array.<number>|Array.<string>|Array.<ReactElement>|
 *   Object.<boolean>|Object.<number>|Object.<string>|Object.<ReactElement>
 * }
 */
var ReactChildrenArgument;

/**
 * @interface
 */
function ReactChildren() {};

/**
 * @param {Object|undefined} children
 * @param {function(*, number)} func
 * @param {*=} context
 * @return {Object|undefined}
 */
ReactChildren.prototype.map = function(children, func, context) {};

/**
 * @param {Object|undefined} children
 * @param {function(*, number)} func
 * @param {*=} context
 */
ReactChildren.prototype.forEach = function(children, func, context) {};

/**
 * @param {Object|undefined} children
 * @return {number}
 */
ReactChildren.prototype.count = function(children) {};

/**
 * @param {Object|undefined} children
 * @return {ReactChild}
 */
ReactChildren.prototype.only = function(children) {};

/**
 * Factory functions for each HTML and SVG tag are generated by
 * ReactCompilerPass.
 *
 * @interface
 */
function ReactDOM() {};

/**
 * Parameters are: props, propName, componentName, location.
 * @typedef {function(Object, string, string, string): Error}
 */
var ReactPropsChainableTypeChecker = function() {};

/**
 * @interface
 */
function ReactPropTypes() {};
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.array;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.array.isRequired;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.bool;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.bool.isRequired;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.func;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.func.isRequired;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.number;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.number.isRequired;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.object;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.object.isRequired;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.string;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.string.isRequired;

/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.any;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.any.isRequired;
/**
 * @param {ReactPropsChainableTypeChecker} typeChecker
 * @return {ReactPropsChainableTypeChecker}
 */
ReactPropTypes.prototype.arrayOf = function(typeChecker) {};
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.element;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.element.isRequired;
/**
 * @param {Function} expectedClass
 * @return {ReactPropsChainableTypeChecker}
 */
ReactPropTypes.prototype.instanceOf = function(expectedClass) {};
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.node;
/** @type {ReactPropsChainableTypeChecker} */ ReactPropTypes.prototype.node.isRequired;
/**
 * @param {ReactPropsChainableTypeChecker} typeChecker
 * @return {ReactPropsChainableTypeChecker}
 */
ReactPropTypes.prototype.objectOf = function(typeChecker) {};
/**
 * @param {Array} expectedValues
 * @return {ReactPropsChainableTypeChecker}
 */
ReactPropTypes.prototype.oneOf = function(expectedValues) {};
/**
 * @param {Array.<ReactPropsChainableTypeChecker>} arrayOfTypeCheckers
 * @return {ReactPropsChainableTypeChecker}
 */
ReactPropTypes.prototype.oneOfType = function(arrayOfTypeCheckers) {};
/**
 * @param {Object.<ReactPropsChainableTypeChecker>} shapeTypes
 * @return {ReactPropsChainableTypeChecker}
 */
ReactPropTypes.prototype.shape = function(shapeTypes) {};

/**
 * @interface
 * @extends {ReactComponent}
 */
function ReactCSSTransitionGroup() {}

/**
 * @interface
 * @extends {ReactComponent}
 */
function ReactTransitionGroup() {}

/**
 * @interface
 */
function ReactAddonsPerf() {}

ReactAddonsPerf.prototype.start = function() {};

ReactAddonsPerf.prototype.stop = function() {};

/**
 * @return {Array.<ReactAddonsPerf.Measurement>}
 */
ReactAddonsPerf.prototype.getLastMeasurements = function() {};

/**
 * @param {ReactAddonsPerf.Measurement=} measurements
 */
ReactAddonsPerf.prototype.printExclusive = function(measurements) {};

/**
 * @param {ReactAddonsPerf.Measurement=} measurements
 */
ReactAddonsPerf.prototype.printInclusive = function(measurements) {};

/**
 * @param {ReactAddonsPerf.Measurement=} measurements
 */
ReactAddonsPerf.prototype.printWasted = function(measurements) {};

/**
 * @typedef {{
 *     exclusive: !Object.<string, number>,
 *     inclusive: !Object.<string, number>,
 *     render: !Object.<string, number>,
 *     counts: !Object.<string, number>,
 *     writes: !Object.<string, {type: string, time: number, args: Array}>,
 *     displayNames: !Object.<string, {current: string, owner: string}>,
 *     totalTime: number
 * }}
 */
ReactAddonsPerf.Measurement;

/**
 * @interface
 */
function ReactAddons() {}

/**
 * @type {ReactClass.<ReactCSSTransitionGroup>}
 */
ReactAddons.prototype.CSSTransitionGroup;

/**
 * @type {ReactClass.<ReactTransitionGroup>}
 */
ReactAddons.prototype.TransitionGroup;

/**
 * @type {ReactAddonsPerf}
 */
ReactAddons.prototype.Perf;

/**
 * @type {Object}
 */
ReactAddons.prototype.PureRenderMixin;

/**
 * @param {Function} callback
 * @param {*=} a
 * @param {*=} b
 * @param {*=} c
 * @param {*=} d
 */
ReactAddons.prototype.batchedUpdates = function(callback, a, b, c, d) {};

/**
 * @param {Object|string} objectOrClassName
 * @param {...string} classNames
 * @return {string}
 * @deprecated
 */
ReactAddons.prototype.classSet = function(objectOrClassName, classNames) {};

/**
 * @param {ReactElement.<T>} element
 * @param {Object=} extraProps
 * @return {ReactElement.<T>}
 * @template T
 */
ReactAddons.prototype.cloneWithProps = function(element, extraProps) {};

/**
 * @param {Object.<string, ReactElement>} object
 * @return {*}
 */
ReactAddons.prototype.createFragment = function(object) {};

/**
 * @typedef {{
 *     $push: (Array|undefined),
 *     $unshift: (Array|undefined),
 *     $splice: (Array.<Array>|undefined),
 *     $set: (Object|undefined),
 *     $merge: (Object|undefined),
 *     $apply: (function(Object): Object|undefined)
 * }}
 */
ReactAddons.UpdateSpec;

/**
 * @param {Object|Array} value
 * @param {ReactAddons.UpdateSpec} updateSpec
 * @return {Object|Array}
 */
ReactAddons.prototype.update = function(value, updateSpec) {};

/**
 * @interface
 */
function ReactModule() {}

/**
 * @type {ReactChildren}
 * @const
 */
ReactModule.prototype.Children;

/**
 * @typedef {ReactComponent}
 */
ReactModule.prototype.Component;

/**
 * @type {ReactDOM}
 * @const
 */
ReactModule.prototype.DOM;

/**
 * @type {ReactPropTypes}
 * @const
 */
ReactModule.prototype.PropTypes;

/**
 * @param {boolean} shouldUseTouch
 * @return {void}
 */
ReactModule.prototype.initializeTouchEvents = function(shouldUseTouch) {};

/**
 * "render()" implementations may be undefined (i.e. missing) if it is instead
 * provided by a mixin.
 *
 * @param {{
 *     render: ((function(): (ReactElement|boolean))|undefined),
 *     displayName: (string|undefined),
 *     propTypes: (Object.<ReactPropsChainableTypeChecker>|undefined),
 *     contextTypes: (Object.<ReactPropsChainableTypeChecker>|undefined),
 *     childContextTypes: (Object.<ReactPropsChainableTypeChecker>|undefined),
 *     mixins: (Array.<Object>|undefined),
 *     statics: (Object|undefined)
 * }} specification
 * @return {ReactClass}
 */
ReactModule.prototype.createClass = function(specification) {};

/**
 * @param {T} mixin
 * @return {T}
 * @template T
 */
ReactModule.prototype.createMixin = function(mixin) {};

/**
 * @param {ReactClass.<T>|string} type
 * @param {Object=} props
 * @param {...ReactChildrenArgument} children
 * @return {ReactElement.<T>}
 * @template T
 */
ReactModule.prototype.createElement = function(type, props, children) {};

/**
 * @param {ReactElement.<T>} element
 * @param {Object=} props
 * @param {...ReactChildrenArgument} children
 * @return {ReactElement.<T>}
 * @template T
 */
ReactModule.prototype.cloneElement = function(element, props, children) {};

/**
 * @param {ReactClass.<T>|string} type
 * @return {function(Object=, ...ReactChildrenArgument): ReactElement.<T>}
 * @template T
 */
ReactModule.prototype.createFactory = function(type) {};

/**
 * @param {ReactElement|Element} componentOrElement
 * @return {Element}
 */
ReactModule.prototype.findDOMNode = function(componentOrElement) {};

/**
 * @param {ReactElement.<T>} element
 * @param {Element} container
 * @param {function()=} callback
 * @return {T}
 * @template T
 */
ReactModule.prototype.render = function(element, container, callback) {};

/**
 * @param {ReactElement} element
 * @return {string}
 */
ReactModule.prototype.renderToString = function(element) {};

/**
 * @param {ReactElement} element
 * @return {string}
 */
ReactModule.prototype.renderToStaticMarkup = function(element) {};

/**
 * @param {Element} container
 * @return {boolean}
 */
ReactModule.prototype.unmountComponentAtNode = function(container) {};

/**
 * @param {Object} element
 * @return {boolean}
 */
ReactModule.prototype.isValidElement = function(element) {};

/**
 * @type {ReactAddons}
 * @const
 */
ReactModule.prototype.addons;

/**
 * @param {Object} target
 * @param {...Object} sources
 * @return {Object}
 */
ReactModule.prototype.__spread = function(target, sources) {};

/**
 * @param {Object} newContext
 * @param {function():ReactComponent|Array.<ReactComponent>} scopedCallback
 * @return {ReactComponent|Array.<ReactComponent>}
 */
ReactModule.prototype.withContext = function(newContext, scopedCallback) {};
<|endoftext|>


<commit_before>CATARSE.UsersShowView = Backbone.View.extend({

  initialize: function() {
    _.bindAll(this, "index", "backs", "projects", "credits", "comments", "request_refund", 'settings', 'closeCreditsModal')
    CATARSE.router.route("", "index", this.index)
    CATARSE.router.route("backs", "backs", this.backs)
    CATARSE.router.route("projects", "projects", this.projects)
    CATARSE.router.route("credits", "credits", this.credits)
    CATARSE.router.route("comments", "comments", this.comments)
    CATARSE.router.route("settings", "settings", this.settings)
    CATARSE.router.route("request_refund/:back_id", "request_refund", this.request_refund)
    this.render()
  },

  events: {
    'click #creditsModal .modal-footer a':'closeCreditsModal',
  },

  closeCreditsModal: function(e) {
    e.preventDefault();
    this.$('#creditsModal').modal('hide');
  },

  user: new CATARSE.User($('#user_profile').data("user")),

  BackView: CATARSE.ModelView.extend({
    template: _.template(this.$('#user_back_template').html())
  }),

  BacksView: CATARSE.PaginatedView.extend({
    template: _.template(this.$('#user_backs_template').html()),
    emptyTemplate: _.template(this.$('#empty_user_back_template').html()),
    afterUpdate: function() {
      FB.XFBML.parse()
    }
  }),

  ProjectView: CATARSE.ModelView.extend({
    template: _.template(this.$('#user_project_template').html())
  }),

  ProjectsView: CATARSE.PaginatedView.extend({
    template: _.template(this.$('#user_projects_template').html()),
    emptyTemplate: _.template(this.$('#empty_user_project_template').html()),
    afterUpdate: function() {
      FB.XFBML.parse()
    }
  }),

  index: function() {
    CATARSE.router.navigate("backs", {trigger: true})
  },

  backs: function() {
    if(typeof(this.backsView) != 'undefined')
      this.backsView.destroy()
    this.selectItem("backed_projects")
    this.backsView = new this.BacksView({
      modelView: this.BackView,
      collection: this.user.backs,
      loading: this.$("#loading"),
      el: this.$("#user_backed_projects")
    })
  },

  projects: function() {
    if(typeof(this.projectsView) != 'undefined')
      this.projectsView.destroy()
    this.selectItem("created_projects")
    this.projectsView = new this.ProjectsView({
      modelView: this.ProjectView,
      collection: this.user.projects,
      loading: this.$("#loading"),
      el: this.$("#user_created_projects")
    })
  },

  credits: function() {
    this.selectItem("credits")
    this.$("#loading").children().hide();
  },

  settings: function() {
    this.selectItem("settings")
    this.$("#loading").children().hide();
  },

  comments: function() {
    this.selectItem("comments")
  },

  request_refund: function(back_id) {
    url = '/users/'+this.user.id+'/request_refund/'+back_id;
    $.post(url, function(result) {
      //alert(result['status']);
      //notificationHtml = '
';
        //notificationHtml += '
';
        //notificationHtml += '×';
        //notificationHtml += result['status'];
        //notificationHtml += '
';
      //notificationHtml +='
';
      $('#creditsModal .modal-body').html(result['status']);
      $('#creditsModal').modal({
        backdrop: true,
      })

      //console.log($('.table_title').append(notificationHtml));

      $("tr#back_"+back_id+" td.status").text(result['status'])
    })
  },

  selectItem: function(item) {
    this.$("#user_profile_content .content").hide()
    this.$("#user_profile_content #user_" + item + ".content").show()
    var link = this.$("#user_profile_menu #" + item + "_link")
    link.parent().children().removeClass('selected')
    link.addClass('selected')
  }

})

$('input,textarea').live('keypress', function(e){
  if (e.which == '13' && $("button:contains('OK')").attr('disabled')) {
    e.preventDefault();
  }
})

$('#user_feed input').live('keyup', function(){
  var value = $(this).val()
  var re = /^[a-z0-9\._-]+@([a-z0-9][a-z0-9-_]*[a-z0-9-_]\.)+([a-z-_]+\.)?([a-z-_]+)$/
  if(value.match(re)){
    $(this).addClass("ok").removeClass("error")
    $("button:contains('OK')").attr('disabled', false)
  } else {
    $(this).addClass("error").removeClass("ok")
    $("button:contains('OK')").attr('disabled', true)
  }
})

$('#content_header textarea').live('keyup', function(){
  var value = $(this).val()
  if(value.length <= 140){
    $(this).addClass("ok").removeClass("error")
    $("button:contains('OK')").attr('disabled', false)
  } else {
    $(this).addClass("error").removeClass("ok")
    $("button:contains('OK')").attr('disabled', true)
  }
})

$('input[type=checkbox]').click(function(){
  $.post('/users/update_attribute_on_the_spot', {
    id: 'user__' + $(this).attr('id') + '__' + $('#id').val(),
    value: ($(this).is(':checked') ? 1 : null)
  })
})
<commit_msg>refactored the 'if(typeof(this.projectsView) != 'undefined')'<commit_after>CATARSE.UsersShowView = Backbone.View.extend({

  initialize: function() {
    _.bindAll(this, "index", "backs", "projects", "credits", "comments", "request_refund", 'settings', 'closeCreditsModal')
    CATARSE.router.route("", "index", this.index)
    CATARSE.router.route("backs", "backs", this.backs)
    CATARSE.router.route("projects", "projects", this.projects)
    CATARSE.router.route("credits", "credits", this.credits)
    CATARSE.router.route("comments", "comments", this.comments)
    CATARSE.router.route("settings", "settings", this.settings)
    CATARSE.router.route("request_refund/:back_id", "request_refund", this.request_refund)
    this.render()
  },

  events: {
    'click #creditsModal .modal-footer a':'closeCreditsModal',
  },

  closeCreditsModal: function(e) {
    e.preventDefault();
    this.$('#creditsModal').modal('hide');
  },

  user: new CATARSE.User($('#user_profile').data("user")),

  BackView: CATARSE.ModelView.extend({
    template: _.template(this.$('#user_back_template').html())
  }),

  BacksView: CATARSE.PaginatedView.extend({
    template: _.template(this.$('#user_backs_template').html()),
    emptyTemplate: _.template(this.$('#empty_user_back_template').html()),
    afterUpdate: function() {
      FB.XFBML.parse()
    }
  }),

  ProjectView: CATARSE.ModelView.extend({
    template: _.template(this.$('#user_project_template').html())
  }),

  ProjectsView: CATARSE.PaginatedView.extend({
    template: _.template(this.$('#user_projects_template').html()),
    emptyTemplate: _.template(this.$('#empty_user_project_template').html()),
    afterUpdate: function() {
      FB.XFBML.parse()
    }
  }),

  index: function() {
    CATARSE.router.navigate("backs", {trigger: true})
  },

  backs: function() {
    if(this.backsView)
      this.backsView.destroy()
    this.selectItem("backed_projects")
    this.backsView = new this.BacksView({
      modelView: this.BackView,
      collection: this.user.backs,
      loading: this.$("#loading"),
      el: this.$("#user_backed_projects")
    })
  },

  projects: function() {
    if(this.projectsView)
      this.projectsView.destroy()
    this.selectItem("created_projects")
    this.projectsView = new this.ProjectsView({
      modelView: this.ProjectView,
      collection: this.user.projects,
      loading: this.$("#loading"),
      el: this.$("#user_created_projects")
    })
  },

  credits: function() {
    this.selectItem("credits")
    this.$("#loading").children().hide();
  },

  settings: function() {
    this.selectItem("settings")
    this.$("#loading").children().hide();
  },

  comments: function() {
    this.selectItem("comments")
  },

  request_refund: function(back_id) {
    url = '/users/'+this.user.id+'/request_refund/'+back_id;
    $.post(url, function(result) {
      //alert(result['status']);
      //notificationHtml = '
';
        //notificationHtml += '
';
        //notificationHtml += '×';
        //notificationHtml += result['status'];
        //notificationHtml += '
';
      //notificationHtml +='
';
      $('#creditsModal .modal-body').html(result['status']);
      $('#creditsModal').modal({
        backdrop: true,
      })

      //console.log($('.table_title').append(notificationHtml));

      $("tr#back_"+back_id+" td.status").text(result['status'])
    })
  },

  selectItem: function(item) {
    this.$("#user_profile_content .content").hide()
    this.$("#user_profile_content #user_" + item + ".content").show()
    var link = this.$("#user_profile_menu #" + item + "_link")
    link.parent().children().removeClass('selected')
    link.addClass('selected')
  }

})

$('input,textarea').live('keypress', function(e){
  if (e.which == '13' && $("button:contains('OK')").attr('disabled')) {
    e.preventDefault();
  }
})

$('#user_feed input').live('keyup', function(){
  var value = $(this).val()
  var re = /^[a-z0-9\._-]+@([a-z0-9][a-z0-9-_]*[a-z0-9-_]\.)+([a-z-_]+\.)?([a-z-_]+)$/
  if(value.match(re)){
    $(this).addClass("ok").removeClass("error")
    $("button:contains('OK')").attr('disabled', false)
  } else {
    $(this).addClass("error").removeClass("ok")
    $("button:contains('OK')").attr('disabled', true)
  }
})

$('#content_header textarea').live('keyup', function(){
  var value = $(this).val()
  if(value.length <= 140){
    $(this).addClass("ok").removeClass("error")
    $("button:contains('OK')").attr('disabled', false)
  } else {
    $(this).addClass("error").removeClass("ok")
    $("button:contains('OK')").attr('disabled', true)
  }
})

$('input[type=checkbox]').click(function(){
  $.post('/users/update_attribute_on_the_spot', {
    id: 'user__' + $(this).attr('id') + '__' + $('#id').val(),
    value: ($(this).is(':checked') ? 1 : null)
  })
})
<|endoftext|>


<commit_before>//
// Emapic panel
//

$('html body').append("\n" +
"
\n"+
"

" +
"

\n" +
"

\n" +
"

\n" +
"
");

var emapic = emapic || {};

(function(emapic) {

    var titlesidebarPanel = $('#titlesidebarPanel'),
    closesidebarPanel = $('#closesidebarPanel'),
    navContainer = $('#navContainer'),
    sidebarPanel,
    closesidebarPanelHtml = "<button type='button' title='" + emapic.utils.getI18n('js_close', 'Cerrar') + "' onclick='emapic.sidebarPanelClose();'></button>",
    navHtml = "<button id='FirstButton' title='" + emapic.utils.getI18n('js_go_first', 'Ir al primero') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToFirst();'></button>\n" +
    "<button id='PrevButton' title='" + emapic.utils.getI18n('js_go_previous', 'Ir al anterior') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToPrevious();'></button>\n" +
    "<input type='text' id='CurrentFeatureNumber' maxlength='7'></input>/\n" +
    "<button id='NextButton' title='" + emapic.utils.getI18n('js_go_next', 'Ir al siguiente') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToNext();'></button>\n" +
    "<button id='LastButton' title='" + emapic.utils.getI18n('js_go_last', 'Ir al último') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToLast();'></button>\n",
    currentFeature = null,
    oldIcon = null,
    currentMarker = null,
    nrLayers,
    selectedLayerNr,
    layers;

    emapic.modules = emapic.modules || {};
    emapic.modules.panel = emapic.modules.panel || {};

    emapic.disableIndivLayerExclusiveComponents = emapic.utils.overrideFunction(emapic.disableIndivLayerExclusiveComponents, null, function() {
        oldIcon = null;
        currentMarker = null;
        if (currentFeature !== null) {
            emapic.sidebarPanelClose();
        }
    });

    emapic.enableIndivLayerExclusiveComponents = emapic.utils.overrideFunction(emapic.enableIndivLayerExclusiveComponents, null, function() {
        oldIcon = null;
        currentMarker = null;
        if (currentFeature !== null) {
            emapic.sidebarPanelClose();
        }
    });

    emapic.getCurrentMarkerToShow = function() {
        return currentMarker;
    };

    emapic.initializeMap = emapic.utils.overrideFunction(emapic.initializeMap, null, function() {
        sidebarPanel = L.control.sidebar('sidebarPanel', {
            position: 'topright',
            autoPan: false,
            closeButton: false
        });
        bodysidebarPanel();
        emapic.map.addControl(sidebarPanel);
        $('#CurrentFeatureNumber').keydown(featureNumberKeydown);
    });

    function bodysidebarPanel() {
        navContainer.html(navHtml);
        closesidebarPanel.html(closesidebarPanelHtml);
    }

    emapic.sidebarPanelClose = emapic.utils.overrideFunction(emapic.sidebarPanelClose, null, function() {
        sidebarPanel.hide();
        emapic.modules.panel.getColorPanelUnselect();
        currentFeature = null;
    });

    emapic.modules.panel.getPanelTitleHTML = function(properties) {
        return "
" + emapic.utils.getI18n('js_see_answers', 'Ver respuestas') + "
\n";
    };

    emapic.modules.panel.updateData = function(number) {
        currentFeature = number;
        var currentFeatureInput = $('#CurrentFeatureNumber');
        $('#TotalFeatures').text(nrLayers);
        currentFeatureInput.attr("size", (nrLayers.toString().length < 3) ? 3 : nrLayers.toString().length);
        currentFeatureInput.attr("maxlength", nrLayers.toString().length);
        currentFeatureInput.val(currentFeature + 1);
        $('#PrevButton').prop('disabled', currentFeature === 0);
        $('#NextButton').prop('disabled', currentFeature === (nrLayers - 1));
        var title = emapic.modules.panel.getPanelTitleHTML(layers[number].feature.properties);
        if (title !== null) {
            titlesidebarPanel.html(title);
            titlesidebarPanel.show();
        } else {
            titlesidebarPanel.hide();
        }
        $("#indivData").html(emapic.getPopupHtml(layers[number].feature.properties));
        emapic.showMarker(layers[number]);
    };

    emapic.modules.panel.getColorPanelSelect = function(number) {
        oldIcon = layers[number].options.icon;
        layers[number].setIcon(emapic.modules.panel.getSelectedIcon(layers[number].feature.properties));
    };

    emapic.modules.panel.getColorPanelUnselect = function() {
        if (currentMarker !== null && oldIcon !== null) {
            currentMarker.setIcon(oldIcon);
        }
        currentMarker = null;
        oldIcon = null;
    };

    emapic.modules.panel.getSelectedIcon = function(properties) {
        return L.divIcon({
            className: 'svg-marker',
            html: emapic.utils.getGlyphiconMarkerIconHtml(null, emapic.getIconColor(properties), 0.5, 7),
            iconAnchor: [16.5, 45]
        });
    };

    emapic.modules.panel.goToRegister = function(number) {
        if (number !== null && currentFeature !== number) {
            emapic.modules.panel.getColorPanelUnselect();
            currentMarker = layers[number];
            emapic.modules.panel.getColorPanelSelect(number);
            emapic.modules.panel.updateData(number);
        }
    };

    emapic.modules.panel.goToFirst =  function () {
        emapic.modules.panel.goToRegister(0);
    };

    emapic.modules.panel.goToLast = function () {
        emapic.modules.panel.goToRegister(layers.length - 1);
    };

    emapic.modules.panel.goToPrevious = function () {
        emapic.modules.panel.goToRegister(currentFeature - 1);
    };

    emapic.modules.panel.goToNext = function () {
        emapic.modules.panel.goToRegister(currentFeature + 1);
    };

    emapic.modules.panel.getDisplayedFeature = function() {
        return currentFeature !== null ? layers[currentFeature].feature : null;
    };

    emapic.modules.panel.getDisplayedFeatureLayer = function() {
        return currentFeature !== null ? layers[currentFeature] : null;
    };

    emapic.indivVotesLayerOnEachFeature = emapic.utils.overrideFunction(emapic.indivVotesLayerOnEachFeature, null, function(data) {
        data.layer.unbindPopup();
        data.layer.on('click', function(e) {
            layers = emapic.getIndivVotesLayerLeafletLayers();
            nrLayers = layers.length;
            selectedLayerNr = null;
            for (var i = 0; i < nrLayers; i++) {
                if (layers[i].feature === data.feature) {
                    selectedLayerNr = i;
                    break;
                }
            }
            if (selectedLayerNr === null) {
                console.error("Can't find layer for panel.");
                return;
            }
            if (currentFeature === null) {
                emapic.sidebarPanelClose();
            }
            emapic.modules.panel.goToRegister(selectedLayerNr);
            sidebarPanel.show();
        });
    });

    function featureNumberKeydown(e) {
        if (emapic.utils.filterKeydownOnlyDigits(e)) {
            var key = e.keyCode || e.which;
            if (key === 13) {
                var valueCurrentNumber = parseInt($("#CurrentFeatureNumber").val(), 10);
                if (valueCurrentNumber <= 0) {
                    valueCurrentNumber = 1;
                } else if (valueCurrentNumber > nrLayers) {
                    valueCurrentNumber = nrLayers;
                }
                emapic.modules.panel.goToRegister(valueCurrentNumber - 1);
            }
        }
    }

}(emapic));
<commit_msg>Update sidebar panel creation process<commit_after>//
// Emapic panel
//

var emapic = emapic || {};

(function(emapic) {

    var sidebarHtml = "\n" +
            "
\n"+
            "

" +
            "

\n" +
            "

\n" +
            "

\n" +
            "
",
        titlesidebarPanel,
        closesidebarPanel,
        navContainer,
        sidebarPanel,
        closesidebarPanelHtml = "<button type='button' title='" + emapic.utils.getI18n('js_close', 'Cerrar') + "' onclick='emapic.sidebarPanelClose();'></button>",
        navHtml = "<button id='FirstButton' title='" + emapic.utils.getI18n('js_go_first', 'Ir al primero') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToFirst();'></button>\n" +
            "<button id='PrevButton' title='" + emapic.utils.getI18n('js_go_previous', 'Ir al anterior') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToPrevious();'></button>\n" +
            "<input type='text' id='CurrentFeatureNumber' maxlength='7'></input>/\n" +
            "<button id='NextButton' title='" + emapic.utils.getI18n('js_go_next', 'Ir al siguiente') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToNext();'></button>\n" +
            "<button id='LastButton' title='" + emapic.utils.getI18n('js_go_last', 'Ir al último') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToLast();'></button>\n",
        currentFeature = null,
        oldIcon = null,
        currentMarker = null,
        nrLayers,
        selectedLayerNr,
        layers;

    emapic.modules = emapic.modules || {};
    emapic.modules.panel = emapic.modules.panel || {};

    emapic.disableIndivLayerExclusiveComponents = emapic.utils.overrideFunction(emapic.disableIndivLayerExclusiveComponents, null, function() {
        oldIcon = null;
        currentMarker = null;
        if (currentFeature !== null) {
            emapic.sidebarPanelClose();
        }
    });

    emapic.enableIndivLayerExclusiveComponents = emapic.utils.overrideFunction(emapic.enableIndivLayerExclusiveComponents, null, function() {
        oldIcon = null;
        currentMarker = null;
        if (currentFeature !== null) {
            emapic.sidebarPanelClose();
        }
    });

    emapic.getCurrentMarkerToShow = function() {
        return currentMarker;
    };

    emapic.initializeMap = emapic.utils.overrideFunction(emapic.initializeMap, null, function() {
        $('html body').append(sidebarHtml);
        sidebarPanel = L.control.sidebar('sidebarPanel', {
            position: 'topright',
            autoPan: false,
            closeButton: false
        });
        emapic.map.addControl(sidebarPanel);
        titlesidebarPanel = $('#titlesidebarPanel');
        closesidebarPanel = $('#closesidebarPanel');
        navContainer = $('#navContainer');
        bodysidebarPanel();
        $('#CurrentFeatureNumber').keydown(featureNumberKeydown);
    });

    function bodysidebarPanel() {
        navContainer.html(navHtml);
        closesidebarPanel.html(closesidebarPanelHtml);
    }

    emapic.sidebarPanelClose = emapic.utils.overrideFunction(emapic.sidebarPanelClose, null, function() {
        sidebarPanel.hide();
        emapic.modules.panel.getColorPanelUnselect();
        currentFeature = null;
    });

    emapic.modules.panel.getPanelTitleHTML = function(properties) {
        return "
" + emapic.utils.getI18n('js_see_answers', 'Ver respuestas') + "
\n";
    };

    emapic.modules.panel.updateData = function(number) {
        currentFeature = number;
        var currentFeatureInput = $('#CurrentFeatureNumber');
        $('#TotalFeatures').text(nrLayers);
        currentFeatureInput.attr("size", (nrLayers.toString().length < 3) ? 3 : nrLayers.toString().length);
        currentFeatureInput.attr("maxlength", nrLayers.toString().length);
        currentFeatureInput.val(currentFeature + 1);
        $('#PrevButton').prop('disabled', currentFeature === 0);
        $('#NextButton').prop('disabled', currentFeature === (nrLayers - 1));
        var title = emapic.modules.panel.getPanelTitleHTML(layers[number].feature.properties);
        if (title !== null) {
            titlesidebarPanel.html(title);
            titlesidebarPanel.show();
        } else {
            titlesidebarPanel.hide();
        }
        $("#indivData").html(emapic.getPopupHtml(layers[number].feature.properties));
        emapic.showMarker(layers[number]);
    };

    emapic.modules.panel.getColorPanelSelect = function(number) {
        oldIcon = layers[number].options.icon;
        layers[number].setIcon(emapic.modules.panel.getSelectedIcon(layers[number].feature.properties));
    };

    emapic.modules.panel.getColorPanelUnselect = function() {
        if (currentMarker !== null && oldIcon !== null) {
            currentMarker.setIcon(oldIcon);
        }
        currentMarker = null;
        oldIcon = null;
    };

    emapic.modules.panel.getSelectedIcon = function(properties) {
        return L.divIcon({
            className: 'svg-marker',
            html: emapic.utils.getGlyphiconMarkerIconHtml(null, emapic.getIconColor(properties), 0.5, 7),
            iconAnchor: [16.5, 45]
        });
    };

    emapic.modules.panel.goToRegister = function(number) {
        if (number !== null && currentFeature !== number) {
            emapic.modules.panel.getColorPanelUnselect();
            currentMarker = layers[number];
            emapic.modules.panel.getColorPanelSelect(number);
            emapic.modules.panel.updateData(number);
        }
    };

    emapic.modules.panel.goToFirst =  function () {
        emapic.modules.panel.goToRegister(0);
    };

    emapic.modules.panel.goToLast = function () {
        emapic.modules.panel.goToRegister(layers.length - 1);
    };

    emapic.modules.panel.goToPrevious = function () {
        emapic.modules.panel.goToRegister(currentFeature - 1);
    };

    emapic.modules.panel.goToNext = function () {
        emapic.modules.panel.goToRegister(currentFeature + 1);
    };

    emapic.modules.panel.getDisplayedFeature = function() {
        return currentFeature !== null ? layers[currentFeature].feature : null;
    };

    emapic.modules.panel.getDisplayedFeatureLayer = function() {
        return currentFeature !== null ? layers[currentFeature] : null;
    };

    emapic.indivVotesLayerOnEachFeature = emapic.utils.overrideFunction(emapic.indivVotesLayerOnEachFeature, null, function(data) {
        data.layer.unbindPopup();
        data.layer.on('click', function(e) {
            layers = emapic.getIndivVotesLayerLeafletLayers();
            nrLayers = layers.length;
            selectedLayerNr = null;
            for (var i = 0; i < nrLayers; i++) {
                if (layers[i].feature === data.feature) {
                    selectedLayerNr = i;
                    break;
                }
            }
            if (selectedLayerNr === null) {
                console.error("Can't find layer for panel.");
                return;
            }
            if (currentFeature === null) {
                emapic.sidebarPanelClose();
            }
            emapic.modules.panel.goToRegister(selectedLayerNr);
            sidebarPanel.show();
        });
    });

    function featureNumberKeydown(e) {
        if (emapic.utils.filterKeydownOnlyDigits(e)) {
            var key = e.keyCode || e.which;
            if (key === 13) {
                var valueCurrentNumber = parseInt($("#CurrentFeatureNumber").val(), 10);
                if (valueCurrentNumber <= 0) {
                    valueCurrentNumber = 1;
                } else if (valueCurrentNumber > nrLayers) {
                    valueCurrentNumber = nrLayers;
                }
                emapic.modules.panel.goToRegister(valueCurrentNumber - 1);
            }
        }
    }

}(emapic));
<|endoftext|>


<commit_before>// The search controller is responsible for managing document/metadata search.
dc.ui.SearchBox = dc.View.extend({

  PAGE_MATCHER        : (/\/p(\d+)$/),

  DOCUMENTS_URL : '/search/documents.json',

  // Error messages to display when your search returns no results.
  NO_RESULTS : {
    project : "This project does not contain any documents.",
    account : "This account has not uploaded any documents.",
    search  : "Your search did not match any documents."
  },

  id            : 'search',
  fragment      : null,

  callbacks : {
    '#search_box.keydown':  'maybeSearch',
    '#search_box.search':   'searchEvent',
    '#search_type.click':   '_setScope',
    '.cancel_search.click': 'cancelSearch'
  },

  // Creating a new SearchBox registers #search page fragments.
  constructor : function(options) {
    this.base(options);
    this.outstandingSearch = false;
    _.bindAll(this, '_loadSearchResults', '_loadFacetResults', 'searchByHash', 'showHelp', 'loadDefault');
    dc.history.register(/^#search\//, this.searchByHash);
    dc.history.register(/^#help$/, this.showHelp);
  },

  render : function() {
    $(this.el).append(JST.search_box({}));
    this.box      = $('#search_box', this.el);
    this.menu     = $('#search_type', this.el);
    this.titleBox = $('#title_box', this.el);
    $(document.body).setMode('no', 'search');
    this.setCallbacks();
    $('#cloud_edge').click(this.showHelp);
    (this._helpTab = $('#help_tab')).click(this.showHelp);
    (this._documentsTab = $('#documents_tab')).click(this.loadDefault);
    return this;
  },

  // Shortcut to the searchbox's value.
  value : function(query) {
    return this.box.val(query);
  },

  urlFragment : function() {
    return this.fragment + (this.page ? '/p' + this.page : '');
  },

  // Load the default starting-point search.
  loadDefault : function() {
    if (!Documents.empty()) return this.showDocuments();
    if (this.value()) {
      this.search(this.value());
    } else if (dc.app.documentCount) {
      Accounts.current().openDocuments();
    } else if (Projects.first()) {
      Projects.first().open();
    }
  },

  showDocuments : function() {
    $(document.body).setMode('active', 'search');
    this._helpTab.removeClass('active');
    this._documentsTab.addClass('active');
    this.entitle(this.value());
    dc.history.save(this.urlFragment());
  },

  showHelp : function() {
    $(document.body).setMode('no', 'search');
    this._documentsTab.removeClass('active');
    this._helpTab.addClass('active');
    dc.history.save('help');
  },

  // Start a search for a query string, updating the page URL.
  search : function(query, pageNumber) {
    dc.ui.Project.highlight(query);
    this.page = pageNumber <= 1 ? null : pageNumber;
    this.value(query);
    this.fragment = 'search/' + encodeURIComponent(query);
    this.showDocuments();
    Documents.refresh();
    this.outstandingSearch = true;
    dc.ui.spinner.show('searching');
    dc.app.paginator.hide();
    var params = {q : query, include_facets : true};
    if (this.page) params.page = this.page;
    $.get(this.DOCUMENTS_URL, params, this._loadSearchResults, 'json');
  },

  loadFacets : function(facet) {
    dc.ui.spinner.show('searching');
    this.outstandingSearch = true;
    var params = {q : this.value(), include_facets : true, facet : facet};
    $.get(this.DOCUMENTS_URL, params, this._loadFacetResults, 'json');
  },

  // Ensure a given prefix for the search, used to scope searches down to
  // a specific qualifier.
  scopeSearch : function(prefix) {
    var search = this.value().replace(/^(organization|documents):\s+\S+ /, '');
    this.value(prefix + search);
  },

  // When searching by the URL's hash value, we need to unescape first.
  searchByHash : function(hash) {
    var page = null, connection = null;
    var pageMatch = hash.match(this.PAGE_MATCHER);
    if (pageMatch) {
      var page = pageMatch[1];
      hash = hash.replace(this.PAGE_MATCHER, '');
    }
    this.search(decodeURIComponent(hash), page);
  },

  // Add a query fragment to the search and search again, if it's not already
  // present in the current search.
  addToSearch : function(fragment) {
    if (this.value().toLowerCase().match(fragment.toLowerCase())) return;
    this.value(this.value() + " " + fragment);
    this.search(this.value());
  },

  // Remove a query fragment from the search and search again, only if it's
  // present in the current search.
  removeFromSearch : function(regex) {
    if (!this.value().match(regex)) return;
    var next = this.value().replace(regex, '');
    if (next == this.value()) return false;
    this.value(next);
    this.search(next);
    return true;
  },

  // Callback fired on key press in the search box. We search when they hit
  // return.
  maybeSearch : function(e) {
    var query = this.value();
    if (!this.outstandingSearch && e.keyCode == 13) this.search(query);
  },

  // Webkit knows how to fire a real "search" event.
  searchEvent : function(e) {
    var query = this.value();
    if (!this.outstandingSearch && query) this.search(query);
  },

  cancelSearch : function() {
    this.value('');
  },

  entitle : function(query) {
    var projectName = dc.app.SearchParser.extractProject(query);
    var accountName = dc.app.SearchParser.extractAccount(query);
    if (projectName) {
      this.titleBox.text(projectName);
    } else if (accountName == Accounts.current().get('email')) {
      this.titleBox.text('Uploaded Documents');
    } else {
      this.titleBox.text('All Documents');
    }
  },

  // Hide the spinner and remove the search lock when finished searching.
  doneSearching : function(empty) {
    if (empty) {
      $(document.body).setMode('empty', 'search');
      var searchType = dc.app.SearchParser.searchType(this.value());
      $('#no_results .explanation').text(this.NO_RESULTS[searchType]);
    }
    dc.ui.spinner.hide();
    this.outstandingSearch = false;
  },

  // After the initial search results come back, send out a request for the
  // associated metadata, as long as something was found. Think about returning
  // the metadata right alongside the document JSON.
  _loadSearchResults : function(resp) {
    dc.app.paginator.setQuery(resp.query);
    dc.app.workspace.organizer.renderFacets(resp.facets, 5, resp.query.total);
    Entities.refresh();
    Documents.refresh(_.map(resp.documents, function(m){
      return new dc.model.Document(m);
    }));
    this.doneSearching(resp.documents.length == 0);
  },

  _loadFacetResults : function(resp) {
    dc.app.workspace.organizer.mergeFacets(resp.facets, 500, resp.query.total);
    dc.ui.spinner.hide();
    this.outstandingSearch = false;
  },

  _setScope : function(e) {
    var scope = null;
    switch (this.menu.val()) {
      case 'all':     scope = '';                                                    break;
      case 'account': scope = 'account: ' + Accounts.current().get('email') + ' '; break;
      case 'group':   scope = 'group: ' + dc.app.organization.slug + ' ';     break;
    }
    this.scopeSearch(scope);
  }

});<commit_msg>adding scroller checks for the help tab...<commit_after>// The search controller is responsible for managing document/metadata search.
dc.ui.SearchBox = dc.View.extend({

  PAGE_MATCHER        : (/\/p(\d+)$/),

  DOCUMENTS_URL : '/search/documents.json',

  // Error messages to display when your search returns no results.
  NO_RESULTS : {
    project : "This project does not contain any documents.",
    account : "This account has not uploaded any documents.",
    search  : "Your search did not match any documents."
  },

  id            : 'search',
  fragment      : null,

  callbacks : {
    '#search_box.keydown':  'maybeSearch',
    '#search_box.search':   'searchEvent',
    '#search_type.click':   '_setScope',
    '.cancel_search.click': 'cancelSearch'
  },

  // Creating a new SearchBox registers #search page fragments.
  constructor : function(options) {
    this.base(options);
    this.outstandingSearch = false;
    _.bindAll(this, '_loadSearchResults', '_loadFacetResults', 'searchByHash', 'showHelp', 'loadDefault');
    dc.history.register(/^#search\//, this.searchByHash);
    dc.history.register(/^#help$/, this.showHelp);
  },

  render : function() {
    $(this.el).append(JST.search_box({}));
    this.box      = $('#search_box', this.el);
    this.menu     = $('#search_type', this.el);
    this.titleBox = $('#title_box', this.el);
    $(document.body).setMode('no', 'search');
    this.setCallbacks();
    $('#cloud_edge').click(this.showHelp);
    (this._helpTab = $('#help_tab')).click(this.showHelp);
    (this._documentsTab = $('#documents_tab')).click(this.loadDefault);
    return this;
  },

  // Shortcut to the searchbox's value.
  value : function(query) {
    return this.box.val(query);
  },

  urlFragment : function() {
    return this.fragment + (this.page ? '/p' + this.page : '');
  },

  // Load the default starting-point search.
  loadDefault : function() {
    if (!Documents.empty()) return this.showDocuments();
    if (this.value()) {
      this.search(this.value());
    } else if (dc.app.documentCount) {
      Accounts.current().openDocuments();
    } else if (Projects.first()) {
      Projects.first().open();
    }
  },

  showDocuments : function() {
    $(document.body).setMode('active', 'search');
    this._helpTab.removeClass('active');
    this._documentsTab.addClass('active');
    this.entitle(this.value());
    dc.app.scroller.check();
    dc.history.save(this.urlFragment());
  },

  showHelp : function() {
    $(document.body).setMode('no', 'search');
    this._documentsTab.removeClass('active');
    this._helpTab.addClass('active');
    dc.app.scroller.check();
    dc.history.save('help');
  },

  // Start a search for a query string, updating the page URL.
  search : function(query, pageNumber) {
    dc.ui.Project.highlight(query);
    this.page = pageNumber <= 1 ? null : pageNumber;
    this.value(query);
    this.fragment = 'search/' + encodeURIComponent(query);
    this.showDocuments();
    Documents.refresh();
    this.outstandingSearch = true;
    dc.ui.spinner.show('searching');
    dc.app.paginator.hide();
    var params = {q : query, include_facets : true};
    if (this.page) params.page = this.page;
    $.get(this.DOCUMENTS_URL, params, this._loadSearchResults, 'json');
  },

  loadFacets : function(facet) {
    dc.ui.spinner.show('searching');
    this.outstandingSearch = true;
    var params = {q : this.value(), include_facets : true, facet : facet};
    $.get(this.DOCUMENTS_URL, params, this._loadFacetResults, 'json');
  },

  // Ensure a given prefix for the search, used to scope searches down to
  // a specific qualifier.
  scopeSearch : function(prefix) {
    var search = this.value().replace(/^(organization|documents):\s+\S+ /, '');
    this.value(prefix + search);
  },

  // When searching by the URL's hash value, we need to unescape first.
  searchByHash : function(hash) {
    var page = null, connection = null;
    var pageMatch = hash.match(this.PAGE_MATCHER);
    if (pageMatch) {
      var page = pageMatch[1];
      hash = hash.replace(this.PAGE_MATCHER, '');
    }
    this.search(decodeURIComponent(hash), page);
  },

  // Add a query fragment to the search and search again, if it's not already
  // present in the current search.
  addToSearch : function(fragment) {
    if (this.value().toLowerCase().match(fragment.toLowerCase())) return;
    this.value(this.value() + " " + fragment);
    this.search(this.value());
  },

  // Remove a query fragment from the search and search again, only if it's
  // present in the current search.
  removeFromSearch : function(regex) {
    if (!this.value().match(regex)) return;
    var next = this.value().replace(regex, '');
    if (next == this.value()) return false;
    this.value(next);
    this.search(next);
    return true;
  },

  // Callback fired on key press in the search box. We search when they hit
  // return.
  maybeSearch : function(e) {
    var query = this.value();
    if (!this.outstandingSearch && e.keyCode == 13) this.search(query);
  },

  // Webkit knows how to fire a real "search" event.
  searchEvent : function(e) {
    var query = this.value();
    if (!this.outstandingSearch && query) this.search(query);
  },

  cancelSearch : function() {
    this.value('');
  },

  entitle : function(query) {
    var projectName = dc.app.SearchParser.extractProject(query);
    var accountName = dc.app.SearchParser.extractAccount(query);
    if (projectName) {
      this.titleBox.text(projectName);
    } else if (accountName == Accounts.current().get('email')) {
      this.titleBox.text('Uploaded Documents');
    } else {
      this.titleBox.text('All Documents');
    }
  },

  // Hide the spinner and remove the search lock when finished searching.
  doneSearching : function(empty) {
    if (empty) {
      $(document.body).setMode('empty', 'search');
      var searchType = dc.app.SearchParser.searchType(this.value());
      $('#no_results .explanation').text(this.NO_RESULTS[searchType]);
    }
    dc.ui.spinner.hide();
    this.outstandingSearch = false;
  },

  // After the initial search results come back, send out a request for the
  // associated metadata, as long as something was found. Think about returning
  // the metadata right alongside the document JSON.
  _loadSearchResults : function(resp) {
    dc.app.paginator.setQuery(resp.query);
    dc.app.workspace.organizer.renderFacets(resp.facets, 5, resp.query.total);
    Entities.refresh();
    Documents.refresh(_.map(resp.documents, function(m){
      return new dc.model.Document(m);
    }));
    this.doneSearching(resp.documents.length == 0);
  },

  _loadFacetResults : function(resp) {
    dc.app.workspace.organizer.mergeFacets(resp.facets, 500, resp.query.total);
    dc.ui.spinner.hide();
    this.outstandingSearch = false;
  },

  _setScope : function(e) {
    var scope = null;
    switch (this.menu.val()) {
      case 'all':     scope = '';                                                    break;
      case 'account': scope = 'account: ' + Accounts.current().get('email') + ' '; break;
      case 'group':   scope = 'group: ' + dc.app.organization.slug + ' ';     break;
    }
    this.scopeSearch(scope);
  }

});<|endoftext|>


<commit_before>Ext.ns('Ext.ux.form');

	Ext.ux.form.UploadField = Ext.extend(Ext.ux.form.FileUploadField, {
		/**
		 * Max surface area (example size 3000 x 2000)
		 */
		maxSurface: 6000000,

		/**
		 * @cfg uploadURL
		 */
		uploadURL: BASE + 'g/content/upload',

		/**
		 * @cfg supportedExtensions
		 */
		supportedExtensions: ['gif', 'jpg', 'jpeg', 'png'],

		/**
		 * Override, because MySQL null values != ''
		 */
		getValue: function(){
			var val = Ext.ux.form.UploadCombo.superclass.getValue.call(this);
			if (!val) {
				val = null;
			}
			return val;
		},

		/**
		 * Simple name based check
		 * @param {Object} fileName
		 */
		validateExtension: function(fileName){
			var extension = fileName.split('.');
			if (!extension) {
				return false;
			}
			extension = extension[extension.length - 1];
			var name = extension[0];
			if (!name.length) {
				return false; // also dont support files with an extension but no name
			}
			return this.supportedExtensions.indexOf(extension.toLowerCase()) > -1;
		},

		/**
		 * Validate resolution
		 */
		validateResolution: function(file, callback) {
			// What to do for browsers with no FileReader support, such as IE9?
			// For now, let's just admit defeat and allow the upload.
			if (typeof FileReader !== 'function') {
				callback(true);
				return;
			}
			var fr = new FileReader();
			var scope = this;
			fr.onload = function() {   // onload fires after reading is complete
				var img = new Image();
				img.onload = function() {
					var surface = img.width * img.height;
					var success = surface <= scope.maxSurface;
					callback(success);
				};
				img.src = fr.result;
			};
			fr.readAsDataURL(file);    // begin reading
		},

		/**
		 * Drop Handler
		 * @param {Object} e
		 */
		handleFileDrop: function(e){
			this.wrap.removeClass('x-focus');
			if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length == 1) {
				this.performUpload(e.dataTransfer.files[0]);
			}
			return false;
		},

		/**
		 * Button Handler
		 */
		handleFileSelect: function(){
			this.performUpload(this.fileInput);
		},

		/**
		 * See if upload is image
		 */
		isImage: function(file) {
			var extension = file.name.split('.').pop();
			if (!extension) {
				return false;
			}

			var img_extensions = ['jpg', 'jpeg', 'png', 'gif'];
			for (var i = 0, ii = img_extensions.length; i < ii; ++i) {
				if (img_extensions[i] === extension) {
					alert('Plaatje ja!');
					return true;
				}
			}
			return false;
		},

		/**
		 * Check extension and go!
		 * @param {Object} fileInput field
		 */
		performUpload: function(fileInput){
			var scope = this;

			if (Ext.isIE) {

				var lm = new Ext.LoadMask(Ext.getBody(),{
					msg: __('Loading')
				});
				lm.show();
				var dh = Ext.DomHelper;
				var iframe = Ext.get(dh.insertHtml('beforeEnd', Ext.getBody().dom, ''));
				var form = Ext.get(dh.insertHtml('beforeEnd', Ext.getBody().dom, '<form method="post" target="uploadFrame" action="' + this.uploadURL + '" enctype="multipart/form-data"></form>'));
				Ext.get(fileInput).appendTo(form);
				iframe.on('load', function(){

					var result = Ext.decode(iframe.dom.contentDocument.body.innerHTML);
					if(!result || !result.success){
						//scope.setValue(scope.originalValue);
						Ext.Msg.alert(__('Garp'), __('Error uploading file.'));
					} else {
						scope.setValue(result.filename);
						scope.fireEvent('change', scope, result.filename);
					}

					form.remove();
					iframe.remove();
					lm.hide();

				});
				form.dom.submit();

			} else {
				var file;
				if (fileInput.dom && fileInput.dom.files) {
					file = fileInput.dom.files[0];
				} else {
					file = fileInput;//.dom.files[0];
				}
				if (!file || !file.name) {
					return;
				}

				var error = function(label, message) {
					scope.setValue(scope.originalValue);
					Ext.Msg.alert(label || __('Garp'), message || __('Error uploading file.'));
				};

				var proceedToUpload = function(success) {
					if (!success) {
						var readableMaxSurface = Ext.util.Format.number(scope.maxSurface, "1000.000/i");
						var exampleA = Math.floor(Math.sqrt(scope.maxSurface));
						// round to nearest 1000
						exampleA = Math.round((exampleA + 500) / 1000) * 1000;
						var exampleB = Math.floor(scope.maxSurface / exampleA);
						error(__('Error'), '' + __('Resolution too high. ' +
								'Please make sure the image\'s surface area does not exceed ' + readableMaxSurface) +
								' pixels.
For instance: ' + exampleA + ' x ' + exampleB + ' pixels.');

					} else if (!scope.validateExtension(file.name)) {

						error(__('Error'),
							'' + __('Extension not supported') + '

' +
							__('Supported extensions are:') + '
 ' + scope.supportedExtensions.join(' ')
						);

					} else {
						var fd = new FormData();
						var xhr = new XMLHttpRequest();
						scope.uploadDialog = Ext.Msg.progress(__('Upload'), __('Initializing upload'));

						fd.append('filename', file);

						xhr.addEventListener('load', function(e){
							var response = Ext.decode(xhr.responseText);
							scope.uploadDialog.hide();
							if (response.success) {
								scope.setValue(response.filename);
								scope.fireEvent('change', scope, response.filename);
							} else {
								error();
							}
						}, false);
						xhr.addEventListener('error', function(e){
							scope.uploadDialog.hide();
							error();
						}, false);
						xhr.upload.addEventListener('progress', function(e){
							if (e.lengthComputable) {
								scope.uploadDialog.updateProgress(e.loaded / e.total);
								scope.uploadDialog.updateText(__('Uploading') + ' ' + (Math.ceil(e.loaded / e.total * 100)) + '%');
							}
						}, false);

						xhr.open('POST', scope.uploadURL);
						scope.uploadDialog.updateText(__('Uploading…'));

						// we'll use a timeout to be sure that the dialog is ready, small downloads otherwise result in an ugly flashy UX
						setTimeout(function(){
							xhr.send(fd);
						}, 350);

					}
				};

				if (this.isImage(file)) {
					this.validateResolution(file, proceedToUpload);
				} else {
					proceedToUpload(true);
				}
			}
		},

		/**
		 * sets up Drag 'n Drop
		 */
		setupDnD: function(){

			var opts = {
				normalized: false,
				preventDefault: true,
				stopPropagation: true
			};

			this.wrap.on('dragenter', function(e){
				// unfortunately, we can't grab file extension here, so we'll present it as allowed. On drop we'll check extensions
				this.wrap.addClass('x-focus');
			}, this, opts);

			this.wrap.on('dragexit', function(e){
				this.wrap.removeClass('x-focus');
			}, this, opts);

			this.wrap.on('dragover', function(e){
			}, this, opts);

			this.wrap.on('drop', function(e){
				this.handleFileDrop(e);
			}, this, opts);
		},

		onDestroy: function(){
			if (this.uploadDialog) {
				this.uploadDialog.hide();
			}
			Ext.ux.form.UploadField.superclass.onDestroy.call(this);
		},

		initComponent: function(){
			this.on('fileselected', this.handleFileSelect, this);
			Ext.ux.form.UploadField.superclass.initComponent.call(this, arguments);
			this.on('afterrender', this.setupDnD, this);
		}
	});

Ext.reg('uploadfield', Ext.ux.form.UploadField);
<commit_msg>Removed debug<commit_after>Ext.ns('Ext.ux.form');

	Ext.ux.form.UploadField = Ext.extend(Ext.ux.form.FileUploadField, {
		/**
		 * Max surface area (example size 3000 x 2000)
		 */
		maxSurface: 6000000,

		/**
		 * @cfg uploadURL
		 */
		uploadURL: BASE + 'g/content/upload',

		/**
		 * @cfg supportedExtensions
		 */
		supportedExtensions: ['gif', 'jpg', 'jpeg', 'png'],

		/**
		 * Override, because MySQL null values != ''
		 */
		getValue: function(){
			var val = Ext.ux.form.UploadCombo.superclass.getValue.call(this);
			if (!val) {
				val = null;
			}
			return val;
		},

		/**
		 * Simple name based check
		 * @param {Object} fileName
		 */
		validateExtension: function(fileName){
			var extension = fileName.split('.');
			if (!extension) {
				return false;
			}
			extension = extension[extension.length - 1];
			var name = extension[0];
			if (!name.length) {
				return false; // also dont support files with an extension but no name
			}
			return this.supportedExtensions.indexOf(extension.toLowerCase()) > -1;
		},

		/**
		 * Validate resolution
		 */
		validateResolution: function(file, callback) {
			// What to do for browsers with no FileReader support, such as IE9?
			// For now, let's just admit defeat and allow the upload.
			if (typeof FileReader !== 'function') {
				callback(true);
				return;
			}
			var fr = new FileReader();
			var scope = this;
			fr.onload = function() {   // onload fires after reading is complete
				var img = new Image();
				img.onload = function() {
					var surface = img.width * img.height;
					var success = surface <= scope.maxSurface;
					callback(success);
				};
				img.src = fr.result;
			};
			fr.readAsDataURL(file);    // begin reading
		},

		/**
		 * Drop Handler
		 * @param {Object} e
		 */
		handleFileDrop: function(e){
			this.wrap.removeClass('x-focus');
			if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length == 1) {
				this.performUpload(e.dataTransfer.files[0]);
			}
			return false;
		},

		/**
		 * Button Handler
		 */
		handleFileSelect: function(){
			this.performUpload(this.fileInput);
		},

		/**
		 * See if upload is image
		 */
		isImage: function(file) {
			var extension = file.name.split('.').pop();
			if (!extension) {
				return false;
			}

			var img_extensions = ['jpg', 'jpeg', 'png', 'gif'];
			for (var i = 0, ii = img_extensions.length; i < ii; ++i) {
				if (img_extensions[i] === extension) {
					return true;
				}
			}
			return false;
		},

		/**
		 * Check extension and go!
		 * @param {Object} fileInput field
		 */
		performUpload: function(fileInput){
			var scope = this;

			if (Ext.isIE) {

				var lm = new Ext.LoadMask(Ext.getBody(),{
					msg: __('Loading')
				});
				lm.show();
				var dh = Ext.DomHelper;
				var iframe = Ext.get(dh.insertHtml('beforeEnd', Ext.getBody().dom, ''));
				var form = Ext.get(dh.insertHtml('beforeEnd', Ext.getBody().dom, '<form method="post" target="uploadFrame" action="' + this.uploadURL + '" enctype="multipart/form-data"></form>'));
				Ext.get(fileInput).appendTo(form);
				iframe.on('load', function(){

					var result = Ext.decode(iframe.dom.contentDocument.body.innerHTML);
					if(!result || !result.success){
						//scope.setValue(scope.originalValue);
						Ext.Msg.alert(__('Garp'), __('Error uploading file.'));
					} else {
						scope.setValue(result.filename);
						scope.fireEvent('change', scope, result.filename);
					}

					form.remove();
					iframe.remove();
					lm.hide();

				});
				form.dom.submit();

			} else {
				var file;
				if (fileInput.dom && fileInput.dom.files) {
					file = fileInput.dom.files[0];
				} else {
					file = fileInput;//.dom.files[0];
				}
				if (!file || !file.name) {
					return;
				}

				var error = function(label, message) {
					scope.setValue(scope.originalValue);
					Ext.Msg.alert(label || __('Garp'), message || __('Error uploading file.'));
				};

				var proceedToUpload = function(success) {
					if (!success) {
						var readableMaxSurface = Ext.util.Format.number(scope.maxSurface, "1000.000/i");
						var exampleA = Math.floor(Math.sqrt(scope.maxSurface));
						// round to nearest 1000
						exampleA = Math.round((exampleA + 500) / 1000) * 1000;
						var exampleB = Math.floor(scope.maxSurface / exampleA);
						error(__('Error'), '' + __('Resolution too high. ' +
								'Please make sure the image\'s surface area does not exceed ' + readableMaxSurface) +
								' pixels.
For instance: ' + exampleA + ' x ' + exampleB + ' pixels.');

					} else if (!scope.validateExtension(file.name)) {

						error(__('Error'),
							'' + __('Extension not supported') + '

' +
							__('Supported extensions are:') + '
 ' + scope.supportedExtensions.join(' ')
						);

					} else {
						var fd = new FormData();
						var xhr = new XMLHttpRequest();
						scope.uploadDialog = Ext.Msg.progress(__('Upload'), __('Initializing upload'));

						fd.append('filename', file);

						xhr.addEventListener('load', function(e){
							var response = Ext.decode(xhr.responseText);
							scope.uploadDialog.hide();
							if (response.success) {
								scope.setValue(response.filename);
								scope.fireEvent('change', scope, response.filename);
							} else {
								error();
							}
						}, false);
						xhr.addEventListener('error', function(e){
							scope.uploadDialog.hide();
							error();
						}, false);
						xhr.upload.addEventListener('progress', function(e){
							if (e.lengthComputable) {
								scope.uploadDialog.updateProgress(e.loaded / e.total);
								scope.uploadDialog.updateText(__('Uploading') + ' ' + (Math.ceil(e.loaded / e.total * 100)) + '%');
							}
						}, false);

						xhr.open('POST', scope.uploadURL);
						scope.uploadDialog.updateText(__('Uploading…'));

						// we'll use a timeout to be sure that the dialog is ready, small downloads otherwise result in an ugly flashy UX
						setTimeout(function(){
							xhr.send(fd);
						}, 350);

					}
				};

				if (this.isImage(file)) {
					this.validateResolution(file, proceedToUpload);
				} else {
					proceedToUpload(true);
				}
			}
		},

		/**
		 * sets up Drag 'n Drop
		 */
		setupDnD: function(){

			var opts = {
				normalized: false,
				preventDefault: true,
				stopPropagation: true
			};

			this.wrap.on('dragenter', function(e){
				// unfortunately, we can't grab file extension here, so we'll present it as allowed. On drop we'll check extensions
				this.wrap.addClass('x-focus');
			}, this, opts);

			this.wrap.on('dragexit', function(e){
				this.wrap.removeClass('x-focus');
			}, this, opts);

			this.wrap.on('dragover', function(e){
			}, this, opts);

			this.wrap.on('drop', function(e){
				this.handleFileDrop(e);
			}, this, opts);
		},

		onDestroy: function(){
			if (this.uploadDialog) {
				this.uploadDialog.hide();
			}
			Ext.ux.form.UploadField.superclass.onDestroy.call(this);
		},

		initComponent: function(){
			this.on('fileselected', this.handleFileSelect, this);
			Ext.ux.form.UploadField.superclass.initComponent.call(this, arguments);
			this.on('afterrender', this.setupDnD, this);
		}
	});

Ext.reg('uploadfield', Ext.ux.form.UploadField);
<|endoftext|>


<commit_before>/*
 * create.js
 * Copyright (c) 2017 thegrumpydictator@gmail.com
 * This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
 *
 * See the LICENSE file for details.
 */

/** global: currencyInfo, overruleCurrency,useAccountCurrency, accountInfo, what,Modernizr, title, breadcrumbs, middleCrumbName, button, piggiesLength, txt, middleCrumbUrl,exchangeRateInstructions, convertForeignToNative, convertSourceToDestination, selectsForeignCurrency, accountInfo */

$(document).ready(function () {
    "use strict";

    // hide ALL exchange things and AMOUNT things
    $('#exchange_rate_instruction_holder').hide();
    $('#native_amount_holder').hide();
    $('#amount_holder').hide();
    $('#source_amount_holder').hide();
    $('#destination_amount_holder').hide();

    // respond to switch buttons (first time always triggers)
    updateButtons();
    updateForm();
    updateLayout();
    updateDescription();

    // when user changes source account or destination, native currency may be different.
    $('select[name="source_account_id"]').on('change', updateNativeCurrency);
    $('select[name="destination_account_id"]').on('change', updateNativeCurrency);

    // convert foreign currency to native currency (when input changes, exchange rate)
    $('#ffInput_amount').on('change', convertForeignToNative);

    // convert source currency to destination currency (slightly different routine for transfers)
    $('#ffInput_source_amount').on('change', convertSourceToDestination);

    // when user selects different currency,
    $('.currency-option').on('click', selectsForeignCurrency);
    $('#ffInput_description').focus();
});

/**
 * This function generates a small helper text to explain the user
 * that they have selected a foreign currency.
 * @returns {XML|string|void}
 */
function getExchangeInstructions() {
    var foreignCurrencyId = parseInt($('input[name="amount_currency_id_amount"]').val());
    var selectedAccountId = getAccountId();
    var nativeCurrencyId = parseInt(accountInfo[selectedAccountId].preferredCurrency);

    var text = exchangeRateInstructions.replace('@name', accountInfo[selectedAccountId].name);
    text = text.replace(/@native_currency/g, currencyInfo[nativeCurrencyId].name);
    text = text.replace(/@foreign_currency/g, currencyInfo[foreignCurrencyId].name);
    return text;
}

/**
 * There is an input that shows the currency symbol that is native to the selected
 * acccount. So when the user changes the selected account, the native currency is updated:
 */
function updateNativeCurrency(useAccountCurrency) {
    var nativeCurrencyId;
    if (useAccountCurrency) {
        var newAccountId = getAccountId();
        nativeCurrencyId = accountInfo[newAccountId].preferredCurrency;
    }
    if (!useAccountCurrency) {
        nativeCurrencyId = overruleCurrency;
    }

    $('.currency-option[data-id="' + nativeCurrencyId + '"]').click();
    $('[data-toggle="dropdown"]').parent().removeClass('open');
    if (what !== 'transfer') {
        $('select[name="source_account_id"]').focus();
    }
    validateCurrencyForTransfer();
}

/**
 *
 */
function updateDescription() {
    $.getJSON('json/transaction-journals/' + what).done(function (data) {
        $('input[name="description"]').typeahead('destroy').typeahead({source: data});
    });
    $('#ffInput_description').focus();
}

/**
 *
 */
function updateLayout() {
    "use strict";
    $('#subTitle').text(title[what]);
    $('.breadcrumb .active').text(breadcrumbs[what]);
    $('.breadcrumb li:nth-child(2)').html('' + middleCrumbName[what] + '');
    $('#transaction-btn').text(button[what]);
}

/**
 *
 */
function updateForm() {
    "use strict";

    $('input[name="what"]').val(what);

    var destName = $('#ffInput_destination_account_name');
    var srcName = $('#ffInput_source_account_name');

    switch (what) {

        case 'withdrawal':
            // show source_id and dest_name
            document.getElementById('source_account_id_holder').style.display = 'block';
            document.getElementById('destination_account_name_holder').style.display = 'block';

            // hide others:
            document.getElementById('source_account_name_holder').style.display = 'none';
            document.getElementById('destination_account_id_holder').style.display = 'none';
            document.getElementById('budget_id_holder').style.display = 'block';

            // hide piggy bank:
            document.getElementById('piggy_bank_id_holder').style.display = 'none';

            // copy destination account name to source account name:
            if (destName.val().length > 0) {
                srcName.val(destName.val());
            }

            // exchange / foreign currencies:
            // hide explanation, hide source and destination amounts, show normal amount
            document.getElementById('exchange_rate_instruction_holder').style.display = 'none';
            document.getElementById('source_amount_holder').style.display = 'none';
            document.getElementById('destination_amount_holder').style.display = 'none';
            document.getElementById('amount_holder').style.display = 'block';
            break;
        case 'deposit':
            // show source_name and dest_id:
            document.getElementById('source_account_name_holder').style.display = 'block';
            document.getElementById('destination_account_id_holder').style.display = 'block';

            // hide others:
            document.getElementById('source_account_id_holder').style.display = 'none';
            document.getElementById('destination_account_name_holder').style.display = 'none';

            // hide budget
            document.getElementById('budget_id_holder').style.display = 'none';

            // hide piggy bank
            document.getElementById('piggy_bank_id_holder').style.display = 'none';

            // copy name
            if (srcName.val().length > 0) {
                destName.val(srcName.val());
            }

            // exchange / foreign currencies:
            // hide explanation, hide source and destination amounts, show amount
            document.getElementById('exchange_rate_instruction_holder').style.display = 'none';
            document.getElementById('source_amount_holder').style.display = 'none';
            document.getElementById('destination_amount_holder').style.display = 'none';
            document.getElementById('amount_holder').style.display = 'block';
            break;
        case 'transfer':
            // show source_id and dest_id:
            document.getElementById('source_account_id_holder').style.display = 'block';
            document.getElementById('destination_account_id_holder').style.display = 'block';

            // hide others:
            document.getElementById('source_account_name_holder').style.display = 'none';
            document.getElementById('destination_account_name_holder').style.display = 'none';

            // hide budget
            document.getElementById('budget_id_holder').style.display = 'none';

            // optional piggies
            var showPiggies = 'block';
            if (piggiesLength === 0) {
                showPiggies = 'none';
            }
            document.getElementById('piggy_bank_id_holder').style.display = showPiggies;
            break;
        default:
            break;
    }
    // get instructions all the time.
    updateNativeCurrency(useAccountCurrency);
    selectsForeignCurrency();
}

/**
 *
 */
function updateButtons() {
    "use strict";
    $('.switch').each(function (i, v) {
        var button = $(v);

        // remove click event:
        button.unbind('click');
        // new click event:
        button.bind('click', clickButton);

        if (button.data('what') === what) {
            button.removeClass('btn-default').addClass('btn-info').html(' ' + txt[button.data('what')]);
        } else {
            button.removeClass('btn-info').addClass('btn-default').text(txt[button.data('what')]);
        }
    });
}

/**
 *
 * @param e
 * @returns {boolean}
 */
function clickButton(e) {
    "use strict";
    var button = $(e.target);
    var newWhat = button.data('what');
    if (newWhat !== what) {
        what = newWhat;
        updateButtons();
        updateForm();
        updateLayout();
        updateDescription();
    }
    return false;
}

/**
 * Get accountID based on some meta info.
 */
function getAccountId() {
    if (what === "withdrawal") {
        return $('select[name="source_account_id"]').val();
    }
    if (what === "deposit" || what === "transfer") {
        return $('select[name="destination_account_id"]').val();
    }
    return undefined;
}
<commit_msg>Fix #881<commit_after>/*
 * create.js
 * Copyright (c) 2017 thegrumpydictator@gmail.com
 * This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
 *
 * See the LICENSE file for details.
 */

/** global: currencyInfo, overruleCurrency,useAccountCurrency, accountInfo, what,Modernizr, title, breadcrumbs, middleCrumbName, button, piggiesLength, txt, middleCrumbUrl,exchangeRateInstructions, convertForeignToNative, convertSourceToDestination, selectsForeignCurrency, accountInfo */

$(document).ready(function () {
    "use strict";

    // hide ALL exchange things and AMOUNT things
    $('#exchange_rate_instruction_holder').hide();
    $('#native_amount_holder').hide();
    $('#amount_holder').hide();
    $('#source_amount_holder').hide();
    $('#destination_amount_holder').hide();

    // respond to switch buttons (first time always triggers)
    updateButtons();
    updateForm();
    updateLayout();
    updateDescription();

    // when user changes source account or destination, native currency may be different.
    $('select[name="source_account_id"]').on('change', updateNativeCurrency);
    $('select[name="destination_account_id"]').on('change', updateNativeCurrency);

    // convert foreign currency to native currency (when input changes, exchange rate)
    $('#ffInput_amount').on('change', convertForeignToNative);

    // convert source currency to destination currency (slightly different routine for transfers)
    $('#ffInput_source_amount').on('change', convertSourceToDestination);

    // when user selects different currency,
    $('.currency-option').on('click', selectsForeignCurrency);
    $('#ffInput_description').focus();
});

/**
 * This function generates a small helper text to explain the user
 * that they have selected a foreign currency.
 * @returns {XML|string|void}
 */
function getExchangeInstructions() {
    var foreignCurrencyId = parseInt($('input[name="amount_currency_id_amount"]').val());
    var selectedAccountId = getAccountId();
    var nativeCurrencyId = parseInt(accountInfo[selectedAccountId].preferredCurrency);

    var text = exchangeRateInstructions.replace('@name', accountInfo[selectedAccountId].name);
    text = text.replace(/@native_currency/g, currencyInfo[nativeCurrencyId].name);
    text = text.replace(/@foreign_currency/g, currencyInfo[foreignCurrencyId].name);
    return text;
}

/**
 * There is an input that shows the currency symbol that is native to the selected
 * acccount. So when the user changes the selected account, the native currency is updated:
 */
function updateNativeCurrency(useAccountCurrency) {
    var nativeCurrencyId;
    if (useAccountCurrency) {
        var newAccountId = getAccountId();
        nativeCurrencyId = accountInfo[newAccountId].preferredCurrency;
    }
    if (!useAccountCurrency) {
        nativeCurrencyId = overruleCurrency;
    }

    $('.currency-option[data-id="' + nativeCurrencyId + '"]').click();
    $('[data-toggle="dropdown"]').parent().removeClass('open');
    if (what === 'withdrawal') {
        $('select[name="source_account_id"]').focus();
    }
    if (what === 'deposit') {
        $('select[name="destination_account_id"]').focus();
    }
    validateCurrencyForTransfer();
}

/**
 *
 */
function updateDescription() {
    $.getJSON('json/transaction-journals/' + what).done(function (data) {
        $('input[name="description"]').typeahead('destroy').typeahead({source: data});
    });
    $('#ffInput_description').focus();
}

/**
 *
 */
function updateLayout() {
    "use strict";
    $('#subTitle').text(title[what]);
    $('.breadcrumb .active').text(breadcrumbs[what]);
    $('.breadcrumb li:nth-child(2)').html('' + middleCrumbName[what] + '');
    $('#transaction-btn').text(button[what]);
}

/**
 *
 */
function updateForm() {
    "use strict";

    $('input[name="what"]').val(what);

    var destName = $('#ffInput_destination_account_name');
    var srcName = $('#ffInput_source_account_name');

    switch (what) {

        case 'withdrawal':
            // show source_id and dest_name
            document.getElementById('source_account_id_holder').style.display = 'block';
            document.getElementById('destination_account_name_holder').style.display = 'block';

            // hide others:
            document.getElementById('source_account_name_holder').style.display = 'none';
            document.getElementById('destination_account_id_holder').style.display = 'none';
            document.getElementById('budget_id_holder').style.display = 'block';

            // hide piggy bank:
            document.getElementById('piggy_bank_id_holder').style.display = 'none';

            // copy destination account name to source account name:
            if (destName.val().length > 0) {
                srcName.val(destName.val());
            }

            // exchange / foreign currencies:
            // hide explanation, hide source and destination amounts, show normal amount
            document.getElementById('exchange_rate_instruction_holder').style.display = 'none';
            document.getElementById('source_amount_holder').style.display = 'none';
            document.getElementById('destination_amount_holder').style.display = 'none';
            document.getElementById('amount_holder').style.display = 'block';
            break;
        case 'deposit':
            // show source_name and dest_id:
            document.getElementById('source_account_name_holder').style.display = 'block';
            document.getElementById('destination_account_id_holder').style.display = 'block';

            // hide others:
            document.getElementById('source_account_id_holder').style.display = 'none';
            document.getElementById('destination_account_name_holder').style.display = 'none';

            // hide budget
            document.getElementById('budget_id_holder').style.display = 'none';

            // hide piggy bank
            document.getElementById('piggy_bank_id_holder').style.display = 'none';

            // copy name
            if (srcName.val().length > 0) {
                destName.val(srcName.val());
            }

            // exchange / foreign currencies:
            // hide explanation, hide source and destination amounts, show amount
            document.getElementById('exchange_rate_instruction_holder').style.display = 'none';
            document.getElementById('source_amount_holder').style.display = 'none';
            document.getElementById('destination_amount_holder').style.display = 'none';
            document.getElementById('amount_holder').style.display = 'block';
            break;
        case 'transfer':
            // show source_id and dest_id:
            document.getElementById('source_account_id_holder').style.display = 'block';
            document.getElementById('destination_account_id_holder').style.display = 'block';

            // hide others:
            document.getElementById('source_account_name_holder').style.display = 'none';
            document.getElementById('destination_account_name_holder').style.display = 'none';

            // hide budget
            document.getElementById('budget_id_holder').style.display = 'none';

            // optional piggies
            var showPiggies = 'block';
            if (piggiesLength === 0) {
                showPiggies = 'none';
            }
            document.getElementById('piggy_bank_id_holder').style.display = showPiggies;
            break;
        default:
            break;
    }
    // get instructions all the time.
    updateNativeCurrency(useAccountCurrency);
    selectsForeignCurrency();
}

/**
 *
 */
function updateButtons() {
    "use strict";
    $('.switch').each(function (i, v) {
        var button = $(v);

        // remove click event:
        button.unbind('click');
        // new click event:
        button.bind('click', clickButton);

        if (button.data('what') === what) {
            button.removeClass('btn-default').addClass('btn-info').html(' ' + txt[button.data('what')]);
        } else {
            button.removeClass('btn-info').addClass('btn-default').text(txt[button.data('what')]);
        }
    });
}

/**
 *
 * @param e
 * @returns {boolean}
 */
function clickButton(e) {
    "use strict";
    var button = $(e.target);
    var newWhat = button.data('what');
    if (newWhat !== what) {
        what = newWhat;
        updateButtons();
        updateForm();
        updateLayout();
        updateDescription();
    }
    return false;
}

/**
 * Get accountID based on some meta info.
 */
function getAccountId() {
    if (what === "withdrawal") {
        return $('select[name="source_account_id"]').val();
    }
    if (what === "deposit" || what === "transfer") {
        return $('select[name="destination_account_id"]').val();
    }
    return undefined;
}
<|endoftext|>