<commit_before>import { createMap, isMap } from '../../utils/map.js'
import { isFunctionNode, isNode, isOperatorNode, isParenthesisNode, isSymbolNode } from '../../utils/is.js'
import { factory } from '../../utils/factory.js'

const name = 'resolve'
const dependencies = [
  'parse',
  'ConstantNode',
  'FunctionNode',
  'OperatorNode',
  'ParenthesisNode'
]

export const createResolve = /* #__PURE__ */ factory(name, dependencies, ({
  parse,
  ConstantNode,
  FunctionNode,
  OperatorNode,
  ParenthesisNode
}) => {
  /**
   * resolve(expr, scope) replaces variable nodes with their scoped values
   *
   * Syntax:
   *
   *     resolve(expr, scope)
   *
   * Examples:
   *
   *     math.resolve('x + y', {x:1, y:2})           // Node {1 + 2}
   *     math.resolve(math.parse('x+y'), {x:1, y:2}) // Node {1 + 2}
   *     math.simplify('x+y', {x:2, y:'x+x'}).toString()      // "6"
   *
   * See also:
   *
   *     simplify, evaluate
   *
   * @param {Node} node
   *     The expression tree to be simplified
   * @param {Object} scope
   *     Scope specifying variables to be resolved
   * @return {Node} Returns `node` with variables recursively substituted.
   * @throws {ReferenceError}
   *     If there is a cyclic dependency among the variables in `scope`,
   *     resolution is impossible and a ReferenceError is thrown.
   */
  function resolve (node, scope, within = new Set()) { // note `within`:
    // `within` is not documented, since it is for internal cycle
    // detection only
    if (!scope) {
      return node
    }
    if (!isMap(scope)) {
      scope = createMap(scope)
    }
    if (isSymbolNode(node)) {
      if (within.has(node.name)) {
        const variables = Array.from(within).join(', ')
        throw new ReferenceError(
          `recursive loop of variable definitions among {${variables}}`
        )
      }
      const value = scope.get(node.name)
      if (isNode(value)) {
        const nextWithin = new Set(within)
        nextWithin.add(node.name)
        return resolve(value, scope, nextWithin)
      } else if (typeof value === 'number') {
        return parse(String(value))
      } else if (value !== undefined) {
        return new ConstantNode(value)
      } else {
        return node
      }
    } else if (isOperatorNode(node)) {
      const args = node.args.map(function (arg) {
        return resolve(arg, scope, within)
      })
      return new OperatorNode(node.op, node.fn, args, node.implicit)
    } else if (isParenthesisNode(node)) {
      return new ParenthesisNode(resolve(node.content, scope, within))
    } else if (isFunctionNode(node)) {
      const args = node.args.map(function (arg) {
        return resolve(arg, scope, within)
      })
      return new FunctionNode(node.name, args)
    }

    // Otherwise just recursively resolve any children (might also work
    // for some of the above special cases)
    return node.map(child => resolve(child, scope, within))
  }

  return resolve
})
<commit_msg>Improve resolve JSDoc to support returning multiple nodes<commit_after>import { createMap, isMap } from '../../utils/map.js'
import { isFunctionNode, isNode, isOperatorNode, isParenthesisNode, isSymbolNode } from '../../utils/is.js'
import { factory } from '../../utils/factory.js'

const name = 'resolve'
const dependencies = [
  'parse',
  'ConstantNode',
  'FunctionNode',
  'OperatorNode',
  'ParenthesisNode'
]

export const createResolve = /* #__PURE__ */ factory(name, dependencies, ({
  parse,
  ConstantNode,
  FunctionNode,
  OperatorNode,
  ParenthesisNode
}) => {
  /**
   * resolve(expr, scope) replaces variable nodes with their scoped values
   *
   * Syntax:
   *
   *     resolve(expr, scope)
   *
   * Examples:
   *
   *     math.resolve('x + y', {x:1, y:2})           // Node {1 + 2}
   *     math.resolve(math.parse('x+y'), {x:1, y:2}) // Node {1 + 2}
   *     math.simplify('x+y', {x:2, y:'x+x'}).toString()      // "6"
   *
   * See also:
   *
   *     simplify, evaluate
   *
   * @template nodeOrNodes
   * @param {nodeOrNodes} node
   *     The expression tree (or trees) to be simplified
   * @param {Object} scope
   *     Scope specifying variables to be resolved
   * @return {numOrStr extends Node[] ? Node[] : Node} Returns `nodeOrNodes` with variables recursively substituted.
   * @throws {ReferenceError}
   *     If there is a cyclic dependency among the variables in `scope`,
   *     resolution is impossible and a ReferenceError is thrown.
   */
  function resolve (node, scope, within = new Set()) { // note `within`:
    // `within` is not documented, since it is for internal cycle
    // detection only
    if (!scope) {
      return node
    }
    if (!isMap(scope)) {
      scope = createMap(scope)
    }
    if (isSymbolNode(node)) {
      if (within.has(node.name)) {
        const variables = Array.from(within).join(', ')
        throw new ReferenceError(
          `recursive loop of variable definitions among {${variables}}`
        )
      }
      const value = scope.get(node.name)
      if (isNode(value)) {
        const nextWithin = new Set(within)
        nextWithin.add(node.name)
        return resolve(value, scope, nextWithin)
      } else if (typeof value === 'number') {
        return parse(String(value))
      } else if (value !== undefined) {
        return new ConstantNode(value)
      } else {
        return node
      }
    } else if (isOperatorNode(node)) {
      const args = node.args.map(function (arg) {
        return resolve(arg, scope, within)
      })
      return new OperatorNode(node.op, node.fn, args, node.implicit)
    } else if (isParenthesisNode(node)) {
      return new ParenthesisNode(resolve(node.content, scope, within))
    } else if (isFunctionNode(node)) {
      const args = node.args.map(function (arg) {
        return resolve(arg, scope, within)
      })
      return new FunctionNode(node.name, args)
    }

    // Otherwise just recursively resolve any children (might also work
    // for some of the above special cases)
    return node.map(child => resolve(child, scope, within))
  }

  return resolve
})
<|endoftext|>


<commit_before>import Immutable from 'immutable'
import yaml from 'js-yaml'
import tv4 from 'tv4'
import swaggerSchema from 'swagger-schema-official/schema.json'

import RequestContext, {
    KeyValue,
    Group,
    Schema,
    Request,
    Response
} from '../../immutables/RequestContext'

export default class SwaggerParser {
    contructor() {
        this.context = new RequestContext()
    }

    // @NotTested -> assumed valid
    parse(string) {
        const swaggerCollection = this._loadSwaggerCollection(string)
        const valid = this._validateSwaggerCollection(swaggerCollection)

        if (!valid) {
            const m = 'Invalid Swagger File (invalid schema / version < 2.0):\n'
            throw new Error(m + tv4.error)
        }

        if (swaggerCollection) {
            let baseSchema = new Schema()
            baseSchema = baseSchema.mergeSchema(swaggerCollection)

            let rootGroup = new Group()
            rootGroup = rootGroup.set('name', swaggerCollection.info.title)
            let pathLinkedRequests = this._applyFuncOverPathArchitecture(
                swaggerCollection,
                baseSchema,
                ::this._createRequest
            )

            rootGroup = this._createGroupTree(rootGroup, pathLinkedRequests)

            let reqContext = new RequestContext()
            reqContext = reqContext
                .set('group', rootGroup)
                .set('schema', baseSchema)

            this.context = reqContext

            return reqContext
        }
    }

    // @tested
    _setSummary(request, path, content) {
        if (content.summary) {
            return request.set('name', content.summary)
        }
        return request.set('name', path)
    }

    // @tested
    _setDescription(request, content) {
        if (content.description) {
            return request.set('description', content.description)
        }
        return request
    }

    // @tested
    _setBasicInfo(request, url, method, headers, responses) {
        const headerSet = this._convertKeyValueListToSet(headers)
        return request
            .set('url', url)
            .set('method', method.toUpperCase())
            .set('headers', new Immutable.OrderedMap(headerSet))
            .set('responses', new Immutable.List(responses))
    }

    _extractContentType(swaggerCollection, content) {
        let contentType
        if (content.consumes && content.consumes.length > 0) {
            contentType = content.consumes[0]
        }
        else if (
            swaggerCollection.consumes &&
            swaggerCollection.consumes.length > 0
        ) {
            contentType = swaggerCollection.consumes[0]
        }

        return contentType
    }

    // @NotTested
    _setBody(request, swaggerCollection, body, formData, content) {
        let _request = request
        if (body) {
            if (!(body instanceof Schema)) {
                throw new Error('expected Schema Object as a body')
            }
            _request = _request
                .set('bodyType', 'schema')
                .set('body', body)
        }

        if (formData.length > 0) {
            let contentType = this
                ._extractContentType(swaggerCollection, content)

            const typeMapping = {
                'application/x-www-form-urlencoded': 'urlEncoded',
                'multipart/form-data': 'formData'
            }

            if (
                typeMapping[contentType]
            ) {
                _request = _request.set(
                    'bodyType', typeMapping[contentType]
                )
            }

            _request = _request.set('body', new Immutable.List(formData))
        }

        return _request
    }

    // @Tested
    _setAuth(request, swaggerCollection, content) {
        let _request = request
        if (content.security) {
            if (!swaggerCollection.securityDefinitions) {
                const m = 'Swagger - expected a security definition to exist'
                throw new Error(m)
            }
            for (let security of content.security) {
                for (let key in security) {
                    if (
                        security.hasOwnProperty(key) &&
                        swaggerCollection.securityDefinitions[key]
                    ) {
                        let definition = Immutable.fromJS(swaggerCollection
                            .securityDefinitions[key])
                        definition = definition.set(
                            'scopes', new Immutable.List(security[key])
                        )
                        _request = _request
                            .setAuthType(definition.get('type'), definition)
                    }
                }
            }
        }

        return _request
    }

    _uriEncodeKeyValueList(kvList) {
        return kvList.map((kv) => {
            return kv
                .set('key', kv.get('key'))
                .set('value', kv.get('value'))
        })
    }

    _setQueries(request, queries) {
        let _queries = this._uriEncodeKeyValueList(queries)
        if (queries.length > 0) {
            return request.set('queries', new Immutable.List(_queries))
        }
        return request
    }

    // @NotTested -> assumed valid
    _createRequest(swaggerCollection, path, method, content) {
        let request = new Request()
        const [ headers, queries, formData, body ] = this._extractParams(
            content.parameters
        )
        const responses = this._extractResponses(content.responses)
        const url = this._generateURL(swaggerCollection, path)

        const contentType = this
            ._extractContentType(swaggerCollection, content)

        if (contentType) {
            headers.push(new KeyValue({
                key: 'Content-Type',
                value: contentType
            }))
        }

        request = this._setSummary(request, path, content)
        request = this._setDescription(request, content)
        request = this._setBasicInfo(
            request,
            url,
            method,
            headers,
            responses
        )
        request = ::this._setQueries(request, queries)
        request = ::this._setBody(
            request,
            swaggerCollection,
            body,
            formData,
            content
        )
        request = this._setAuth(request, swaggerCollection, content)

        return request
    }

    // @tested
    _loadSwaggerCollection(string) {
        let swaggerCollection
        try {
            swaggerCollection = JSON.parse(string)
        }
        catch (jsonParseError) {
            try {
                swaggerCollection = yaml.safeLoad(string)
            }
            catch (yamlParseError) {
                let m = 'Invalid Swagger File format (invalid JSON or YAML)'
                m += '\nJSON Error: ' + jsonParseError
                m += '\nYAML Error: ' + yamlParseError
                throw new Error(m)
            }
        }

        return swaggerCollection
    }

    // @tested
    _validateSwaggerCollection(swag) {
        return tv4.validate(swag, swaggerSchema)
    }

    _updateParametersInMethod(content, baseParams) {
        // shallow copy
        let params = (baseParams || []).map(d => { return d })
        let contentParams = content.parameters || []
        for (let param of contentParams) {
            let name = param.name
            let index = 0
            let used = false
            for (let _param of baseParams || []) {
                let _name = _param.name
                if (name === _name) {
                    params[index] = param
                    used = true
                }
                index += 1
            }
            if (!used) {
                params.push(param)
            }
        }
        return params
    }

    // @tested
    _applyFuncOverPathArchitecture(collection, schema, func) {
        let architecture = {}
        for (let path in collection.paths) {
            if (collection.paths.hasOwnProperty(path)) {
                architecture[path] = architecture[path] || {}
                let methods = collection.paths[path]
                if (methods.parameters) {
                    let _params = new Schema()
                    _params = _params
                        .mergeSchema(methods.parameters)
                        .resolve(schema)
                        .toJS()

                    let _methods = Object.keys(methods)
                    let paramKey = _methods.indexOf('parameters')
                    // remove paramKey
                    _methods.splice(paramKey, 1)
                    for (let method of _methods) {
                        let params = this._updateParametersInMethod(
                            methods[method],
                            _params
                        )
                        methods[method].parameters = params
                    }
                }
                for (let method in methods) {
                    if (
                        methods.hasOwnProperty(method) &&
                        method !== 'parameters'
                    ) {
                        architecture[path][method] = func(
                            collection,
                            path,
                            method,
                            methods[method]
                        )
                    }
                }
            }
        }

        return architecture
    }

    // @tested
    _generateURL(swaggerCollection, path) {
        const protocol = (
            swaggerCollection.schemes ?
            swaggerCollection.schemes[0] : 'http'
        ) + '://'
        const domain = swaggerCollection.host || 'localhost'
        let basePath = ''
        let subPath = ''

        if (
            swaggerCollection.basePath &&
            swaggerCollection.basePath.length > 0
        ) {
            basePath = swaggerCollection.basePath
            if (!basePath.startsWith('/')) {
                basePath = '/' + basePath
            }

            if (basePath.endsWith('/')) {
                basePath = basePath.substr(0, basePath.length - 1)
            }
        }

        if (!path || path.length === 0 || path[0] !== '/') {
            throw new Error('Invalid Swagger, path must begin with a /')
        }
        else {
            subPath = path
        }

        const url = protocol + domain + basePath + subPath
        return url
    }

    // @tested
    _extractResponses(responses) {
        let result = []

        if (responses) {
            for (let code in responses) {
                if (responses.hasOwnProperty(code)) {
                    let schema = null
                    if (responses[code].schema) {
                        schema = new Schema()
                        schema = schema.mergeSchema(responses[code].schema)
                    }

                    let response = new Response({
                        code: code,
                        description: responses[code].description || null,
                        schema: schema
                    })

                    result.push(response)
                }
            }
        }

        return result
    }

    // @tested
    _convertKeyValueListToSet(kvList) {
        return kvList.reduce((set, pair) => {
            set[pair.get('key')] = pair.get('value')
            return set
        }, {})
    }

    // @tested
    _extractParams(parameters) {
        let headers = []
        let queries = []
        let formData = []
        let body

        const mapping = {
            query: queries,
            header: headers,
            formData: formData
        }

        if (
            parameters &&
            typeof parameters[Symbol.iterator] === 'function'
        ) {
            for (let param of parameters) {
                let fieldList = mapping[param.in]
                if (fieldList) {
                    let value = param.default ? param.default : param.name
                    fieldList.push(new KeyValue(
                        {
                            key: param.name,
                            value: value,
                            valueType: param.type
                        }
                    ))
                }

                if (param.in === 'body') {
                    if (!param.schema) {
                        const m = 'Expected a schema object in body param'
                        throw new Error(m)
                    }
                    body = (new Schema()).mergeSchema(param.schema)
                }
            }
        }
        return [ headers, queries, formData, body ]
    }

    // @tested
    _createGroupTree(group, paths) {
        let _group = group
        for (let path in paths) {
            if (paths.hasOwnProperty(path)) {
                let nodes = path.split('/')

                if (path.startsWith('/') === true) {
                    nodes.splice(0, 1)
                }

                let keyPath = []
                for (let node of nodes) {
                    keyPath.push('children')
                    keyPath.push('/' + node)

                    let sub = _group.getIn(keyPath)
                    if (!sub) {
                        _group = _group.setIn(keyPath, new Group({
                            name: '/' + node
                        }))
                    }
                }

                keyPath.push('children')
                for (let method in paths[path]) {
                    if (paths[path].hasOwnProperty(method)) {
                        _group = _group.setIn(
                            keyPath.concat(method),
                            paths[path][method]
                        )
                    }
                }
            }
        }

        return _group
    }
}

<commit_msg>slightly refactored code<commit_after>import Immutable from 'immutable'
import yaml from 'js-yaml'
import tv4 from 'tv4'
import swaggerSchema from 'swagger-schema-official/schema.json'

import RequestContext, {
    KeyValue,
    Group,
    Schema,
    Request,
    Response
} from '../../immutables/RequestContext'

export default class SwaggerParser {
    contructor() {
        this.context = new RequestContext()
    }

    // @NotTested -> assumed valid
    parse(string) {
        const swaggerCollection = this._loadSwaggerCollection(string)
        const valid = this._validateSwaggerCollection(swaggerCollection)

        if (!valid) {
            const m = 'Invalid Swagger File (invalid schema / version < 2.0):\n'
            throw new Error(m + tv4.error)
        }

        if (swaggerCollection) {
            let baseSchema = new Schema()
            baseSchema = baseSchema.mergeSchema(swaggerCollection)

            let rootGroup = new Group()
            rootGroup = rootGroup.set('name', swaggerCollection.info.title)
            let pathLinkedRequests = this._applyFuncOverPathArchitecture(
                swaggerCollection,
                baseSchema,
                ::this._createRequest
            )

            rootGroup = this._createGroupTree(rootGroup, pathLinkedRequests)

            let reqContext = new RequestContext()
            reqContext = reqContext
                .set('group', rootGroup)
                .set('schema', baseSchema)

            this.context = reqContext

            return reqContext
        }
    }

    // @tested
    _setSummary(request, path, content) {
        if (content.summary) {
            return request.set('name', content.summary)
        }
        return request.set('name', path)
    }

    // @tested
    _setDescription(request, content) {
        if (content.description) {
            return request.set('description', content.description)
        }
        return request
    }

    // @tested
    _setBasicInfo(request, url, method, headers, responses) {
        const headerSet = this._convertKeyValueListToSet(headers)
        return request
            .set('url', url)
            .set('method', method.toUpperCase())
            .set('headers', new Immutable.OrderedMap(headerSet))
            .set('responses', new Immutable.List(responses))
    }

    _extractContentType(swaggerCollection, content) {
        let contentType
        if (content.consumes && content.consumes.length > 0) {
            contentType = content.consumes[0]
        }
        else if (
            swaggerCollection.consumes &&
            swaggerCollection.consumes.length > 0
        ) {
            contentType = swaggerCollection.consumes[0]
        }

        return contentType
    }

    // @NotTested
    _setBody(request, swaggerCollection, body, formData, content) {
        let _request = request
        if (body) {
            if (!(body instanceof Schema)) {
                throw new Error('expected Schema Object as a body')
            }
            _request = _request
                .set('bodyType', 'schema')
                .set('body', body)
        }

        if (formData.length > 0) {
            let contentType = this
                ._extractContentType(swaggerCollection, content)

            const typeMapping = {
                'application/x-www-form-urlencoded': 'urlEncoded',
                'multipart/form-data': 'formData'
            }

            if (
                typeMapping[contentType]
            ) {
                _request = _request.set(
                    'bodyType', typeMapping[contentType]
                )
            }

            _request = _request.set('body', new Immutable.List(formData))
        }

        return _request
    }

    // @Tested
    _setAuth(request, swaggerCollection, content) {
        let _request = request
        if (content.security) {
            if (!swaggerCollection.securityDefinitions) {
                const m = 'Swagger - expected a security definition to exist'
                throw new Error(m)
            }
            for (let security of content.security) {
                for (let key in security) {
                    if (
                        security.hasOwnProperty(key) &&
                        swaggerCollection.securityDefinitions[key]
                    ) {
                        let definition = Immutable.fromJS(swaggerCollection
                            .securityDefinitions[key])
                        definition = definition.set(
                            'scopes', new Immutable.List(security[key])
                        )
                        _request = _request
                            .setAuthType(definition.get('type'), definition)
                    }
                }
            }
        }

        return _request
    }

    _uriEncodeKeyValueList(kvList) {
        return kvList.map((kv) => {
            return kv
                .set('key', kv.get('key'))
                .set('value', kv.get('value'))
        })
    }

    _setQueries(request, queries) {
        let _queries = this._uriEncodeKeyValueList(queries)
        if (queries.length > 0) {
            return request.set('queries', new Immutable.List(_queries))
        }
        return request
    }

    // @NotTested -> assumed valid
    _createRequest(swaggerCollection, path, method, content) {
        let request = new Request()
        const [ headers, queries, formData, body ] = this._extractParams(
            content.parameters
        )
        const responses = this._extractResponses(content.responses)
        const url = this._generateURL(swaggerCollection, path)

        const contentType = this
            ._extractContentType(swaggerCollection, content)

        if (contentType) {
            headers.push(new KeyValue({
                key: 'Content-Type',
                value: contentType
            }))
        }

        request = this._setSummary(request, path, content)
        request = this._setDescription(request, content)
        request = this._setBasicInfo(
            request,
            url,
            method,
            headers,
            responses
        )
        request = ::this._setQueries(request, queries)
        request = ::this._setBody(
            request,
            swaggerCollection,
            body,
            formData,
            content
        )
        request = this._setAuth(request, swaggerCollection, content)

        return request
    }

    // @tested
    _loadSwaggerCollection(string) {
        let swaggerCollection
        try {
            swaggerCollection = JSON.parse(string)
        }
        catch (jsonParseError) {
            try {
                swaggerCollection = yaml.safeLoad(string)
            }
            catch (yamlParseError) {
                let m = 'Invalid Swagger File format (invalid JSON or YAML)'
                m += '\nJSON Error: ' + jsonParseError
                m += '\nYAML Error: ' + yamlParseError
                throw new Error(m)
            }
        }

        return swaggerCollection
    }

    // @tested
    _validateSwaggerCollection(swag) {
        return tv4.validate(swag, swaggerSchema)
    }

    _updateParametersInMethod(content, baseParams) {
        // shallow copy
        let params = (baseParams || []).map(d => { return d })
        let contentParams = content.parameters || []
        for (let param of contentParams) {
            let name = param.name
            let index = 0
            let used = false
            for (let _param of baseParams || []) {
                let _name = _param.name
                if (name === _name) {
                    params[index] = param
                    used = true
                }
                index += 1
            }
            if (!used) {
                params.push(param)
            }
        }
        return params
    }

    // @tested
    _applyFuncOverPathArchitecture(collection, schema, func) {
        let architecture = {}
        for (let path in collection.paths) {
            if (collection.paths.hasOwnProperty(path)) {
                architecture[path] = architecture[path] || {}
                let methods = collection.paths[path]
                let _methods = Object.keys(methods)
                if (methods.parameters) {
                    let _params = new Schema()
                    _params = _params
                        .mergeSchema(methods.parameters)
                        .resolve(schema)
                        .toJS()

                    let paramKey = _methods.indexOf('parameters')
                    // remove paramKey
                    _methods.splice(paramKey, 1)

                    for (let method of _methods) {
                        let params = this._updateParametersInMethod(
                            methods[method],
                            _params
                        )
                        methods[method].parameters = params
                    }
                }
                for (let method of _methods) {
                    architecture[path][method] = func(
                        collection,
                        path,
                        method,
                        methods[method]
                    )
                }
            }
        }

        return architecture
    }

    // @tested
    _generateURL(swaggerCollection, path) {
        const protocol = (
            swaggerCollection.schemes ?
            swaggerCollection.schemes[0] : 'http'
        ) + '://'
        const domain = swaggerCollection.host || 'localhost'
        let basePath = ''
        let subPath = ''

        if (
            swaggerCollection.basePath &&
            swaggerCollection.basePath.length > 0
        ) {
            basePath = swaggerCollection.basePath
            if (!basePath.startsWith('/')) {
                basePath = '/' + basePath
            }

            if (basePath.endsWith('/')) {
                basePath = basePath.substr(0, basePath.length - 1)
            }
        }

        if (!path || path.length === 0 || path[0] !== '/') {
            throw new Error('Invalid Swagger, path must begin with a /')
        }
        else {
            subPath = path
        }

        const url = protocol + domain + basePath + subPath
        return url
    }

    // @tested
    _extractResponses(responses) {
        let result = []

        if (responses) {
            for (let code in responses) {
                if (responses.hasOwnProperty(code)) {
                    let schema = null
                    if (responses[code].schema) {
                        schema = new Schema()
                        schema = schema.mergeSchema(responses[code].schema)
                    }

                    let response = new Response({
                        code: code,
                        description: responses[code].description || null,
                        schema: schema
                    })

                    result.push(response)
                }
            }
        }

        return result
    }

    // @tested
    _convertKeyValueListToSet(kvList) {
        return kvList.reduce((set, pair) => {
            set[pair.get('key')] = pair.get('value')
            return set
        }, {})
    }

    // @tested
    _extractParams(parameters) {
        let headers = []
        let queries = []
        let formData = []
        let body

        const mapping = {
            query: queries,
            header: headers,
            formData: formData
        }

        if (
            parameters &&
            typeof parameters[Symbol.iterator] === 'function'
        ) {
            for (let param of parameters) {
                let fieldList = mapping[param.in]
                if (fieldList) {
                    let value = param.default ? param.default : param.name
                    fieldList.push(new KeyValue(
                        {
                            key: param.name,
                            value: value,
                            valueType: param.type
                        }
                    ))
                }

                if (param.in === 'body') {
                    if (!param.schema) {
                        const m = 'Expected a schema object in body param'
                        throw new Error(m)
                    }
                    body = (new Schema()).mergeSchema(param.schema)
                }
            }
        }
        return [ headers, queries, formData, body ]
    }

    // @tested
    _createGroupTree(group, paths) {
        let _group = group
        for (let path in paths) {
            if (paths.hasOwnProperty(path)) {
                let nodes = path.split('/')

                if (path.startsWith('/') === true) {
                    nodes.splice(0, 1)
                }

                let keyPath = []
                for (let node of nodes) {
                    keyPath.push('children')
                    keyPath.push('/' + node)

                    let sub = _group.getIn(keyPath)
                    if (!sub) {
                        _group = _group.setIn(keyPath, new Group({
                            name: '/' + node
                        }))
                    }
                }

                keyPath.push('children')
                for (let method in paths[path]) {
                    if (paths[path].hasOwnProperty(method)) {
                        _group = _group.setIn(
                            keyPath.concat(method),
                            paths[path][method]
                        )
                    }
                }
            }
        }

        return _group
    }
}

<|endoftext|>


<commit_before>import classNames from 'classnames';
import _ from 'underscore';
import createSheet from './create-sheet';

function getClassNames(classes, style, className, component) {
  if (_.isEmpty(style)) {
    return classNames(classes[className]);
  }

  const sheet = createSheet(style, className, component);

  return classNames(classes[className], sheet.classes[className]);
}

export default getClassNames;
<commit_msg>:heavy_minus_sign: Removed underscore<commit_after>import classNames from 'classnames';
import createSheet from './create-sheet';

function getClassNames(classes, style, className, component) {
  if (typeof style === 'undefined' || Object.keys(style).length === 0) {
    return classNames(classes[className]);
  }

  const sheet = createSheet(style, className, component);

  return classNames(classes[className], sheet.classes[className]);
}

export default getClassNames;
<|endoftext|>


<commit_before>(function() {
    'use strict';

    Game.Controller.AI = function(game, controlled) {
        this.game = game;

        this.initialize();

        this.controlled = controlled;

        return this;
    };

    Game.Controller.AI.prototype = Object.create(Game.Controller.prototype);
    Game.Controller.AI.prototype.constructor = Game.Controller.AI;

    Game.Controller.AI.prototype.update = function(toTrack) {
        if (toTrack.position.x - this.controlled.position.x > 500) {
            this.right.setDown.call(this);
        } else {
            this.right.setUp.call(this);
        }

        if (toTrack.position.x - this.controlled.position.x < -500) {
            this.left.setDown.call(this);
        } else {
            this.left.setUp.call(this);
        }

        if (toTrack.position.y - this.controlled.position.y < -300) {
            this.jump.setDown.call(this);
        } else {
            this.jump.setUp.call(this);
        }
    };

})();
<commit_msg>The AI has learned to fling you!<commit_after>(function() {
    'use strict';

    Game.Controller.AI = function(game, controlled) {
        this.game = game;

        this.initialize();

        this.controlled = controlled;

        return this;
    };

    Game.Controller.AI.prototype = Object.create(Game.Controller.prototype);
    Game.Controller.AI.prototype.constructor = Game.Controller.AI;

    Game.Controller.AI.prototype.update = function(toTrack) {
        if (this.game.physics.arcade.intersects(toTrack.body, this.controlled.body)) {

            var dir = toTrack.position.x > this.controlled.position.x ? 1 : -1;

            toTrack.body.position.y -= 5;
            toTrack.body.velocity.setTo(1500 * dir, -1500);
        } else {

        }

        if (toTrack.position.x > this.controlled.position.x) {
            this.right.setDown.call(this);
        } else {
            this.right.setUp.call(this);
        }

        if (toTrack.position.x < this.controlled.position.x) {
            this.left.setDown.call(this);
        } else {
            this.left.setUp.call(this);
        }

        if (toTrack.position.y - this.controlled.position.y < -300) {
            this.jump.setDown.call(this);
        } else {
            this.jump.setUp.call(this);
        }
    };

})();
<|endoftext|>


<commit_before>import $ from 'jquery';
const EDITABLE_PADDING = 24;

export default class Statusbar {
  constructor(context) {
    this.$document = $(document);
    this.$statusbar = context.layoutInfo.statusbar;
    this.$editable = context.layoutInfo.editable;
    this.$codable = context.layoutInfo.codable;
    this.options = context.options;
  }

  initialize() {
    if (this.options.airMode || this.options.disableResizeEditor) {
      this.destroy();
      return;
    }

    this.$statusbar.on('mousedown', (event) => {
      event.preventDefault();
      event.stopPropagation();

      const editableTop = this.$editable.offset().top - this.$document.scrollTop();
      const editableCodeTop = this.$codable.offset().top - this.$document.scrollTop();

      const onMouseMove = (event) => {
        let height = event.clientY - (editableTop + EDITABLE_PADDING);
        let heightCode = event.clientY - (editableCodeTop + EDITABLE_PADDING);

        height = (this.options.minheight > 0) ? Math.max(height, this.options.minheight) : height;
        height = (this.options.maxHeight > 0) ? Math.min(height, this.options.maxHeight) : height;
        heightCode = (this.options.minheight > 0) ? Math.max(heightCode, this.options.minheight) : heightCode;
        heightCode = (this.options.maxHeight > 0) ? Math.min(heightCode, this.options.maxHeight) : heightCode;

        this.$editable.height(height);
        this.$codable.height(heightCode);
      };

      this.$document.on('mousemove', onMouseMove).one('mouseup', () => {
        this.$document.off('mousemove', onMouseMove);
      });
    });
  }

  destroy() {
    this.$statusbar.off();
    this.$statusbar.addClass('note-locked');
  }
}
<commit_msg>Update class for older class name<commit_after>import $ from 'jquery';
const EDITABLE_PADDING = 24;

export default class Statusbar {
  constructor(context) {
    this.$document = $(document);
    this.$statusbar = context.layoutInfo.statusbar;
    this.$editable = context.layoutInfo.editable;
    this.$codable = context.layoutInfo.codable;
    this.options = context.options;
  }

  initialize() {
    if (this.options.airMode || this.options.disableResizeEditor) {
      this.destroy();
      return;
    }

    this.$statusbar.on('mousedown', (event) => {
      event.preventDefault();
      event.stopPropagation();

      const editableTop = this.$editable.offset().top - this.$document.scrollTop();
      const editableCodeTop = this.$codable.offset().top - this.$document.scrollTop();

      const onMouseMove = (event) => {
        let height = event.clientY - (editableTop + EDITABLE_PADDING);
        let heightCode = event.clientY - (editableCodeTop + EDITABLE_PADDING);

        height = (this.options.minheight > 0) ? Math.max(height, this.options.minheight) : height;
        height = (this.options.maxHeight > 0) ? Math.min(height, this.options.maxHeight) : height;
        heightCode = (this.options.minheight > 0) ? Math.max(heightCode, this.options.minheight) : heightCode;
        heightCode = (this.options.maxHeight > 0) ? Math.min(heightCode, this.options.maxHeight) : heightCode;

        this.$editable.height(height);
        this.$codable.height(heightCode);
      };

      this.$document.on('mousemove', onMouseMove).one('mouseup', () => {
        this.$document.off('mousemove', onMouseMove);
      });
    });
  }

  destroy() {
    this.$statusbar.off();
    this.$statusbar.addClass('locked');
  }
}
<|endoftext|>


<commit_before>'use strict';

angular.module('copayApp.controllers').controller('lockSetupController', function($state, $rootScope, $scope, $timeout, $log, configService, gettextCatalog, fingerprintService, profileService, lodash, applicationService) {

  function init() {
    $scope.options = [
      {
        method: 'none',
        label: gettextCatalog.getString('Disabled'),
        disabled: false,
      },
      {
        method: 'pin',
        label: gettextCatalog.getString('Lock by PIN'),
        needsBackup: false,
        disabled: false,
      },
    ];

    if (fingerprintService.isAvailable()) {
      $scope.options.push({
        method: 'fingerprint',
        label: gettextCatalog.getString('Lock by Fingerprint'),
        needsBackup: false,
        disabled: false,
      });
    }

    initMethodSelector();
    processWallets();
  };

  $scope.$on("$ionicView.beforeEnter", function(event) {
    init();
  });

  function getSavedMethod() {
    var config = configService.getSync();
    if (config.lock) return config.lock.method;
    return 'none';
  };

  function initMethodSelector() {
    function disable(method) {
      lodash.find($scope.options, {
        method: method
      }).disabled = true;
    };

    var savedMethod = getSavedMethod();

    lodash.each($scope.options, function(o) {
      o.disabled = false;
    });

    // HACK: Disable until we allow to change between methods directly
    if (fingerprintService.isAvailable()) {
      switch (savedMethod) {
        case 'pin':
          disable('fingerprint');
          break;
        case 'fingerprint':
          disable('pin');
          break;
      }
    }

    $scope.currentOption = lodash.find($scope.options, {
      method: savedMethod
    });
    $timeout(function() {
      $scope.$apply();
    });
  };

  function processWallets() {
    var wallets = profileService.getWallets();
    var singleLivenetWallet = wallets.length == 1 && wallets[0].network == 'livenet' && wallets[0].needsBackup;
    var atLeastOneLivenetWallet = lodash.any(wallets, function(w) {
      return w.network == 'livenet' && w.needsBackup;
    });

    if (singleLivenetWallet) {
      $scope.errorMsg = gettextCatalog.getString('Backup your wallet before using this function');
      disableOptsUntilBackup();
    } else if (atLeastOneLivenetWallet) {
      $scope.errorMsg = gettextCatalog.getString('Backup all livenet wallets before using this function');
      disableOptsUntilBackup();
    } else {
      enableOptsAfterBackup();
      $scope.errorMsg = null;
    }

    function enableOptsAfterBackup() {
      $scope.options[1].needsBackup = false;
      if ($scope.options[2]) $scope.options[2].needsBackup = false;
    };

    function disableOptsUntilBackup() {
      $scope.options[1].needsBackup = true;
      if ($scope.options[2]) $scope.options[2].needsBackup = true;
    };

    $timeout(function() {
      $scope.$apply();
    });
  };

  $scope.select = function(selectedMethod) {
    var savedMethod = getSavedMethod();
    if (savedMethod == selectedMethod) return;

    if (selectedMethod == 'none') {
      disableMethod(savedMethod);
    } else {
      enableMethod(selectedMethod);
    }
  };

  function disableMethod(method) {
    switch (method) {
      case 'pin':
        applicationService.pinModal('disable');
        break;
      case 'fingerprint':
        fingerprintService.check('unlockingApp', function(err) {
          if (err) init();
          else saveConfig('none');
        });
        break;
    }
  };

  function enableMethod(method) {
    switch (method) {
      case 'pin':
        applicationService.pinModal('setup');
        break;
      case 'fingerprint':
        saveConfig('fingerprint');
        break;
    }
  };

  function saveConfig(method) {
    var opts = {
      lock: {
        method: method,
        value: null,
      }
    };

    configService.set(opts, function(err) {
      if (err) $log.debug(err);
      initMethodSelector();
    });
  };

  $rootScope.$on('pinModalClosed', function() {
    init()
  });

});
<commit_msg>disabled is default option<commit_after>'use strict';

angular.module('copayApp.controllers').controller('lockSetupController', function($state, $rootScope, $scope, $timeout, $log, configService, gettextCatalog, fingerprintService, profileService, lodash, applicationService) {

  function init() {
    $scope.options = [
      {
        method: 'none',
        label: gettextCatalog.getString('Disabled'),
        disabled: false,
      },
      {
        method: 'pin',
        label: gettextCatalog.getString('Lock by PIN'),
        needsBackup: false,
        disabled: false,
      },
    ];

    if (fingerprintService.isAvailable()) {
      $scope.options.push({
        method: 'fingerprint',
        label: gettextCatalog.getString('Lock by Fingerprint'),
        needsBackup: false,
        disabled: false,
      });
    }

    initMethodSelector();
    processWallets();
  };

  $scope.$on("$ionicView.beforeEnter", function(event) {
    init();
  });

  function getSavedMethod() {
    var config = configService.getSync();
    if (config.lock && config.lock.method) return config.lock.method;
    return 'none';
  };

  function initMethodSelector() {
    function disable(method) {
      lodash.find($scope.options, {
        method: method
      }).disabled = true;
    };

    var savedMethod = getSavedMethod();

    lodash.each($scope.options, function(o) {
      o.disabled = false;
    });

    // HACK: Disable until we allow to change between methods directly
    if (fingerprintService.isAvailable()) {
      switch (savedMethod) {
        case 'pin':
          disable('fingerprint');
          break;
        case 'fingerprint':
          disable('pin');
          break;
      }
    }

    $scope.currentOption = lodash.find($scope.options, {
      method: savedMethod
    });
    $timeout(function() {
      $scope.$apply();
    });
  };

  function processWallets() {
    var wallets = profileService.getWallets();
    var singleLivenetWallet = wallets.length == 1 && wallets[0].network == 'livenet' && wallets[0].needsBackup;
    var atLeastOneLivenetWallet = lodash.any(wallets, function(w) {
      return w.network == 'livenet' && w.needsBackup;
    });

    if (singleLivenetWallet) {
      $scope.errorMsg = gettextCatalog.getString('Backup your wallet before using this function');
      disableOptsUntilBackup();
    } else if (atLeastOneLivenetWallet) {
      $scope.errorMsg = gettextCatalog.getString('Backup all livenet wallets before using this function');
      disableOptsUntilBackup();
    } else {
      enableOptsAfterBackup();
      $scope.errorMsg = null;
    }

    function enableOptsAfterBackup() {
      $scope.options[1].needsBackup = false;
      if ($scope.options[2]) $scope.options[2].needsBackup = false;
    };

    function disableOptsUntilBackup() {
      $scope.options[1].needsBackup = true;
      if ($scope.options[2]) $scope.options[2].needsBackup = true;
    };

    $timeout(function() {
      $scope.$apply();
    });
  };

  $scope.select = function(selectedMethod) {
    var savedMethod = getSavedMethod();
    if (savedMethod == selectedMethod) return;

    if (selectedMethod == 'none') {
      disableMethod(savedMethod);
    } else {
      enableMethod(selectedMethod);
    }
  };

  function disableMethod(method) {
    switch (method) {
      case 'pin':
        applicationService.pinModal('disable');
        break;
      case 'fingerprint':
        fingerprintService.check('unlockingApp', function(err) {
          if (err) init();
          else saveConfig('none');
        });
        break;
    }
  };

  function enableMethod(method) {
    switch (method) {
      case 'pin':
        applicationService.pinModal('setup');
        break;
      case 'fingerprint':
        saveConfig('fingerprint');
        break;
    }
  };

  function saveConfig(method) {
    var opts = {
      lock: {
        method: method,
        value: null,
      }
    };

    configService.set(opts, function(err) {
      if (err) $log.debug(err);
      initMethodSelector();
    });
  };

  $rootScope.$on('pinModalClosed', function() {
    init()
  });

});
<|endoftext|>


<commit_before>/* Transcript
 *
 */

var Transcript = (function(document, hyperaudio) {

	function Transcript(options) {

		this.options = hyperaudio.extend({}, this.options, {

			entity: 'TRANSCRIPT', // Not really an option... More like a manifest

			target: '#transcript', // The selector of element where the transcript is written to.

			id: '', // The ID of the transcript.

			// src: '', // [obsolete] The URL of the transcript.
			// video: '', // [obsolete] The URL of the video.

			media: {
				// transcript, mp4, webm urls
			},

			select: true, // Enables selection of the transcript

			wordsPlay: true, // Enables word clicks forcing play

			group: 'p', // Element type used to group paragraphs.
			word: 'a', // Element type used per word.

			timeAttr: 'data-m', // Attribute name that holds the timing information.
			unit: 0.001, // Milliseconds.

			async: true, // When true, some operations are delayed by a timeout.

			stage: null,
			player: null
		}, options);

		// State Flags
		this.ready = false;
		this.enabled = true;

		// Properties
		this.target = typeof this.options.target === 'string' ? document.querySelector(this.options.target) : this.options.target;
		this.textSelect = null;

		// Setup Debug
		if(this.options.DEBUG) {
			this._debug();
		}

		// If we have the info, kick things off
		if(this.options.id || this.options.media.youtube || this.options.media.mp4) {
			this.load();
		}
	}

	Transcript.prototype = {

		load: function(id) {
			var self = this;

			this.ready = false;

			if(typeof id !== 'undefined') {
				if(typeof id === 'string') {
					this.options.id = id;
					this.options.media = {};
				} else if(typeof id === 'object') {
					this.options.id = '';
					this.options.media = id;
				} else {
					this.options.id = '';
					this.options.media = {};
				}
			}

			var setVideo = function() {
				if(self.options.async) {
					setTimeout(function() {
						self.setVideo();
					}, 0);
				} else {
					self.setVideo();
				}
			};

			if(this.target) {
				this.target.innerHTML = '';

				if(this.options.id) {
					hyperaudio.api.getTranscript(this.options.id, function(success) {
						if(success) {
							self.target.innerHTML = this.transcript.content;
							self._trigger(hyperaudio.event.load, {msg: 'Loaded "' + self.options.id + '"'});
						} else {
							self.target.innerHTML = 'Problem with transcript URL.'; // TMP - This sort of things should not be in the lib code, but acting off an error event hander.
							self._error(this.status + ' ' + this.statusText + ' : "' + self.options.id + '"');
						}
						setVideo();
					});

				} else if(this.options.media.transcript) {
					hyperaudio.xhr({
						url: this.options.media.transcript,
						complete: function(event) {
							self.target.innerHTML = this.responseText;
							self._trigger(hyperaudio.event.load, {msg: 'Loaded "' + self.options.src + '"'});
							setVideo();
						},
						error: function(event) {
							self.target.innerHTML = 'Problem with transcript URL.'; // TMP - This sort of things should not be in the lib code, but acting off an error event hander.
							self._error(this.status + ' ' + this.statusText + ' : "' + self.options.src + '"');
							setVideo();
						}
					});
				}
			}
		},

		setVideo: function() {
			var self = this;

			// Setup the player
			if(this.options.player) {

				if(this.options.id && hyperaudio.api.transcript) {

/*
					var hapi = hyperaudio.api,
						path = hapi.options.api + hapi.transcript.media.owner + '/' + hapi.transcript.media.meta.filename;

					// TMP - Have two types of media definition in the API during its dev.
					// In final API, the URLs will be given explicitly - similar to the 1st clause.

					if(hapi.transcript.media.meta.media) {
						this.options.media = {
							youtube: hapi.transcript.media.meta.media.youtube.url,
							mp4: hapi.transcript.media.meta.media.mp4.url,
							webm: hapi.transcript.media.meta.media.webm.url
						};
					} else {
						this.options.media = {
							mp4: path,
							webm: path.replace(/\.mp4$/, '.webm') // Huge assumption!
						};
					}
*/

					var media = hyperaudio.api.transcript.media;

					this.options.media = {};

					if(media && media.source) {
						for(var type in media.source) {
							this.options.media[type] = media.source[type].url;
						}
					}
				}

				this.options.player.load(this.options.media);
				if(this.options.async) {
					setTimeout(function() {
						self.parse();
					}, 0);
				} else {
					this.parse();
				}
			} else {
				this._error('Player not defined');
				this.selectorize();
			}
		},

		parse: function() {
			var self = this,
				opts = this.options;

			if(this.target && opts.player && opts.player.popcorn) {

				var wordList = this.target.querySelectorAll(opts.target + ' ' + opts.word),
					i, l = wordList.length;

				var onNewPara = function(parent) {
					// $("#transcript-content").stop().scrollTo($(parent), 800, {axis:'y',margin:true,offset:{top:0}});
				};

				for(i = 0; i < l; i++) {
					opts.player.popcorn.transcript({
						time: wordList[i].getAttribute(opts.timeAttr) * opts.unit, // seconds
						futureClass: "transcript-grey",
						target: wordList[i],
						onNewPara: onNewPara
					});
				}

				this.target.addEventListener('click', function(event) {
					event.preventDefault();
					if(event.target.nodeName.toLowerCase() === opts.word) {
						var tAttr = event.target.getAttribute(opts.timeAttr),
							time = tAttr * opts.unit;
						if(opts.wordsPlay) {
							opts.player.play(time);
						} else {
							opts.player.currentTime(time);
						}
					}
				}, false);
			}

			this.selectorize();
		},

		selectorize: function() {

			var self = this,
				opts = this.options;

			// if(opts.stage) {
			if(opts.select) {

				// Destroy any existing WordSelect.
				this.deselectorize();

				this.textSelect = new hyperaudio.WordSelect({
					el: opts.target,
					onDragStart: function(e) {
						if(opts.stage) {
							hyperaudio.addClass(opts.stage.target, opts.stage.options.dragdropClass);
							var dragdrop = new hyperaudio.DragDrop({
								dropArea: opts.stage.target,
								init: false,
								onDrop: function(el) {
									self.textSelect.clearSelection();
									this.destroy();

									if ( !el ) {
										return;
									}

									if(opts.id) {
										el.setAttribute(opts.stage.options.idAttr, opts.id); // Pass the transcript ID
									}
									if(opts.media.transcript) {
										el.setAttribute(opts.stage.options.transAttr, opts.media.transcript); // Pass the transcript url
									}
									if(opts.media.mp4) {
										el.setAttribute(opts.stage.options.mp4Attr, opts.media.mp4); // Pass the transcript mp4 url
										el.setAttribute(opts.stage.options.webmAttr, opts.media.webm); // Pass the transcript webm url
									}
									if(opts.media.youtube) {
										el.setAttribute(opts.stage.options.ytAttr, opts.media.youtube); // Pass the transcript youtube url
									}
									el.setAttribute(opts.stage.options.unitAttr, opts.unit); // Pass the transcript Unit
									opts.stage.dropped(el);
								}
							});

							var html = this.getSelection().replace(/ class="[\d\w\s\-]*\s?"/gi, '') + '

';
							dragdrop.init(html, e);
						}
					}
				});
				this.ready = true;
				this._trigger(hyperaudio.event.ready);
			}
		},

		deselectorize: function() {
			if(this.textSelect) {
				this.textSelect.destroy();
			}
			delete this.textSelect;
		},

		getSelection: function() {
			if(this.textSelect) {
				var opts = this.options,
					html = this.textSelect.getSelection(),
					el = document.createElement('div'),
					words, start, end;

				el.innerHTML = html;
				words = el.querySelectorAll(opts.word);

				if(words.length) {
					start = words[0].getAttribute(opts.timeAttr);
					end = words[words.length - 1].getAttribute(opts.timeAttr);
				}

				// The end time is the start of the last word, so needs padding.
				return {
					text: el.textContent,
					start: start,
					end: end
				};
			}
			return {};
		},

		enable: function() {
			this.enabled = true;
		},
		disable: function() {
			this.enabled = false;
		}
	};

	return Transcript;
}(document, hyperaudio));
<commit_msg>Changed Mix section IDs to media IDs from Transcript IDs<commit_after>/* Transcript
 *
 */

var Transcript = (function(document, hyperaudio) {

	function Transcript(options) {

		this.options = hyperaudio.extend({}, this.options, {

			entity: 'TRANSCRIPT', // Not really an option... More like a manifest

			target: '#transcript', // The selector of element where the transcript is written to.

			id: '', // The ID of the transcript.

			// src: '', // [obsolete] The URL of the transcript.
			// video: '', // [obsolete] The URL of the video.

			media: {
				// transcript, mp4, webm urls
			},

			select: true, // Enables selection of the transcript

			wordsPlay: true, // Enables word clicks forcing play

			group: 'p', // Element type used to group paragraphs.
			word: 'a', // Element type used per word.

			timeAttr: 'data-m', // Attribute name that holds the timing information.
			unit: 0.001, // Milliseconds.

			async: true, // When true, some operations are delayed by a timeout.

			stage: null,
			player: null
		}, options);

		// State Flags
		this.ready = false;
		this.enabled = true;

		// Properties
		this.target = typeof this.options.target === 'string' ? document.querySelector(this.options.target) : this.options.target;
		this.textSelect = null;

		// Setup Debug
		if(this.options.DEBUG) {
			this._debug();
		}

		// If we have the info, kick things off
		if(this.options.id || this.options.media.youtube || this.options.media.mp4) {
			this.load();
		}
	}

	Transcript.prototype = {

		load: function(id) {
			var self = this;

			this.ready = false;

			if(typeof id !== 'undefined') {
				if(typeof id === 'string') {
					this.options.id = id;
					this.options.media = {};
				} else if(typeof id === 'object') {
					this.options.id = '';
					this.options.media = id;
				} else {
					this.options.id = '';
					this.options.media = {};
				}
			}

			var setVideo = function() {
				if(self.options.async) {
					setTimeout(function() {
						self.setVideo();
					}, 0);
				} else {
					self.setVideo();
				}
			};

			if(this.target) {
				this.target.innerHTML = '';

				if(this.options.id) {
					hyperaudio.api.getTranscript(this.options.id, function(success) {
						if(success) {
							self.target.innerHTML = this.transcript.content;
							self._trigger(hyperaudio.event.load, {msg: 'Loaded "' + self.options.id + '"'});
						} else {
							self.target.innerHTML = 'Problem with transcript URL.'; // TMP - This sort of things should not be in the lib code, but acting off an error event hander.
							self._error(this.status + ' ' + this.statusText + ' : "' + self.options.id + '"');
						}
						setVideo();
					});

				} else if(this.options.media.transcript) {
					hyperaudio.xhr({
						url: this.options.media.transcript,
						complete: function(event) {
							self.target.innerHTML = this.responseText;
							self._trigger(hyperaudio.event.load, {msg: 'Loaded "' + self.options.src + '"'});
							setVideo();
						},
						error: function(event) {
							self.target.innerHTML = 'Problem with transcript URL.'; // TMP - This sort of things should not be in the lib code, but acting off an error event hander.
							self._error(this.status + ' ' + this.statusText + ' : "' + self.options.src + '"');
							setVideo();
						}
					});
				}
			}
		},

		setVideo: function() {
			var self = this;

			// Setup the player
			if(this.options.player) {

				if(this.options.id && hyperaudio.api.transcript) {

/*
					var hapi = hyperaudio.api,
						path = hapi.options.api + hapi.transcript.media.owner + '/' + hapi.transcript.media.meta.filename;

					// TMP - Have two types of media definition in the API during its dev.
					// In final API, the URLs will be given explicitly - similar to the 1st clause.

					if(hapi.transcript.media.meta.media) {
						this.options.media = {
							youtube: hapi.transcript.media.meta.media.youtube.url,
							mp4: hapi.transcript.media.meta.media.mp4.url,
							webm: hapi.transcript.media.meta.media.webm.url
						};
					} else {
						this.options.media = {
							mp4: path,
							webm: path.replace(/\.mp4$/, '.webm') // Huge assumption!
						};
					}
*/

					var media = hyperaudio.api.transcript.media;

					this.options.media = {
						id: media ? media._id : '' // Store the media ID
					};

					if(media && media.source) {
						for(var type in media.source) {
							this.options.media[type] = media.source[type].url;
						}
					}
				}

				this.options.player.load(this.options.media);
				if(this.options.async) {
					setTimeout(function() {
						self.parse();
					}, 0);
				} else {
					this.parse();
				}
			} else {
				this._error('Player not defined');
				this.selectorize();
			}
		},

		parse: function() {
			var self = this,
				opts = this.options;

			if(this.target && opts.player && opts.player.popcorn) {

				var wordList = this.target.querySelectorAll(opts.target + ' ' + opts.word),
					i, l = wordList.length;

				var onNewPara = function(parent) {
					// $("#transcript-content").stop().scrollTo($(parent), 800, {axis:'y',margin:true,offset:{top:0}});
				};

				for(i = 0; i < l; i++) {
					opts.player.popcorn.transcript({
						time: wordList[i].getAttribute(opts.timeAttr) * opts.unit, // seconds
						futureClass: "transcript-grey",
						target: wordList[i],
						onNewPara: onNewPara
					});
				}

				this.target.addEventListener('click', function(event) {
					event.preventDefault();
					if(event.target.nodeName.toLowerCase() === opts.word) {
						var tAttr = event.target.getAttribute(opts.timeAttr),
							time = tAttr * opts.unit;
						if(opts.wordsPlay) {
							opts.player.play(time);
						} else {
							opts.player.currentTime(time);
						}
					}
				}, false);
			}

			this.selectorize();
		},

		selectorize: function() {

			var self = this,
				opts = this.options;

			// if(opts.stage) {
			if(opts.select) {

				// Destroy any existing WordSelect.
				this.deselectorize();

				this.textSelect = new hyperaudio.WordSelect({
					el: opts.target,
					onDragStart: function(e) {
						if(opts.stage) {
							hyperaudio.addClass(opts.stage.target, opts.stage.options.dragdropClass);
							var dragdrop = new hyperaudio.DragDrop({
								dropArea: opts.stage.target,
								init: false,
								onDrop: function(el) {
									self.textSelect.clearSelection();
									this.destroy();

									if ( !el ) {
										return;
									}

									if(opts.media.id) {
										el.setAttribute(opts.stage.options.idAttr, opts.media.id); // Pass the media ID
									}
									if(opts.media.transcript) {
										el.setAttribute(opts.stage.options.transAttr, opts.media.transcript); // Pass the transcript url
									}
									if(opts.media.mp4) {
										el.setAttribute(opts.stage.options.mp4Attr, opts.media.mp4); // Pass the transcript mp4 url
										el.setAttribute(opts.stage.options.webmAttr, opts.media.webm); // Pass the transcript webm url
									}
									if(opts.media.youtube) {
										el.setAttribute(opts.stage.options.ytAttr, opts.media.youtube); // Pass the transcript youtube url
									}
									el.setAttribute(opts.stage.options.unitAttr, opts.unit); // Pass the transcript Unit
									opts.stage.dropped(el);
								}
							});

							var html = this.getSelection().replace(/ class="[\d\w\s\-]*\s?"/gi, '') + '

';
							dragdrop.init(html, e);
						}
					}
				});
				this.ready = true;
				this._trigger(hyperaudio.event.ready);
			}
		},

		deselectorize: function() {
			if(this.textSelect) {
				this.textSelect.destroy();
			}
			delete this.textSelect;
		},

		getSelection: function() {
			if(this.textSelect) {
				var opts = this.options,
					html = this.textSelect.getSelection(),
					el = document.createElement('div'),
					words, start, end;

				el.innerHTML = html;
				words = el.querySelectorAll(opts.word);

				if(words.length) {
					start = words[0].getAttribute(opts.timeAttr);
					end = words[words.length - 1].getAttribute(opts.timeAttr);
				}

				// The end time is the start of the last word, so needs padding.
				return {
					text: el.textContent,
					start: start,
					end: end
				};
			}
			return {};
		},

		enable: function() {
			this.enabled = true;
		},
		disable: function() {
			this.enabled = false;
		}
	};

	return Transcript;
}(document, hyperaudio));
<|endoftext|>


<commit_before>GTEdit.module('Config', function(Config, App, Backbone, Marionette, $, _) {

  _.extend(Config, {

    Map: {
      basemap: 'Streets',
      center: [45.516484,-122.676339],
      zoom: 12
    },

    imagePath: '/images',

    // shape properties
    polygonOptions: {
      showArea: false,
      shapeOptions: {
        stroke: true,
        color: '#00b1dc',
        weight: 2,
        opacity: 0.8,
        fill: true,
        fillColor: null, //same as color by default
        fillOpacity: 0.2,
        clickable: true
      }
    },
    circleOptions: {
      showArea: false,
      shapeOptions: {
        stroke: true,
        color: '#00b1dc',
        weight: 2,
        opacity: 0.8,
        fill: true,
        fillColor: null, //same as color by default
        fillOpacity: 0.2,
        clickable: true
      }
    },
    drivetimeOptions: {
      icon: L.icon({
        iconUrl: 'img/blue-dot.png',
        iconRetinaUrl: 'img/blue-dot@2x.png',
        iconSize: [12, 12],
        iconAnchor: [6, 6],
        popupAnchor: [0, 0],
        shadowUrl: null,
        shadowRetinaUrl: null,
        shadowSize: [0, 0],
        shadowAnchor: [0, 0]
      })
    },
    editModeOptions: {
      moveIcon: new L.DivIcon({
        iconSize: new L.Point(4, 4),
        className: 'leaflet-div-icon leaflet-editing-icon leaflet-edit-move'
      }),
      resizeIcon: new L.DivIcon({
        iconSize: new L.Point(4, 4),
        className: 'leaflet-div-icon leaflet-editing-icon leaflet-edit-resize'
      })
    }

  });

});<commit_msg>you know that thing I just did? yeah... undo that<commit_after>GTEdit.module('Config', function(Config, App, Backbone, Marionette, $, _) {

  _.extend(Config, {

    Map: {
      basemap: 'Streets',
      center: [45.516484,-122.676339],
      zoom: 12
    },

    imagePath: '/images',

    // shape properties
    polygonOptions: {
      showArea: false,
      shapeOptions: {
        stroke: true,
        color: '#00b1dc',
        weight: 2,
        opacity: 0.8,
        fill: true,
        fillColor: null, //same as color by default
        fillOpacity: 0.2,
        clickable: true
      }
    },
    circleOptions: {
      showArea: false,
      shapeOptions: {
        stroke: true,
        color: '#00b1dc',
        weight: 2,
        opacity: 0.8,
        fill: true,
        fillColor: null, //same as color by default
        fillOpacity: 0.2,
        clickable: true
      }
    },
    drivetimeOptions: {
      icon: L.icon({
        iconUrl: 'img/blue-dot.png',
        iconRetinaUrl: 'img/blue-dot@2x.png',
        iconSize: [12, 12],
        iconAnchor: [6, 6],
        popupAnchor: [0, 0],
        shadowUrl: null,
        shadowRetinaUrl: null,
        shadowSize: [0, 0],
        shadowAnchor: [0, 0]
      })
    }

  });

});<|endoftext|>