<commit_before>import utils from 'osg/utils';
import notify from 'osg/notify';
import GLObject from 'osg/GLObject';
import StateAttribute from 'osg/StateAttribute';
import ShaderProcessor from 'osgShader/ShaderProcessor';
import Timer from 'osg/Timer';

// singleton
var sp = new ShaderProcessor();
var errorCallback;

var uniformRegexp = /uniform\s+\w+\s+(\w+)((\s)?\[(.*?)\])?/g;
var attributesRegexp = /(in|attribute)\s+\w+\s+(\w+)\s*;/g;

var getAttributeList = function(shaderText) {
    var attributeMap = {};
    var r, attr;
    while ((r = attributesRegexp.exec(shaderText)) !== null) {
        attr = r[2];
        attributeMap[attr] = true;
    }

    return attributeMap;
};

var getUniformList = function(shaderText) {
    var uniformMap = {};
    var r;
    while ((r = uniformRegexp.exec(shaderText)) !== null) {
        var uniform = r[1];
        uniformMap[uniform] = true;
    }
    return uniformMap;
};

/**
 * Program encapsulate an vertex and fragment shader
 * @class Program
 */
var Program = function(vShader, fShader) {
    GLObject.call(this);
    StateAttribute.call(this);
    this._program = null;

    // used to know if it's a default program
    // a default program does nothing but avoid to do some
    // useless logic
    // if we vertex or fragment shader are set it's not a default
    // program anymore
    this._nullProgram = true;

    this._vertex = undefined;
    this._fragment = undefined;

    this._uniformsCache = undefined;
    this._attributesCache = undefined;
    // state caches
    this._activeUniforms = undefined;
    this._foreignUniforms = undefined;
    this._trackAttributes = undefined;

    if (vShader) this.setVertexShader(vShader);
    if (fShader) this.setFragmentShader(fShader);

    this._dirty = true;
};

// static cache of glPrograms flagged for deletion, which will actually
// be deleted in the correct GL context.
Program._sDeletedGLProgramCache = new window.Map();

// static method to delete Program
Program.deleteGLProgram = function(gl, program) {
    if (!Program._sDeletedGLProgramCache.has(gl)) Program._sDeletedGLProgramCache.set(gl, []);

    Program._sDeletedGLProgramCache.get(gl).push(program);
};

// static method to flush all the cached glPrograms which need to be deleted in the GL context specified
Program.flushDeletedGLPrograms = function(gl, availableTime) {
    // if no time available don't try to flush objects.
    if (availableTime <= 0.0) return availableTime;

    if (!Program._sDeletedGLProgramCache.has(gl)) return availableTime;

    var elapsedTime = 0.0;
    var beginTime = Timer.instance().tick();
    var deleteList = Program._sDeletedGLProgramCache.get(gl);
    var numPrograms = deleteList.length;

    for (var i = numPrograms - 1; i >= 0 && elapsedTime < availableTime; i--) {
        gl.deleteProgram(deleteList[i]);
        deleteList.splice(i, 1);
        elapsedTime = Timer.instance().deltaS(beginTime, Timer.instance().tick());
    }

    return availableTime - elapsedTime;
};

Program.flushAllDeletedGLPrograms = function(gl) {
    if (!Program._sDeletedGLProgramCache.has(gl)) return;

    var deleteList = Program._sDeletedGLProgramCache.get(gl);
    var numPrograms = deleteList.length;

    for (var i = numPrograms - 1; i >= 0; i--) {
        gl.deleteProgram(deleteList[i]);
        deleteList.splice(i, 1);
    }
};

Program.onLostContext = function(gl) {
    if (!Program._sDeletedGLProgramCache.has(gl)) return;
    var deleteList = Program._sDeletedGLProgramCache.get(gl);
    deleteList.length = 0;
    return;
};

/** @lends Program.prototype */
utils.createPrototypeStateAttribute(
    Program,
    utils.objectInherit(
        GLObject.prototype,
        utils.objectInherit(StateAttribute.prototype, {
            attributeType: 'Program',

            cloneType: function() {
                return new Program();
            },

            setVertexShader: function(vs) {
                this._vertex = vs;
                this._nullProgram = false;
                vs.setText(sp.processShader(vs.getText()));
            },

            setFragmentShader: function(fs) {
                this._fragment = fs;
                this._nullProgram = false;
                fs.setText(sp.processShader(fs.getText()));
            },

            getVertexShader: function() {
                return this._vertex;
            },
            getFragmentShader: function() {
                return this._fragment;
            },

            getProgram: function() {
                return this._program;
            },

            setActiveUniforms: function(activeUniforms) {
                this._activeUniforms = activeUniforms;
            },

            getActiveUniforms: function() {
                return this._activeUniforms;
            },

            setForeignUniforms: function(foreignUniforms) {
                this._foreignUniforms = foreignUniforms;
            },

            getForeignUniforms: function() {
                return this._foreignUniforms;
            },

            setUniformsCache: function(uniformsCache) {
                this._uniformsCache = uniformsCache;
            },

            getUniformsCache: function() {
                return this._uniformsCache;
            },

            setAttributesCache: function(attributesCache) {
                this._attributesCache = attributesCache;
            },

            getAttributesCache: function() {
                return this._attributesCache;
            },

            setTrackAttributes: function(trackAttributes) {
                this._trackAttributes = trackAttributes;
            },

            getTrackAttributes: function() {
                return this._trackAttributes;
            },

            releaseGLObjects: function() {
                // Call to releaseGLOBjects on shaders
                if (this._vertex !== undefined) this._vertex.releaseGLObjects();
                if (this._fragment !== undefined) this._fragment.releaseGLObjects();
                if (this._program === null) return;
                if (this._gl !== undefined) {
                    Program.deleteGLProgram(this._gl, this._program);
                    GLObject.removeObject(this._gl, this);
                }
                this.invalidate();
            },

            dirty: function() {
                this._program = undefined;
            },

            invalidate: function() {
                this._cacheUniformId = undefined;

                this._uniformsCache = undefined;
                this._attributesCache = undefined;
                this._foreignUniforms = undefined;
                this._trackAttributes = undefined;

                this._program = undefined;
            },

            _rebuildProgramFromSpector: function(
                vertexShaderText,
                fragmentShaderText,
                onCompiled,
                onError
            ) {
                this._dirty = true;
                this._vertex.invalidate();
                this._fragment.invalidate();
                this.invalidate();
                this._vertex.setText(vertexShaderText);
                this._fragment.setText(fragmentShaderText);
                this._spectorOnCompiled = onCompiled;
                this._spectorOnError = onError;
            },

            _onErrorToSpector: function(errLink) {
                if (!this._spectorOnError) return false;
                this._spectorOnError(errLink);
                return true;
            },

            _onCompilationToSpector: function() {
                if (!this._spectorOnCompiled) return;
                this._spectorOnCompiled(this.program);
            },

            _bindProgramToSpector: function() {
                if (!window || !window.spector || this._program.__SPECTOR_rebuildProgram) return;
                this._program.__SPECTOR_rebuildProgram = this._rebuildProgramFromSpector.bind(this);
            },

            _logDebugShaders: function(gl, errLink) {
                if (errLink !== 'Failed to create D3D shaders.\n') return;
                // rawgl trick is for webgl inspector
                var debugShader = gl.rawgl !== undefined ? gl.rawgl : gl;
                if (debugShader === undefined || debugShader.getExtension !== undefined) return;
                debugShader = debugShader.getExtension('WEBGL_debug_shaders');
                if (!debugShader) return;
                notify.error(debugShader.getTranslatedShaderSource(this._vertex.shader));
                notify.error(debugShader.getTranslatedShaderSource(this._fragment.shader));
            },

            _activateFailSafe: function(gl) {
                var program = gl.createProgram();
                this._vertex.failSafe(gl, this._vertex.getText());
                this._fragment.failSafe(gl, this._fragment.getText());
                this._glAttachAndCompile(gl, program, this._vertex, this._fragment);
                notify.warn('FailSafe shader Activated ');
                this._program = program;
            },

            _glAttachAndCompile: function(gl, programGL, vertexShader, fragmentShader) {
                gl.attachShader(programGL, vertexShader.shader);
                gl.attachShader(programGL, fragmentShader.shader);
                utils.timeStamp('osgjs.metrics:linkShader');
                gl.linkProgram(programGL);
            },

            compile: function() {
                var gl = this._gl;

                var shaderName = this._fragment
                    .getText()
                    .match(/#define[\s]+SHADER_NAME[\s]+([\S]+)(\n|$)/);

                var compileClean = true;

                this._shaderName = shaderName ? shaderName[1] : '';

                if (!this._vertex.shader) {
                    compileClean = this._vertex.compile(gl, errorCallback);
                }

                if (!this._fragment.shader) {
                    compileClean = this._fragment.compile(gl, errorCallback);
                }

                this._attributeMap = getAttributeList(this._vertex.getText());

                if (!compileClean) {
                    // Any error, Any
                    // Pink must die.
                    return false;
                }

                this._program = gl.createProgram();

                if (this._attributeMap.Vertex) {
                    // force Vertex to be on 0
                    gl.bindAttribLocation(this._program, 0, 'Vertex');
                }
                this._glAttachAndCompile(gl, this._program, this._vertex, this._fragment);

                this._uniformMap = getUniformList(
                    this._fragment.getText() + '\n' + this._vertex.getText()
                );

                return true;
            },

            getCompilationResult: function(compileClean, gl) {
                if (compileClean) {
                    if (
                        !gl.getProgramParameter(this._program, gl.LINK_STATUS) &&
                        !gl.isContextLost()
                    ) {
                        var errLink = gl.getProgramInfoLog(this._program);

                        notify.errorFold(
                            errLink,
                            "can't link program\nvertex shader:\n" +
                                this._vertex.text +
                                '\n fragment shader:\n' +
                                this._fragment.text
                        );

                        this._logDebugShaders(gl, errLink);
                        if (errorCallback) {
                            errorCallback(this._vertex.text, this._fragment.text, errLink);
                        }
                        compileClean = false;
                        if (this._onErrorToSpector(errLink)) return;
                    } else {
                        this._onCompilationToSpector(this.program);
                    }
                }

                this._bindProgramToSpector();

                this._uniformsCache = {};
                this._attributesCache = {};

                if (!compileClean) {
                    // Any error, Any
                    // Pink must die.
                    this._activateFailSafe(gl);
                } else {
                    this.cacheAttributeList(gl, window.Object.keys(this._attributeMap));
                    this.cacheUniformList(gl, window.Object.keys(this._uniformMap));
                }
                return compileClean;
            },

            apply: function(state) {
                if (this._nullProgram) return;

                if (!this._gl) {
                    this.setGraphicContext(state.getGraphicContext());
                }

                if (this._program && !this._dirty) {
                    state.applyProgram(this._program);
                    return;
                }

                this._compileClean = this.compile();
                this.getCompilationResult(this._compileClean, this._gl);
                state.applyProgram(this._program);
                this._dirty = false;
            },

            cacheUniformList: function(gl, uniformList) {
                var map = this._uniformsCache;
                for (var i = 0, l = uniformList.length; i < l; i++) {
                    var uniform = uniformList[i];
                    var location = gl.getUniformLocation(this._program, uniform);
                    if (location !== undefined && location !== null) {
                        if (map[uniform] === undefined) {
                            map[uniform] = location;
                        }
                    }
                }
            },

            cacheAttributeList: function(gl, attributeList) {
                var map = this._attributesCache;
                for (var i = 0, l = attributeList.length; i < l; i++) {
                    var attr = attributeList[i];
                    var location = gl.getAttribLocation(this._program, attr);

                    if (location !== -1 && location !== undefined) {
                        if (map[attr] === undefined) {
                            map[attr] = location;
                        }
                    }
                }
            }
        })
    ),
    'osg',
    'Program'
);

Program.registerErrorCallback = function(callback) {
    errorCallback = callback;
};

export default Program;
<commit_msg>Fixes typo<commit_after>import utils from 'osg/utils';
import notify from 'osg/notify';
import GLObject from 'osg/GLObject';
import StateAttribute from 'osg/StateAttribute';
import ShaderProcessor from 'osgShader/ShaderProcessor';
import Timer from 'osg/Timer';

// singleton
var sp = new ShaderProcessor();
var errorCallback;

var uniformRegexp = /uniform\s+\w+\s+(\w+)((\s)?\[(.*?)\])?/g;
var attributesRegexp = /(in|attribute)\s+\w+\s+(\w+)\s*;/g;

var getAttributeList = function(shaderText) {
    var attributeMap = {};
    var r, attr;
    while ((r = attributesRegexp.exec(shaderText)) !== null) {
        attr = r[2];
        attributeMap[attr] = true;
    }

    return attributeMap;
};

var getUniformList = function(shaderText) {
    var uniformMap = {};
    var r;
    while ((r = uniformRegexp.exec(shaderText)) !== null) {
        var uniform = r[1];
        uniformMap[uniform] = true;
    }
    return uniformMap;
};

/**
 * Program encapsulate an vertex and fragment shader
 * @class Program
 */
var Program = function(vShader, fShader) {
    GLObject.call(this);
    StateAttribute.call(this);
    this._program = null;

    // used to know if it's a default program
    // a default program does nothing but avoid to do some
    // useless logic
    // if we vertex or fragment shader are set it's not a default
    // program anymore
    this._nullProgram = true;

    this._vertex = undefined;
    this._fragment = undefined;

    this._uniformsCache = undefined;
    this._attributesCache = undefined;
    // state caches
    this._activeUniforms = undefined;
    this._foreignUniforms = undefined;
    this._trackAttributes = undefined;

    if (vShader) this.setVertexShader(vShader);
    if (fShader) this.setFragmentShader(fShader);

    this._dirty = true;
};

// static cache of glPrograms flagged for deletion, which will actually
// be deleted in the correct GL context.
Program._sDeletedGLProgramCache = new window.Map();

// static method to delete Program
Program.deleteGLProgram = function(gl, program) {
    if (!Program._sDeletedGLProgramCache.has(gl)) Program._sDeletedGLProgramCache.set(gl, []);

    Program._sDeletedGLProgramCache.get(gl).push(program);
};

// static method to flush all the cached glPrograms which need to be deleted in the GL context specified
Program.flushDeletedGLPrograms = function(gl, availableTime) {
    // if no time available don't try to flush objects.
    if (availableTime <= 0.0) return availableTime;

    if (!Program._sDeletedGLProgramCache.has(gl)) return availableTime;

    var elapsedTime = 0.0;
    var beginTime = Timer.instance().tick();
    var deleteList = Program._sDeletedGLProgramCache.get(gl);
    var numPrograms = deleteList.length;

    for (var i = numPrograms - 1; i >= 0 && elapsedTime < availableTime; i--) {
        gl.deleteProgram(deleteList[i]);
        deleteList.splice(i, 1);
        elapsedTime = Timer.instance().deltaS(beginTime, Timer.instance().tick());
    }

    return availableTime - elapsedTime;
};

Program.flushAllDeletedGLPrograms = function(gl) {
    if (!Program._sDeletedGLProgramCache.has(gl)) return;

    var deleteList = Program._sDeletedGLProgramCache.get(gl);
    var numPrograms = deleteList.length;

    for (var i = numPrograms - 1; i >= 0; i--) {
        gl.deleteProgram(deleteList[i]);
        deleteList.splice(i, 1);
    }
};

Program.onLostContext = function(gl) {
    if (!Program._sDeletedGLProgramCache.has(gl)) return;
    var deleteList = Program._sDeletedGLProgramCache.get(gl);
    deleteList.length = 0;
    return;
};

/** @lends Program.prototype */
utils.createPrototypeStateAttribute(
    Program,
    utils.objectInherit(
        GLObject.prototype,
        utils.objectInherit(StateAttribute.prototype, {
            attributeType: 'Program',

            cloneType: function() {
                return new Program();
            },

            setVertexShader: function(vs) {
                this._vertex = vs;
                this._nullProgram = false;
                vs.setText(sp.processShader(vs.getText()));
            },

            setFragmentShader: function(fs) {
                this._fragment = fs;
                this._nullProgram = false;
                fs.setText(sp.processShader(fs.getText()));
            },

            getVertexShader: function() {
                return this._vertex;
            },
            getFragmentShader: function() {
                return this._fragment;
            },

            getProgram: function() {
                return this._program;
            },

            setActiveUniforms: function(activeUniforms) {
                this._activeUniforms = activeUniforms;
            },

            getActiveUniforms: function() {
                return this._activeUniforms;
            },

            setForeignUniforms: function(foreignUniforms) {
                this._foreignUniforms = foreignUniforms;
            },

            getForeignUniforms: function() {
                return this._foreignUniforms;
            },

            setUniformsCache: function(uniformsCache) {
                this._uniformsCache = uniformsCache;
            },

            getUniformsCache: function() {
                return this._uniformsCache;
            },

            setAttributesCache: function(attributesCache) {
                this._attributesCache = attributesCache;
            },

            getAttributesCache: function() {
                return this._attributesCache;
            },

            setTrackAttributes: function(trackAttributes) {
                this._trackAttributes = trackAttributes;
            },

            getTrackAttributes: function() {
                return this._trackAttributes;
            },

            releaseGLObjects: function() {
                // Call to releaseGLOBjects on shaders
                if (this._vertex !== undefined) this._vertex.releaseGLObjects();
                if (this._fragment !== undefined) this._fragment.releaseGLObjects();
                if (this._program === null) return;
                if (this._gl !== undefined) {
                    Program.deleteGLProgram(this._gl, this._program);
                    GLObject.removeObject(this._gl, this);
                }
                this.invalidate();
            },

            dirty: function() {
                this._program = undefined;
            },

            invalidate: function() {
                this._cacheUniformId = undefined;

                this._uniformsCache = undefined;
                this._attributesCache = undefined;
                this._foreignUniforms = undefined;
                this._trackAttributes = undefined;

                this._program = undefined;
            },

            _rebuildProgramFromSpector: function(
                vertexShaderText,
                fragmentShaderText,
                onCompiled,
                onError
            ) {
                this._dirty = true;
                this._vertex.invalidate();
                this._fragment.invalidate();
                this.invalidate();
                this._vertex.setText(vertexShaderText);
                this._fragment.setText(fragmentShaderText);
                this._spectorOnCompiled = onCompiled;
                this._spectorOnError = onError;
            },

            _onErrorToSpector: function(errLink) {
                if (!this._spectorOnError) return false;
                this._spectorOnError(errLink);
                return true;
            },

            _onCompilationToSpector: function() {
                if (!this._spectorOnCompiled) return;
                this._spectorOnCompiled(this._program);
            },

            _bindProgramToSpector: function() {
                if (!window || !window.spector || this._program.__SPECTOR_rebuildProgram) return;
                this._program.__SPECTOR_rebuildProgram = this._rebuildProgramFromSpector.bind(this);
            },

            _logDebugShaders: function(gl, errLink) {
                if (errLink !== 'Failed to create D3D shaders.\n') return;
                // rawgl trick is for webgl inspector
                var debugShader = gl.rawgl !== undefined ? gl.rawgl : gl;
                if (debugShader === undefined || debugShader.getExtension !== undefined) return;
                debugShader = debugShader.getExtension('WEBGL_debug_shaders');
                if (!debugShader) return;
                notify.error(debugShader.getTranslatedShaderSource(this._vertex.shader));
                notify.error(debugShader.getTranslatedShaderSource(this._fragment.shader));
            },

            _activateFailSafe: function(gl) {
                var program = gl.createProgram();
                this._vertex.failSafe(gl, this._vertex.getText());
                this._fragment.failSafe(gl, this._fragment.getText());
                this._glAttachAndCompile(gl, program, this._vertex, this._fragment);
                notify.warn('FailSafe shader Activated ');
                this._program = program;
            },

            _glAttachAndCompile: function(gl, programGL, vertexShader, fragmentShader) {
                gl.attachShader(programGL, vertexShader.shader);
                gl.attachShader(programGL, fragmentShader.shader);
                utils.timeStamp('osgjs.metrics:linkShader');
                gl.linkProgram(programGL);
            },

            compile: function() {
                var gl = this._gl;

                var shaderName = this._fragment
                    .getText()
                    .match(/#define[\s]+SHADER_NAME[\s]+([\S]+)(\n|$)/);

                var compileClean = true;

                this._shaderName = shaderName ? shaderName[1] : '';

                if (!this._vertex.shader) {
                    compileClean = this._vertex.compile(gl, errorCallback);
                }

                if (!this._fragment.shader) {
                    compileClean = this._fragment.compile(gl, errorCallback);
                }

                this._attributeMap = getAttributeList(this._vertex.getText());

                if (!compileClean) {
                    // Any error, Any
                    // Pink must die.
                    return false;
                }

                this._program = gl.createProgram();

                if (this._attributeMap.Vertex) {
                    // force Vertex to be on 0
                    gl.bindAttribLocation(this._program, 0, 'Vertex');
                }
                this._glAttachAndCompile(gl, this._program, this._vertex, this._fragment);

                this._uniformMap = getUniformList(
                    this._fragment.getText() + '\n' + this._vertex.getText()
                );

                return true;
            },

            getCompilationResult: function(compileClean, gl) {
                if (compileClean) {
                    if (
                        !gl.getProgramParameter(this._program, gl.LINK_STATUS) &&
                        !gl.isContextLost()
                    ) {
                        var errLink = gl.getProgramInfoLog(this._program);

                        notify.errorFold(
                            errLink,
                            "can't link program\nvertex shader:\n" +
                                this._vertex.text +
                                '\n fragment shader:\n' +
                                this._fragment.text
                        );

                        this._logDebugShaders(gl, errLink);
                        if (errorCallback) {
                            errorCallback(this._vertex.text, this._fragment.text, errLink);
                        }
                        compileClean = false;
                        if (this._onErrorToSpector(errLink)) return;
                    } else {
                        this._onCompilationToSpector(this._program);
                    }
                }

                this._bindProgramToSpector();

                this._uniformsCache = {};
                this._attributesCache = {};

                if (!compileClean) {
                    // Any error, Any
                    // Pink must die.
                    this._activateFailSafe(gl);
                } else {
                    this.cacheAttributeList(gl, window.Object.keys(this._attributeMap));
                    this.cacheUniformList(gl, window.Object.keys(this._uniformMap));
                }
                return compileClean;
            },

            apply: function(state) {
                if (this._nullProgram) return;

                if (!this._gl) {
                    this.setGraphicContext(state.getGraphicContext());
                }

                if (this._program && !this._dirty) {
                    state.applyProgram(this._program);
                    return;
                }

                this._compileClean = this.compile();
                this.getCompilationResult(this._compileClean, this._gl);
                state.applyProgram(this._program);
                this._dirty = false;
            },

            cacheUniformList: function(gl, uniformList) {
                var map = this._uniformsCache;
                for (var i = 0, l = uniformList.length; i < l; i++) {
                    var uniform = uniformList[i];
                    var location = gl.getUniformLocation(this._program, uniform);
                    if (location !== undefined && location !== null) {
                        if (map[uniform] === undefined) {
                            map[uniform] = location;
                        }
                    }
                }
            },

            cacheAttributeList: function(gl, attributeList) {
                var map = this._attributesCache;
                for (var i = 0, l = attributeList.length; i < l; i++) {
                    var attr = attributeList[i];
                    var location = gl.getAttribLocation(this._program, attr);

                    if (location !== -1 && location !== undefined) {
                        if (map[attr] === undefined) {
                            map[attr] = location;
                        }
                    }
                }
            }
        })
    ),
    'osg',
    'Program'
);

Program.registerErrorCallback = function(callback) {
    errorCallback = callback;
};

export default Program;
<|endoftext|>


<commit_before>(function () {
    var defaults = {
        tooltip: {
            animate: true,
            opacity: 0.85,
            showTime: 300,
            hideTime: 500,
            distance: 5
        }
    };

    function render() {

        var clearHideTimer = function () {
            clearTimeout(this.tooltip.hideTimer);
        };

        var changeOpacity = function (opacity, delay) {
            if(this.options.tooltip.animate) {
                this.tooltipElement
                    .transition().duration(delay)
                        .style('opacity', opacity);
            } else {
                this.tooltipElement.style('opacity', opacity);
            }
        };

        var positionTooltip = function (d) {
            var plotLeft = this.options.chart.plotLeft;
            var plotWidth = this.options.chart.plotWidth;
            var plotTop = this.options.chart.plotTop;
            var plotHeight = this.options.chart.plotHeight;
            var distance = this.options.tooltip.distance;
            var width = parseFloat(this.tooltipElement.style('width'));
            var height = parseFloat(this.tooltipElement.style('height'));
            var pointX = this.xScale ? this.xScale(d.x) : d3.event.x;
            var pointY = this.yScale ? this.yScale(d.y) : d3.event.y;
            var alignedRight;

            var pos = {
                x: plotLeft + pointX - (distance + width),
                y: plotTop + pointY - (distance + height)
            };

            // Check outside plot area (left)
            if (pos.x < plotLeft) {
                pos.x = plotLeft + Math.max(pos.x, 0) + distance;
            }

            // Check outside plot area (right)
            if (pos.x + width > plotLeft + plotWidth) {
                pos.x -= (pos.x + width) - (plotLeft + plotWidth);
                // Don't overlap point
                pos.y = plotTop + pointY - (height + distance);
                alignedRight = true;
            }

            // Check outside the plot area (top)
            if (pos.y < plotTop) {
                pos.y = plotTop + distance;

                // Don't overlap point
                if (alignedRight && pointY >= pos.y && pointY <= pos.y + height) {
                    pos.y = pointY + plotTop + distance;
                }
            }

            // Check outside the plot area (bottom)
            if (pos.y + height > plotTop + plotHeight) {
                pos.y = Math.max(plotTop, plotTop + plotHeight - (height + distance));
            }

            return pos;
        };

        var onMouseOver = function (d) {
            show.call(this, d);
        };

        var onMouseOut = function () {
            changeOpacity.call(this, 0, this.options.tooltip.hideTime);
        };

        var getTooltipText = function (d) {
            function match() {
                var params = Array.prototype.slice.call(arguments);
                var list = params[0];
                var rest = params.slice(1);

                var response = _.map(list, function(fn) { return fn.apply(this, rest); }).concat([_.noop]);

                return _.first(_.select(response));
            }
            var options = this.options.tooltip;
            var formatters = [
                function (d) { return options.formatter ? _.partial(options.formatter, d) : null; },
                function (d) { return d.hasOwnProperty('x') ? _.partial(function (d) { return 'x: ' + d.x + '
' + 'y: ' + d.y; }, d) : null; },
                function (d) { return d.data && d.data.hasOwnProperty('x') ? _.partial(function (d) { return 'x: ' + d.x + '
' + 'y: ' + d.y; }, d.data) : null; },
                function (d) { return d.hasOwnProperty('value') ? _.partial(function (d) { return d.value; }, d) : null;  },
                function () { return function () { return 'NA'; }; }
            ];

            return match(formatters, d)();
        };

        var show = function (d) {
            clearHideTimer.call(this);

            this.tooltipElement.select('.text').html(getTooltipText.call(this, d));

            var pos = positionTooltip.call(this, d);

            this.tooltipElement
                .style('top', pos.y + 'px')
                .style('left', pos.x + 'px');

            changeOpacity.call(this, this.options.tooltip.opacity, this.options.tooltip.showTime);
        };

        this.tooltipElement = this.container
            .style('position', 'relative')
            .selectAll('.nw-tooltip').data([1]);

        this.tooltipElement
            .enter().append('div')
            .attr('class', 'nw-tooltip')
            .style('opacity', 0)
            .append('div')
                .attr('class', 'text');

        this.svg.selectAll('.tooltip-tracker')
            .on('mouseover.tooltip', onMouseOver.bind(this))
            .on('mouseout.tooltip',  onMouseOut.bind(this));
    }

    render.defaults = defaults;

    /**
    * Adds a tooltip on hover to all other visualizations in the Contour instance.
    *
    * Although not strictly required, this visualization does not appear unless there are one or more additional visualizations in this Contour instance for which to show the tooltips.
    *
    * ### Example:
    *
    *     new Contour({el: '.myChart'})
    *           .cartesian()
    *           .line([2, 4, 3, 5, 7])
    *           .tooltip()
    *           .render();
    *
    * @name tooltip(data, options)
    * @param {object|array} data Ignored!
    * @param {object} options Configuration options particular to this visualization that override the defaults.
    * @api public
    *
    */
    Contour.export('tooltip', render);

})();

<commit_msg>Fixed positioning of tooltip when is outside of the left edge of the chart<commit_after>(function () {
    var defaults = {
        tooltip: {
            animate: true,
            opacity: 0.85,
            showTime: 300,
            hideTime: 500,
            distance: 5
        }
    };

    function render() {

        var clearHideTimer = function () {
            clearTimeout(this.tooltip.hideTimer);
        };

        var changeOpacity = function (opacity, delay) {
            if(this.options.tooltip.animate) {
                this.tooltipElement
                    .transition().duration(delay)
                        .style('opacity', opacity);
            } else {
                this.tooltipElement.style('opacity', opacity);
            }
        };

        var positionTooltip = function (d) {
            var plotLeft = this.options.chart.plotLeft;
            var plotWidth = this.options.chart.plotWidth;
            var plotTop = this.options.chart.plotTop;
            var plotHeight = this.options.chart.plotHeight;
            var distance = this.options.tooltip.distance;
            var width = parseFloat(this.tooltipElement.style('width'));
            var height = parseFloat(this.tooltipElement.style('height'));
            var pointX = this.xScale ? this.xScale(d.x) : d3.event.x;
            var pointY = this.yScale ? this.yScale(d.y) : d3.event.y;
            var alignedRight;

            var pos = {
                x: plotLeft + pointX - (distance + width),
                y: plotTop + pointY - (distance + height)
            };

            // Check outside plot area (left)
            if (pos.x < plotLeft) {
                pos.x = plotLeft + distance;
            }

            // Check outside plot area (right)
            if (pos.x + width > plotLeft + plotWidth) {
                pos.x -= (pos.x + width) - (plotLeft + plotWidth);
                // Don't overlap point
                pos.y = plotTop + pointY - (height + distance);
                alignedRight = true;
            }

            // Check outside the plot area (top)
            if (pos.y < plotTop) {
                pos.y = plotTop + distance;

                // Don't overlap point
                if (alignedRight && pointY >= pos.y && pointY <= pos.y + height) {
                    pos.y = pointY + plotTop + distance;
                }
            }

            // Check outside the plot area (bottom)
            if (pos.y + height > plotTop + plotHeight) {
                pos.y = Math.max(plotTop, plotTop + plotHeight - (height + distance));
            }

            return pos;
        };

        var onMouseOver = function (d) {
            show.call(this, d);
        };

        var onMouseOut = function () {
            changeOpacity.call(this, 0, this.options.tooltip.hideTime);
        };

        var getTooltipText = function (d) {
            function match() {
                var params = Array.prototype.slice.call(arguments);
                var list = params[0];
                var rest = params.slice(1);

                var response = _.map(list, function(fn) { return fn.apply(this, rest); }).concat([_.noop]);

                return _.first(_.select(response));
            }
            var options = this.options.tooltip;
            var formatters = [
                function (d) { return options.formatter ? _.partial(options.formatter, d) : null; },
                function (d) { return d.hasOwnProperty('x') ? _.partial(function (d) { return 'x: ' + d.x + '
' + 'y: ' + d.y; }, d) : null; },
                function (d) { return d.data && d.data.hasOwnProperty('x') ? _.partial(function (d) { return 'x: ' + d.x + '
' + 'y: ' + d.y; }, d.data) : null; },
                function (d) { return d.hasOwnProperty('value') ? _.partial(function (d) { return d.value; }, d) : null;  },
                function () { return function () { return 'NA'; }; }
            ];

            return match(formatters, d)();
        };

        var show = function (d) {
            clearHideTimer.call(this);

            this.tooltipElement.select('.text').html(getTooltipText.call(this, d));

            var pos = positionTooltip.call(this, d);

            this.tooltipElement
                .style('top', pos.y + 'px')
                .style('left', pos.x + 'px');

            changeOpacity.call(this, this.options.tooltip.opacity, this.options.tooltip.showTime);
        };

        this.tooltipElement = this.container
            .style('position', 'relative')
            .selectAll('.nw-tooltip').data([1]);

        this.tooltipElement
            .enter().append('div')
            .attr('class', 'nw-tooltip')
            .style('opacity', 0)
            .append('div')
                .attr('class', 'text');

        this.svg.selectAll('.tooltip-tracker')
            .on('mouseover.tooltip', onMouseOver.bind(this))
            .on('mouseout.tooltip',  onMouseOut.bind(this));
    }

    render.defaults = defaults;

    /**
    * Adds a tooltip on hover to all other visualizations in the Contour instance.
    *
    * Although not strictly required, this visualization does not appear unless there are one or more additional visualizations in this Contour instance for which to show the tooltips.
    *
    * ### Example:
    *
    *     new Contour({el: '.myChart'})
    *           .cartesian()
    *           .line([2, 4, 3, 5, 7])
    *           .tooltip()
    *           .render();
    *
    * @name tooltip(data, options)
    * @param {object|array} data Ignored!
    * @param {object} options Configuration options particular to this visualization that override the defaults.
    * @api public
    *
    */
    Contour.export('tooltip', render);

})();

<|endoftext|>


<commit_before>"use strict";

var m        = require("mithril"),
    paginate = require("paginationator"),
    moment   = require("moment"),

    db = require("../../lib/firebase");

module.exports = {
    controller : function(options) {
        var ctrl = this;

        ctrl.schema = options.schema;

        ctrl.page = 0;

        ctrl.content = null;

        // need to go get schema name
        db.child("schemas/" + ctrl.schema.key).once("value", function(snap) {
            ctrl.schema.name = snap.val().name;
        });

        db.child("content/" + ctrl.schema.key).on("value", function(snap) {
            var entries = [];

            snap.forEach(function(record) {
                var data = record.val();

                data.key = record.key();
                data.created = moment(data._created);
                data.updated = moment(data._updated);

                entries.push(data);
            });

            ctrl.content = paginate(entries);

            m.redraw();
        });

        ctrl.add = function() {
            var result;

            result = db.child("content/" + ctrl.schema.key).push({
                _name    : "New " + ctrl.schema.name,
                _created : db.TIMESTAMP
            });

            m.route("/content/" + ctrl.schema.key + "/" + result.key());
        };

        ctrl.change = function(page, e) {
            e.preventDefault();

            ctrl.page = page;
        };
    },

    view : function(ctrl) {
        var page = ctrl.content ? ctrl.content.pages[ctrl.page] : { items : [] };

        return m("div",
            m("h2", ctrl.schema.name),
            m("p",
                m("button", { onclick : ctrl.add }, "Add " + ctrl.schema.name)
            ),
            m("table",
                m("tr",
                    m("th", "Name"),
                    m("th", "Created"),
                    m("th", "Updated"),
                    m("th", m.trust(" "))
                ),
                page.items.map(function(data) {
                    return m("tr", { key : data.key },
                        m("td",
                            m("a", { href : "/content/" + ctrl.schema.key + "/" + data.key, config : m.route }, data._name)
                        ),
                        m("td", { title : data.created.format("LLL") }, data.created.fromNow()),
                        m("td", { title : data.updated.format("LLL") }, data.updated.fromNow()),
                        m("td",
                            m("button", "Delete")
                        )
                    );
                })
            ),
            ctrl.content ?
                m("div",
                    page.prev ?
                        m("a", {
                            href : "#/page" + page.prev - 1,
                            onclick : ctrl.change.bind(null, page.prev - 1)
                        }, m.trust("< "), page.prev) :
                        m.trust("<  "),
                    ctrl.content.pages.map(function(page) {
                        return m("a", {
                            href : "#/page" + page.idx,
                            onclick : ctrl.change.bind(null, page.idx)
                        }, page.current);
                    }),
                    page.next ?
                        m("a", {
                            href : "#/page" + page.next - 1,
                            onclick : ctrl.change.bind(null, page.next - 1)
                        }, page.next, m.trust(">")) :
                        m.trust("  >")
                ) :
                null
        );
    }
};
<commit_msg>Pagination is the worst. THE WORST.<commit_after>"use strict";

var m        = require("mithril"),
    paginate = require("paginationator"),
    moment   = require("moment"),

    db = require("../../lib/firebase");

module.exports = {
    controller : function(options) {
        var ctrl = this;

        ctrl.schema = options.schema;

        ctrl.page = 0;

        ctrl.content = null;

        // need to go get schema name
        db.child("schemas/" + ctrl.schema.key).once("value", function(snap) {
            ctrl.schema.name = snap.val().name;
        });

        db.child("content/" + ctrl.schema.key).on("value", function(snap) {
            var entries = [];

            snap.forEach(function(record) {
                var data = record.val();

                data.key = record.key();
                data.created = moment(data._created);
                data.updated = moment(data._updated);

                entries.push(data);
            });

            ctrl.content = paginate(entries, { limit : 20 });

            m.redraw();
        });

        ctrl.add = function() {
            var result;

            result = db.child("content/" + ctrl.schema.key).push({
                _name    : "New " + ctrl.schema.name,
                _created : db.TIMESTAMP
            });

            m.route("/content/" + ctrl.schema.key + "/" + result.key());
        };

        ctrl.change = function(page, e) {
            e.preventDefault();

            ctrl.page = page;
        };
    },

    view : function(ctrl) {
        var current = ctrl.content ? ctrl.content.pages[ctrl.page] : { items : [] },
            pages   = [];

        if(ctrl.content) {
            if(ctrl.content.pages.length > 15) {
                if(current.idx > 5) {
                    pages.push("...");
                }

                pages = pages.concat(ctrl.content.pages.slice(
                    Math.max(current.idx - 5, 0),
                    Math.min(current.idx + 5, ctrl.content.pages.length)
                ));

                if(current.idx < (ctrl.content.pages.length - 5)) {
                    pages.push("...");
                }
            } else {
                pages = ctrl.content.pages;
            }
        }

        return m("div",
            m("h2", ctrl.schema.name),
            m("p",
                m("button", { onclick : ctrl.add }, "Add " + ctrl.schema.name)
            ),
            m("table",
                m("tr",
                    m("th", "Name"),
                    m("th", "Created"),
                    m("th", "Updated"),
                    m("th", m.trust(" "))
                ),
                current.items.map(function(data) {
                    return m("tr", { key : data.key },
                        m("td",
                            m("a", { href : "/content/" + ctrl.schema.key + "/" + data.key, config : m.route }, data._name)
                        ),
                        m("td", { title : data.created.format("LLL") }, data.created.fromNow()),
                        m("td", { title : data.updated.format("LLL") }, data.updated.fromNow()),
                        m("td",
                            m("button", "Delete")
                        )
                    );
                })
            ),
            ctrl.content ?
                m("div",
                    current.prev ?
                        m("a", {
                            href : "#/page" + current.prev - 1,
                            onclick : ctrl.change.bind(null, current.prev - 1)
                        }, m.trust("< "), current.prev) :
                        m.trust("<  "),
                    pages.map(function(page) {
                        if(typeof page === "string") {
                            return m.trust(page);
                        }

                        if(page.idx === current.idx) {
                            return page.current;
                        }

                        return m("a", {
                            href : "#/page" + page.idx,
                            onclick : ctrl.change.bind(null, page.idx)
                        }, page.current);
                    }),
                    current.next ?
                        m("a", {
                            href : "#/page" + current.next - 1,
                            onclick : ctrl.change.bind(null, current.next - 1)
                        }, current.next, m.trust(">")) :
                        m.trust("  >")
                ) :
                null
        );
    }
};
<|endoftext|>


<commit_before>angular.module("seAuthentication.popup", ["seNotifications.service", "ui.router"]).
directive("seAuthenticationPopup", function (SeNotificationsService, SeAuthenticationService) {
	"use strict";
	function closeDropdown(element) {
		if (element.parent().is(".open")) {
			// close
			element.dropdown("toggle");
		}
	}
	function openDropdown(element) {
		if (!element.parent().is(".open")) {
			// open
			element.dropdown("toggle");
		}
	}

	return {
		restrict: "A",
		link: function(scope, element) {
			scope.$on("$stateChangeStart", function() {
				closeDropdown(element);
			});
			var unregister = SeAuthenticationService.addAuthenticationListener({
				onLoginRequired: function() {
					openDropdown(element);
				}
			});
			scope.$on("$destroy", unregister);
		}
	};
});
<commit_msg>#2 seAuthenticationPopup should use SeAuthenticationService for unauthorized checking - removed not used injection<commit_after>angular.module("seAuthentication.popup", ["seNotifications.service", "ui.router"]).
directive("seAuthenticationPopup", function (SeAuthenticationService) {
	"use strict";
	function closeDropdown(element) {
		if (element.parent().is(".open")) {
			// close
			element.dropdown("toggle");
		}
	}
	function openDropdown(element) {
		if (!element.parent().is(".open")) {
			// open
			element.dropdown("toggle");
		}
	}

	return {
		restrict: "A",
		link: function(scope, element) {
			scope.$on("$stateChangeStart", function() {
				closeDropdown(element);
			});
			var unregister = SeAuthenticationService.addAuthenticationListener({
				onLoginRequired: function() {
					openDropdown(element);
				}
			});
			scope.$on("$destroy", unregister);
		}
	};
});
<|endoftext|>


<commit_before>/* global describe it expect fail belhop */
describe('belhop', function() {
  'use strict';

  var types = [];

  describe('annotation', function() {

    describe('types', function() {

      it('can be retrieved', function(done) {
        expect(belhop.annotations.getTypes).toBeDefined();
        var onSucc = function(annotations, status, xhr) {
          expect(xhr.status).toEqual(200);
          expect(annotations.length).toBeGreaterThan(0);
          annotations.forEach(function(x) {
            types.push(x);
          });
          done();
        };
        var onErr = function(xhr) {
          expect(xhr.status).toEqual(200);
          done();
        };
        var cb = belhop.factory.callback(onSucc, onErr);
        belhop.annotations.getTypes(cb);
      });

      it('can be retrieved individually', function(done) {
        var retrieved = 0;
        expect(types.length).toBeGreaterThan(0);
        var onSucc = function(annotations, status, xhr) {
          expect(xhr.status).toEqual(200);
          retrieved++;
          if (retrieved === types.length) {
            done();
          }
        };
        var onErr = function(xhr) {
          expect(xhr.status).toEqual(200);
          done();
        };
        var cb = belhop.factory.callback(onSucc, onErr);
        types.forEach(function(x) {
          belhop.annotations.getType(x.prefix, cb);
        });
      });

      it('can be retrieved even when not found', function(done) {
        var onSucc = function(annotations, status, xhr) {
          expect(xhr.status).toEqual(404);
          expect(annotations).toBeNull();
          done();
        };
        var onErr = function() {
          fail();
        };
        var cb = belhop.factory.callback(onSucc, onErr);
        belhop.annotations.getType('BAD_ANNOTYPE_PREFIX', cb);
      });

    });

    describe('values', function() {

      it('can be retrieved', function(done) {
        expect(belhop.annotations.getTypes).toBeDefined();
        var onSucc = function(annotations, status, xhr) {
          expect(xhr.status).toEqual(200);
          expect(annotations.length).toBeGreaterThan(0);
          annotations.forEach(function(x) {
            types.push(x);
          });
          done();
        };
        var onErr = function(xhr) {
          expect(xhr.status).toEqual(200);
          done();
        };
        var cb = belhop.factory.callback(onSucc, onErr);
        belhop.annotations.getTypes(cb);
      });

      it('can be retrieved even when not found', function(done) {
        var onSucc = function(annotations, status, xhr) {
          expect(xhr.status).toEqual(404);
          expect(annotations).toBeNull();
          done();
        };
        var onErr = function() {
          fail();
        };
        var cb = belhop.factory.callback(onSucc, onErr);
        belhop.annotations.getValue('BAD_ANNOTYPE_PREFIX', 'BAD_VALUE', cb);
      });

      it('can be searched', function(done) {
        done();
      });

    });

  });

});
<commit_msg>fix spec covering annotation getValue<commit_after>/* global describe it expect fail belhop */
describe('belhop', function() {
  'use strict';

  var types = [];

  describe('annotation', function() {

    describe('types', function() {

      it('can be retrieved', function(done) {
        expect(belhop.annotations.getTypes).toBeDefined();
        var onSucc = function(annotations, status, xhr) {
          expect(xhr.status).toEqual(200);
          expect(annotations.length).toBeGreaterThan(0);
          annotations.forEach(function(x) {
            types.push(x);
          });
          done();
        };
        var onErr = function(xhr) {
          expect(xhr.status).toEqual(200);
          done();
        };
        var cb = belhop.factory.callback(onSucc, onErr);
        belhop.annotations.getTypes(cb);
      });

      it('can be retrieved individually', function(done) {
        var retrieved = 0;
        expect(types.length).toBeGreaterThan(0);
        var onSucc = function(annotations, status, xhr) {
          expect(xhr.status).toEqual(200);
          retrieved++;
          if (retrieved === types.length) {
            done();
          }
        };
        var onErr = function(xhr) {
          expect(xhr.status).toEqual(200);
          done();
        };
        var cb = belhop.factory.callback(onSucc, onErr);
        types.forEach(function(x) {
          belhop.annotations.getType(x.prefix, cb);
        });
      });

      it('can be retrieved even when not found', function(done) {
        var onSucc = function(annotations, status, xhr) {
          expect(xhr.status).toEqual(404);
          expect(annotations).toBeNull();
          done();
        };
        var onErr = function() {
          fail();
        };
        var cb = belhop.factory.callback(onSucc, onErr);
        belhop.annotations.getType('BAD_ANNOTYPE_PREFIX', cb);
      });

    });

    describe('values', function() {

      it('can be retrieved', function(done) {
        expect(belhop.annotations.getValue).toBeDefined();
        var onSucc = function(annotationValue, status, xhr) {
          expect(xhr.status).toEqual(200);
          expect(annotationValue).not.toBeNull();
          done();
        };
        var onErr = function(xhr) {
          expect(xhr.status).toEqual(200);
          done();
        };
        var cb = belhop.factory.callback(onSucc, onErr);
        belhop.annotations.getValue('taxon', '9606', cb);
      });

      it('can be retrieved even when not found', function(done) {
        var onSucc = function(annotations, status, xhr) {
          expect(xhr.status).toEqual(404);
          expect(annotations).toBeNull();
          done();
        };
        var onErr = function() {
          fail();
        };
        var cb = belhop.factory.callback(onSucc, onErr);
        belhop.annotations.getValue('BAD_ANNOTYPE_PREFIX', 'BAD_VALUE', cb);
      });

      it('can be searched', function(done) {
        done();
      });

    });

  });

});
<|endoftext|>


<commit_before>var map, currentMapSources = {}, oldMapSources = {};

function renderMap(){
  var mapOptions = {
    zoom: 3,
    center: new google.maps.LatLng(0, 0),
  };
  map = new google.maps.Map(document.getElementById("map"), mapOptions);
}

function renderInfluencesInMap(influences){
  var influencers = [], events = [];
  $(influences).each(function(i, influence){
    if(influence.kind == "event"){
      events.push(influence);
    } else if (influence.kind == "person"){
      influencers.push(influence);
    }
  });

  _renderInfluencers(influencers);
  _renderEvents(events);
}

function _renderInfluencers(influencers){
  oldMapSources = currentMapSources;
  currentMapSources = {};

  $(influencers).each(function(i, influencer){
    if(oldMapSources[influencer.id] == undefined){
      influencer.shouldRender = true;
    } else {
      // Retrieves marker for this influencer
      influencer.marker = oldMapSources[influencer.id].marker;
    }

    currentMapSources[influencer.id] = influencer;
    delete oldMapSources[influencer.id];
  });

  $.each(currentMapSources, function(influencerId, influencer){
    // Add new Markers
    if(influencer.shouldRender == true){
      influencer.marker = _createMarker(influencer);
      currentMapSources[influencerId] = influencer;
    } else {
      // Update existent marker
      influencer.marker.infowindow.setContent(_createInfoWindowContent(influencer));
    }
  });

  // Remove Markers
  $.each(oldMapSources, function(influencerId, influencer){
    influencer.marker.setMap(null);
  });
}

function _renderEvents(mapEvents){
  var locations = [];
  $(mapEvents).each(function(i, mapEvent){
    var location = new google.maps.LatLng(mapEvent.latlng[0], mapEvent.latlng[1]);
    locations.push({
      location: location, weight: mapEvent.density
    });
  });
  _createHeatmap(locations);
}

function _createHeatmap(locations) {
  var heatmap = new google.maps.visualization.HeatmapLayer({
    data: locations,
    map: map
  });
  heatmap.set('radius', 20);
}

function _createMarker(influencer) {
  var influencerLocation = influencer.locations[0];
  var myLatlng = new google.maps.LatLng(influencerLocation.latlng[0],
                                        influencerLocation.latlng[1]);
  var infowindow = new google.maps.InfoWindow({
    content: _createInfoWindowContent(influencer)
  });

  var marker = new google.maps.Marker({
    position: myLatlng,
    animation: google.maps.Animation.DROP,
    map: map,
    title: influencer.name,
    icon: '/assets/pin-' + influencer.gender + '2.png'
  });

  marker.addListener('click', function() {
    infowindow.open(map, marker);
  });
  infowindow.open(map, marker);

  marker.infowindow = infowindow;
  return marker;
}

function _createInfoWindowContent(influencer) {
  return influencer.name + " (" + influencer.age + "y)";
}
<commit_msg>Fix setPosition for new marker position of the same influencer<commit_after>var map, currentMapSources = {}, oldMapSources = {};

function renderMap(){
  map = new google.maps.Map(document.getElementById("map"),
                            { zoom: 3, center: new google.maps.LatLng(0, 0) });
}

function renderInfluencesInMap(influences){
  var influencers = [];

  $(influences).each(function(i, inf){ influencers.push(inf) });

  _renderInfluencers(influencers);
}

function _renderInfluencers(influencers){
  oldMapSources = currentMapSources;
  currentMapSources = {};

  $(influencers).each(function(i, influencer){

    if(oldMapSources[influencer.id] == undefined){
      influencer.marker = _createMarker(influencer);
    } else {
      influencer.marker = oldMapSources[influencer.id].marker;
      _moveMarker(influencer.marker, influencer.locations[0]);
    }

    influencer.marker.infowindow.setContent(_createInfoWindowContent(influencer));

    currentMapSources[influencer.id] = influencer;
    delete oldMapSources[influencer.id];
  });

  // Remove Markers
  $.each(oldMapSources, function(id, influencer){ influencer.marker.setMap(null) });
}

function _moveMarker(marker, newLocation){
  var newLatLng = new google.maps.LatLng(newLocation.latlng[0],
                                         newLocation.latlng[1]);
  marker.setPosition(newLatLng)
}

function _createMarker(influencer) {
  var influencerLocation = influencer.locations[0];
  var myLatlng = new google.maps.LatLng(influencerLocation.latlng[0],
                                        influencerLocation.latlng[1]);
  var infowindow = new google.maps.InfoWindow();

  var marker = new google.maps.Marker({
    position: myLatlng,
    animation: google.maps.Animation.DROP,
    map: map,
    title: influencer.name,
    icon: '/assets/pin-' + influencer.gender + '2.png'
  });

  marker.addListener('click', function() { infowindow.open(map, marker) });
  infowindow.open(map, marker);

  marker.infowindow = infowindow;
  return marker;
}

function _createInfoWindowContent(influencer) {
  return influencer.name + " (" + influencer.age + "y)";
}
<|endoftext|>


<commit_before>/* @flow */

const path = require('path')
const serialize = require('serialize-javascript')

import { isJS, isCSS } from '../util'
import TemplateStream from './template-stream'
import { parseTemplate } from './parse-template'
import { createMapper } from './create-async-file-mapper'
import type { ParsedTemplate } from './parse-template'
import type { AsyncFileMapper } from './create-async-file-mapper'

type TemplateRendererOptions = {
  template: ?string;
  inject?: boolean;
  clientManifest?: ClientManifest;
  shouldPreload?: (file: string, type: string) => boolean;
  shouldPrefetch?: (file: string, type: string) => boolean;
};

export type ClientManifest = {
  publicPath: string;
  all: Array<string>;
  initial: Array<string>;
  async: Array<string>;
  modules: {
    [id: string]: Array<number>;
  },
  hasNoCssVersion?: {
    [file: string]: boolean;
  }
};

type Resource = {
  file: string;
  extension: string;
  fileWithoutQuery: string;
  asType: string;
};

export default class TemplateRenderer {
  options: TemplateRendererOptions;
  inject: boolean;
  parsedTemplate: ParsedTemplate | null;
  publicPath: string;
  clientManifest: ClientManifest;
  preloadFiles: Array<Resource>;
  prefetchFiles: Array<Resource>;
  mapFiles: AsyncFileMapper;

  constructor (options: TemplateRendererOptions) {
    this.options = options
    this.inject = options.inject !== false
    // if no template option is provided, the renderer is created
    // as a utility object for rendering assets like preload links and scripts.
    this.parsedTemplate = options.template
      ? parseTemplate(options.template)
      : null

    // extra functionality with client manifest
    if (options.clientManifest) {
      const clientManifest = this.clientManifest = options.clientManifest
      this.publicPath = clientManifest.publicPath.replace(/\/$/, '')
      // preload/prefetch directives
      this.preloadFiles = (clientManifest.initial || []).map(normalizeFile)
      this.prefetchFiles = (clientManifest.async || []).map(normalizeFile)
      // initial async chunk mapping
      this.mapFiles = createMapper(clientManifest)
    }
  }

  bindRenderFns (context: Object) {
    const renderer: any = this
    ;['ResourceHints', 'State', 'Scripts', 'Styles'].forEach(type => {
      context[`render${type}`] = renderer[`render${type}`].bind(renderer, context)
    })
    // also expose getPreloadFiles, useful for HTTP/2 push
    context.getPreloadFiles = renderer.getPreloadFiles.bind(renderer, context)
  }

  // render synchronously given rendered app content and render context
  renderSync (content: string, context: ?Object) {
    const template = this.parsedTemplate
    if (!template) {
      throw new Error('renderSync cannot be called without a template.')
    }
    context = context || {}
    if (this.inject) {
      return (
        template.head(context) +
        (context.head || '') +
        this.renderResourceHints(context) +
        this.renderStyles(context) +
        template.neck(context) +
        content +
        this.renderState(context) +
        this.renderScripts(context) +
        template.tail(context)
      )
    } else {
      return (
        template.head(context) +
        template.neck(context) +
        content +
        template.tail(context)
      )
    }
  }

  renderStyles (context: Object): string {
    const cssFiles = this.clientManifest
      ? this.clientManifest.all.filter(isCSS)
      : []
    return (
      // render links for css files
      (cssFiles.length
        ? cssFiles.map(file => `<link rel="stylesheet" href="${this.publicPath}/${file}">`).join('')
        : '') +
      // context.styles is a getter exposed by vue-style-loader which contains
      // the inline component styles collected during SSR
      (context.styles || '')
    )
  }

  renderResourceHints (context: Object): string {
    return this.renderPreloadLinks(context) + this.renderPrefetchLinks(context)
  }

  getPreloadFiles (context: Object): Array<Resource> {
    const usedAsyncFiles = this.getUsedAsyncFiles(context)
    if (this.preloadFiles || usedAsyncFiles) {
      return (this.preloadFiles || []).concat(usedAsyncFiles || [])
    } else {
      return []
    }
  }

  renderPreloadLinks (context: Object): string {
    const files = this.getPreloadFiles(context)
    const shouldPreload = this.options.shouldPreload
    if (files.length) {
      return files.map(({ file, extension, fileWithoutQuery, asType }) => {
        let extra = ''
        // by default, we only preload scripts or css
        if (!shouldPreload && asType !== 'script' && asType !== 'style') {
          return ''
        }
        // user wants to explicitly control what to preload
        if (shouldPreload && !shouldPreload(fileWithoutQuery, asType)) {
          return ''
        }
        if (asType === 'font') {
          extra = ` type="font/${extension}" crossorigin`
        }
        return `<link rel="preload" href="${
          this.publicPath}/${file
        }"${
          asType !== '' ? ` as="${asType}"` : ''
        }${
          extra
        }>`
      }).join('')
    } else {
      return ''
    }
  }

  renderPrefetchLinks (context: Object): string {
    const shouldPrefetch = this.options.shouldPrefetch
    if (this.prefetchFiles) {
      const usedAsyncFiles = this.getUsedAsyncFiles(context)
      const alreadyRendered = file => {
        return usedAsyncFiles && usedAsyncFiles.some(f => f.file === file)
      }
      return this.prefetchFiles.map(({ file, fileWithoutQuery, asType }) => {
        if (shouldPrefetch && !shouldPrefetch(fileWithoutQuery, asType)) {
          return ''
        }
        if (alreadyRendered(file)) {
          return ''
        }
        return `<link rel="prefetch" href="${this.publicPath}/${file}">`
      }).join('')
    } else {
      return ''
    }
  }

  renderState (context: Object, options?: Object): string {
    const {
      contextKey = 'state',
      windowKey = '__INITIAL_STATE__'
    } = options || {}
    const autoRemove = process.env.NODE_ENV === 'production'
      ? '(function(){var s;(s=document.currentScript||document.scripts[document.scripts.length-1]).parentNode.removeChild(s);}());'
      : ''
    return context[contextKey]
      ? `<script>window.${windowKey}=${
          serialize(context[contextKey], { isJSON: true })
        }${autoRemove}</script>`
      : ''
  }

  renderScripts (context: Object): string {
    if (this.clientManifest) {
      const initial = this.preloadFiles
      const async = this.getUsedAsyncFiles(context)
      const needed = [initial[0]].concat(async || [], initial.slice(1))
      return needed.filter(({ file }) => isJS(file)).map(({ file }) => {
        return `<script src="${this.publicPath}/${file}" defer></script>`
      }).join('')
    } else {
      return ''
    }
  }

  getUsedAsyncFiles (context: Object): ?Array<Resource> {
    if (!context._mappedFiles && context._registeredComponents && this.mapFiles) {
      const registered = Array.from(context._registeredComponents)
      context._mappedFiles = this.mapFiles(registered).map(normalizeFile)
    }
    return context._mappedFiles
  }

  // create a transform stream
  createStream (context: ?Object): TemplateStream {
    if (!this.parsedTemplate) {
      throw new Error('createStream cannot be called without a template.')
    }
    return new TemplateStream(this, this.parsedTemplate, context || {})
  }
}

function normalizeFile (file: string): Resource {
  const withoutQuery = file.replace(/\?.*/, '')
  const extension = path.extname(withoutQuery).slice(1)
  return {
    file,
    extension,
    fileWithoutQuery: withoutQuery,
    asType: getPreloadType(extension)
  }
}

function getPreloadType (ext: string): string {
  if (ext === 'js') {
    return 'script'
  } else if (ext === 'css') {
    return 'style'
  } else if (/jpe?g|png|svg|gif|webp|ico/.test(ext)) {
    return 'image'
  } else if (/woff2?|ttf|otf|eot/.test(ext)) {
    return 'font'
  } else {
    // not exhausting all possibilities here, but above covers common cases
    return ''
  }
}
<commit_msg>fix(ssr): add semicolon before self-removal script (#6794)<commit_after>/* @flow */

const path = require('path')
const serialize = require('serialize-javascript')

import { isJS, isCSS } from '../util'
import TemplateStream from './template-stream'
import { parseTemplate } from './parse-template'
import { createMapper } from './create-async-file-mapper'
import type { ParsedTemplate } from './parse-template'
import type { AsyncFileMapper } from './create-async-file-mapper'

type TemplateRendererOptions = {
  template: ?string;
  inject?: boolean;
  clientManifest?: ClientManifest;
  shouldPreload?: (file: string, type: string) => boolean;
  shouldPrefetch?: (file: string, type: string) => boolean;
};

export type ClientManifest = {
  publicPath: string;
  all: Array<string>;
  initial: Array<string>;
  async: Array<string>;
  modules: {
    [id: string]: Array<number>;
  },
  hasNoCssVersion?: {
    [file: string]: boolean;
  }
};

type Resource = {
  file: string;
  extension: string;
  fileWithoutQuery: string;
  asType: string;
};

export default class TemplateRenderer {
  options: TemplateRendererOptions;
  inject: boolean;
  parsedTemplate: ParsedTemplate | null;
  publicPath: string;
  clientManifest: ClientManifest;
  preloadFiles: Array<Resource>;
  prefetchFiles: Array<Resource>;
  mapFiles: AsyncFileMapper;

  constructor (options: TemplateRendererOptions) {
    this.options = options
    this.inject = options.inject !== false
    // if no template option is provided, the renderer is created
    // as a utility object for rendering assets like preload links and scripts.
    this.parsedTemplate = options.template
      ? parseTemplate(options.template)
      : null

    // extra functionality with client manifest
    if (options.clientManifest) {
      const clientManifest = this.clientManifest = options.clientManifest
      this.publicPath = clientManifest.publicPath.replace(/\/$/, '')
      // preload/prefetch directives
      this.preloadFiles = (clientManifest.initial || []).map(normalizeFile)
      this.prefetchFiles = (clientManifest.async || []).map(normalizeFile)
      // initial async chunk mapping
      this.mapFiles = createMapper(clientManifest)
    }
  }

  bindRenderFns (context: Object) {
    const renderer: any = this
    ;['ResourceHints', 'State', 'Scripts', 'Styles'].forEach(type => {
      context[`render${type}`] = renderer[`render${type}`].bind(renderer, context)
    })
    // also expose getPreloadFiles, useful for HTTP/2 push
    context.getPreloadFiles = renderer.getPreloadFiles.bind(renderer, context)
  }

  // render synchronously given rendered app content and render context
  renderSync (content: string, context: ?Object) {
    const template = this.parsedTemplate
    if (!template) {
      throw new Error('renderSync cannot be called without a template.')
    }
    context = context || {}
    if (this.inject) {
      return (
        template.head(context) +
        (context.head || '') +
        this.renderResourceHints(context) +
        this.renderStyles(context) +
        template.neck(context) +
        content +
        this.renderState(context) +
        this.renderScripts(context) +
        template.tail(context)
      )
    } else {
      return (
        template.head(context) +
        template.neck(context) +
        content +
        template.tail(context)
      )
    }
  }

  renderStyles (context: Object): string {
    const cssFiles = this.clientManifest
      ? this.clientManifest.all.filter(isCSS)
      : []
    return (
      // render links for css files
      (cssFiles.length
        ? cssFiles.map(file => `<link rel="stylesheet" href="${this.publicPath}/${file}">`).join('')
        : '') +
      // context.styles is a getter exposed by vue-style-loader which contains
      // the inline component styles collected during SSR
      (context.styles || '')
    )
  }

  renderResourceHints (context: Object): string {
    return this.renderPreloadLinks(context) + this.renderPrefetchLinks(context)
  }

  getPreloadFiles (context: Object): Array<Resource> {
    const usedAsyncFiles = this.getUsedAsyncFiles(context)
    if (this.preloadFiles || usedAsyncFiles) {
      return (this.preloadFiles || []).concat(usedAsyncFiles || [])
    } else {
      return []
    }
  }

  renderPreloadLinks (context: Object): string {
    const files = this.getPreloadFiles(context)
    const shouldPreload = this.options.shouldPreload
    if (files.length) {
      return files.map(({ file, extension, fileWithoutQuery, asType }) => {
        let extra = ''
        // by default, we only preload scripts or css
        if (!shouldPreload && asType !== 'script' && asType !== 'style') {
          return ''
        }
        // user wants to explicitly control what to preload
        if (shouldPreload && !shouldPreload(fileWithoutQuery, asType)) {
          return ''
        }
        if (asType === 'font') {
          extra = ` type="font/${extension}" crossorigin`
        }
        return `<link rel="preload" href="${
          this.publicPath}/${file
        }"${
          asType !== '' ? ` as="${asType}"` : ''
        }${
          extra
        }>`
      }).join('')
    } else {
      return ''
    }
  }

  renderPrefetchLinks (context: Object): string {
    const shouldPrefetch = this.options.shouldPrefetch
    if (this.prefetchFiles) {
      const usedAsyncFiles = this.getUsedAsyncFiles(context)
      const alreadyRendered = file => {
        return usedAsyncFiles && usedAsyncFiles.some(f => f.file === file)
      }
      return this.prefetchFiles.map(({ file, fileWithoutQuery, asType }) => {
        if (shouldPrefetch && !shouldPrefetch(fileWithoutQuery, asType)) {
          return ''
        }
        if (alreadyRendered(file)) {
          return ''
        }
        return `<link rel="prefetch" href="${this.publicPath}/${file}">`
      }).join('')
    } else {
      return ''
    }
  }

  renderState (context: Object, options?: Object): string {
    const {
      contextKey = 'state',
      windowKey = '__INITIAL_STATE__'
    } = options || {}
    const autoRemove = process.env.NODE_ENV === 'production'
      ? ';(function(){var s;(s=document.currentScript||document.scripts[document.scripts.length-1]).parentNode.removeChild(s);}());'
      : ''
    return context[contextKey]
      ? `<script>window.${windowKey}=${
          serialize(context[contextKey], { isJSON: true })
        }${autoRemove}</script>`
      : ''
  }

  renderScripts (context: Object): string {
    if (this.clientManifest) {
      const initial = this.preloadFiles
      const async = this.getUsedAsyncFiles(context)
      const needed = [initial[0]].concat(async || [], initial.slice(1))
      return needed.filter(({ file }) => isJS(file)).map(({ file }) => {
        return `<script src="${this.publicPath}/${file}" defer></script>`
      }).join('')
    } else {
      return ''
    }
  }

  getUsedAsyncFiles (context: Object): ?Array<Resource> {
    if (!context._mappedFiles && context._registeredComponents && this.mapFiles) {
      const registered = Array.from(context._registeredComponents)
      context._mappedFiles = this.mapFiles(registered).map(normalizeFile)
    }
    return context._mappedFiles
  }

  // create a transform stream
  createStream (context: ?Object): TemplateStream {
    if (!this.parsedTemplate) {
      throw new Error('createStream cannot be called without a template.')
    }
    return new TemplateStream(this, this.parsedTemplate, context || {})
  }
}

function normalizeFile (file: string): Resource {
  const withoutQuery = file.replace(/\?.*/, '')
  const extension = path.extname(withoutQuery).slice(1)
  return {
    file,
    extension,
    fileWithoutQuery: withoutQuery,
    asType: getPreloadType(extension)
  }
}

function getPreloadType (ext: string): string {
  if (ext === 'js') {
    return 'script'
  } else if (ext === 'css') {
    return 'style'
  } else if (/jpe?g|png|svg|gif|webp|ico/.test(ext)) {
    return 'image'
  } else if (/woff2?|ttf|otf|eot/.test(ext)) {
    return 'font'
  } else {
    // not exhausting all possibilities here, but above covers common cases
    return ''
  }
}
<|endoftext|>


<commit_before>angular.module("leaflet-directive").factory('leafletControlHelpers', function ($rootScope, $log, leafletHelpers, leafletMapDefaults) {
    var isDefined = leafletHelpers.isDefined;
    var isObject = leafletHelpers.isObject;
    var _controls = {};

    var _controlLayersMustBeVisible = function(baselayers, overlays, mapId) {
        var defaults = leafletMapDefaults.getDefaults(mapId);
        if(!defaults.controls.layers.visible) {
            return false;
        }

        var atLeastOneControlItemMustBeShown = false;

        if (isObject(baselayers)) {
            Object.keys(baselayers).forEach(function(key) {
                var layer = baselayers[key];
                if (!isDefined(layer.layerOptions) || layer.layerOptions.showOnSelector !== false) {
                    atLeastOneControlItemMustBeShown = true;
                }
            });
        }

        if (isObject(overlays)) {
            Object.keys(overlays).forEach(function(key) {
                var layer = overlays[key];
                if (!isDefined(layer.layerParams) || layer.layerParams.showOnSelector !== false) {
                    atLeastOneControlItemMustBeShown = true;
                }
            });
        }

        return atLeastOneControlItemMustBeShown;
    };

    var _createLayersControl = function(mapId) {
        var defaults = leafletMapDefaults.getDefaults(mapId);
        var controlOptions = {
            collapsed: defaults.controls.layers.collapsed,
            position: defaults.controls.layers.position,
            autoZIndex: false
        };

        angular.extend(controlOptions, defaults.controls.layers.options);

        var control;
        if(defaults.controls.layers && isDefined(defaults.controls.layers.control)) {
			control = defaults.controls.layers.control.apply(this, [[], [], controlOptions]);
		} else {
			control = new L.control.layers([], [], controlOptions);
		}

        return control;
    };

    return {
        layersControlMustBeVisible: _controlLayersMustBeVisible,

        updateLayersControl: function(map, mapId, loaded, baselayers, overlays, leafletLayers) {
            var i;

            var _layersControl = _controls[mapId];
            var mustBeLoaded = _controlLayersMustBeVisible(baselayers, overlays, mapId);
            if (isDefined(_layersControl) && loaded) {
                for (i in leafletLayers.baselayers) {
                    _layersControl.removeLayer(leafletLayers.baselayers[i]);
                }
                for (i in leafletLayers.overlays) {
                    _layersControl.removeLayer(leafletLayers.overlays[i]);
                }
                map.removeControl(_layersControl);
                delete _controls[mapId];
            }

            if (mustBeLoaded) {
                _layersControl = _createLayersControl(mapId);
                _controls[mapId] = _layersControl;
                for (i in baselayers) {
                    var hideOnSelector = isDefined(baselayers[i].layerOptions) &&
                                         baselayers[i].layerOptions.showOnSelector === false;
                    if (!hideOnSelector && isDefined(leafletLayers.baselayers[i])) {
                        _layersControl.addBaseLayer(leafletLayers.baselayers[i], baselayers[i].name);
                    }
                }
                for (i in overlays) {
                	var hideOverlayOnSelector = isDefined(overlays[i].layerOptions) &&
                            overlays[i].layerOptions.showOnSelector === false;
                    if (!hideOverlayOnSelector && isDefined(leafletLayers.overlays[i])) {
                        _layersControl.addOverlay(leafletLayers.overlays[i], overlays[i].name);
                    }
                }

                map.addControl(_layersControl);
            }
            return mustBeLoaded;
        }
    };
});
<commit_msg>Small fix on layers control which allows dinamically hide/show overlays with "shownOnSelector" property<commit_after>angular.module("leaflet-directive").factory('leafletControlHelpers', function ($rootScope, $log, leafletHelpers, leafletMapDefaults) {
    var isDefined = leafletHelpers.isDefined;
    var isObject = leafletHelpers.isObject;
    var _controls = {};

    var _controlLayersMustBeVisible = function(baselayers, overlays, mapId) {
        var defaults = leafletMapDefaults.getDefaults(mapId);
        if(!defaults.controls.layers.visible) {
            return false;
        }

        var atLeastOneControlItemMustBeShown = false;

        if (isObject(baselayers)) {
            Object.keys(baselayers).forEach(function(key) {
                var layer = baselayers[key];
                if (!isDefined(layer.layerOptions) || layer.layerOptions.showOnSelector !== false) {
                    atLeastOneControlItemMustBeShown = true;
                }
            });
        }

        if (isObject(overlays)) {
            Object.keys(overlays).forEach(function(key) {
                var layer = overlays[key];
                if (!isDefined(layer.layerParams) || layer.layerParams.showOnSelector !== false) {
                    atLeastOneControlItemMustBeShown = true;
                }
            });
        }

        return atLeastOneControlItemMustBeShown;
    };

    var _createLayersControl = function(mapId) {
        var defaults = leafletMapDefaults.getDefaults(mapId);
        var controlOptions = {
            collapsed: defaults.controls.layers.collapsed,
            position: defaults.controls.layers.position,
            autoZIndex: false
        };

        angular.extend(controlOptions, defaults.controls.layers.options);

        var control;
        if(defaults.controls.layers && isDefined(defaults.controls.layers.control)) {
			control = defaults.controls.layers.control.apply(this, [[], [], controlOptions]);
		} else {
			control = new L.control.layers([], [], controlOptions);
		}

        return control;
    };

    return {
        layersControlMustBeVisible: _controlLayersMustBeVisible,

        updateLayersControl: function(map, mapId, loaded, baselayers, overlays, leafletLayers) {
            var i;
            var _layersControl = _controls[mapId];
            var mustBeLoaded = _controlLayersMustBeVisible(baselayers, overlays, mapId);

            console.log(overlays);
            if (isDefined(_layersControl) && loaded) {
                for (i in leafletLayers.baselayers) {
                    _layersControl.removeLayer(leafletLayers.baselayers[i]);
                }
                for (i in leafletLayers.overlays) {
                    _layersControl.removeLayer(leafletLayers.overlays[i]);
                }
                map.removeControl(_layersControl);
                delete _controls[mapId];
            }

            if (mustBeLoaded) {
                _layersControl = _createLayersControl(mapId);
                _controls[mapId] = _layersControl;
                for (i in baselayers) {
                    var hideOnSelector = isDefined(baselayers[i].layerOptions) &&
                                         baselayers[i].layerOptions.showOnSelector === false;
                    if (!hideOnSelector && isDefined(leafletLayers.baselayers[i])) {
                        _layersControl.addBaseLayer(leafletLayers.baselayers[i], baselayers[i].name);
                    }
                }
                for (i in overlays) {
                	var hideOverlayOnSelector = isDefined(overlays[i].layerParams) &&
                            overlays[i].layerParams.showOnSelector === false;
                    if (!hideOverlayOnSelector && isDefined(leafletLayers.overlays[i])) {
                        _layersControl.addOverlay(leafletLayers.overlays[i], overlays[i].name);
                    }
                }

                map.addControl(_layersControl);
            }
            return mustBeLoaded;
        }
    };
});
<|endoftext|>


<commit_before>/**
 * Shared exports among WPDashboard Stories.
 *
 * Site Kit by Google, Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Internal dependencies
 */
import { provideModules } from '../../../../tests/js/utils';
import { CORE_USER } from '../../googlesitekit/datastore/user/constants';
import { MODULES_SEARCH_CONSOLE } from '../../modules/search-console/datastore/constants';
import { MODULES_ANALYTICS } from '../../modules/analytics/datastore/constants';
import { getAnalyticsMockResponse } from '../../modules/analytics/util/data-mock';
import WithRegistrySetup from '../../../../tests/js/WithRegistrySetup';
import { provideSearchConsoleMockReport } from '../../modules/search-console/util/data-mock';

const wpDashboardSearchConsoleOptions = {
	startDate: '2020-12-03',
	endDate: '2021-01-27',
	dimensions: 'date',
};

const wpDashboardAnalyticsMockData = [
	// Mock Total Users widget data
	{
		startDate: '2020-12-31',
		endDate: '2021-01-27',
		compareStartDate: '2020-12-03',
		compareEndDate: '2020-12-30',
		metrics: [
			{
				expression: 'ga:users',
				alias: 'Total Users',
			},
		],
	},

	// Mock Sessions widget data
	{
		startDate: '2020-12-31',
		endDate: '2021-01-27',
		compareStartDate: '2020-12-03',
		compareEndDate: '2020-12-30',
		dimensions: 'ga:date',
		limit: 10,
		metrics: [
			{
				expression: 'ga:avgSessionDuration',
				alias: 'Average Session Duration',
			},
		],
	},
];
export const setupBaseRegistry = ( registry, args ) => {
	// Set up the search console and analytics modules stores but provide no data.
	provideModules( registry, [
		{
			slug: 'search-console',
			active: true,
			connected: true,
		},
		{
			slug: 'analytics',
			active: true,
			connected: true,
		},
	] );

	// Call story-specific setup.
	if ( typeof args?.setupRegistry === 'function' ) {
		args.setupRegistry( registry );
	}
};

export function setupSearchConsoleMockReports( registry, data ) {
	registry.dispatch( CORE_USER ).setReferenceDate( '2021-01-28' );

	if ( data ) {
		registry.dispatch( MODULES_SEARCH_CONSOLE ).receiveGetReport( data, {
			options: wpDashboardSearchConsoleOptions,
		} );
	} else {
		provideSearchConsoleMockReport(
			registry,
			wpDashboardSearchConsoleOptions
		);
	}
}

export const setupAnalyticsMockReports = (
	registry,
	data = wpDashboardAnalyticsMockData
) => {
	registry.dispatch( CORE_USER ).setReferenceDate( '2021-01-28' );
	data.forEach( ( options ) => {
		registry
			.dispatch( MODULES_ANALYTICS )
			.receiveGetReport( getAnalyticsMockResponse( options ), {
				options,
			} );
	} );
};

export const setupSearchConsoleAnalyticsMockReports = ( registry ) => {
	setupSearchConsoleMockReports( registry );
	setupAnalyticsMockReports( registry );
};

export const widgetDecorators = [
	( Story ) => (

				<Story />

	),
	( Story, { args } ) => {
		const setupRegistry = ( registry ) => {
			setupBaseRegistry( registry, args );
		};

		return (
			<WithRegistrySetup func={ setupRegistry }>
				<Story />
			</WithRegistrySetup>
		);
	},
];

export function setupSearchConsoleGatheringData( registry ) {
	registry.dispatch( CORE_USER ).setReferenceDate( '2021-01-28' );
	registry.dispatch( MODULES_SEARCH_CONSOLE ).receiveGetReport( [], {
		options: wpDashboardSearchConsoleOptions,
	} );
}

export const setupAnalyticsGatheringData = (
	registry,
	data = wpDashboardAnalyticsMockData
) => {
	registry.dispatch( CORE_USER ).setReferenceDate( '2021-01-28' );
	data.forEach( ( options ) => {
		registry.dispatch( MODULES_ANALYTICS ).receiveGetReport(
			[
				{
					data: {
						rows: [],
						totals: [ { values: [] }, { values: [] } ],
					},
				},
			],
			{
				options,
			}
		);
	} );
};
<commit_msg>Improve naming and documentation to differentiate mock options from data.<commit_after>/**
 * Shared exports among WPDashboard Stories.
 *
 * Site Kit by Google, Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Internal dependencies
 */
import { provideModules } from '../../../../tests/js/utils';
import { CORE_USER } from '../../googlesitekit/datastore/user/constants';
import { MODULES_SEARCH_CONSOLE } from '../../modules/search-console/datastore/constants';
import { MODULES_ANALYTICS } from '../../modules/analytics/datastore/constants';
import { getAnalyticsMockResponse } from '../../modules/analytics/util/data-mock';
import WithRegistrySetup from '../../../../tests/js/WithRegistrySetup';
import { provideSearchConsoleMockReport } from '../../modules/search-console/util/data-mock';

const wpDashboardSearchConsoleOptions = {
	startDate: '2020-12-03',
	endDate: '2021-01-27',
	dimensions: 'date',
};

const wpDashboardAnalyticsOptionSets = [
	// Mock options for mocking Total Users report's response.
	{
		startDate: '2020-12-31',
		endDate: '2021-01-27',
		compareStartDate: '2020-12-03',
		compareEndDate: '2020-12-30',
		metrics: [
			{
				expression: 'ga:users',
				alias: 'Total Users',
			},
		],
	},

	// Mock options for mocking Sessions report's response.
	{
		startDate: '2020-12-31',
		endDate: '2021-01-27',
		compareStartDate: '2020-12-03',
		compareEndDate: '2020-12-30',
		dimensions: 'ga:date',
		limit: 10,
		metrics: [
			{
				expression: 'ga:avgSessionDuration',
				alias: 'Average Session Duration',
			},
		],
	},
];

export const setupBaseRegistry = ( registry, args ) => {
	// Set up the search console and analytics modules stores but provide no data.
	provideModules( registry, [
		{
			slug: 'search-console',
			active: true,
			connected: true,
		},
		{
			slug: 'analytics',
			active: true,
			connected: true,
		},
	] );

	// Call story-specific setup.
	if ( typeof args?.setupRegistry === 'function' ) {
		args.setupRegistry( registry );
	}
};

export function setupSearchConsoleMockReports( registry, data ) {
	registry.dispatch( CORE_USER ).setReferenceDate( '2021-01-28' );

	if ( data ) {
		registry.dispatch( MODULES_SEARCH_CONSOLE ).receiveGetReport( data, {
			options: wpDashboardSearchConsoleOptions,
		} );
	} else {
		provideSearchConsoleMockReport(
			registry,
			wpDashboardSearchConsoleOptions
		);
	}
}

export const setupAnalyticsMockReports = (
	registry,
	mockOptions = wpDashboardAnalyticsOptionSets
) => {
	registry.dispatch( CORE_USER ).setReferenceDate( '2021-01-28' );
	mockOptions.forEach( ( options ) => {
		registry
			.dispatch( MODULES_ANALYTICS )
			.receiveGetReport( getAnalyticsMockResponse( options ), {
				options,
			} );
	} );
};

export const setupSearchConsoleAnalyticsMockReports = ( registry ) => {
	setupSearchConsoleMockReports( registry );
	setupAnalyticsMockReports( registry );
};

export const widgetDecorators = [
	( Story ) => (

				<Story />

	),
	( Story, { args } ) => {
		const setupRegistry = ( registry ) => {
			setupBaseRegistry( registry, args );
		};

		return (
			<WithRegistrySetup func={ setupRegistry }>
				<Story />
			</WithRegistrySetup>
		);
	},
];

export function setupSearchConsoleGatheringData( registry ) {
	registry.dispatch( CORE_USER ).setReferenceDate( '2021-01-28' );
	registry.dispatch( MODULES_SEARCH_CONSOLE ).receiveGetReport( [], {
		options: wpDashboardSearchConsoleOptions,
	} );
}

export const setupAnalyticsGatheringData = (
	registry,
	mockOptions = wpDashboardAnalyticsOptionSets
) => {
	registry.dispatch( CORE_USER ).setReferenceDate( '2021-01-28' );
	mockOptions.forEach( ( options ) => {
		registry.dispatch( MODULES_ANALYTICS ).receiveGetReport(
			[
				{
					data: {
						rows: [],
						totals: [ { values: [] }, { values: [] } ],
					},
				},
			],
			{
				options,
			}
		);
	} );
};
<|endoftext|>


<commit_before>// Load all tabs
const tabs = getElementsByClassName('hero-slide-container')

// Preload images and randomly rotate
const fadeInSlide = slideNumber => {
	const literalNumbers = ['one', 'two', 'three', 'four', 'five', 'six']
	// Hero Image
	const hero = getElementByClassName('hero-slide', slideNumber)
	hero.classList.add('fade')
	// Slide in Hero Text
	setTimeout(() => {
		for (let i = 0; i < 3; i++) {
			const title = getElementByClassName('hero-title ' + literalNumbers[i], slideNumber)
			title.classList.add('fade-slide')
		}
	}, 500)
	// Slide in Hero Button
	setTimeout(() => {
		const heroButton = getElementByClassName('hero-button', slideNumber)
		heroButton.classList.add('fade-slide')
	}, 800)
	// Slide in Hero Arrows
	setTimeout(() => {
		const heroArrows = getElementByClassName('hero-arrows', slideNumber)
		heroArrows.classList.add('fade-slide')
	}, 1100)
}

const getSlideNumber = () => {
	for (let i = 0; i < tabs.length; i++) {
		if (tabs[i].classList.contains('w--tab-active')) {
			// Add active status to next tab
			return i === tabs.length - 1
				? { current: i, next: 0 }
				: { current: i, next: i + 1 }
		}
	}
}

// Begin
if (window.location.pathname === '/') {

	fadeInSlide(0)

	// Add event listener to cycle through all hero messages on arrow click
	const rightArrow = getElementByClassName('hero-arrow right', 0)
	rightArrow.addEventListener('click', () => {
			// Deactivate current tab
			tabs[getSlideNumber().current].classList.remove('w--tab-active')
			// Activate new tab
			tabs[getSlideNumber().next].classList.add('w--tab-active')
			// Fade in new slide
			fadeInSlide(getSlideNumber().next)
	})

}<commit_msg>Hero.<commit_after>// Load all tabs
const tabs = getElementsByClassName('hero-slide-container')

// Preload images and randomly rotate
const fadeInSlide = slideNumber => {
	const literalNumbers = ['one', 'two', 'three', 'four', 'five', 'six']
	// Hero Image
	const hero = getElementByClassName('hero-slide', slideNumber)
	hero.classList.add('fade')
	// Slide in Hero Text
	setTimeout(() => {
		for (let i = 0; i < 3; i++) {
			const title = getElementByClassName('hero-title ' + literalNumbers[i], slideNumber)
			title.classList.add('fade-slide')
		}
	}, 500)
	// Slide in Hero Button
	setTimeout(() => {
		const heroButton = getElementByClassName('hero-button', slideNumber)
		heroButton.classList.add('fade-slide')
	}, 800)
	// Slide in Hero Arrows
	setTimeout(() => {
		const heroArrows = getElementByClassName('hero-arrows', slideNumber)
		heroArrows.classList.add('fade-slide')
	}, 1100)
}

const getSlideNumber = () => {
	let obj
	for (let i = 0; i < tabs.length; i++) {
		if (tabs[i].classList.contains('w--tab-active')) {
			obj = i === tabs.length - 1
				? { current: i, next: 0 }
				: { current: i, next: i + 1 }
		}
	}
	return obj
}

// Begin
if (window.location.pathname === '/') {

	fadeInSlide(0)

	// Add event listener to cycle through all hero messages on arrow click
	const rightArrow = getElementByClassName('hero-arrow right', 0)
	rightArrow.addEventListener('click', () => {
			// Deactivate current tab
			tabs[getSlideNumber().current].classList.remove('w--tab-active')
			// Activate new tab
			tabs[getSlideNumber().next].classList.add('w--tab-active')
			// Fade in new slide
			fadeInSlide(getSlideNumber().next)
	})

}<|endoftext|>