<commit_before>/**
 * Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for
 * full list of contributors). Published under the 2-clause BSD license.
 * See license.txt in the OpenLayers distribution or repository for the
 * full text of the license.
 *
 * @requires OpenLayers/SingleFile.js
 */

/**
 * @requires OpenLayers/Geometry.js
 * @requires OpenLayers/Feature/Vector.js
 * @requires OpenLayers/Format/WKT.js
 * @requires OpenLayers/Format/GeoJSON.js
 * @requires OpenLayers/Format/WPSExecute.js
 * @requires OpenLayers/Request.js
 */

/**
 * Class: OpenLayers.WPSProcess
 * Representation of a WPS process. Usually instances of
 * <OpenLayers.WPSProcess> are created by calling 'getProcess' on an
 * <OpenLayers.WPSClient> instance.
 *
 * Currently <OpenLayers.WPSProcess> supports processes that have geometries
 * or features as output, using WKT or GeoJSON as output format. It also
 * supports chaining of processes by using the <output> method to create a
 * handle that is used as process input instead of a static value.
 */
OpenLayers.WPSProcess = OpenLayers.Class({

    /**
     * Property: client
     * {<OpenLayers.WPSClient>} The client that manages this process.
     */
    client: null,

    /**
     * Property: server
     * {String} Local client identifier for this process's server.
     */
    server: null,

    /**
     * Property: identifier
     * {String} Process identifier known to the server.
     */
    identifier: null,

    /**
     * Property: description
     * {Object} DescribeProcess response for this process.
     */
    description: null,

    /**
     * APIProperty: localWPS
     * {String} Service endpoint for locally chained WPS processes. Default is
     *     'http://geoserver/wps'.
     */
    localWPS: 'http://geoserver/wps',

    /**
     * Property: formats
     * {Object} OpenLayers.Format instances keyed by mimetype.
     */
    formats: null,

    /**
     * Property: chained
     * {Integer} Number of chained processes for pending execute requests that
     * don't have a full configuration yet.
     */
    chained: 0,

    /**
     * Property: executeCallbacks
     * {Array} Callbacks waiting to be executed until all chained processes
     * are configured;
     */
    executeCallbacks: null,

    /**
     * Constructor: OpenLayers.WPSProcess
     *
     * Parameters:
     * options - {Object} Object whose properties will be set on the instance.
     *
     * Avaliable options:
     * client - {<OpenLayers.WPSClient>} Mandatory. Client that manages this
     *     process.
     * server - {String} Mandatory. Local client identifier of this process's
     *     server.
     * identifier - {String} Mandatory. Process identifier known to the server.
     */
    initialize: function(options) {
        OpenLayers.Util.extend(this, options);
        this.executeCallbacks = [];
        this.formats = {
            'application/wkt': new OpenLayers.Format.WKT(),
            'application/json': new OpenLayers.Format.GeoJSON()
        };
    },

    /**
     * Method: describe
     * Makes the client issue a DescribeProcess request asynchronously.
     *
     * Parameters:
     * options - {Object} Configuration for the method call
     *
     * Available options:
     * callback - {Function} Callback to execute when the description is
     *     available. Will be called with the parsed description as argument.
     *     Optional.
     * scope - {Object} The scope in which the callback will be executed.
     *     Default is the global object.
     */
    describe: function(options) {
        options = options || {};
        if (!this.description) {
            this.client.describeProcess(this.server, this.identifier, function(description) {
                if (!this.description) {
                    this.parseDescription(description);
                }
                if (options.callback) {
                    options.callback.call(options.scope, this.description);
                }
            }, this);
        } else if (options.callback) {
            var description = this.description;
            window.setTimeout(function() {
                options.callback.call(options.scope, description);
            }, 0);
        }
    },

    /**
     * APIMethod: configure
     * Configure the process, but do not execute it. Use this for processes
     * that are chained as input of a different process by means of the
     * <output> method.
     *
     * Parameters:
     * options - {Object}
     *
     * Returns:
     * {<OpenLayers.WPSProcess>} this process.
     *
     * Available options:
     * inputs - {Object} The inputs for the process, keyed by input identifier.
     *     For spatial data inputs, the value of an input is usually an
     *     <OpenLayers.Geometry>, an <OpenLayers.Feature.Vector> or an array of
     *     geometries or features.
     * callback - {Function} Callback to call when the configuration is
     *     complete. Optional.
     * scope - {Object} Optional scope for the callback.
     */
    configure: function(options) {
        this.describe({
            callback: function() {
                var description = this.description,
                    inputs = options.inputs,
                    input, i, ii;
                for (i=0, ii=description.dataInputs.length; i<ii; ++i) {
                    input = description.dataInputs[i];
                    this.setInputData(input, inputs[input.identifier]);
                }
                if (options.callback) {
                    options.callback.call(options.scope);
                }
            },
            scope: this
        });
        return this;
    },

    /**
     * APIMethod: execute
     * Configures and executes the process
     *
     * Parameters:
     * options - {Object}
     *
     * Available options:
     * inputs - {Object} The inputs for the process, keyed by input identifier.
     *     For spatial data inputs, the value of an input is usually an
     *     <OpenLayers.Geometry>, an <OpenLayers.Feature.Vector> or an array of
     *     geometries or features.
     * output - {String} The identifier of the output to request and parse.
     *     Optional. If not provided, the first output will be requested.
     * success - {Function} Callback to call when the process is complete.
     *     This function is called with an outputs object as argument, which
     *     will have a property with the identifier of the requested output
     *     (or 'result' if output was not configured). For processes that
     *     generate spatial output, the value will be an array of
     *     <OpenLayers.Feature.Vector> instances.
     * scope - {Object} Optional scope for the success callback.
     */
    execute: function(options) {
        this.configure({
            inputs: options.inputs,
            callback: function() {
                var me = this;
                //TODO For now we only deal with a single output
                var outputIndex = this.getOutputIndex(
                    me.description.processOutputs, options.output
                );
                me.setResponseForm({outputIndex: outputIndex});
                (function callback() {
                    OpenLayers.Util.removeItem(me.executeCallbacks, callback);
                    if (me.chained !== 0) {
                        // need to wait until chained processes have a
                        // description and configuration - see chainProcess
                        me.executeCallbacks.push(callback);
                        return;
                    }
                    // all chained processes are added as references now, so
                    // let's proceed.
                    OpenLayers.Request.POST({
                        url: me.client.servers[me.server].url,
                        data: new OpenLayers.Format.WPSExecute().write(me.description),
                        success: function(response) {
                            var output = me.description.processOutputs[outputIndex];
                            var mimeType = me.findMimeType(
                                output.complexOutput.supported.formats
                            );
                            //TODO For now we assume a spatial output
                            var features = me.formats[mimeType].read(response.responseText);
                            if (features instanceof OpenLayers.Feature.Vector) {
                                features = [features];
                            }
                            if (options.success) {
                                var outputs = {};
                                outputs[options.output || 'result'] = features;
                                options.success.call(options.scope, outputs);
                            }
                        },
                        scope: me
                    });
                })();
            },
            scope: this
        });
    },

    /**
     * APIMethod: output
     * Chain an output of a configured process (see <configure>) as input to
     * another process.
     *
     * (code)
     * intersect = client.getProcess('opengeo', 'JTS:intersection');
     * intersect.configure({
     *     // ...
     * });
     * buffer = client.getProcess('opengeo', 'JTS:buffer');
     * buffer.execute({
     *     inputs: {
     *         geom: intersect.output('result'), // <-- here we're chaining
     *         distance: 1
     *     },
     *     // ...
     * });
     * (end)
     *
     * Parameters:
     * identifier - {String} Identifier of the output that we're chaining. If
     *     not provided, the first output will be used.
     */
    output: function(identifier) {
        return new OpenLayers.WPSProcess.ChainLink({
            process: this,
            output: identifier
        });
    },

    /**
     * Method: parseDescription
     * Parses the DescribeProcess response
     *
     * Parameters:
     * description - {Object}
     */
    parseDescription: function(description) {
        var server = this.client.servers[this.server];
        this.description = new OpenLayers.Format.WPSDescribeProcess()
            .read(server.processDescription[this.identifier])
            .processDescriptions[this.identifier];
    },

    /**
     * Method: setInputData
     * Sets the data for a single input
     *
     * Parameters:
     * input - {Object}  An entry from the dataInputs array of the process
     *     description.
     * data - {Mixed} For spatial data inputs, this is usually an
     *     <OpenLayers.Geometry>, an <OpenLayers.Feature.Vector> or an array of
     *     geometries or features.
     */
    setInputData: function(input, data) {
        // clear any previous data
        delete input.data;
        delete input.reference;
        if (data instanceof OpenLayers.WPSProcess.ChainLink) {
            ++this.chained;
            input.reference = {
                method: 'POST',
                href: data.process.server === this.server ?
                    this.localWPS : this.client.servers[data.process.server].url
            };
            data.process.describe({
                callback: function() {
                    --this.chained;
                    this.chainProcess(input, data);
                },
                scope: this
            });
        } else {
            input.data = {};
            var complexData = input.complexData;
            if (complexData) {
                var format = this.findMimeType(complexData.supported.formats);
                input.data.complexData = {
                    mimeType: format,
                    value: this.formats[format].write(this.toFeatures(data))
                };
            } else {
                input.data.literalData = {
                    value: data
                };
            }
        }
    },

    /**
     * Method: setResponseForm
     * Sets the responseForm property of the <execute> payload.
     *
     * Parameters:
     * options - {Object} See below.
     *
     * Available options:
     * outputIndex - {Integer} The index of the output to use. Optional.
     * supportedFormats - {Object} Object with supported mime types as key,
     *     and true as value for supported types. Optional.
     */
    setResponseForm: function(options) {
        options = options || {};
        output = this.description.processOutputs[options.outputIndex || 0];
        this.description.responseForm = {
            rawDataOutput: {
                identifier: output.identifier,
                mimeType: this.findMimeType(output.complexOutput.supported.formats, options.supportedFormats)
            }
        };
    },

    /**
     * Method: getOutputIndex
     * Gets the index of a processOutput by its identifier
     *
     * Parameters:
     * outputs - {Array} The processOutputs array to look at
     * identifier - {String} The identifier of the output
     *
     * Returns
     * {Integer} The index of the processOutput with the provided identifier
     *     in the outputs array.
     */
    getOutputIndex: function(outputs, identifier) {
        var output;
        if (identifier) {
            for (var i=outputs.length-1; i>=0; --i) {
                if (outputs[i].identifier === identifier) {
                    output = i;
                    break;
                }
            }
        } else {
            output = 0;
        }
        return output;
    },

    /**
     * Method: chainProcess
     * Sets a fully configured chained process as input for this process.
     *
     * Parameters:
     * input - {Object} The dataInput that the chained process provides.
     * chainLink - {<OpenLayers.WPSProcess.ChainLink>} The process to chain.
     */
    chainProcess: function(input, chainLink) {
        var output = this.getOutputIndex(
            chainLink.process.description.processOutputs, chainLink.output
        );
        input.reference.mimeType = this.findMimeType(
            input.complexData.supported.formats,
            chainLink.process.description.processOutputs[output].complexOutput.supported.formats
        );
        var formats = {};
        formats[input.reference.mimeType] = true;
        chainLink.process.setResponseForm({
            outputIndex: output,
            supportedFormats: formats
        });
        input.reference.body = chainLink.process.description;
        while (this.executeCallbacks.length > 0) {
            this.executeCallbacks[0]();
        }
    },

    /**
     * Method: toFeatures
     * Converts spatial input into features so it can be processed by
     * <OpenLayers.Format> instances.
     *
     * Parameters:
     * source - {Mixed} An <OpenLayers.Geometry>, an
     *     <OpenLayers.Feature.Vector>, or an array of geometries or features
     *
     * Returns:
     * {Array(<OpenLayers.Feature.Vector>)}
     */
    toFeatures: function(source) {
        var isArray = OpenLayers.Util.isArray(source);
        if (!isArray) {
            source = [source];
        }
        var target = new Array(source.length),
            current;
        for (var i=0, ii=source.length; i<ii; ++i) {
            current = source[i];
            target[i] = current instanceof OpenLayers.Feature.Vector ?
                current : new OpenLayers.Feature.Vector(current);
        }
        return isArray ? target : target[0];
    },

    /**
     * Method: findMimeType
     * Finds a supported mime type.
     *
     * Parameters:
     * sourceFormats - {Object} An object literal with mime types as key and
     *     true as value for supported formats.
     * targetFormats - {Object} Like <sourceFormats>, but optional to check for
     *     supported mime types on a different target than this process.
     *     Default is to check against this process's supported formats.
     *
     * Returns:
     * {String} A supported mime type.
     */
    findMimeType: function(sourceFormats, targetFormats) {
        targetFormats = targetFormats || this.formats;
        for (var f in sourceFormats) {
            if (f in targetFormats) {
                return f;
            }
        }
    },

    CLASS_NAME: "OpenLayers.WPSProcess"

});

/**
 * Class: OpenLayers.WPSProcess.ChainLink
 * Type for chaining processes.
 */
OpenLayers.WPSProcess.ChainLink = OpenLayers.Class({

    /**
     * Property: process
     * {<OpenLayers.WPSProcess>} The process to chain
     */
    process: null,

    /**
     * Property: output
     * {String} The output identifier of the output we are going to use as
     *     input for another process.
     */
    output: null,

    /**
     * Constructor: OpenLayers.WPSProcess.ChainLink
     *
     * Parameters:
     * options - {Object} Properties to set on the instance.
     */
    initialize: function(options) {
        OpenLayers.Util.extend(this, options);
    },

    CLASS_NAME: "OpenLayers.WPSProcess.ChainLink"

});
<commit_msg>Declaring undeclared variable<commit_after>/**
 * Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for
 * full list of contributors). Published under the 2-clause BSD license.
 * See license.txt in the OpenLayers distribution or repository for the
 * full text of the license.
 *
 * @requires OpenLayers/SingleFile.js
 */

/**
 * @requires OpenLayers/Geometry.js
 * @requires OpenLayers/Feature/Vector.js
 * @requires OpenLayers/Format/WKT.js
 * @requires OpenLayers/Format/GeoJSON.js
 * @requires OpenLayers/Format/WPSExecute.js
 * @requires OpenLayers/Request.js
 */

/**
 * Class: OpenLayers.WPSProcess
 * Representation of a WPS process. Usually instances of
 * <OpenLayers.WPSProcess> are created by calling 'getProcess' on an
 * <OpenLayers.WPSClient> instance.
 *
 * Currently <OpenLayers.WPSProcess> supports processes that have geometries
 * or features as output, using WKT or GeoJSON as output format. It also
 * supports chaining of processes by using the <output> method to create a
 * handle that is used as process input instead of a static value.
 */
OpenLayers.WPSProcess = OpenLayers.Class({

    /**
     * Property: client
     * {<OpenLayers.WPSClient>} The client that manages this process.
     */
    client: null,

    /**
     * Property: server
     * {String} Local client identifier for this process's server.
     */
    server: null,

    /**
     * Property: identifier
     * {String} Process identifier known to the server.
     */
    identifier: null,

    /**
     * Property: description
     * {Object} DescribeProcess response for this process.
     */
    description: null,

    /**
     * APIProperty: localWPS
     * {String} Service endpoint for locally chained WPS processes. Default is
     *     'http://geoserver/wps'.
     */
    localWPS: 'http://geoserver/wps',

    /**
     * Property: formats
     * {Object} OpenLayers.Format instances keyed by mimetype.
     */
    formats: null,

    /**
     * Property: chained
     * {Integer} Number of chained processes for pending execute requests that
     * don't have a full configuration yet.
     */
    chained: 0,

    /**
     * Property: executeCallbacks
     * {Array} Callbacks waiting to be executed until all chained processes
     * are configured;
     */
    executeCallbacks: null,

    /**
     * Constructor: OpenLayers.WPSProcess
     *
     * Parameters:
     * options - {Object} Object whose properties will be set on the instance.
     *
     * Avaliable options:
     * client - {<OpenLayers.WPSClient>} Mandatory. Client that manages this
     *     process.
     * server - {String} Mandatory. Local client identifier of this process's
     *     server.
     * identifier - {String} Mandatory. Process identifier known to the server.
     */
    initialize: function(options) {
        OpenLayers.Util.extend(this, options);
        this.executeCallbacks = [];
        this.formats = {
            'application/wkt': new OpenLayers.Format.WKT(),
            'application/json': new OpenLayers.Format.GeoJSON()
        };
    },

    /**
     * Method: describe
     * Makes the client issue a DescribeProcess request asynchronously.
     *
     * Parameters:
     * options - {Object} Configuration for the method call
     *
     * Available options:
     * callback - {Function} Callback to execute when the description is
     *     available. Will be called with the parsed description as argument.
     *     Optional.
     * scope - {Object} The scope in which the callback will be executed.
     *     Default is the global object.
     */
    describe: function(options) {
        options = options || {};
        if (!this.description) {
            this.client.describeProcess(this.server, this.identifier, function(description) {
                if (!this.description) {
                    this.parseDescription(description);
                }
                if (options.callback) {
                    options.callback.call(options.scope, this.description);
                }
            }, this);
        } else if (options.callback) {
            var description = this.description;
            window.setTimeout(function() {
                options.callback.call(options.scope, description);
            }, 0);
        }
    },

    /**
     * APIMethod: configure
     * Configure the process, but do not execute it. Use this for processes
     * that are chained as input of a different process by means of the
     * <output> method.
     *
     * Parameters:
     * options - {Object}
     *
     * Returns:
     * {<OpenLayers.WPSProcess>} this process.
     *
     * Available options:
     * inputs - {Object} The inputs for the process, keyed by input identifier.
     *     For spatial data inputs, the value of an input is usually an
     *     <OpenLayers.Geometry>, an <OpenLayers.Feature.Vector> or an array of
     *     geometries or features.
     * callback - {Function} Callback to call when the configuration is
     *     complete. Optional.
     * scope - {Object} Optional scope for the callback.
     */
    configure: function(options) {
        this.describe({
            callback: function() {
                var description = this.description,
                    inputs = options.inputs,
                    input, i, ii;
                for (i=0, ii=description.dataInputs.length; i<ii; ++i) {
                    input = description.dataInputs[i];
                    this.setInputData(input, inputs[input.identifier]);
                }
                if (options.callback) {
                    options.callback.call(options.scope);
                }
            },
            scope: this
        });
        return this;
    },

    /**
     * APIMethod: execute
     * Configures and executes the process
     *
     * Parameters:
     * options - {Object}
     *
     * Available options:
     * inputs - {Object} The inputs for the process, keyed by input identifier.
     *     For spatial data inputs, the value of an input is usually an
     *     <OpenLayers.Geometry>, an <OpenLayers.Feature.Vector> or an array of
     *     geometries or features.
     * output - {String} The identifier of the output to request and parse.
     *     Optional. If not provided, the first output will be requested.
     * success - {Function} Callback to call when the process is complete.
     *     This function is called with an outputs object as argument, which
     *     will have a property with the identifier of the requested output
     *     (or 'result' if output was not configured). For processes that
     *     generate spatial output, the value will be an array of
     *     <OpenLayers.Feature.Vector> instances.
     * scope - {Object} Optional scope for the success callback.
     */
    execute: function(options) {
        this.configure({
            inputs: options.inputs,
            callback: function() {
                var me = this;
                //TODO For now we only deal with a single output
                var outputIndex = this.getOutputIndex(
                    me.description.processOutputs, options.output
                );
                me.setResponseForm({outputIndex: outputIndex});
                (function callback() {
                    OpenLayers.Util.removeItem(me.executeCallbacks, callback);
                    if (me.chained !== 0) {
                        // need to wait until chained processes have a
                        // description and configuration - see chainProcess
                        me.executeCallbacks.push(callback);
                        return;
                    }
                    // all chained processes are added as references now, so
                    // let's proceed.
                    OpenLayers.Request.POST({
                        url: me.client.servers[me.server].url,
                        data: new OpenLayers.Format.WPSExecute().write(me.description),
                        success: function(response) {
                            var output = me.description.processOutputs[outputIndex];
                            var mimeType = me.findMimeType(
                                output.complexOutput.supported.formats
                            );
                            //TODO For now we assume a spatial output
                            var features = me.formats[mimeType].read(response.responseText);
                            if (features instanceof OpenLayers.Feature.Vector) {
                                features = [features];
                            }
                            if (options.success) {
                                var outputs = {};
                                outputs[options.output || 'result'] = features;
                                options.success.call(options.scope, outputs);
                            }
                        },
                        scope: me
                    });
                })();
            },
            scope: this
        });
    },

    /**
     * APIMethod: output
     * Chain an output of a configured process (see <configure>) as input to
     * another process.
     *
     * (code)
     * intersect = client.getProcess('opengeo', 'JTS:intersection');
     * intersect.configure({
     *     // ...
     * });
     * buffer = client.getProcess('opengeo', 'JTS:buffer');
     * buffer.execute({
     *     inputs: {
     *         geom: intersect.output('result'), // <-- here we're chaining
     *         distance: 1
     *     },
     *     // ...
     * });
     * (end)
     *
     * Parameters:
     * identifier - {String} Identifier of the output that we're chaining. If
     *     not provided, the first output will be used.
     */
    output: function(identifier) {
        return new OpenLayers.WPSProcess.ChainLink({
            process: this,
            output: identifier
        });
    },

    /**
     * Method: parseDescription
     * Parses the DescribeProcess response
     *
     * Parameters:
     * description - {Object}
     */
    parseDescription: function(description) {
        var server = this.client.servers[this.server];
        this.description = new OpenLayers.Format.WPSDescribeProcess()
            .read(server.processDescription[this.identifier])
            .processDescriptions[this.identifier];
    },

    /**
     * Method: setInputData
     * Sets the data for a single input
     *
     * Parameters:
     * input - {Object}  An entry from the dataInputs array of the process
     *     description.
     * data - {Mixed} For spatial data inputs, this is usually an
     *     <OpenLayers.Geometry>, an <OpenLayers.Feature.Vector> or an array of
     *     geometries or features.
     */
    setInputData: function(input, data) {
        // clear any previous data
        delete input.data;
        delete input.reference;
        if (data instanceof OpenLayers.WPSProcess.ChainLink) {
            ++this.chained;
            input.reference = {
                method: 'POST',
                href: data.process.server === this.server ?
                    this.localWPS : this.client.servers[data.process.server].url
            };
            data.process.describe({
                callback: function() {
                    --this.chained;
                    this.chainProcess(input, data);
                },
                scope: this
            });
        } else {
            input.data = {};
            var complexData = input.complexData;
            if (complexData) {
                var format = this.findMimeType(complexData.supported.formats);
                input.data.complexData = {
                    mimeType: format,
                    value: this.formats[format].write(this.toFeatures(data))
                };
            } else {
                input.data.literalData = {
                    value: data
                };
            }
        }
    },

    /**
     * Method: setResponseForm
     * Sets the responseForm property of the <execute> payload.
     *
     * Parameters:
     * options - {Object} See below.
     *
     * Available options:
     * outputIndex - {Integer} The index of the output to use. Optional.
     * supportedFormats - {Object} Object with supported mime types as key,
     *     and true as value for supported types. Optional.
     */
    setResponseForm: function(options) {
        options = options || {};
        var output = this.description.processOutputs[options.outputIndex || 0];
        this.description.responseForm = {
            rawDataOutput: {
                identifier: output.identifier,
                mimeType: this.findMimeType(output.complexOutput.supported.formats, options.supportedFormats)
            }
        };
    },

    /**
     * Method: getOutputIndex
     * Gets the index of a processOutput by its identifier
     *
     * Parameters:
     * outputs - {Array} The processOutputs array to look at
     * identifier - {String} The identifier of the output
     *
     * Returns
     * {Integer} The index of the processOutput with the provided identifier
     *     in the outputs array.
     */
    getOutputIndex: function(outputs, identifier) {
        var output;
        if (identifier) {
            for (var i=outputs.length-1; i>=0; --i) {
                if (outputs[i].identifier === identifier) {
                    output = i;
                    break;
                }
            }
        } else {
            output = 0;
        }
        return output;
    },

    /**
     * Method: chainProcess
     * Sets a fully configured chained process as input for this process.
     *
     * Parameters:
     * input - {Object} The dataInput that the chained process provides.
     * chainLink - {<OpenLayers.WPSProcess.ChainLink>} The process to chain.
     */
    chainProcess: function(input, chainLink) {
        var output = this.getOutputIndex(
            chainLink.process.description.processOutputs, chainLink.output
        );
        input.reference.mimeType = this.findMimeType(
            input.complexData.supported.formats,
            chainLink.process.description.processOutputs[output].complexOutput.supported.formats
        );
        var formats = {};
        formats[input.reference.mimeType] = true;
        chainLink.process.setResponseForm({
            outputIndex: output,
            supportedFormats: formats
        });
        input.reference.body = chainLink.process.description;
        while (this.executeCallbacks.length > 0) {
            this.executeCallbacks[0]();
        }
    },

    /**
     * Method: toFeatures
     * Converts spatial input into features so it can be processed by
     * <OpenLayers.Format> instances.
     *
     * Parameters:
     * source - {Mixed} An <OpenLayers.Geometry>, an
     *     <OpenLayers.Feature.Vector>, or an array of geometries or features
     *
     * Returns:
     * {Array(<OpenLayers.Feature.Vector>)}
     */
    toFeatures: function(source) {
        var isArray = OpenLayers.Util.isArray(source);
        if (!isArray) {
            source = [source];
        }
        var target = new Array(source.length),
            current;
        for (var i=0, ii=source.length; i<ii; ++i) {
            current = source[i];
            target[i] = current instanceof OpenLayers.Feature.Vector ?
                current : new OpenLayers.Feature.Vector(current);
        }
        return isArray ? target : target[0];
    },

    /**
     * Method: findMimeType
     * Finds a supported mime type.
     *
     * Parameters:
     * sourceFormats - {Object} An object literal with mime types as key and
     *     true as value for supported formats.
     * targetFormats - {Object} Like <sourceFormats>, but optional to check for
     *     supported mime types on a different target than this process.
     *     Default is to check against this process's supported formats.
     *
     * Returns:
     * {String} A supported mime type.
     */
    findMimeType: function(sourceFormats, targetFormats) {
        targetFormats = targetFormats || this.formats;
        for (var f in sourceFormats) {
            if (f in targetFormats) {
                return f;
            }
        }
    },

    CLASS_NAME: "OpenLayers.WPSProcess"

});

/**
 * Class: OpenLayers.WPSProcess.ChainLink
 * Type for chaining processes.
 */
OpenLayers.WPSProcess.ChainLink = OpenLayers.Class({

    /**
     * Property: process
     * {<OpenLayers.WPSProcess>} The process to chain
     */
    process: null,

    /**
     * Property: output
     * {String} The output identifier of the output we are going to use as
     *     input for another process.
     */
    output: null,

    /**
     * Constructor: OpenLayers.WPSProcess.ChainLink
     *
     * Parameters:
     * options - {Object} Properties to set on the instance.
     */
    initialize: function(options) {
        OpenLayers.Util.extend(this, options);
    },

    CLASS_NAME: "OpenLayers.WPSProcess.ChainLink"

});
<|endoftext|>


<commit_before>'use strict'

angular.module('antismash.db.ui.genome', [])
  .controller('GenomeCtrl', ['$scope', '$window', 'GenomeSvc',
    function ($scope, $window, GenomeSvc) {
    var vm = this;
    vm.currentGenome = null;
    vm.getMibigUrl = getMibigUrl;
    vm.showCluster = showCluster;
    vm.pending = false;

    if (vm.genomeId){
      vm.pending = true;
      GenomeSvc.getGenome(vm.genomeId).then(
        function (result) {
          vm.pending = false;
          vm.currentGenome = result.data;
        }
      );
    }

    $scope.$on("genomeSelected", function(event, args){
      if (vm.currentGenome &&
          vm.currentGenome.length > 0 &&
          vm.currentGenome[0].acc.toLowerCase() == args.toLowerCase()){
        return;
      }
      vm.pending = true;
      vm.currentGenome = null;
      GenomeSvc.getGenome(args).then(function(result){
        vm.pending = false;
        vm.currentGenome = result.data;
      })
    })

    function showCluster(entry) {
      var cluster_acc = entry.acc + '_c' + entry.cluster_number;
      $window.open('/output/' + entry.acc + '/index.html#cluster-' + entry.cluster_number, '_new');
    };

    function getMibigUrl(accession) {
      if (!accession) {
        return '';
      }
      var acc = accession.split(/_/)[0];
      return "http://mibig.secondarymetabolites.org/repository/" + acc + "/index.html#cluster-1";
    };
  }])
  .factory('GenomeSvc', function ($http) {
    var getGenome = function(genomeId) {
      return $http.get('/api/v1.0/genome/' + genomeId);
    };

    return {
      getGenome: getGenome
    };
  })
  .directive('asGenome', function () {
    return {
      scope: {},
      bindToController: {
        genomeId: "@"
      },
      templateUrl: 'genome/genome.html',
      controller: 'GenomeCtrl',
      controllerAs: 'ctrl'
    }
  });
<commit_msg>genome: Reduce code duplication<commit_after>'use strict'

angular.module('antismash.db.ui.genome', [])
  .controller('GenomeCtrl', ['$scope', '$window', 'GenomeSvc',
    function ($scope, $window, GenomeSvc) {
    var vm = this;
    vm.currentGenome = null;
    vm.getMibigUrl = getMibigUrl;
    vm.showCluster = showCluster;
    vm.pending = false;

    if (vm.genomeId){
      loadGenome(vm.genomeId);
    }

    $scope.$on("genomeSelected", function(event, args){
      if (vm.currentGenome &&
          vm.currentGenome.length > 0 &&
          vm.currentGenome[0].acc.toLowerCase() == args.toLowerCase()){
        return;
      }
      loadGenome(args);
    })

    function showCluster(entry) {
      var cluster_acc = entry.acc + '_c' + entry.cluster_number;
      $window.open('/output/' + entry.acc + '/index.html#cluster-' + entry.cluster_number, '_new');
    };

    function getMibigUrl(accession) {
      if (!accession) {
        return '';
      }
      var acc = accession.split(/_/)[0];
      return "http://mibig.secondarymetabolites.org/repository/" + acc + "/index.html#cluster-1";
    };

    function loadGenome(genome_id) {
      vm.pending = true;
      GenomeSvc.getGenome(genome_id).then(
        function (result) {
          vm.pending = false;
          vm.currentGenome = result.data;
        }
      );
    };
  }])
  .factory('GenomeSvc', function ($http) {
    var getGenome = function(genomeId) {
      return $http.get('/api/v1.0/genome/' + genomeId);
    };

    return {
      getGenome: getGenome
    };
  })
  .directive('asGenome', function () {
    return {
      scope: {},
      bindToController: {
        genomeId: "@"
      },
      templateUrl: 'genome/genome.html',
      controller: 'GenomeCtrl',
      controllerAs: 'ctrl'
    }
  });
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Text } from 'react-native';

import styles from '../../styles/styles.ios';
import InPageImage from '../inPageImage';
import AnimalText from '../animalText';
import AnimalTemplate from '../animalTemplate';

const IMAGES = [
  require('../../images/animals/dzelada/01.jpg'),
  require('../../images/animals/dzelada/02.jpg'),
  require('../../images/animals/dzelada/03.jpg'),
];

const THUMBNAILS = [
  require('../../images/animals/dzelada/01-thumb.jpg'),
  require('../../images/animals/dzelada/02-thumb.jpg'),
  require('../../images/animals/dzelada/03-thumb.jpg'),
];

var AnimalDetail = React.createClass({
  render() {
    return (
      <AnimalTemplate firstIndex={[2]} thumbnails={THUMBNAILS} images={IMAGES} navigator={this.props.navigator}>
        <AnimalText>
          Dželada je opice, která je velmi podobná paviánům. Od nich se však liší červenou lysinou na prsou. Díky tomuto charakteristickému znaku se dželadám přezdívá „pavián s krvácejícím srdcem“.
        </AnimalText>
        <AnimalText>
          Průměrná délka života v zajetí bývá 30 let, v přírodě se odhaduje na 24 let. Volně se vyskytují jen na horských loukách etiopských skalnatých masivů. Jsou na toto prostředí dokonale adaptované, noci tráví schoulené na okraji strmých svahů. Může se to sice jevit nebezpečně, ale velkou výhodou je, že se k nim nedostanou téměř žádní predátoři. Vysokohorskému prostředí se dželady přizpůsobily mimo jiné i svým pozadím, které je velmi podobné tomu lidskému. Sedací partie těchto savců jsou ideálně uzpůsobeny vysedávání na ostrých skalách. Evoluční biologové uvažují, zda mohly v podobných podmínkách vzniknout i naše sedací partie.
        </AnimalText>
      <AnimalTemplate firstIndex={[0]} thumbnails={THUMBNAILS} images={IMAGES} navigator={this.props.navigator}>
        <AnimalText>
          Po zemi se pohybují po všech čtyřech končetinách. Jejich protistojný palec jim pomáhá při hledání a zpracování potravy, umožňuje dokonalé třídění trávy a travních semen. Krátké a robustní prsty jim zároveň umožňují v období sucha vykopávat hlízy a kořínky. Krmí se vsedě, tudíž mají obě ruce volné. Jednou rukou třídí a v druhé shromažďují potravu, dokud si nevytvoří sousto vhodné ke žvýkání a spolknutí.
        </AnimalText>
        <AnimalText>
          U těchto opic také můžeme pozorovat různé expresivní výrazy, například přivírání očních víček k vyjádření dominance. Při pocitu strachu či ohrožení ohrnují horní ret až téměř k nosu, vyzývají tak také oponenta ke konfliktní situaci. Mezi další osvojenou mimiku patří zívání, upřené pohledy, strnulé zírání, a dokonce pohyby rtů. Komunikují spolu i akusticky, tedy pomocí varovných signálů jako například vřískání, mručení či štěkání. Pachovou komunikaci užívají v průběhu páření samice. Hmatová komunikace je určena většinou k posílení sociálních vztahů. Jedinci si navzájem probírají srst či jako jistou formu pozdravu třou nosy o sebe. Stejně jako většina primátů používají fyzický kontakt také při péči o mláďata.
        </AnimalText>
      <AnimalTemplate firstIndex={[1]} thumbnails={THUMBNAILS} images={IMAGES} navigator={this.props.navigator}>
        <AnimalText>
          Další zajímavostí je fakt, že samci tohoto druhu jsou sice větší a silnější, ale samice jsou dominantnější. Pokud u samec na svou roli v tlupě nestačí, vyberou si samice jeho následníka. Tito samci, kteří o své místo v tlupě přišli, nebo na něj naopak teprve čekají, si vytváří vlastní, samčí skupiny. S rodinami se pak často spojují do větších tlup o mnoha desítkách členů. Zatím největší pozorovaná skupina měla 670 členů.
        </AnimalText>
        <AnimalText>
          Tímto živočišným druhem se pyšní pouze patnáct evropských zoologických zahrad a naše zoo patří právě mezi ně. A to se třemi samci, kteří se jmenují Heiko, Helge a Asrak. Heiko i Helge pochází z Rheine (Německo) a oba nový domov poznali 25. 11. 2005. Heiko se narodil 21. 10. 2000 a Helge 11. 11. 1999. Třetí samec Asrak se narodil 26. 7. 2000 ve Wilhelma Zoo (Stuttgart) a k nám dorazil 30. 11. 2008.
        </AnimalText>
      </AnimalTemplate>
    );
  }
});

module.exports = AnimalDetail;
<commit_msg>Update dzelada.adult.js<commit_after>import React, { Component } from 'react';
import { Text } from 'react-native';

import styles from '../../styles/styles.ios';
import InPageImage from '../inPageImage';
import AnimalText from '../animalText';
import AnimalTemplate from '../animalTemplate';

const IMAGES = [
  require('../../images/animals/dzelada/01.jpg'),
  require('../../images/animals/dzelada/02.jpg'),
  require('../../images/animals/dzelada/03.jpg'),
];

const THUMBNAILS = [
  require('../../images/animals/dzelada/01-thumb.jpg'),
  require('../../images/animals/dzelada/02-thumb.jpg'),
  require('../../images/animals/dzelada/03-thumb.jpg'),
];

var AnimalDetail = React.createClass({
  render() {
    return (
      <AnimalTemplate firstIndex={[2]} thumbnails={THUMBNAILS} images={IMAGES} navigator={this.props.navigator}>
        <AnimalText>
          Dželada je opice, která je velmi podobná paviánům. Od nich se však liší červenou lysinou na prsou. Díky tomuto charakteristickému znaku se dželadám přezdívá „pavián s krvácejícím srdcem“.
        </AnimalText>
        <AnimalText>
          Průměrná délka života v zajetí bývá 30 let, v přírodě se odhaduje na 24 let. Volně se vyskytují jen na horských loukách etiopských skalnatých masivů. Jsou na toto prostředí dokonale adaptované, noci tráví schoulené na okraji strmých svahů. Může se to sice jevit nebezpečně, ale velkou výhodou je, že se k nim nedostanou téměř žádní predátoři. Vysokohorskému prostředí se dželady přizpůsobily mimo jiné i svým pozadím, které je velmi podobné tomu lidskému. Sedací partie těchto savců jsou ideálně uzpůsobeny vysedávání na ostrých skalách. Evoluční biologové uvažují, zda mohly v podobných podmínkách vzniknout i naše sedací partie.
        </AnimalText>
      <AnimalTemplate firstIndex={[0]} thumbnails={THUMBNAILS} images={IMAGES} navigator={this.props.navigator} />
        <AnimalText>
          Po zemi se pohybují po všech čtyřech končetinách. Jejich protistojný palec jim pomáhá při hledání a zpracování potravy, umožňuje dokonalé třídění trávy a travních semen. Krátké a robustní prsty jim zároveň umožňují v období sucha vykopávat hlízy a kořínky. Krmí se vsedě, tudíž mají obě ruce volné. Jednou rukou třídí a v druhé shromažďují potravu, dokud si nevytvoří sousto vhodné ke žvýkání a spolknutí.
        </AnimalText>
        <AnimalText>
          U těchto opic také můžeme pozorovat různé expresivní výrazy, například přivírání očních víček k vyjádření dominance. Při pocitu strachu či ohrožení ohrnují horní ret až téměř k nosu, vyzývají tak také oponenta ke konfliktní situaci. Mezi další osvojenou mimiku patří zívání, upřené pohledy, strnulé zírání, a dokonce pohyby rtů. Komunikují spolu i akusticky, tedy pomocí varovných signálů jako například vřískání, mručení či štěkání. Pachovou komunikaci užívají v průběhu páření samice. Hmatová komunikace je určena většinou k posílení sociálních vztahů. Jedinci si navzájem probírají srst či jako jistou formu pozdravu třou nosy o sebe. Stejně jako většina primátů používají fyzický kontakt také při péči o mláďata.
        </AnimalText>
      <AnimalTemplate firstIndex={[1]} thumbnails={THUMBNAILS} images={IMAGES} navigator={this.props.navigator} />
        <AnimalText>
          Další zajímavostí je fakt, že samci tohoto druhu jsou sice větší a silnější, ale samice jsou dominantnější. Pokud u samec na svou roli v tlupě nestačí, vyberou si samice jeho následníka. Tito samci, kteří o své místo v tlupě přišli, nebo na něj naopak teprve čekají, si vytváří vlastní, samčí skupiny. S rodinami se pak často spojují do větších tlup o mnoha desítkách členů. Zatím největší pozorovaná skupina měla 670 členů.
        </AnimalText>
        <AnimalText>
          Tímto živočišným druhem se pyšní pouze patnáct evropských zoologických zahrad a naše zoo patří právě mezi ně. A to se třemi samci, kteří se jmenují Heiko, Helge a Asrak. Heiko i Helge pochází z Rheine (Německo) a oba nový domov poznali 25. 11. 2005. Heiko se narodil 21. 10. 2000 a Helge 11. 11. 1999. Třetí samec Asrak se narodil 26. 7. 2000 ve Wilhelma Zoo (Stuttgart) a k nám dorazil 30. 11. 2008.
        </AnimalText>
      </AnimalTemplate>
    );
  }
});

module.exports = AnimalDetail;
<|endoftext|>


<commit_before>/**
 * Finds the salesforce viewstate string, if any, base64 decodes it, and returns its length.
 * This means the result will be blob size, not base64 string size - which is how SFDC calculates it for limit checking
 * @return {integer|null}
 */
var calculateViewstateSize = function(){
    var restult;
    try{
        result = atob(document.getElementById('com.salesforce.visualforce.ViewState').value).length;
    }catch(ex){
        result = null;
    }
    return result;
};

/**
 * Get cookie value
 * @param key
 * @return {String|null}
 */
var getCookie = function(key) {
	var decode = function(value) {return decodeURIComponent(value.replace(/\+/g, ' '));};
	var cookies = document.cookie.split('; ');
	for (var i = 0, l = cookies.length; i < l; i++) {
		var parts = cookies[i].split('=');
		if (decode(parts.shift()) === key) {
			//success; found the key!
			return decode(parts.join('='));
		}
	}
	//failure; no such key
	return null;
};

/**
 * Get URL parameters
 * @return {Array}
 */
var getUrlParam = function(param) {
	var hash, params = [];
	var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
	for(var i = 0; i < hashes.length; i++)    {
		hash = hashes[i].split('=');
		params.push(hash[0]);
		params[hash[0]] = hash[1];
	}
	return params[param] || null;
};

/**
 * Good ol Carlos - get record Id
 * @param url
 */
var getCurrentRecordId = function(url) {
	var href, iframehtml, id, theMatch, startParam;
	try{
		startParam = getUrlParam('timetracker_start');
	}catch(err){
		console.log(err);
	}

	var match;
	if (match = url.match(/\.com\/\w{15}|\.com\/\w{18}/)) {
		//success; captured id from salesforce.com/000xxxxxxxxxxxxXXX)
		return match[0].substr(5);
	} else if (match = url.match(/id\=\w{15}|id\=\w{18}/)) {
		//success; captured id from salesforce.com/id=000xxxxxxxxxxxxXXX
		return match[0].substr(3);
	} else {
		//failure; not on a page with an id
		return null;
	}
};

var context = {
	currentRecord : getCurrentRecordId(window.location.href),
	sessionId     : getCookie('sid'),
	orgId         : getCookie('sid').substring(0,15),
	sid_Client    : getCookie('sid_Client'),
	pod           : null,
	sfhost        : null
};

( function() {
    var instance = null;
    var hostname = window.location.host;
    //modified from http://stackoverflow.com/a/9722468/740787
    var parts = hostname.split("\.");
    if (parts.length == 3)
        instance = parts[0];
    else if (parts.length == 5)
        instance = parts[1];
    else if (parts.length == 4 && parts[1] === "my")
        instance = parts[0]+".my";
    else if (parts.length == 4)
        // my domain on sandbox instances
        instance = parts[0]+"."+parts[1];

    if(instance === null)
        throw new Error("Unable to determine salesforce instance");
    context.pod = instance;

    var isVf = hostname.indexOf(".visual.force.com") > 0;
    if(parts[0].indexOf("--") > 0 && isVf){ //using my domain & this is sandbox or managed vf page
        var subparts = parts[0].split("--");
        context.sfhost = hostname.replace("--"+subparts[subparts.length-1],"").replace(".visual.force.com",".salesforce.com").replace(instance,"my");
    }else if(parts[0].indexOf("--") > 0 && !isVf){ //named sandbox
    	context.sfhost = hostname;
    }else{
        context.sfhost = context.pod + ".salesforce.com";
    }

}());

chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
	if(request.command == 'getContext')
	    sendResponse(context);
	else if(request.command == 'getViewstateSize')
	    sendResponse(calculateViewstateSize());
	else
	    throw 'Unknown command ' + request.command;
});
<commit_msg>Unlike apex javascript has switch statements!<commit_after>/**
 * Finds the salesforce viewstate string, if any, base64 decodes it, and returns its length.
 * This means the result will be blob size, not base64 string size - which is how SFDC calculates it for limit checking
 * @return {integer|null}
 */
var calculateViewstateSize = function(){
    var restult;
    try{
        result = atob(document.getElementById('com.salesforce.visualforce.ViewState').value).length;
    }catch(ex){
        result = null;
    }
    return result;
};

/**
 * Get cookie value
 * @param key
 * @return {String|null}
 */
var getCookie = function(key) {
	var decode = function(value) {return decodeURIComponent(value.replace(/\+/g, ' '));};
	var cookies = document.cookie.split('; ');
	for (var i = 0, l = cookies.length; i < l; i++) {
		var parts = cookies[i].split('=');
		if (decode(parts.shift()) === key) {
			//success; found the key!
			return decode(parts.join('='));
		}
	}
	//failure; no such key
	return null;
};

/**
 * Get URL parameters
 * @return {Array}
 */
var getUrlParam = function(param) {
	var hash, params = [];
	var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
	for(var i = 0; i < hashes.length; i++)    {
		hash = hashes[i].split('=');
		params.push(hash[0]);
		params[hash[0]] = hash[1];
	}
	return params[param] || null;
};

/**
 * Good ol Carlos - get record Id
 * @param url
 */
var getCurrentRecordId = function(url) {
	var href, iframehtml, id, theMatch, startParam;
	try{
		startParam = getUrlParam('timetracker_start');
	}catch(err){
		console.log(err);
	}

	var match;
	if (match = url.match(/\.com\/\w{15}|\.com\/\w{18}/)) {
		//success; captured id from salesforce.com/000xxxxxxxxxxxxXXX)
		return match[0].substr(5);
	} else if (match = url.match(/id\=\w{15}|id\=\w{18}/)) {
		//success; captured id from salesforce.com/id=000xxxxxxxxxxxxXXX
		return match[0].substr(3);
	} else {
		//failure; not on a page with an id
		return null;
	}
};

var context = {
	currentRecord : getCurrentRecordId(window.location.href),
	sessionId     : getCookie('sid'),
	orgId         : getCookie('sid').substring(0,15),
	sid_Client    : getCookie('sid_Client'),
	pod           : null,
	sfhost        : null
};

( function() {
    var instance = null;
    var hostname = window.location.host;
    //modified from http://stackoverflow.com/a/9722468/740787
    var parts = hostname.split("\.");
    if (parts.length == 3)
        instance = parts[0];
    else if (parts.length == 5)
        instance = parts[1];
    else if (parts.length == 4 && parts[1] === "my")
        instance = parts[0]+".my";
    else if (parts.length == 4)
        // my domain on sandbox instances
        instance = parts[0]+"."+parts[1];

    if(instance === null)
        throw new Error("Unable to determine salesforce instance");
    context.pod = instance;

    var isVf = hostname.indexOf(".visual.force.com") > 0;
    if(parts[0].indexOf("--") > 0 && isVf){ //using my domain & this is sandbox or managed vf page
        var subparts = parts[0].split("--");
        context.sfhost = hostname.replace("--"+subparts[subparts.length-1],"").replace(".visual.force.com",".salesforce.com").replace(instance,"my");
    }else if(parts[0].indexOf("--") > 0 && !isVf){ //named sandbox
    	context.sfhost = hostname;
    }else{
        context.sfhost = context.pod + ".salesforce.com";
    }

}());

chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
	switch(request.command){
        case 'getContext':
            sendResponse(context);
            break;
        case 'getViewstateSize':
            sendResponse(calculateViewstateSize());
            break;
        default:
            throw 'Unknown command ' + request.command;
    }
});
<|endoftext|>


<commit_before>/**
 * Created by mahowa on 11/29/2016.
 */
years = [1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013];
var selectedyear1 = years[0];
var selectedyear2 = years[years.length-1];
function createYear() {
    var margin = {top: 10, right: 40, bottom: 35, left: 40},
        width = 960 - margin.left - margin.right,
        height = 65 - margin.top - margin.bottom;

    x = d3.scaleBand()
        .domain(years)
        .range([0, width]);

    var svg = d3.select("#years").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    svg.append("g")
        .attr("class", "axis axis--grid")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(x).tickSize(-height))
        .selectAll("text")
        .style("text-anchor","end")
        .attr("dx","0em")
        .attr("dy","1.5em")
        .attr("transform","rotate(-55)")
        .style("font-size", "12px")

    svg.append("g")
        .attr("class", "brush")
        .call(d3.brushX()
            .extent([[0, 0], [width, height]])
            .on("end", brushended));
}
function brushended() {
    var self = this;
    selectedyear1 = years[0];
    selectedyear2 = years[years.length-1];
    if (!d3.event.sourceEvent) return; // Only transition after input.
    if (!d3.event.selection) return; // Ignore empty selections.

    var y = d3.event.selection;
    var eachBand = x.step();
    var index = Math.round((y[0] / eachBand));
    var year1 = x.domain()[index];

    index = Math.round((y[1] / eachBand));
    var year2 = x.domain()[index];

    if(year2 === undefined)
        year2 = years[years.length -1];

    if(year1 == undefined)
        year1 =year2;

    selectedyear1 = year1;
    selectedyear2 = year2;
    //

    _WordCloud.setGlobal(false);
    //Wait for the data to reload
    setTimeout(function(){
        chooseData();
    }, 100);

}<commit_msg>Fixed year brushing...<commit_after>/**
 * Created by mahowa on 11/29/2016.
 */
years = [1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013];
var selectedyear1 = years[0];
var selectedyear2 = years[years.length-1];
function createYear() {
    var margin = {top: 10, right: 40, bottom: 35, left: 40},
        width = 960 - margin.left - margin.right,
        height = 65 - margin.top - margin.bottom;

    x = d3.scaleBand()
        .domain(years)
        .range([0, width]);

    var svg = d3.select("#years").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    svg.append("g")
        .attr("class", "axis axis--grid")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(x).tickSize(-height))
        .selectAll("text")
        .style("text-anchor","end")
        .attr("dx","0em")
        .attr("dy","1.5em")
        .attr("transform","rotate(0)")
        .style("font-size", "12px")

    svg.append("g")
        .attr("class", "brush")
        .call(d3.brushX()
            .extent([[0, 0], [width, height]])
            .on("end", brushended));
}
function brushended() {
    var self = this;
    selectedyear1 = years[0];
    selectedyear2 = years[years.length-1];
    if (!d3.event.sourceEvent) return; // Only transition after input.
    if (!d3.event.selection) return; // Ignore empty selections.

    var y = d3.event.selection;
    var eachBand = x.step();
    var index = Math.round((y[0] / eachBand));
    var year1 = x.domain()[index];

    index = Math.round((y[1] / eachBand));
    var year2 = x.domain()[index];

    if(year2 === undefined)
        year2 = years[years.length -1];

    if(year1 == undefined)
        year1 =year2;

    selectedyear1 = year1;
    selectedyear2 = year2;
    //

    _WordCloud.setGlobal(false);
    //Wait for the data to reload
    setTimeout(function(){
        chooseData();
    }, 100);

}<|endoftext|>


<commit_before>var Http = require('http'),
    Url = require('url'),
    EventEmitter = require('events').EventEmitter;

const POOL_SIZE = 10;

function noOp() {}

function CouchClient(url) {
  var uri = Url.parse(url);
  var pool = new Array(POOL_SIZE);
  var poolIndex = 0;
  var revCache = {};

  function getServerFromPool() {
    poolIndex = (poolIndex + 1) % POOL_SIZE;
    if (!pool[poolIndex]) {
      pool[poolIndex] = getServer();
    }
    return pool[poolIndex];
  }

  function getServer() {
    return Http.createClient(uri.port || 5984, uri.hostname);
  }

  // A simple wrapper around node's http client.
  function request(method, path, body, callback) {
    var stream;
    // Body is optional
    if (typeof body === 'function' && typeof callback === 'undefined') {
      callback = body;
      body = undefined;
    }
    // Return a stream if no callback is specified
    if (!callback) {
      stream = new EventEmitter();
      stream.setEncoding = function () {
        throw new Error("This stream is always utf8");
      };
    }

    function errorHandler(err) {
      if (callback) callback(err);
      if (stream) stream.emit('error', err);
    }

    var headers = {
      "Host": uri.host
    };
    if (body) {
      body = JSON.stringify(body);
      headers["Content-Length"] = Buffer.byteLength(body);
      headers["Content-Type"] = "application/json";
      headers["Connection"] = "keep-alive";
    }
    // Callbacks are for short-lived requests and come off the connection pool
    // streams need their own connection
    var server = callback ? getServerFromPool() : getServer();

    var request = server.request(method, path, headers);
    if (body) {
      request.write(body, 'utf8');
    }
    request.end();

    request.on('response', function (response) {
      response.setEncoding('utf8');
      var body = "";
      response.on('data', function (chunk) {
        if (callback) body += chunk;
        if (stream) stream.emit('data', chunk);
      });
      response.on('end', function () {
        if (callback) callback(null, JSON.parse(body));
        if (stream) stream.emit('end');
      });
      response.on('error', errorHandler);
    });
    request.on('error', errorHandler);
    return stream;
  }

  // Requests UUIDs from the couch server in tick batches
  var uuidQueue = [];
  function getUUID(callback) {
    uuidQueue.push(callback);
    if (uuidQueue.length > 1) return;
    process.nextTick(function () {
      var pending = uuidQueue.splice(0);
      // console.log("Bulk getting UUIDs %s", pending.length);
      request("GET", "/_uuids?count=" + pending.length, function (err, result) {
        if (err) {
          pending.forEach(function (callback) {
            callback(err);
          });
          return;
        }
        if (result.uuids.length !== pending.length) {
          throw new Error("Wrong number of UUIDs generated " + result.uuids.length + " != " + pending.length);
        }
        result.uuids.forEach(function (uuid, i) {
          pending[i](null, uuid);
        });
      });
    });
  }

  // Saves documents in batches
  var saveValues = [];
  var saveQueue = [];
  function realSave(doc, callback) {
    // Put key and rev on the value without changing the original
    saveValues.push(doc);
    saveQueue.push(callback);
    if (saveQueue.length > 1) return;
    process.nextTick(function () {
      var pending = saveQueue.splice(0);
      var body = saveValues.splice(0);
      // console.log("Bulk saving %s", body.length);
      request("POST", uri.pathname + "/_bulk_docs", {docs: body}, function (err, results) {
        if (err) {
          pending.forEach(function (callback) {
            callback(err);
          });
          return;
        }
        results.forEach(function (result, i) {
          var doc = body[i];
          doc._id = result.id;
          doc._rev = result.rev;
          revCache[result.id] = result.rev;
          pending[i](null, doc);
        });
      });
    });
  }

  var getQueue = [];
  var getKeys = [];
  function realGet(key, includeDoc, callback) {
    getKeys.push(key);
    getQueue.push(callback);
    if (getQueue.length > 1) return;
    process.nextTick(function () {
      var pending = getQueue.splice(0);
      var keys = getKeys.splice(0);
      var path = uri.pathname + "/_all_docs";
      if (includeDoc) path += "?include_docs=true";
      // console.log("Bulk Getting %s documents", keys.length);
      request("POST", path, {keys: keys}, function (err, results) {
        if (!results.rows) {
          err = new Error("CouchDB Error: " + JSON.stringify(results));
        }
        if (err) {
          pending.forEach(function (callback) {
            callback(err);
          });
          return;
        }
        results.rows.forEach(function (result, i) {
          if (includeDoc) {
            if (result.error) {
              pending[i](new Error("CouchDB Error: " + JSON.stringify(result)));
              return;
            }
            if (!result.doc) {
              var err = new Error("Document not found for " + JSON.stringify(result.key));
              err.errno = process.ENOENT;
              pending[i](err);
              return;
            }
            pending[i](null, result.doc);
            return;
          }
          pending[i](null, result.value);
        });
      });
    });
  }

  function save(doc, callback) {
    if (!callback) callback = noOp;
    if (doc._id) {
      if (!doc._rev) {
        if (!revCache.hasOwnProperty(doc._id)) {
          realGet(doc._id, false, function (err, result) {
            if (err) return callback(err);
            if (result) {
              revCache[doc._id] = result.rev;
              doc._rev = result.rev;
            }
            realSave(doc, callback);
          });
          return;
        }
        doc._rev = revCache[doc._id];
      }
    }
    realSave(doc, callback);
  }

  function get(key, callback) {
    realGet(key, true, callback);
  }

  function remove(doc, callback) {
    if (typeof doc === 'string') {
      doc = {_id: doc};
    }
    doc._deleted = true;
    save(doc, callback);
  }

  function changes(since, callback) {
    var stream = request("GET", uri.pathname + "/_changes?feed=continuous&heartbeat=1000&since=" + since);
    var data = "";
    function checkData() {
      var p = data.indexOf("\n");
      if (p >= 0) {
        var line = data.substr(0, p).trim();
        data = data.substr(p + 1);
        if (line.length) {
          callback(null, JSON.parse(line));
        }
        checkData();
      }
    }
    stream.on('error', callback);
    stream.on('data', function (chunk) {
      data += chunk;
      checkData();
    });
    stream.on('end', function () {
      throw new Error("Changes feed got broken!");
    });
  }

  // Expose the public API
  return {
    get: get,
    save: save,
    remove: remove,
    changes: changes,
    request: request
  };
}

module.exports = CouchClient;<commit_msg>Put a proper ENOENT errno on the exception.<commit_after>var Http = require('http'),
    Url = require('url'),
    EventEmitter = require('events').EventEmitter;

const POOL_SIZE = 10;

function noOp() {}

function CouchClient(url) {
  var uri = Url.parse(url);
  var pool = new Array(POOL_SIZE);
  var poolIndex = 0;
  var revCache = {};

  function getServerFromPool() {
    poolIndex = (poolIndex + 1) % POOL_SIZE;
    if (!pool[poolIndex]) {
      pool[poolIndex] = getServer();
    }
    return pool[poolIndex];
  }

  function getServer() {
    return Http.createClient(uri.port || 5984, uri.hostname);
  }

  // A simple wrapper around node's http client.
  function request(method, path, body, callback) {
    var stream;
    // Body is optional
    if (typeof body === 'function' && typeof callback === 'undefined') {
      callback = body;
      body = undefined;
    }
    // Return a stream if no callback is specified
    if (!callback) {
      stream = new EventEmitter();
      stream.setEncoding = function () {
        throw new Error("This stream is always utf8");
      };
    }

    function errorHandler(err) {
      if (callback) callback(err);
      if (stream) stream.emit('error', err);
    }

    var headers = {
      "Host": uri.host
    };
    if (body) {
      body = JSON.stringify(body);
      headers["Content-Length"] = Buffer.byteLength(body);
      headers["Content-Type"] = "application/json";
      headers["Connection"] = "keep-alive";
    }
    // Callbacks are for short-lived requests and come off the connection pool
    // streams need their own connection
    var server = callback ? getServerFromPool() : getServer();

    var request = server.request(method, path, headers);
    if (body) {
      request.write(body, 'utf8');
    }
    request.end();

    request.on('response', function (response) {
      response.setEncoding('utf8');
      var body = "";
      response.on('data', function (chunk) {
        if (callback) body += chunk;
        if (stream) stream.emit('data', chunk);
      });
      response.on('end', function () {
        if (callback) callback(null, JSON.parse(body));
        if (stream) stream.emit('end');
      });
      response.on('error', errorHandler);
    });
    request.on('error', errorHandler);
    return stream;
  }

  // Requests UUIDs from the couch server in tick batches
  var uuidQueue = [];
  function getUUID(callback) {
    uuidQueue.push(callback);
    if (uuidQueue.length > 1) return;
    process.nextTick(function () {
      var pending = uuidQueue.splice(0);
      // console.log("Bulk getting UUIDs %s", pending.length);
      request("GET", "/_uuids?count=" + pending.length, function (err, result) {
        if (err) {
          pending.forEach(function (callback) {
            callback(err);
          });
          return;
        }
        if (result.uuids.length !== pending.length) {
          throw new Error("Wrong number of UUIDs generated " + result.uuids.length + " != " + pending.length);
        }
        result.uuids.forEach(function (uuid, i) {
          pending[i](null, uuid);
        });
      });
    });
  }

  // Saves documents in batches
  var saveValues = [];
  var saveQueue = [];
  function realSave(doc, callback) {
    // Put key and rev on the value without changing the original
    saveValues.push(doc);
    saveQueue.push(callback);
    if (saveQueue.length > 1) return;
    process.nextTick(function () {
      var pending = saveQueue.splice(0);
      var body = saveValues.splice(0);
      // console.log("Bulk saving %s", body.length);
      request("POST", uri.pathname + "/_bulk_docs", {docs: body}, function (err, results) {
        if (err) {
          pending.forEach(function (callback) {
            callback(err);
          });
          return;
        }
        results.forEach(function (result, i) {
          var doc = body[i];
          doc._id = result.id;
          doc._rev = result.rev;
          revCache[result.id] = result.rev;
          pending[i](null, doc);
        });
      });
    });
  }

  var getQueue = [];
  var getKeys = [];
  function realGet(key, includeDoc, callback) {
    getKeys.push(key);
    getQueue.push(callback);
    if (getQueue.length > 1) return;
    process.nextTick(function () {
      var pending = getQueue.splice(0);
      var keys = getKeys.splice(0);
      var path = uri.pathname + "/_all_docs";
      if (includeDoc) path += "?include_docs=true";
      // console.log("Bulk Getting %s documents", keys.length);
      request("POST", path, {keys: keys}, function (err, results) {
        if (!results.rows) {
          err = new Error("CouchDB Error: " + JSON.stringify(results));
        }
        if (err) {
          pending.forEach(function (callback) {
            callback(err);
          });
          return;
        }
        results.rows.forEach(function (result, i) {
          if (includeDoc) {
            if (result.error) {
              var err = new Error("CouchDB Error: " + JSON.stringify(result));
              if (result.error == 'not_found') err.errno = process.ENOENT;
              pending[i](err);
              return;
            }
            if (!result.doc) {
              var err = new Error("Document not found for " + JSON.stringify(result.key));
              err.errno = process.ENOENT;
              pending[i](err);
              return;
            }
            pending[i](null, result.doc);
            return;
          }
          pending[i](null, result.value);
        });
      });
    });
  }

  function save(doc, callback) {
    if (!callback) callback = noOp;
    if (doc._id) {
      if (!doc._rev) {
        if (!revCache.hasOwnProperty(doc._id)) {
          realGet(doc._id, false, function (err, result) {
            if (err) return callback(err);
            if (result) {
              revCache[doc._id] = result.rev;
              doc._rev = result.rev;
            }
            realSave(doc, callback);
          });
          return;
        }
        doc._rev = revCache[doc._id];
      }
    }
    realSave(doc, callback);
  }

  function get(key, callback) {
    realGet(key, true, callback);
  }

  function remove(doc, callback) {
    if (typeof doc === 'string') {
      doc = {_id: doc};
    }
    doc._deleted = true;
    save(doc, callback);
  }

  function changes(since, callback) {
    var stream = request("GET", uri.pathname + "/_changes?feed=continuous&heartbeat=1000&since=" + since);
    var data = "";
    function checkData() {
      var p = data.indexOf("\n");
      if (p >= 0) {
        var line = data.substr(0, p).trim();
        data = data.substr(p + 1);
        if (line.length) {
          callback(null, JSON.parse(line));
        }
        checkData();
      }
    }
    stream.on('error', callback);
    stream.on('data', function (chunk) {
      data += chunk;
      checkData();
    });
    stream.on('end', function () {
      throw new Error("Changes feed got broken!");
    });
  }

  // Expose the public API
  return {
    get: get,
    save: save,
    remove: remove,
    changes: changes,
    request: request
  };
}

module.exports = CouchClient;<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var load = require('require-sdk');

/**
 * Expose `createPlayer`
 */

module.exports = createPlayer;

/**
 * Load the YouTube API
 */

var sdk = load('https://www.youtube.com/iframe_api', 'YT');
var loadTrigger = sdk.trigger();

/**
 * The YouTube API requires a global ready event handler.
 * The YouTube API really sucks.
 */

window.onYouTubeIframeAPIReady = function () {
  loadTrigger();
  delete window.onYouTubeIframeAPIReady;
};

/**
 * Create a new `player` by requesting and using the YouTube Iframe API
 *
 * @param {String} id - reference to element for player
 * @param {Function} cb
 */

function createPlayer(id, cb) {
  return sdk(function(err) {
    var player = new YT.Player(id);
    return cb(player);
  });
}
<commit_msg>move global YT methods inside of createPlayer<commit_after>/**
 * Module dependencies
 */

var load = require('require-sdk');

/**
 * Expose `createPlayer`
 */

module.exports = createPlayer;

/**
 * Create a new `player` by requesting and using the YouTube Iframe API
 *
 * @param {String} id - reference to element for player
 * @param {Function} cb
 */

function createPlayer(id, cb) {
  var sdk = loadApi();

  return sdk(function(err) {
    var player = new YT.Player(id);
    return cb(player);
  });
}

/**
 * Load the YouTube API
 *
 * @returns {Function}
 */

function loadApi() {
  var sdk = load('https://www.youtube.com/iframe_api', 'YT');
  var loadTrigger = sdk.trigger();

  /**
   * The YouTube API requires a global ready event handler.
   * The YouTube API really sucks.
   */

  window.onYouTubeIframeAPIReady = function () {
    loadTrigger();
    delete window.onYouTubeIframeAPIReady;
  };

  return sdk;
}
<|endoftext|>


<commit_before>import app from '../app';
import axios from 'axios';

function makeServer() {
  return app.listen(0);
}

function request(server) {
  const address = server.address();

  return axios.create({
    baseURL: `http://127.0.0.1:${address.port}`,
    timeout: 2000,
  });
}
<commit_msg>Export test utils<commit_after>import app from '../app';
import axios from 'axios';

export function makeServer() {
  return app.listen(0);
}

export function request(server) {
  const address = server.address();

  return axios.create({
    baseURL: `http://127.0.0.1:${address.port}`,
    timeout: 2000,
  });
}
<|endoftext|>


<commit_before>const instance = require('../helpers/weak_cache');

module.exports = function checkSessionAction(provider) {
  const removeHeaders = !instance(provider).configuration('features.sessionManagement.keepHeaders');

  return async function checkSessionIframe(ctx, next) {
    const debug = ctx.query.debug !== undefined;

    if (removeHeaders) {
      ctx.response.remove('X-Frame-Options');
      const csp = ctx.response.get('Content-Security-Policy');
      if (csp.includes('frame-ancestors')) {
        ctx.response.set('Content-Security-Policy', csp.replace(/ ?frame-ancestors [^;]+;/, ''));
      }
    }

    ctx.type = 'html';
    ctx.body = `<!DOCTYPE html>
  <html>
  <head lang="en">
    <meta charset="UTF-8">
    <title>Session Management - OP iframe</title>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jsSHA/2.2.0/sha256.js" integrity="sha256-cZOjfJHUnIR4AN0bIASJHvhhJudsombORNNWzHKVoXY=" crossorigin="anonymous"></script>
  </head>
  <body>

  <script type="application/javascript">
    var debug = ${debug};
    var thirdPartyCookies = true;

    function receiveMessage(e) {
      if (e.data === 'MM:3PCunsupported') {
        thirdPartyCookies = false;
        return;
      } else if (e.data === 'MM:3PCsupported') {
        return;
      }
      try {
        var message_parts = e.data.split(' ');
        var clientId = message_parts[0];
        var actual = message_parts[1];
        if (debug && console) console.log('OP recv session state: ' + actual);
        var salt = actual.split('.')[1];

        var opbs = getOPBrowserState(clientId);
        var shaObj = new jsSHA('SHA-256', 'TEXT');
        shaObj.update(clientId + ' ' + e.origin + ' ' + opbs + ' ' + salt);
        var expected = shaObj.getHash('HEX') + ['.' + salt];
        if (debug && console) console.log('OP computed session state: ' + expected);

        var stat;
        if (actual === expected) {
          stat = 'unchanged';
        } else {
          stat = 'changed';
        }

        if (debug && console) console.log('OP status: ' + stat);

        e.source.postMessage(stat, e.origin);
      } catch (err) {
        e.source.postMessage('error', e.origin);
      }
    }

    function getOPBrowserState(clientId) {
      var cookie = readCookie('${provider.cookieName('state')}.' + clientId);
      if (debug && console) console.log('session state cookie: ' + cookie);
      if (!thirdPartyCookies && !cookie) throw new Error('third party cookies are most likely blocked');
      return cookie;
    }

    function readCookie(name) {
      var nameEQ = name + "=";
      var ca = document.cookie.split(';');
      for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
      }
      return null;
    }

    window.addEventListener('message', receiveMessage, false);
  </script>
  <iframe src="https://cdn.rawgit.com/panva/3rdpartycookiecheck/92fead3f/start.html" style="display:none" />

  </body>
  </html>`;
    await next();
  };
};
<commit_msg>update referenced cdn sha256 js script<commit_after>const instance = require('../helpers/weak_cache');

module.exports = function checkSessionAction(provider) {
  const removeHeaders = !instance(provider).configuration('features.sessionManagement.keepHeaders');

  return async function checkSessionIframe(ctx, next) {
    const debug = ctx.query.debug !== undefined;

    if (removeHeaders) {
      ctx.response.remove('X-Frame-Options');
      const csp = ctx.response.get('Content-Security-Policy');
      if (csp.includes('frame-ancestors')) {
        ctx.response.set('Content-Security-Policy', csp.replace(/ ?frame-ancestors [^;]+;/, ''));
      }
    }

    ctx.type = 'html';
    ctx.body = `<!DOCTYPE html>
  <html>
  <head lang="en">
    <meta charset="UTF-8">
    <title>Session Management - OP iframe</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jsSHA/2.3.0/sha256.js" integrity="sha256-i0NzTCxFBlHzBJWfs3UzaR49qrFl7GGwlHTP5QokMKo=" crossorigin="anonymous"></script>
  </head>
  <body>

  <script type="application/javascript">
    var debug = ${debug};
    var thirdPartyCookies = true;

    function receiveMessage(e) {
      if (e.data === 'MM:3PCunsupported') {
        thirdPartyCookies = false;
        return;
      } else if (e.data === 'MM:3PCsupported') {
        return;
      }
      try {
        var message_parts = e.data.split(' ');
        var clientId = message_parts[0];
        var actual = message_parts[1];
        if (debug && console) console.log('OP recv session state: ' + actual);
        var salt = actual.split('.')[1];

        var opbs = getOPBrowserState(clientId);
        var shaObj = new jsSHA('SHA-256', 'TEXT');
        shaObj.update(clientId + ' ' + e.origin + ' ' + opbs + ' ' + salt);
        var expected = shaObj.getHash('HEX') + ['.' + salt];
        if (debug && console) console.log('OP computed session state: ' + expected);

        var stat;
        if (actual === expected) {
          stat = 'unchanged';
        } else {
          stat = 'changed';
        }

        if (debug && console) console.log('OP status: ' + stat);

        e.source.postMessage(stat, e.origin);
      } catch (err) {
        e.source.postMessage('error', e.origin);
      }
    }

    function getOPBrowserState(clientId) {
      var cookie = readCookie('${provider.cookieName('state')}.' + clientId);
      if (debug && console) console.log('session state cookie: ' + cookie);
      if (!thirdPartyCookies && !cookie) throw new Error('third party cookies are most likely blocked');
      return cookie;
    }

    function readCookie(name) {
      var nameEQ = name + "=";
      var ca = document.cookie.split(';');
      for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
      }
      return null;
    }

    window.addEventListener('message', receiveMessage, false);
  </script>
  <iframe src="https://cdn.rawgit.com/panva/3rdpartycookiecheck/92fead3f/start.html" style="display:none" />

  </body>
  </html>`;
    await next();
  };
};
<|endoftext|>