<commit_before>/**
* Copyright 2012-2020, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var Lib = require('../../lib');
var sanitizeHTML = require('../../lib/svg_text_utils').sanitizeHTML;
var convertTextOpts = require('./convert_text_opts');
var constants = require('./constants');

function MapboxLayer(subplot, index) {
    this.subplot = subplot;

    this.uid = subplot.uid + '-' + index;
    this.index = index;

    this.idSource = 'source-' + this.uid;
    this.idLayer = constants.layoutLayerPrefix + this.uid;

    // some state variable to check if a remove/add step is needed
    this.sourceType = null;
    this.source = null;
    this.layerType = null;
    this.below = null;

    // is layer currently visible
    this.visible = false;
}

var proto = MapboxLayer.prototype;

proto.update = function update(opts) {
    if(!this.visible) {
        // IMPORTANT: must create source before layer to not cause errors
        this.updateSource(opts);
        this.updateLayer(opts);
    } else if(this.needsNewImage(opts)) {
        this.updateImage(opts);
    } else if(this.needsNewSource(opts)) {
        // IMPORTANT: must delete layer before source to not cause errors
        this.removeLayer();
        this.updateSource(opts);
        this.updateLayer(opts);
    } else if(this.needsNewLayer(opts)) {
        this.updateLayer(opts);
    } else {
        this.updateStyle(opts);
    }

    this.visible = isVisible(opts);
};

proto.needsNewImage = function(opts) {
    var map = this.subplot.map;
    return (
        map.getSource(this.idSource) &&
        this.sourceType === 'image' &&
        opts.sourcetype === 'image' &&
        (this.source !== opts.source ||
            JSON.stringify(this.coordinates) !==
            JSON.stringify(opts.coordinates))
    );
};

proto.needsNewSource = function(opts) {
    // for some reason changing layer to 'fill' or 'symbol'
    // w/o changing the source throws an exception in mapbox-gl 0.18 ;
    // stay safe and make new source on type changes
    return (
        this.sourceType !== opts.sourcetype ||
        this.source !== opts.source ||
        this.layerType !== opts.type
    );
};

proto.needsNewLayer = function(opts) {
    return (
        this.layerType !== opts.type ||
        this.below !== this.subplot.belowLookup['layout-' + this.index]
    );
};

proto.updateImage = function(opts) {
    var map = this.subplot.map;
    map.getSource(this.idSource).updateImage({
        url: opts.source, coordinates: opts.coordinates
    });
};

proto.updateSource = function(opts) {
    var map = this.subplot.map;

    if(map.getSource(this.idSource)) map.removeSource(this.idSource);

    this.sourceType = opts.sourcetype;
    this.source = opts.source;

    if(!isVisible(opts)) return;

    var sourceOpts = convertSourceOpts(opts);

    map.addSource(this.idSource, sourceOpts);
};

proto.updateLayer = function(opts) {
    var subplot = this.subplot;
    var convertedOpts = convertOpts(opts);

    var below = this.subplot.belowLookup['layout-' + this.index];
    var _below;

    if(below === 'traces') {
        var mapLayers = subplot.getMapLayers();

        // find id of first plotly trace layer
        for(var i = 0; i < mapLayers.length; i++) {
            var layerId = mapLayers[i].id;
            if(typeof layerId === 'string' &&
                layerId.indexOf(constants.traceLayerPrefix) === 0
            ) {
                _below = layerId;
                break;
            }
        }
    } else {
        _below = below;
    }

    this.removeLayer();

    if(isVisible(opts)) {
        subplot.addLayer({
            id: this.idLayer,
            source: this.idSource,
            'source-layer': opts.sourcelayer || '',
            type: opts.type,
            minzoom: opts.minzoom,
            maxzoom: opts.maxzoom,
            layout: convertedOpts.layout,
            paint: convertedOpts.paint
        }, _below);<commit_msg>Refactor to extract lookupBelow and findFollowingMapboxLayerId functions<commit_after>/**
* Copyright 2012-2020, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var Lib = require('../../lib');
var sanitizeHTML = require('../../lib/svg_text_utils').sanitizeHTML;
var convertTextOpts = require('./convert_text_opts');
var constants = require('./constants');

function MapboxLayer(subplot, index) {
    this.subplot = subplot;

    this.uid = subplot.uid + '-' + index;
    this.index = index;

    this.idSource = 'source-' + this.uid;
    this.idLayer = constants.layoutLayerPrefix + this.uid;

    // some state variable to check if a remove/add step is needed
    this.sourceType = null;
    this.source = null;
    this.layerType = null;
    this.below = null;

    // is layer currently visible
    this.visible = false;
}

var proto = MapboxLayer.prototype;

proto.update = function update(opts) {
    if(!this.visible) {
        // IMPORTANT: must create source before layer to not cause errors
        this.updateSource(opts);
        this.updateLayer(opts);
    } else if(this.needsNewImage(opts)) {
        this.updateImage(opts);
    } else if(this.needsNewSource(opts)) {
        // IMPORTANT: must delete layer before source to not cause errors
        this.removeLayer();
        this.updateSource(opts);
        this.updateLayer(opts);
    } else if(this.needsNewLayer(opts)) {
        this.updateLayer(opts);
    } else {
        this.updateStyle(opts);
    }

    this.visible = isVisible(opts);
};

proto.needsNewImage = function(opts) {
    var map = this.subplot.map;
    return (
        map.getSource(this.idSource) &&
        this.sourceType === 'image' &&
        opts.sourcetype === 'image' &&
        (this.source !== opts.source ||
            JSON.stringify(this.coordinates) !==
            JSON.stringify(opts.coordinates))
    );
};

proto.needsNewSource = function(opts) {
    // for some reason changing layer to 'fill' or 'symbol'
    // w/o changing the source throws an exception in mapbox-gl 0.18 ;
    // stay safe and make new source on type changes
    return (
        this.sourceType !== opts.sourcetype ||
        this.source !== opts.source ||
        this.layerType !== opts.type
    );
};

proto.needsNewLayer = function(opts) {
    return (
        this.layerType !== opts.type ||
        this.below !== this.subplot.belowLookup['layout-' + this.index]
    );
};

proto.lookupBelow = function() {
    return this.subplot.belowLookup['layout-' + this.index];
};

proto.updateImage = function(opts) {
    var map = this.subplot.map;
    map.getSource(this.idSource).updateImage({
        url: opts.source, coordinates: opts.coordinates
    });
};

proto.updateSource = function(opts) {
    var map = this.subplot.map;

    if(map.getSource(this.idSource)) map.removeSource(this.idSource);

    this.sourceType = opts.sourcetype;
    this.source = opts.source;

    if(!isVisible(opts)) return;

    var sourceOpts = convertSourceOpts(opts);

    map.addSource(this.idSource, sourceOpts);
};

proto.findFollowingMapboxLayerId = function(below) {
    if(below === 'traces') {
        var mapLayers = this.subplot.getMapLayers();

        // find id of first plotly trace layer
        for(var i = 0; i < mapLayers.length; i++) {
            var layerId = mapLayers[i].id;
            if(typeof layerId === 'string' &&
                layerId.indexOf(constants.traceLayerPrefix) === 0
            ) {
                below = layerId;
                break;
            }
        }
    }
    return below;
};

proto.updateLayer = function(opts) {
    var subplot = this.subplot;
    var convertedOpts = convertOpts(opts);
    var below = this.lookupBelow();
    var _below = this.findFollowingMapboxLayerId(below);

    this.removeLayer();

    if(isVisible(opts)) {
        subplot.addLayer({
            id: this.idLayer,
            source: this.idSource,
            'source-layer': opts.sourcelayer || '',
            type: opts.type,
            minzoom: opts.minzoom,
            maxzoom: opts.maxzoom,
            layout: convertedOpts.layout,
            paint: convertedOpts.paint
        }, _below);
{'fraction_non_alphanumeric': 0.12876974629009094, 'fraction_numerical': 0.0031115366203925323, 'mean_word_length': 2.447607260726073, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7361092', 'n_tokens_mistral': 2573, 'n_tokens_neox': 2484, 'n_words': 577}