<commit_before>import _find from 'lodash/find';
import _findIndex from 'lodash/findIndex';
import DataTableSource from './source/DataTableSource';
import { ModalChart, DataAnalytics } from '@entrylabs/tool';

class DataTable {
    #tables = [];
    #view;
    modal;
    selected;

    banAllBlock() {
        Entry.playground.blockMenu.banClass('analysis');
    }

    unbanBlock() {
        Entry.playground.blockMenu.unbanClass('analysis');
    }

    set view(view) {
        this.#view = view;
        this.#generateView();
    }

    get tables() {
        return this.#tables;
    }

    getSource(id) {
        if (!id) {
            console.warn('empty argument');
            return null;
        }
        return _find(this.#tables, { id });
    }

    getIndex({ id }) {
        if (!id) {
            console.warn('empty argument');
            return null;
        }
        return _findIndex(this.#tables, { id });
    }

    addSource(table) {
        Entry.do('playgroundChangeViewMode', 'table');
        let data = table || { name: Lang.Workspace.data_table };
        data.name = Entry.getOrderedName(data.name, this.#tables, 'name');
        const isDataTableSource = data instanceof DataTableSource;
        Entry.do('dataTableAddSource', isDataTableSource ? data : new DataTableSource(data));
    }

    removeSource(table) {
        Entry.do('dataTableRemoveSource', table);
    }

    changeItemPosition(start, end) {
        if (this.#tables.length) {
            this.#tables.splice(end, 0, this.#tables.splice(start, 1)[0]);
        }
    }

    selectTable(table = {}) {
        const json = table.toJSON && table.toJSON();
        const { tab } = table;
        this.selected = table;
        this.dataAnalytics.setData({
            table: { ...json, tab },
        });
        delete table.tab;
    }

    #generateView() {
        this.dataAnalytics = new DataAnalytics({ container: this.#view, data: {} })
            .on('submit', (dataAnalytics) => {
                const { id, table = [[]], charts = [], title } = dataAnalytics;
                if (
                    Entry.playground.isDuplicatedTableName(
                        title,
                        _.findIndex(this.tables, (table) => table.id === id)
                    )
                ) {
                    return Entry.toast.alert(
                        Lang.DataAnalytics.duplicate_table_name_title,
                        Lang.DataAnalytics.duplicate_table_name_content
                    );
                }
                if (Entry.playground.dataTable.getSource(id)) {
                    Entry.playground.dataTable.getSource(id).setArray({
                        chart: charts,
                        fields: table[0],
                        chart: charts,
                        data: table.slice(1),
                        name: title,
                    });
                    Entry.playground.injectTable();
                }
                Entry.toast.success(
                    Lang.DataAnalytics.saved_table_title,
                    Lang.DataAnalytics.saved_table_content
                );
            })
            .on('toast', (message) => {
                const { title, content } = message;
                Entry.toast.alert(title, content);
            });
    }

    getTableJSON() {
        return this.tables.filter(_.identity).map((v) => (v.toJSON ? v.toJSON() : v));
    }

    setTables(tables = []) {
        tables.forEach((table) => {
            this.addSource(table);
        });
    }

    setTableName(id, name) {
        if (!name) {
            return;
        }

        const source = this.getSource(id);
        if (!source) {
            return;
        }

        const { chart, array, fields } = source;
        source.setArray({ chart, data: array, fields, name });
    }

    showChart(tableId) {
        this.closeChart();
        const source = this.getSource(tableId);
        if (!source.modal) {
            source.modal = this.createChart(source);
        }
        source.modal.show();
        this.modal = source.modal;
    }

    closeChart() {
        if (this.modal && this.modal.isShow) {
            this.modal.hide();
        }
    }

    createChart(source) {
        const tables = this.#tables.map(({ id, name }) => [name, id]);
        const container = Entry.Dom('div', {
            class: 'entry-table-chart',
            parent: $('body'),
        })[0];
        return new ModalChart({
            data: {
                tables,
                source,
                setTable: (selected) => {
                    const [tableName, tableId] = selected;
                    this.showChart(tableId);
                },
            },
            container,
        });
    }

    clear() {
        this.#tables = [];
        this.modal = null;
    }
}

export default new DataTable();
<commit_msg>[DataTable] 빈칸 이름 저장 실패 토스트 추가<commit_after>import _find from 'lodash/find';
import _findIndex from 'lodash/findIndex';
import DataTableSource from './source/DataTableSource';
import { ModalChart, DataAnalytics } from '@entrylabs/tool';

class DataTable {
    #tables = [];
    #view;
    modal;
    selected;

    banAllBlock() {
        Entry.playground.blockMenu.banClass('analysis');
    }

    unbanBlock() {
        Entry.playground.blockMenu.unbanClass('analysis');
    }

    set view(view) {
        this.#view = view;
        this.#generateView();
    }

    get tables() {
        return this.#tables;
    }

    getSource(id) {
        if (!id) {
            console.warn('empty argument');
            return null;
        }
        return _find(this.#tables, { id });
    }

    getIndex({ id }) {
        if (!id) {
            console.warn('empty argument');
            return null;
        }
        return _findIndex(this.#tables, { id });
    }

    addSource(table) {
        Entry.do('playgroundChangeViewMode', 'table');
        let data = table || { name: Lang.Workspace.data_table };
        data.name = Entry.getOrderedName(data.name, this.#tables, 'name');
        const isDataTableSource = data instanceof DataTableSource;
        Entry.do('dataTableAddSource', isDataTableSource ? data : new DataTableSource(data));
    }

    removeSource(table) {
        Entry.do('dataTableRemoveSource', table);
    }

    changeItemPosition(start, end) {
        if (this.#tables.length) {
            this.#tables.splice(end, 0, this.#tables.splice(start, 1)[0]);
        }
    }

    selectTable(table = {}) {
        const json = table.toJSON && table.toJSON();
        const { tab } = table;
        this.selected = table;
        this.dataAnalytics.setData({
            table: { ...json, tab },
        });
        delete table.tab;
    }

    #generateView() {
        this.dataAnalytics = new DataAnalytics({ container: this.#view, data: {} })
            .on('submit', (dataAnalytics) => {
                const { id, table = [[]], charts = [], title } = dataAnalytics;
                if (!title) {
                    return Entry.toast.alert(
                        Lang.DataAnalytics.fail_save_table,
                        Lang.DataAnalytics.empty_table_name_content
                    );
                }
                if (
                    Entry.playground.isDuplicatedTableName(
                        title,
                        _.findIndex(this.tables, (table) => table.id === id)
                    )
                ) {
                    return Entry.toast.alert(
                        Lang.DataAnalytics.fail_save_table,
                        Lang.DataAnalytics.duplicate_table_name_content
                    );
                }
                if (Entry.playground.dataTable.getSource(id)) {
                    Entry.playground.dataTable.getSource(id).setArray({
                        chart: charts,
                        fields: table[0],
                        chart: charts,
                        data: table.slice(1),
                        name: title,
                    });
                    Entry.playground.injectTable();
                }
                Entry.toast.success(
                    Lang.DataAnalytics.saved_table_title,
                    Lang.DataAnalytics.saved_table_content
                );
            })
            .on('toast', (message) => {
                const { title, content } = message;
                Entry.toast.alert(title, content);
            });
    }

    getTableJSON() {
        return this.tables.filter(_.identity).map((v) => (v.toJSON ? v.toJSON() : v));
    }

    setTables(tables = []) {
        tables.forEach((table) => {
            this.addSource(table);
        });
    }

    setTableName(id, name) {
        if (!name) {
            return;
        }

        const source = this.getSource(id);
        if (!source) {
            return;
        }

        const { chart, array, fields } = source;
        source.setArray({ chart, data: array, fields, name });
    }

    showChart(tableId) {
        this.closeChart();
        const source = this.getSource(tableId);
        if (!source.modal) {
            source.modal = this.createChart(source);
        }
        source.modal.show();
        this.modal = source.modal;
    }

    closeChart() {
        if (this.modal && this.modal.isShow) {
            this.modal.hide();
        }
    }

    createChart(source) {
        const tables = this.#tables.map(({ id, name }) => [name, id]);
        const container = Entry.Dom('div', {
            class: 'entry-table-chart',
            parent: $('body'),
        })[0];
        return new ModalChart({
            data: {
                tables,
                source,
                setTable: (selected) => {
                    const [tableName, tableId] = selected;
                    this.showChart(tableId);
                },
            },
            container,
        });
    }

    clear() {
        this.#tables = [];
        this.modal = null;
    }
}

export default new DataTable();
<|endoftext|>


<commit_before>/* Copyright 2011 Hashmapd Ltd  <http://hashmapd.com>
 * written by Douglas Bagnall
 */

/* $hm holds global state.
 * Capitalised names are assumed to be constant (unnecessarily in some cases).
 */
var $hm = {
    DATA_URL: 'locations-15.json',
    //DATA_URL: 'http://hashmapd.couchone.com/frontend_dev/_design/user/_view/xy_coords?group=true',
    PADDING: 16,    /*padding for the image as a whole. it should exceed FUZZ_RADIUS */
    FUZZ_RADIUS: 10, /*distance of points convolution */
    FUZZ_MAX: 15,
    USING_QUAD_TREE: true
};

var HTTP_OK = 200;
var XML_HTTP_READY = 4;

/** hm_draw_map is the main entrance point.
 *
 * Nothing happens until the json is loaded, then the hm_on_data
 * function is called with the canvas reference and JSON
 * data. hm_on_data is differently defined for processing and bare
 * canvas implementations..
 *
 * @param canvas is the html5 canvas element to draw on
 */

function hm_draw_map(canvas){
    $.getJSON($hm.DATA_URL, function(data){
                  hm_on_data(canvas, data);
              });
}

/** make_colour_range utility
 *
 * @return a 256 long array of colours or gradients.
 */
function make_colour_range(){
    var colours = [];
    for (var i = 255; i >= 0; i--){
        var r = ((i >> 1) + 16);
        var g = i;
        var b = 0;
        colours.push('rgb(' + r + ',' + g + ',' + b + ')');
    }
    return colours;
}

function find_nice_shape_constant(k, peak, radius, offset, concentration){
    if (k >= 0){/*fools, including myself*/
        k = -0.5;
    }
    var max_spill = 0.67;
    for (var i = 0; i < 200; i++){
        var a = parseInt(Math.exp(radius * k) * peak + offset);
        var outside = parseInt(Math.exp((radius + max_spill) * k) * peak + offset);
        if (a < 1){
            k *= 1 - Math.random() * 0.6;
        }
        else if (a > 1 || outside != 0){
            k /= 1 - Math.random() * 0.6;
        }
        else {
            /* a == 1, and outside == 0.
             * Now, check concentration.
             *
             */
            var b = parseInt(Math.exp((radius * (1 - concentration)) * k) * peak + offset);
            if (b < 1){
                k *= 1 - Math.random() * 0.4;
            }
            else if (b > 1){
                k /= 1 - Math.random() * 0.4;
            }
            else {
                //alert(i, k);
                return k;
            }
        }
    }
    /*give up*/
    return k;
}

function new_canvas(width, height, id){
    var canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    if (id){
        canvas.id = id;
    }
    return canvas;
}

/*XXX ignoring cases where CSS pixels are not device pixels */

/** Make_fuzz makes a little fuzzy circle image for point convolution
 *
 * The fuzz is approximately gaussian and carried in the images alpha
 * channel.  All values are 8-bit integers less than <peak>.  The
 * shape is tuned stochastically until the pixels at <radius> and at
 * (1 - <concetnration>) * <radius> have alpha 1, while those a bit
 * beyond <radius> have alpha 0. The image is sized <radius> * 2 + 1.
 *
 * If you ignore <concentration> and <floor>, sensible (or at least
 * frequently successful) defaults will be chosen.
 *
 * The formula used is Math.exp(k * d) + <floor>
 *
 * where k is fiddled until both <radius> and <radius> * (1 -
 * <concentration>) are 1.  Thus increasing <concentration> flattens
 * the outside and steepens the centre.
 *
 * @param radius is the distance
 * @param peak is the alpha for the centre pixel
 * @param concentration is a sort of inverse variance. try 0.25.
 * @param floor positive values lift the whole curve, creating long tails.
 */

function make_fuzz(radius, peak, concentration, floor){
    peak = (peak === undefined) ? $hm.FUZZ_MAX : peak;
    concentration = (concentration === undefined) ? 0.25 : concentration;
    var offset = (floor === undefined) ? 0.7 : floor + 0.5;
    /* middle pixel + radius on either side */
    var size = 1 + 2 * radius;
    var canvas = new_canvas(size, size);
    var helpers = document.getElementById("helpers");
    helpers.appendChild(canvas);
    var ctx = canvas.getContext("2d");
    var imgd = ctx.getImageData(0, 0, size, size);
    var pixels = imgd.data;
    var stride = size * 4;
    var k = find_nice_shape_constant(-0.5, peak, radius, offset, concentration);
    var s = "";
    for (var y = 0; y < size; y++){
        var dy2 = (y - radius) * (y - radius);
        var row = y * stride;
        for (var x = 0; x < size; x++){
            var dx2 = (x - radius) * (x - radius);
            var a = parseInt(Math.exp(Math.sqrt(dx2 + dy2) * k) * peak + offset);
            var p = row + x * 4;
            s += a + " ";
            pixels[p] = 255;
            pixels[p + 1] = 255;
            pixels[p + 2] = 255;
            pixels[p + 3] = a;
        }
        s+="\n";
    }
    //alert(k);
    ctx.putImageData(imgd, 0, 0);
    var img = new Image();
    img.src = canvas.toDataURL();
    //alert(img.complete);
    return img;
}

function decode_and_filter_points(raw, xmin, xmax, ymin, ymax){
    var i, j;
    var points = [];
    if ($hm.USING_QUAD_TREE){
        for (i = 0; i < raw.length; i++){
            var r = raw[i];
            var coords = r.key;
            var x = 0;
            var y = 0;
            for (j = 0; j < coords.length; j++){
                var p = coords[j];
                x = (x << 1) | (p & 1);
                y = (y << 1) | (p >> 1);
            }
            points.push([x, y, r.value]);
        }
    }
    else {
        for (i = 0; i < raw.length; i++){
            var r = raw[i];
            points.push([r.key[0], r.key[1],  r.value]);
        }
    }

    /*passing straight through is a common case*/
    if (xmin === undefined &&
        xmax === undefined &&
        ymin === undefined &&
        ymax === undefined){
        return points;
    }
    /*undefined is equivalent to +/- inf */
    xmin = (xmin !== undefined) ? xmin : -1e999;
    ymin = (ymin !== undefined) ? ymin : -1e999;
    xmax = (xmax !== undefined) ? xmax :  1e999;
    ymax = (ymax !== undefined) ? ymax :  1e999;
    return points.filter(function(p){
                             return  ((xmin < p[0]) &&
                                      (xmax > p[0]) &&
                                      (ymin < p[1]) &&
                                      (ymax > p[1]));
                         });
}

/** hm_on_data is a callback from hm_draw_map.
 *
 * It coordinates the actual drawing.
 *
 * @param canvas the html5 canvas
 * @param data is parsed but otherwise unprocessed JSON data.
 */

function hm_on_data(canvas, data){
    var i;
    var ctx = canvas.getContext("2d");
    var width = canvas.width - 2 * $hm.PADDING;
    var height = canvas.height - 2 * $hm.PADDING;
    var max_value = 0;
    var max_x = -1e999;
    var max_y = -1e999;
    var min_x =  1e999;
    var min_y =  1e999;
    var points = decode_and_filter_points(data.rows);
    /*find the coordinate and value ranges */
    for (i = 0; i < points.length; i++){
        var r = points[i];
        max_value = Math.max(r.value, max_value);
        max_x = Math.max(r[0], max_x);
        max_y = Math.max(r[1], max_y);
        min_x = Math.min(r[0], min_x);
        min_y = Math.min(r[1], min_y);
    }

    var range_x = max_x - min_x;
    var range_y = max_y - min_y;
    var x_scale = width / range_x;
    var y_scale = height / range_y;

    ctx.font = "10px Inconsolata";
    var fuzz = make_fuzz($hm.FUZZ_RADIUS);
    //alert(fuzz.complete);
    fuzz.onload = function(){
        paste_fuzz(ctx, points, fuzz, min_x, min_y, x_scale, y_scale);
        var img_data = ctx.getImageData(0, 0, canvas.width, canvas.height);
        var height_map = img_data.data;
        for (i = 100000; i < 1000000; i++){
            height_map[i] = 255;
        }
    };
}

function paste_fuzz(ctx, points, img, min_x, min_y, x_scale, y_scale){
    if (img === undefined){
        img = new Image();
        img.src = "fuzz-19.PNG";
    }
    for (var i = 0; i < points.length; i++){
        var r = points[i];
        var x = $hm.PADDING + (r[0] - min_x) * x_scale;
        var y = $hm.PADDING + (r[1] - min_y) * y_scale;
        //ctx.putImageData(fuzz, x, y);
        ctx.drawImage(img, x, y);
    }
}

function blur_dots(ctx, points, min_x, min_y, x_scale, y_scale){
    ctx.fillStyle = "rgba(255,255,255,1)";
    //ctx.fillStyle = "#888";
    ctx.shadowColor = "rgba(255,255,255,1)";
    ctx.shadowBlur = 6;
    //    ctx.globalAlpha = 0;
    for (i = 0; i < points.length; i++){
        var r = points[i];
        var x = $hm.PADDING + (r[0] - min_x) * x_scale;
        var y = $hm.PADDING + (r[1] - min_y) * y_scale;
        ctx.fillRect(x, y, 1, 1);
    }
}

function generate_height_map(){}

function add_label(ctx, text, x, y, text_fill, rect_fill, rect_w, rect_h){
    if (text_fill === undefined){
        text_fill = "#000";
    }
    ctx.fillStyle = text_fill;
    if (rect_w !== undefined && rect_h !== undefined){
        ctx.fillStyle = rect_fill;
        ctx.fillRect(x, y, rect_w, rect_h);
        ctx.fillStyle = text_fill;
    }
    ctx.fillText(text, x, y);
}
<commit_msg>canvas: only fuzz in red/alpha channels, leaving green and blue for other work<commit_after>/* Copyright 2011 Hashmapd Ltd  <http://hashmapd.com>
 * written by Douglas Bagnall
 */

/* $hm holds global state.
 * Capitalised names are assumed to be constant (unnecessarily in some cases).
 */
var $hm = {
    DATA_URL: 'locations-15.json',
    //DATA_URL: 'http://hashmapd.couchone.com/frontend_dev/_design/user/_view/xy_coords?group=true',
    PADDING: 16,    /*padding for the image as a whole. it should exceed FUZZ_RADIUS */
    FUZZ_RADIUS: 10, /*distance of points convolution */
    FUZZ_MAX: 15,
    USING_QUAD_TREE: true
};

var HTTP_OK = 200;
var XML_HTTP_READY = 4;

/** hm_draw_map is the main entrance point.
 *
 * Nothing happens until the json is loaded, then the hm_on_data
 * function is called with the canvas reference and JSON
 * data. hm_on_data is differently defined for processing and bare
 * canvas implementations..
 *
 * @param canvas is the html5 canvas element to draw on
 */

function hm_draw_map(canvas){
    $.getJSON($hm.DATA_URL, function(data){
                  hm_on_data(canvas, data);
              });
}

/** make_colour_range utility
 *
 * @return a 256 long array of colours or gradients.
 */
function make_colour_range(){
    var colours = [];
    for (var i = 255; i >= 0; i--){
        var r = ((i >> 1) + 16);
        var g = i;
        var b = 0;
        colours.push('rgb(' + r + ',' + g + ',' + b + ')');
    }
    return colours;
}

function find_nice_shape_constant(k, peak, radius, offset, concentration){
    if (k >= 0){/*fools, including myself*/
        k = -0.5;
    }
    var max_spill = 0.67;
    for (var i = 0; i < 200; i++){
        var a = parseInt(Math.exp(radius * k) * peak + offset);
        var outside = parseInt(Math.exp((radius + max_spill) * k) * peak + offset);
        if (a < 1){
            k *= 1 - Math.random() * 0.6;
        }
        else if (a > 1 || outside != 0){
            k /= 1 - Math.random() * 0.6;
        }
        else {
            /* a == 1, and outside == 0.
             * Now, check concentration.
             *
             */
            var b = parseInt(Math.exp((radius * (1 - concentration)) * k) * peak + offset);
            if (b < 1){
                k *= 1 - Math.random() * 0.4;
            }
            else if (b > 1){
                k /= 1 - Math.random() * 0.4;
            }
            else {
                return k;
            }
        }
    }
    /*give up*/
    return k;
}

function new_canvas(width, height, id){
    var canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    if (id){
        canvas.id = id;
    }
    return canvas;
}

/*XXX ignoring cases where CSS pixels are not device pixels */

/** Make_fuzz makes a little fuzzy circle image for point convolution
 *
 * The fuzz is approximately gaussian and carried in the images alpha
 * channel.  All values are 8-bit integers less than <peak>.  The
 * shape is tuned stochastically until the pixels at <radius> and at
 * (1 - <concetnration>) * <radius> have alpha 1, while those a bit
 * beyond <radius> have alpha 0. The image is sized <radius> * 2 + 1.
 *
 * If you ignore <concentration> and <floor>, sensible (or at least
 * frequently successful) defaults will be chosen.
 *
 * The formula used is Math.exp(k * d) + <floor>
 *
 * where k is fiddled until both <radius> and <radius> * (1 -
 * <concentration>) are 1.  Thus increasing <concentration> flattens
 * the outside and steepens the centre.
 *
 * @param radius is the distance
 * @param peak is the alpha for the centre pixel
 * @param concentration is a sort of inverse variance. try 0.25.
 * @param floor positive values lift the whole curve, creating long tails.
 */

function make_fuzz(radius, peak, concentration, floor){
    peak = (peak === undefined) ? $hm.FUZZ_MAX : peak;
    concentration = (concentration === undefined) ? 0.25 : concentration;
    var offset = (floor === undefined) ? 0.7 : floor + 0.5;
    /* middle pixel + radius on either side */
    var size = 1 + 2 * radius;
    var canvas = new_canvas(size, size);
    var helpers = document.getElementById("helpers");
    helpers.appendChild(canvas);
    var ctx = canvas.getContext("2d");
    var imgd = ctx.getImageData(0, 0, size, size);
    var pixels = imgd.data;
    var stride = size * 4;
    var k = find_nice_shape_constant(-0.5, peak, radius, offset, concentration);
    var s = "";
    for (var y = 0; y < size; y++){
        var dy2 = (y - radius) * (y - radius);
        var row = y * stride;
        for (var x = 0; x < size; x++){
            var dx2 = (x - radius) * (x - radius);
            var a = parseInt(Math.exp(Math.sqrt(dx2 + dy2) * k) * peak + offset);
            var p = row + x * 4;
            s += a + " ";
            pixels[p] = 255;
            pixels[p + 3] = a;
        }
        s+="\n";
    }
    ctx.putImageData(imgd, 0, 0);
    var img = new Image();
    img.src = canvas.toDataURL();
    return img;
}

function decode_and_filter_points(raw, xmin, xmax, ymin, ymax){
    var i, j;
    var points = [];
    if ($hm.USING_QUAD_TREE){
        for (i = 0; i < raw.length; i++){
            var r = raw[i];
            var coords = r.key;
            var x = 0;
            var y = 0;
            for (j = 0; j < coords.length; j++){
                var p = coords[j];
                x = (x << 1) | (p & 1);
                y = (y << 1) | (p >> 1);
            }
            points.push([x, y, r.value]);
        }
    }
    else {
        for (i = 0; i < raw.length; i++){
            var r = raw[i];
            points.push([r.key[0], r.key[1],  r.value]);
        }
    }

    /*passing straight through is a common case*/
    if (xmin === undefined &&
        xmax === undefined &&
        ymin === undefined &&
        ymax === undefined){
        return points;
    }
    /*undefined is equivalent to +/- inf */
    xmin = (xmin !== undefined) ? xmin : -1e999;
    ymin = (ymin !== undefined) ? ymin : -1e999;
    xmax = (xmax !== undefined) ? xmax :  1e999;
    ymax = (ymax !== undefined) ? ymax :  1e999;
    return points.filter(function(p){
                             return  ((xmin < p[0]) &&
                                      (xmax > p[0]) &&
                                      (ymin < p[1]) &&
                                      (ymax > p[1]));
                         });
}

/** hm_on_data is a callback from hm_draw_map.
 *
 * It coordinates the actual drawing.
 *
 * @param canvas the html5 canvas
 * @param data is parsed but otherwise unprocessed JSON data.
 */

function hm_on_data(canvas, data){
    var i;
    var ctx = canvas.getContext("2d");
    var width = canvas.width - 2 * $hm.PADDING;
    var height = canvas.height - 2 * $hm.PADDING;
    var max_value = 0;
    var max_x = -1e999;
    var max_y = -1e999;
    var min_x =  1e999;
    var min_y =  1e999;
    var points = decode_and_filter_points(data.rows);
    /*find the coordinate and value ranges */
    for (i = 0; i < points.length; i++){
        var r = points[i];
        max_value = Math.max(r.value, max_value);
        max_x = Math.max(r[0], max_x);
        max_y = Math.max(r[1], max_y);
        min_x = Math.min(r[0], min_x);
        min_y = Math.min(r[1], min_y);
    }

    var range_x = max_x - min_x;
    var range_y = max_y - min_y;
    var x_scale = width / range_x;
    var y_scale = height / range_y;

    ctx.font = "10px Inconsolata";
    var fuzz = make_fuzz($hm.FUZZ_RADIUS);
    //alert(fuzz.complete);
    fuzz.onload = function(){
        paste_fuzz(ctx, points, fuzz, min_x, min_y, x_scale, y_scale);
        var img_data = ctx.getImageData(0, 0, canvas.width, canvas.height);
        var height_map = img_data.data;
        for (i = 100000; i < 1000000; i++){
            height_map[i] = 255;
        }
    };
}

function paste_fuzz(ctx, points, img, min_x, min_y, x_scale, y_scale){
    if (img === undefined){
        img = new Image();
        img.src = "fuzz-19.PNG";
    }
    for (var i = 0; i < points.length; i++){
        var r = points[i];
        var x = $hm.PADDING + (r[0] - min_x) * x_scale;
        var y = $hm.PADDING + (r[1] - min_y) * y_scale;
        //ctx.putImageData(fuzz, x, y);
        ctx.drawImage(img, x, y);
    }
}

function blur_dots(ctx, points, min_x, min_y, x_scale, y_scale){
    ctx.fillStyle = "rgba(255,255,255,1)";
    //ctx.fillStyle = "#888";
    ctx.shadowColor = "rgba(255,255,255,1)";
    ctx.shadowBlur = 6;
    //    ctx.globalAlpha = 0;
    for (i = 0; i < points.length; i++){
        var r = points[i];
        var x = $hm.PADDING + (r[0] - min_x) * x_scale;
        var y = $hm.PADDING + (r[1] - min_y) * y_scale;
        ctx.fillRect(x, y, 1, 1);
    }
}

function generate_height_map(){}

function add_label(ctx, text, x, y, text_fill, rect_fill, rect_w, rect_h){
    if (text_fill === undefined){
        text_fill = "#000";
    }
    ctx.fillStyle = text_fill;
    if (rect_w !== undefined && rect_h !== undefined){
        ctx.fillStyle = rect_fill;
        ctx.fillRect(x, y, rect_w, rect_h);
        ctx.fillStyle = text_fill;
    }
    ctx.fillText(text, x, y);
}
<|endoftext|>


<commit_before>const passport = require('passport')
const R = require('ramda')
const spMetadata = require('./sp-meta')
const misc = require('./utils/misc')
const logger = require('./utils/logging')
const extraPassportParams = require('./extra-passport-params')
const cacheProvider = require('./cache-provider')
// oiclienth = require('./utils/openid-client-helper')

let prevConfigHash = 0

// These are the (node) strategies loaded so far: [{id: "...", Strategy: ...}, ... ]
const passportStrategies = []

function applyMapping (profile, provider) {
  let mappedProfile
  try {
    const mapping = global.providers.find(
      providerObj => providerObj.id === provider).mapping

    const additionalParams = profile.extras

    delete profile.extras
    logger.log2('silly', `Raw profile is ${JSON.stringify(profile._json)}`)
    logger.log2('info', `Applying mapping '${mapping}' to profile`)

    mappedProfile = require('./mappings/' + mapping)(profile, additionalParams)
    logger.log2('debug', `Resulting profile data is\n${JSON.stringify(mappedProfile, null, 4)}`)
  } catch (err) {
    logger.log2('error', `An error occurred: ${err}`)
  }
  return mappedProfile
}

function getVerifyFunction (provider) {
  const arity = provider.verifyCallbackArity

  const uncurried = (...args) => {
    // profile and callback are the last 2 params in all passport verify functions,
    // except for passport-openidconnect which does not follow this convention
    let profile, extras

    if (provider.passportStrategyId === 'passport-openidconnect') {
      // Check passport-openidconnect/lib/strategy.js
      const index = provider.options.passReqToCallback ? 1 : 0

      profile = args[2 + index]
      extras = args.slice(0, 2 + index)
      extras = extras.concat(args.slice(3 + index, arity - 1))
    } else {
      profile = args[arity - 2]
      extras = args.slice(0, arity - 2)
    }
    const cb = args[arity - 1]
    profile.providerKey = provider.id
    profile.extras = extras

    return cb(null, profile)
  }

  // guarantee the function has the arity required
  return R.curryN(arity, uncurried)
}

function setupStrategy (provider) {
  logger.log2('info', `Setting up strategy for provider ${provider.displayName}`)
  logger.log2('debug', `Provider data is\n${JSON.stringify(provider, null, 4)}`)

  const id = provider.id
  const strategyModule = provider.passportStrategyId

  let Strategy = passportStrategies.find(strategy => strategy.id === id)

  // if strategyModule is not found, load it
  if (Strategy) {
    Strategy = Strategy.Strategy
  } else {
    logger.log2('info', `Loading node strategy module ${strategyModule}`)
    Strategy = require(strategyModule)

    if (provider.type === 'oauth' && Strategy.OAuth2Strategy) {
      Strategy = Strategy.OAuth2Strategy
    } else {
      Strategy = Strategy.Strategy
    }

    logger.log2('verbose', 'Adding to list of known strategies')
    passportStrategies.push({ id, Strategy })
  }

  const providerOptions = provider.options
  const isSaml = strategyModule === 'passport-saml'
  const verify = getVerifyFunction(provider)

  // Create strategy
  if (isSaml) {
    // Turn off inResponseTo validation if the IDP is configured for IDP-initiated:
    // "an IDP would never do both IDP initiated and SP initiated..."
    if (global.iiconfig.authorizationParams.find(
      authorizationParam => authorizationParam.provider === id)) {
      providerOptions.validateInResponseTo = false
    }

    // Instantiate custom cache provider if required
    if (providerOptions.validateInResponseTo) {
      const f = R.anyPass([R.isNil, R.isEmpty])
      const exp = providerOptions.requestIdExpirationPeriodMs / 1000

      if (!f(providerOptions.redisCacheOptions)) {
        providerOptions.cacheProvider = cacheProvider.get(
          'redis', providerOptions.redisCacheOptions, exp
        )
      } else if (!f(providerOptions.memcachedCacheOptions)) {
        providerOptions.cacheProvider = cacheProvider.get(
          'memcached', providerOptions.memcachedCacheOptions, exp
        )
      }
    }

    const samlStrategy = new Strategy(providerOptions, verify)
    passport.use(id, samlStrategy)
    spMetadata.generate(provider, samlStrategy)
  } else {
    passport.use(id, new Strategy(providerOptions, verify))
  }
}

function parseProp (value) {
  try {
    if (typeof value === 'string') {
      value = JSON.parse(value)
    }
  } catch (err) {
    // not an error. For datatypes other than string,
    // the original parameter value is returned

  }
  return value
}

/**
* @TODO refactor ramda to native
*/
function fixDataTypes (providers) {
  for (const provider of providers) {
    // The subproperties of provider's options potentially come from the server as strings, they should
    // be converted to other types if possible
    let value = provider.options

    if (misc.isObject(value)) {
      R.forEach((key) => {
        value[key] = parseProp(value[key])
      }, R.keys(value))
    } else {
      logger.log2(
        'warn', `Object expected for property options, found ${JSON.stringify(value)}`
      )
      value = {}
    }
    provider.options = value

    // Tries to convert passportAuthnParams to a dictionary, otherwise {} is left
    value = parseProp(provider.passportAuthnParams)
    if (!misc.isObject(value)) {
      // log message only if passportAuthnParams is not absent
      if (!R.isNil(value)) {
        logger.log2(
          'warn', `Parsable object expected for property passportAuthnParams, found ${JSON.stringify(value)}`
        )
      }
      value = {}
    }
    provider.passportAuthnParams = value
  }
}

function mergeProperty (strategyId, obj, property) {
  const extraParams = extraPassportParams.get(strategyId, property)
  return R.mergeLeft(obj[property], extraParams)
}

function fillMissingData (providers) {
  const paramsToFill = ['passportAuthnParams', 'options']

  // eslint-disable-next-line no-return-assign
  R.forEach(provider => R.forEach(prop => provider[prop] = mergeProperty(
    provider.passportStrategyId, provider, prop), paramsToFill), providers)

  for (const provider of providers) {
    const options = provider.options
    const strategyId = provider.passportStrategyId
    const isSaml = strategyId === 'passport-saml'
    const callbackUrl = R.defaultTo(options.callbackUrl, options.callbackURL)
    const prefix = global.config.serverURI + '/passport/auth'

    if (isSaml) {
      // Different casing in saml
      options.callbackUrl = R.defaultTo(`${prefix}/saml/${provider.id}/callback`, callbackUrl)
    } else {
      options.callbackURL = R.defaultTo(`${prefix}/${provider.id}/callback`, callbackUrl)
      // Some passport strategies expect consumer* instead of client*
      options.consumerKey = options.clientID
      options.consumerSecret = options.clientSecret
      // Allow state validation in passport-oauth2 based strategies
      options.state = true
    }

    // Strategies with "special" treatments
    if (strategyId.indexOf('passport-apple') >= 0 && options.key) {
      // Smells like apple...
      try {
        // @TODO: we have to make the UI fields multiline so they can paste the contents and avoid this
        options.key = require('fs').readFileSync(options.key, 'utf8')
      } catch (e) {
        logger.log2('warn', `There was a problem reading file ${options.key}. Ensure the file exists and is readable`)
        logger.log2('error', e.stack)
        options.key = ''
      }
    }
    /*
    //Disabled temporarily: strategy failing to validate id_tokens, see issue #78
    else if (strategyId == 'openid-client') {
      options.redirect_uri = options.callbackURL
      options = oiclienth.makeOptions(options)
      p.options = options
    }
    */

    // Fills verifyCallbackArity (number expected)
    const value = extraPassportParams.get(strategyId, 'verifyCallbackArity')
    let toadd
    if (options.passReqToCallback) {
      toadd = 1
    } else {
      toadd = 0
    }

    // In most passport strategies the verify callback has arity 4 except for saml
    if (typeof value === 'number') {
      provider.verifyCallbackArity = value
    } else {
      let arity
      if (isSaml) {
        arity = 2
      } else {
        arity = 4
      }
      provider.verifyCallbackArity = toadd + arity
    }
  }
}

/**
 * Setup providers and sets global `providers`
 * @param providers : Object containing providers (fetched from config endpoint)
 * @TODO refactor function name to setupProviders
 */
function setup (providers) {
  providers = R.defaultTo([], providers)
  const hashConfig = misc.hash(providers)
  if (hashConfig !== prevConfigHash) {
    // Only makes recomputations if config data changed
    logger.log2('info', 'Reconfiguring providers')

    prevConfigHash = hashConfig
    // Unuse all strategies before reconfiguring
    R.forEach(s => passport.unuse(s), R.map(R.prop('id'), passportStrategies))

    // "Fix" incoming data
    fixDataTypes(providers)
    fillMissingData(providers)

    R.forEach(setupStrategy, providers)
    // Needed for routes.js
    global.providers = providers
  }
}

module.exports = {
  setup: setup,
  applyMapping: applyMapping
}
<commit_msg>refactor(providers.js): remove commented unused function for openid-client unused strategy<commit_after>const passport = require('passport')
const R = require('ramda')
const spMetadata = require('./sp-meta')
const misc = require('./utils/misc')
const logger = require('./utils/logging')
const extraPassportParams = require('./extra-passport-params')
const cacheProvider = require('./cache-provider')
// oiclienth = require('./utils/openid-client-helper')

let prevConfigHash = 0

// These are the (node) strategies loaded so far: [{id: "...", Strategy: ...}, ... ]
const passportStrategies = []

function applyMapping (profile, provider) {
  let mappedProfile
  try {
    const mapping = global.providers.find(
      providerObj => providerObj.id === provider).mapping

    const additionalParams = profile.extras

    delete profile.extras
    logger.log2('silly', `Raw profile is ${JSON.stringify(profile._json)}`)
    logger.log2('info', `Applying mapping '${mapping}' to profile`)

    mappedProfile = require('./mappings/' + mapping)(profile, additionalParams)
    logger.log2('debug', `Resulting profile data is\n${JSON.stringify(mappedProfile, null, 4)}`)
  } catch (err) {
    logger.log2('error', `An error occurred: ${err}`)
  }
  return mappedProfile
}

function getVerifyFunction (provider) {
  const arity = provider.verifyCallbackArity

  const uncurried = (...args) => {
    // profile and callback are the last 2 params in all passport verify functions,
    // except for passport-openidconnect which does not follow this convention
    let profile, extras

    if (provider.passportStrategyId === 'passport-openidconnect') {
      // Check passport-openidconnect/lib/strategy.js
      const index = provider.options.passReqToCallback ? 1 : 0

      profile = args[2 + index]
      extras = args.slice(0, 2 + index)
      extras = extras.concat(args.slice(3 + index, arity - 1))
    } else {
      profile = args[arity - 2]
      extras = args.slice(0, arity - 2)
    }
    const cb = args[arity - 1]
    profile.providerKey = provider.id
    profile.extras = extras

    return cb(null, profile)
  }

  // guarantee the function has the arity required
  return R.curryN(arity, uncurried)
}

function setupStrategy (provider) {
  logger.log2('info', `Setting up strategy for provider ${provider.displayName}`)
  logger.log2('debug', `Provider data is\n${JSON.stringify(provider, null, 4)}`)

  const id = provider.id
  const strategyModule = provider.passportStrategyId

  let Strategy = passportStrategies.find(strategy => strategy.id === id)

  // if strategyModule is not found, load it
  if (Strategy) {
    Strategy = Strategy.Strategy
  } else {
    logger.log2('info', `Loading node strategy module ${strategyModule}`)
    Strategy = require(strategyModule)

    if (provider.type === 'oauth' && Strategy.OAuth2Strategy) {
      Strategy = Strategy.OAuth2Strategy
    } else {
      Strategy = Strategy.Strategy
    }

    logger.log2('verbose', 'Adding to list of known strategies')
    passportStrategies.push({ id, Strategy })
  }

  const providerOptions = provider.options
  const isSaml = strategyModule === 'passport-saml'
  const verify = getVerifyFunction(provider)

  // Create strategy
  if (isSaml) {
    // Turn off inResponseTo validation if the IDP is configured for IDP-initiated:
    // "an IDP would never do both IDP initiated and SP initiated..."
    if (global.iiconfig.authorizationParams.find(
      authorizationParam => authorizationParam.provider === id)) {
      providerOptions.validateInResponseTo = false
    }

    // Instantiate custom cache provider if required
    if (providerOptions.validateInResponseTo) {
      const f = R.anyPass([R.isNil, R.isEmpty])
      const exp = providerOptions.requestIdExpirationPeriodMs / 1000

      if (!f(providerOptions.redisCacheOptions)) {
        providerOptions.cacheProvider = cacheProvider.get(
          'redis', providerOptions.redisCacheOptions, exp
        )
      } else if (!f(providerOptions.memcachedCacheOptions)) {
        providerOptions.cacheProvider = cacheProvider.get(
          'memcached', providerOptions.memcachedCacheOptions, exp
        )
      }
    }

    const samlStrategy = new Strategy(providerOptions, verify)
    passport.use(id, samlStrategy)
    spMetadata.generate(provider, samlStrategy)
  } else {
    passport.use(id, new Strategy(providerOptions, verify))
  }
}

function parseProp (value) {
  try {
    if (typeof value === 'string') {
      value = JSON.parse(value)
    }
  } catch (err) {
    // not an error. For datatypes other than string,
    // the original parameter value is returned

  }
  return value
}

/**
* @TODO refactor ramda to native
*/
function fixDataTypes (providers) {
  for (const provider of providers) {
    // The subproperties of provider's options potentially come from the server as strings, they should
    // be converted to other types if possible
    let value = provider.options

    if (misc.isObject(value)) {
      R.forEach((key) => {
        value[key] = parseProp(value[key])
      }, R.keys(value))
    } else {
      logger.log2(
        'warn', `Object expected for property options, found ${JSON.stringify(value)}`
      )
      value = {}
    }
    provider.options = value

    // Tries to convert passportAuthnParams to a dictionary, otherwise {} is left
    value = parseProp(provider.passportAuthnParams)
    if (!misc.isObject(value)) {
      // log message only if passportAuthnParams is not absent
      if (!R.isNil(value)) {
        logger.log2(
          'warn', `Parsable object expected for property passportAuthnParams, found ${JSON.stringify(value)}`
        )
      }
      value = {}
    }
    provider.passportAuthnParams = value
  }
}

function mergeProperty (strategyId, obj, property) {
  const extraParams = extraPassportParams.get(strategyId, property)
  return R.mergeLeft(obj[property], extraParams)
}

function fillMissingData (providers) {
  const paramsToFill = ['passportAuthnParams', 'options']

  // eslint-disable-next-line no-return-assign
  R.forEach(provider => R.forEach(prop => provider[prop] = mergeProperty(
    provider.passportStrategyId, provider, prop), paramsToFill), providers)

  for (const provider of providers) {
    const options = provider.options
    const strategyId = provider.passportStrategyId
    const isSaml = strategyId === 'passport-saml'
    const callbackUrl = R.defaultTo(options.callbackUrl, options.callbackURL)
    const prefix = global.config.serverURI + '/passport/auth'

    if (isSaml) {
      // Different casing in saml
      options.callbackUrl = R.defaultTo(`${prefix}/saml/${provider.id}/callback`, callbackUrl)
    } else {
      options.callbackURL = R.defaultTo(`${prefix}/${provider.id}/callback`, callbackUrl)
      // Some passport strategies expect consumer* instead of client*
      options.consumerKey = options.clientID
      options.consumerSecret = options.clientSecret
      // Allow state validation in passport-oauth2 based strategies
      options.state = true
    }

    // Strategies with "special" treatments
    if (strategyId.indexOf('passport-apple') >= 0 && options.key) {
      // Smells like apple...
      try {
        // @TODO: we have to make the UI fields multiline so they can paste the contents and avoid this
        options.key = require('fs').readFileSync(options.key, 'utf8')
      } catch (e) {
        logger.log2('warn', `There was a problem reading file ${options.key}. Ensure the file exists and is readable`)
        logger.log2('error', e.stack)
        options.key = ''
      }
    }

    // Fills verifyCallbackArity (number expected)
    const value = extraPassportParams.get(strategyId, 'verifyCallbackArity')
    let toadd
    if (options.passReqToCallback) {
      toadd = 1
    } else {
      toadd = 0
    }

    // In most passport strategies the verify callback has arity 4 except for saml
    if (typeof value === 'number') {
      provider.verifyCallbackArity = value
    } else {
      let arity
      if (isSaml) {
        arity = 2
      } else {
        arity = 4
      }
      provider.verifyCallbackArity = toadd + arity
    }
  }
}

/**
 * Setup providers and sets global `providers`
 * @param providers : Object containing providers (fetched from config endpoint)
 * @TODO refactor function name to setupProviders
 */
function setup (providers) {
  providers = R.defaultTo([], providers)
  const hashConfig = misc.hash(providers)
  if (hashConfig !== prevConfigHash) {
    // Only makes recomputations if config data changed
    logger.log2('info', 'Reconfiguring providers')

    prevConfigHash = hashConfig
    // Unuse all strategies before reconfiguring
    R.forEach(s => passport.unuse(s), R.map(R.prop('id'), passportStrategies))

    // "Fix" incoming data
    fixDataTypes(providers)
    fillMissingData(providers)

    R.forEach(setupStrategy, providers)
    // Needed for routes.js
    global.providers = providers
  }
}

module.exports = {
  setup: setup,
  applyMapping: applyMapping
}
<|endoftext|>


<commit_before>/**
 * Feature track that draws features using HTML5 canvas elements.
 */

define( [
            'dojo/_base/declare',
            'dojo/dom-construct',
            'dojo/_base/array',
            'JBrowse/View/GranularRectLayout',
            'JBrowse/View/Track/Canvas'
        ],
        function( declare, dom, array, Layout, CanvasTrack ) {

return declare( CanvasTrack, {

    constructor: function( args ) {
    },

    _defaultConfig: function() {
        return {
            maxFeatureScreenDensity: 400,
            style: {
                bgcolor: 'goldenrod',
                fgcolor: null,
                height: 3,
                marginBottom: 1
            }
        };
    },

    fillBlock: function( args ) {
        var blockIndex = args.blockIndex;
        var block = args.block;
        var leftBase = args.leftBase;
        var rightBase = args.rightBase;
        var scale = args.scale;

        if( ! this.testCanvasSupport( blockIndex, block ) )
            return;

        var region = { ref: this.refSeq.name, start: leftBase, end: rightBase };

        this.store.getRegionStats(
            region,
            dojo.hitch( this, function( stats ) {

                var density        = stats.featureDensity;
                var featureScale   = this.config.style.featureScale || density / this.config.maxFeatureScreenDensity; // (feat/bp) / ( feat/px ) = px/bp )

                if( scale < featureScale ) {
                    this.fillTooManyFeaturesMessage(
                        blockIndex,
                        block,
                        scale
                    );
                    args.finishCallback();
                }
                else {
                    this.fillFeatures( dojo.mixin( {stats: stats}, args ) );
                }
        }));
    },

    _getLayout: function( scale ) {
        // create the layout if we need to, and if we can
        if( ( ! this.layout || this.layout.pitchX != 4/scale ) && scale  )
            this.layout = new Layout({pitchX: 4/scale, pitchY: this.config.layoutPitchY || (this.config.style.height + this.config.style.marginBottom) });

        return this.layout;
    },

    fillFeatures: function( args ) {
        var track = this;

        var blockIndex = args.blockIndex;
        var block = args.block;
        var scale = args.scale;
        var leftBase = args.leftBase;
        var rightBase = args.rightBase;
        var finishCallback = args.finishCallback;

        var timedOut = false;
        var timeOutError = { toString: function() { return 'Timed out trying to display '+track.name+' block '+blockIndex; } };
        if( this.config.blockDisplayTimeout )
            window.setTimeout( function() { timedOut = true; }, this.config.blockDisplayTimeout );

        var fRects = [];
        var featCallback = dojo.hitch(this,function( feature ) {
            if( timedOut )
                throw timeOutError;

            fRects.push( this.layoutFeature( feature, leftBase, scale ) );
        });

        this.store.getFeatures( { ref: this.refSeq.name,
                                  start: leftBase,
                                  end: rightBase
                                },
                                featCallback,
                                function () {
                                    var totalHeight = track._getLayout(scale).getTotalHeight();
                                    var c = dojo.create(
                                        'canvas',
                                        { height: totalHeight,
                                          width:  block.offsetWidth+1,
                                          style: { cursor: 'default' },
                                          innerHTML: 'Your web browser cannot display this type of track.',
                                          className: 'canvas-track'
                                        },
                                        block
                                    );
                                    track.renderFeatures( fRects, c );

                                    track.layoutCanvases([c]);
                                    track.heightUpdate( totalHeight,
                                                        blockIndex );
                                    finishCallback();
                                },
                                function( error ) {
                                    track.error = error;
                                    if( error === timeOutError ) {
                                        track.fillTimeout( blockIndex, block );
                                    } else {
                                        console.error( error, error.stack );
                                        track.fillError( blockIndex, block );
                                    }
                                    finishCallback();
                                }
                              );
    },

    // calculate the placement of the feature on the canvas for this
    // block.
    layoutFeature: function( feature, leftBase, scale ) {
        var layoutStart = feature.get('start');
        var layoutEnd   = feature.get('end');

        var fHeight = this.config.style.height;
        var levelHeight = fHeight + this.config.style.marginBottom;

        var uniqueId = feature.id();
        var top = this._getLayout( scale )
                      .addRect( uniqueId,
                                layoutStart,
                                layoutEnd,
                                levelHeight);

        var fRect = {
            w: (layoutEnd-layoutStart)*scale,
            l: (layoutStart-leftBase)*scale,
            h: fHeight,
            t: top,

            f: feature
        };
        return fRect;
    },

    // draw the features on the canvas
    renderFeatures: function( fRects, canvas ) {
        var context = canvas.getContext('2d');
        var fgcolor = this.config.style.fgcolor;
        context.fillStyle = this.config.style.bgcolor;
        array.forEach( fRects, function( fRect ) {
            context.fillRect( fRect.l, fRect.t, fRect.w, fRect.h );
        });
        if( fgcolor ) {
            context.lineWidth = 1;
            context.strokeStyle = fgcolor;
            array.forEach( fRects, function( fRect ) {
                // need to stroke a smaller rectangle to remain within
                // the bounds of the feature's overall height and
                // width, because of the way stroking is done in
                // canvas.  thus the +0.5 and -1 business.
                context.strokeRect( fRect.l+0.5, fRect.t+0.5, fRect.w-1, fRect.h-1 );
            });
        }
    }
});
});<commit_msg>tweak canvas features drawing code<commit_after>/**
 * Feature track that draws features using HTML5 canvas elements.
 */

define( [
            'dojo/_base/declare',
            'dojo/dom-construct',
            'dojo/_base/array',
            'JBrowse/View/GranularRectLayout',
            'JBrowse/View/Track/Canvas'
        ],
        function( declare, dom, array, Layout, CanvasTrack ) {

return declare( CanvasTrack, {

    constructor: function( args ) {
    },

    _defaultConfig: function() {
        return {
            maxFeatureScreenDensity: 400,
            style: {
                bgcolor: 'goldenrod',
                fgcolor: null,
                height: 3,
                marginBottom: 1
            }
        };
    },

    fillBlock: function( args ) {
        var blockIndex = args.blockIndex;
        var block = args.block;
        var leftBase = args.leftBase;
        var rightBase = args.rightBase;
        var scale = args.scale;

        if( ! this.testCanvasSupport( blockIndex, block ) )
            return;

        var region = { ref: this.refSeq.name, start: leftBase, end: rightBase };

        this.store.getRegionStats(
            region,
            dojo.hitch( this, function( stats ) {

                var density        = stats.featureDensity;
                var featureScale   = this.config.style.featureScale || density / this.config.maxFeatureScreenDensity; // (feat/bp) / ( feat/px ) = px/bp )

                if( scale < featureScale ) {
                    this.fillTooManyFeaturesMessage(
                        blockIndex,
                        block,
                        scale
                    );
                    args.finishCallback();
                }
                else {
                    this.fillFeatures( dojo.mixin( {stats: stats}, args ) );
                }
        }));
    },

    _getLayout: function( scale ) {
        // create the layout if we need to, and if we can
        if( ( ! this.layout || this.layout.pitchX != 4/scale ) && scale  )
            this.layout = new Layout({pitchX: 4/scale, pitchY: this.config.layoutPitchY || (this.config.style.height + this.config.style.marginBottom) });

        return this.layout;
    },

    fillFeatures: function( args ) {
        var track = this;

        var blockIndex = args.blockIndex;
        var block = args.block;
        var scale = args.scale;
        var leftBase = args.leftBase;
        var rightBase = args.rightBase;
        var finishCallback = args.finishCallback;

        var timedOut = false;
        var timeOutError = { toString: function() { return 'Timed out trying to display '+track.name+' block '+blockIndex; } };
        if( this.config.blockDisplayTimeout )
            window.setTimeout( function() { timedOut = true; }, this.config.blockDisplayTimeout );

        var fRects = [];

        var toX = function(coord) { return (coord-leftBase)*scale; };

        var featCallback = dojo.hitch(this,function( feature ) {
            if( timedOut )
                throw timeOutError;

            fRects.push( this.layoutFeature( args, feature, toX ) );
        });

        this.store.getFeatures( { ref: this.refSeq.name,
                                  start: leftBase,
                                  end: rightBase
                                },
                                featCallback,
                                function () {
                                    var totalHeight = track._getLayout(scale).getTotalHeight();
                                    var c = dojo.create(
                                        'canvas',
                                        { height: totalHeight,
                                          width:  block.offsetWidth+1,
                                          style: { cursor: 'default' },
                                          innerHTML: 'Your web browser cannot display this type of track.',
                                          className: 'canvas-track'
                                        },
                                        block
                                    );
                                    track.renderFeatures( args, c, fRects );

                                    track.layoutCanvases([c]);
                                    track.heightUpdate( totalHeight,
                                                        blockIndex );
                                    finishCallback();
                                },
                                function( error ) {
                                    track.error = error;
                                    if( error === timeOutError ) {
                                        track.fillTimeout( blockIndex, block );
                                    } else {
                                        console.error( error, error.stack );
                                        track.fillError( blockIndex, block );
                                    }
                                    finishCallback();
                                }
                              );
    },

    // calculate the placement of the feature on the canvas for this
    // block.
    layoutFeature: function( viewArgs, feature, toX ) {
        var scale = viewArgs.scale;
        var layoutStart = feature.get('start');
        var layoutEnd   = feature.get('end');

        var fHeight = this.config.style.height;
        var levelHeight = fHeight + this.config.style.marginBottom;

        var uniqueId = feature.id();
        var top = this._getLayout( scale )
                      .addRect( uniqueId,
                                layoutStart,
                                layoutEnd,
                                levelHeight);

        var fRect = {
            l: toX(layoutStart),
            h: fHeight,
            t: top,

            f: feature,
            toX: toX
        };
        fRect.w = toX(layoutEnd) - fRect.l;

        return fRect;
    },

    // draw the features on the canvas
    renderFeatures: function( args, canvas, fRects ) {
        var context = canvas.getContext('2d');
        var fgcolor = this.config.style.fgcolor;
        context.fillStyle = this.config.style.bgcolor;
        array.forEach( fRects, function( fRect ) {
            context.fillRect( fRect.l, fRect.t, fRect.w, fRect.h );
        });
        if( fgcolor ) {
            context.lineWidth = 1;
            context.strokeStyle = fgcolor;
            array.forEach( fRects, function( fRect ) {
                // need to stroke a smaller rectangle to remain within
                // the bounds of the feature's overall height and
                // width, because of the way stroking is done in
                // canvas.  thus the +0.5 and -1 business.
                context.strokeRect( fRect.l+0.5, fRect.t+0.5, fRect.w-1, fRect.h-1 );
            });
        }
    }
});
});<|endoftext|>


<commit_before>/* See license.txt for terms of usage */

define([
    "firebug/lib/xpcom",
    "firebug/lib/object",
    "firebug/lib/locale",
    "firebug/lib/domplate",
    "firebug/lib/dom",
    "firebug/lib/options",
    "firebug/lib/persist",
    "firebug/lib/string",
    "firebug/lib/http",
    "firebug/lib/css",
    "firebug/lib/events",
    "firebug/cookies/baseObserver",
    "firebug/chrome/tabWatcher",
    "firebug/cookies/cookieReps",
    "firebug/cookies/cookieUtils",
    "firebug/cookies/cookie",
    "firebug/cookies/breakpoints",
    "firebug/cookies/cookieEvents",
    "firebug/lib/array",
],
function(Xpcom, Obj, Locale, Domplate, Dom, Options, Persist, Str, Http, Css, Events,
    BaseObserver, TabWatcher, CookieReps, CookieUtils, Cookie, Breakpoints, CookieEvents, Arr) {

// ********************************************************************************************* //
// Constants

const Cc = Components.classes;
const Ci = Components.interfaces;

const filterByPath = "cookies.filterByPath";

const panelName = "cookies";

const idnService = Xpcom.CCSV("@mozilla.org/network/idn-service;1", "nsIIDNService");

// ********************************************************************************************* //
// Cookie observer

/**
 * @class This class represents an observer (nsIObserver) for cookie-changed
 * and cookie-rejected events. These events are dispatche by Firefox
 * see https://developer.mozilla.org/En/Observer_Notifications.
 */
var CookieObserver = Obj.extend(BaseObserver,
/** @lends CookieObserver */
{
    // nsIObserver
    observe: function(aSubject, aTopic, aData)
    {
        try
        {
            if (!Firebug.CookieModule.isAlwaysEnabled())
                return;

            // See: https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsICookieService
            // For all possible values.
            if (aTopic == "cookie-changed")
            {
                var cookies = []
                if (aData == "batch-deleted")
                {
                    // In this case the subject is nsIArray.
                    var enumerator = aSubject.QueryInterface(Ci.nsIArray).enumerate();
                    while (enumerator.hasMoreElements())
                        cookies.push(enumerator.getNext().QueryInterface(Ci.nsICookie2));

                    // The event will be further distributed as standard "delete" event.
                    aData = "deleted";
                }
                else
                {
                    aSubject = aSubject ? aSubject.QueryInterface(Ci.nsICookie2) : null;
                    cookies.push(aSubject);
                }

                for (var i=0; i<cookies.length; i++)
                    this.iterateContexts(this.onCookieChanged, cookies[i], aData);
            }
            else if (aTopic == "cookie-rejected")
            {
                aSubject = aSubject.QueryInterface(Ci.nsIURI);
                this.iterateContexts(this.onCookieRejected, aSubject, aData);
            }
        }
        catch (err)
        {
            if (FBTrace.DBG_ERRORS)
            {
                FBTrace.sysout("cookies.CookieObserver.observe; ERROR " +
                    aTopic + ", " + aData, err);
                FBTrace.sysout("cookies.CookieObserver.observe; subject ", aSubject);
            }
        }
    },

    iterateContexts: function(fn)
    {
        var oThis = this;
        var args = Arr.cloneArray(arguments);
        TabWatcher.iterateContexts(function(context)
        {
            args[0] = context;
            fn.apply(oThis, args);
        });
    },

    /**
     * @param {String} activeUri This object represents currently active host. Notice that there
     *      can be more active hosts (activeHosts map) on one page in case
     *      of embedded iframes or/and previous redirects.
     *      Properties:
     *      host: www.example.com
     *      path: /subdir/
     *
     * @param {String} host: Represents the host of a cookie for which
     *      we are checking if it should be displayed for the active URI.
     *
     * @param {String} path: Represents the path of a cookie for which
     *      we are checking if it should be displayed for the active URI.
     *
     * @returns {Boolean} If the method returns true the host/path belongs
     *      to the activeUri.
     */
    isHostFromURI: function(activeUri, host, cookiePath)
    {
        var pathFilter = Options.get(filterByPath);

        // Get directory path (without the file name)
        var queryStringPos = activeUri.path.lastIndexOf("?");
        var activePath = queryStringPos != -1 ?
            activeUri.path.substr(0, queryStringPos) : activeUri.path;

        //Steps 2,3 of RFC 6265 section 5.1.4
        if (activePath.length == 0 || activePath.charAt(0) != "/" || activePath.lastIndexOf("/") == 0)
            activePath = "/";
        else {
            // Remove slash at the end of the active path according to step 4 of RFC 6265 section 5.1.4
        	var lastChar = activePath.charAt(activePath.length - 1);
            if (lastChar == "/")
        		activePath = activePath.substr(0, activePath.length - 1);
        }

        // If the path filter is on, only cookies that match given path
        // according to RFC 6265 section 5.1.4 will be displayed.
        if (pathFilter && (activePath != cookiePath && !(Str.hasPrefix(activePath, cookiePath) &&
            (cookiePath.charAt(cookiePath.length - 1) == "/" ||
                activePath.substr(cookiePath.length, 1) == "/"))))
        {
            return false;
        }

        // The cookie must belong to given URI from this context,
        // otherwise it won't be displayed in this tab.
        var uri = CookieUtils.makeStrippedHost(activeUri.host);
        if (uri == host)
            return true;

        if (uri.length < host.length)
            return false;

        var h = "." + host;
        var u = "." + uri;
        if (u.substr(u.length - h.length) == h)
            return true;

        return false;
    },

    isHostFromContext: function(context, host, path)
    {
        var location;
        try
        {
            host = idnService.convertACEtoUTF8(host);
        }
        catch(exc)
        {
            if (FBTrace.DBG_ERRORS || FBTrace.DBG_COOKIES)
                FBTrace.sysout("Host could not be converted to UTF-8", exc);
        }

        // Invalid in Chromebug.
        try
        {
            location = context.window.location;
            if (!location || !location.protocol)
                return;
        }
        catch (err)
        {
            return false;
        }

        if (location.protocol.indexOf("http") != 0)
            return false;

        var rawHost = CookieUtils.makeStrippedHost(host);

        // Test the current main URI first.
        // The location isn't nsIURI, so make a fake object (aka nsIURI).
        var fakeUri = {host: location.host, path: location.pathname};
        if (this.isHostFromURI(fakeUri, rawHost, path))
            return true;

        // xxxHonza
        // If the context.cookies is not initialized, it's bad. It means that
        // neither temporary context no real context has been initialized
        // One reason is that Sript model issues panel.show in onModuleActivate
        // which consequently requests a file (double load prblem), which
        // consequently rises this cookie event.
        if (!context.cookies)
            return false;

        // Now test if the cookie doesn't belong to some of the
        // activeHosts (redirects, frames).
        var activeHosts = context.cookies.activeHosts;
        for (var activeHost in activeHosts)
        {
            if (this.isHostFromURI(activeHosts[activeHost], rawHost, path))
                return true;
        }

        return false;
    },

    isCookieFromContext: function(context, cookie)
    {
        return this.isHostFromContext(context, cookie.host, cookie.path);
    },

    onCookieChanged: function(context, cookie, action)
    {
        // If the action == "cleared" the cookie is *not* set. This action is triggered
        // when all cookies are removed (cookieManager.removeAll)
        // In such a case let's displaye the event in all contexts.
        if (cookie && !this.isCookieFromContext(context, cookie))
            return;

        if (FBTrace.DBG_COOKIES)
            FBTrace.sysout("cookies.onCookieChanged: '" + (cookie ? cookie.name : "null") +
                "', " + action);

        if (action != "cleared")
        {
            // If log into the Console tab is on, create "deleted", "added" and "changed" events.
            if (logEvents())
                this.logEvent(new CookieEvents.CookieChangedEvent(context, CookieUtils.makeCookieObject(cookie),
                    action), context, "cookie");

            // Break on cookie if "Break On" is activated or if a cookie breakpoint exist.
            Breakpoints.breakOnCookie(context, cookie, action);
        }

        switch(action)
        {
          case "deleted":
            this.onRemoveCookie(context, cookie);
            break;
          case "added":
            this.onAddCookie(context, cookie);
            break;
          case "changed":
            this.onUpdateCookie(context, cookie);
            break;
          case "cleared":
            this.onClear(context);
            return;
          case "reload":
            context.invalidatePanels(panelName);
            return;
        }
    },

    onClear: function(context)
    {
        var panel = context.getPanel(panelName);
        panel.clear();

        if (logEvents())
            this.logEvent(new CookieEvents.CookieClearedEvent(), context, "cookiesCleared");
    },

    onCookieRejected: function(context, uri)
    {
        var path = uri.path.substr(0, (uri.path.lastIndexOf("/") || 1));
        if (!this.isHostFromContext(context, uri.host, path))
            return;

        if (FBTrace.DBG_COOKIES)
            FBTrace.sysout("cookies.onCookieRejected: " + uri.spec);

        // Mark host and all its cookies as rejected.
        // xxxHonza there was an exception "context.cookies is undefined".
        var activeHost = context.cookies.activeHosts[uri.host];
        if (activeHost)
            activeHost.rejected = true;

        var receivedCookies = activeHost ? activeHost.receivedCookies : null;
        for (var i=0; receivedCookies && i<receivedCookies.length; i++)
            receivedCookies[i].cookie.rejected = true;

        // Refresh the panel asynchronously.
        context.invalidatePanels(panelName);

        // Bail out if events are not logged into the Console.
        if (!logEvents())
            return;

        // The "cookies-rejected" event is sent even if no cookies
        // from the blocked site have been actually received.
        // So, the receivedCookies array can be null.
        // Don't display anything in the console in that case,
        // there could be a lot of "Cookie Rejected" events.
        // There would be actually one for each embedded request.
        if (!receivedCookies)
            return;

        // Create group log for list of rejected cookies.
        var groupRow = Firebug.Console.openGroup(
            [new CookieEvents.CookieRejectedEvent(context, uri)],
            context, "cookiesRejected", null, true, null, true);

        // The console can be disabled (since FB 1.2).
        if (!groupRow)
            return;

        // It's closed by default.
        Css.removeClass(groupRow, "opened");
        Firebug.Console.closeGroup(context, true);

        // Create embedded table.
        CookieReps.CookieTable.render(receivedCookies, groupRow.lastChild);
    },

    onAddCookie: function(context, cookie)
    {
        var panel = context.getPanel(panelName, true);
        var repCookie = panel ? panel.findRepObject(cookie) : null;
        if (repCookie)
        {
            this.onUpdateCookie(context, cookie);
            return;
        }

        if (!panel || !panel.table)
            return;

        var repCookie = panel ? panel.findRepObject(cookie) : null;

        cookie = new Cookie(CookieUtils.makeCookieObject(cookie));

        var tbody = panel.table.lastChild;
        var parent = tbody.lastChild ? tbody.lastChild : tbody;
        var row = CookieReps.CookieRow.cookieTag.insertRows({cookies: [cookie]}, parent)[0];

        cookie.row = row;
        row.repObject = cookie;

        //xxxHonza the new cookie should respect current sorting.
    },

    onUpdateCookie: function(context, cookie)
    {
        var panel = context.getPanel(panelName, true);

        // The table doesn't have to be initialized yet.
        if (!panel || !panel.table)
            return;

        var repCookie = panel ? panel.findRepObject(cookie) : null;
        if (!repCookie)
        {
            this.onAddCookie(context, cookie);
            return;
        }

        repCookie.cookie = CookieUtils.makeCookieObject(cookie);
        repCookie.rawHost = CookieUtils.makeStrippedHost(cookie.host);

        // These are helpers so, the XML and JSON cookies don't have to be parsed
        // again and again. But we need to reset them if the value is changed.
        repCookie.json = null;
        repCookie.xml = null;

        if (FBTrace.DBG_COOKIES)
            FBTrace.sysout("cookies.onUpdateCookie: " + cookie.name, repCookie);

        var row = repCookie.row;
        var rowTemplate = CookieReps.CookieRow;

        if (Css.hasClass(row, "opened"))
        {
            var cookieInfoBody = Dom.getElementByClass(row.nextSibling, "cookieInfoBody");

            // Invalidate content of all tabs.
            cookieInfoBody.valuePresented = false;
            cookieInfoBody.rawValuePresented = false;
            cookieInfoBody.xmlPresented = false;
            cookieInfoBody.jsonPresented = false;

            // Update tabs visibility and content of the selected tab.
            rowTemplate.updateTabs(cookieInfoBody, repCookie, context);
            rowTemplate.updateInfo(cookieInfoBody, repCookie, context);
        }

        rowTemplate.updateRow(repCookie, context);
    },

    onRemoveCookie: function(context, cookie)
    {
        var panel = context.getPanel(panelName, true);
        var repCookie = panel ? panel.findRepObject(cookie) : null;
        if (!repCookie)
            return;

        // Remove cookie from UI.
        var row = repCookie.row;
        var parent = repCookie.row.parentNode;

        if (Css.hasClass(repCookie.row, "opened"))
            parent.removeChild(row.nextSibling);

        if (!parent)
            return;

        parent.removeChild(repCookie.row);
    },

    logEvent: function(eventObject, context, className)
    {
        // xxxHonza: if the cookie is changed befor initContext, the log in
        // console is lost.
        Firebug.Console.log(eventObject, context, className, null, true);
    }
});

// ********************************************************************************************* //
// Helpers

function logEvents()
{
    return Options.get("cookies.logEvents");
}

// ********************************************************************************************* //

return CookieObserver;

// ********************************************************************************************* //
});

<commit_msg>Fixed coding style<commit_after>/* See license.txt for terms of usage */

define([
    "firebug/lib/xpcom",
    "firebug/lib/object",
    "firebug/lib/locale",
    "firebug/lib/domplate",
    "firebug/lib/dom",
    "firebug/lib/options",
    "firebug/lib/persist",
    "firebug/lib/string",
    "firebug/lib/http",
    "firebug/lib/css",
    "firebug/lib/events",
    "firebug/cookies/baseObserver",
    "firebug/chrome/tabWatcher",
    "firebug/cookies/cookieReps",
    "firebug/cookies/cookieUtils",
    "firebug/cookies/cookie",
    "firebug/cookies/breakpoints",
    "firebug/cookies/cookieEvents",
    "firebug/lib/array",
],
function(Xpcom, Obj, Locale, Domplate, Dom, Options, Persist, Str, Http, Css, Events,
    BaseObserver, TabWatcher, CookieReps, CookieUtils, Cookie, Breakpoints, CookieEvents, Arr) {

// ********************************************************************************************* //
// Constants

const Cc = Components.classes;
const Ci = Components.interfaces;

const filterByPath = "cookies.filterByPath";

const panelName = "cookies";

const idnService = Xpcom.CCSV("@mozilla.org/network/idn-service;1", "nsIIDNService");

// ********************************************************************************************* //
// Cookie observer

/**
 * @class This class represents an observer (nsIObserver) for cookie-changed
 * and cookie-rejected events. These events are dispatche by Firefox
 * see https://developer.mozilla.org/En/Observer_Notifications.
 */
var CookieObserver = Obj.extend(BaseObserver,
/** @lends CookieObserver */
{
    // nsIObserver
    observe: function(aSubject, aTopic, aData)
    {
        try
        {
            if (!Firebug.CookieModule.isAlwaysEnabled())
                return;

            // See: https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsICookieService
            // For all possible values.
            if (aTopic == "cookie-changed")
            {
                var cookies = []
                if (aData == "batch-deleted")
                {
                    // In this case the subject is nsIArray.
                    var enumerator = aSubject.QueryInterface(Ci.nsIArray).enumerate();
                    while (enumerator.hasMoreElements())
                        cookies.push(enumerator.getNext().QueryInterface(Ci.nsICookie2));

                    // The event will be further distributed as standard "delete" event.
                    aData = "deleted";
                }
                else
                {
                    aSubject = aSubject ? aSubject.QueryInterface(Ci.nsICookie2) : null;
                    cookies.push(aSubject);
                }

                for (var i=0; i<cookies.length; i++)
                    this.iterateContexts(this.onCookieChanged, cookies[i], aData);
            }
            else if (aTopic == "cookie-rejected")
            {
                aSubject = aSubject.QueryInterface(Ci.nsIURI);
                this.iterateContexts(this.onCookieRejected, aSubject, aData);
            }
        }
        catch (err)
        {
            if (FBTrace.DBG_ERRORS)
            {
                FBTrace.sysout("cookies.CookieObserver.observe; ERROR " +
                    aTopic + ", " + aData, err);
                FBTrace.sysout("cookies.CookieObserver.observe; subject ", aSubject);
            }
        }
    },

    iterateContexts: function(fn)
    {
        var oThis = this;
        var args = Arr.cloneArray(arguments);
        TabWatcher.iterateContexts(function(context)
        {
            args[0] = context;
            fn.apply(oThis, args);
        });
    },

    /**
     * @param {String} activeUri This object represents currently active host. Notice that there
     *      can be more active hosts (activeHosts map) on one page in case
     *      of embedded iframes or/and previous redirects.
     *      Properties:
     *      host: www.example.com
     *      path: /subdir/
     *
     * @param {String} host: Represents the host of a cookie for which
     *      we are checking if it should be displayed for the active URI.
     *
     * @param {String} path: Represents the path of a cookie for which
     *      we are checking if it should be displayed for the active URI.
     *
     * @returns {Boolean} If the method returns true the host/path belongs
     *      to the activeUri.
     */
    isHostFromURI: function(activeUri, host, cookiePath)
    {
        var pathFilter = Options.get(filterByPath);

        // Get directory path (without the file name)
        var queryStringPos = activeUri.path.lastIndexOf("?");
        var activePath = queryStringPos != -1 ?
            activeUri.path.substr(0, queryStringPos) : activeUri.path;

        //Steps 2,3 of RFC 6265 section 5.1.4
        if (activePath.length == 0 || activePath.charAt(0) != "/" || activePath.lastIndexOf("/") == 0)
            activePath = "/";
        else
	{
            // Remove slash at the end of the active path according to step 4 of RFC 6265 section 5.1.4
            var lastChar = activePath.charAt(activePath.length - 1);
            if (lastChar == "/")
       	        activePath = activePath.substr(0, activePath.length - 1);
        }

        // If the path filter is on, only cookies that match given path
        // according to RFC 6265 section 5.1.4 will be displayed.
        if (pathFilter && (activePath != cookiePath && !(Str.hasPrefix(activePath, cookiePath) &&
            (cookiePath.charAt(cookiePath.length - 1) == "/" ||
                activePath.substr(cookiePath.length, 1) == "/"))))
        {
            return false;
        }

        // The cookie must belong to given URI from this context,
        // otherwise it won't be displayed in this tab.
        var uri = CookieUtils.makeStrippedHost(activeUri.host);
        if (uri == host)
            return true;

        if (uri.length < host.length)
            return false;

        var h = "." + host;
        var u = "." + uri;
        if (u.substr(u.length - h.length) == h)
            return true;

        return false;
    },

    isHostFromContext: function(context, host, path)
    {
        var location;
        try
        {
            host = idnService.convertACEtoUTF8(host);
        }
        catch(exc)
        {
            if (FBTrace.DBG_ERRORS || FBTrace.DBG_COOKIES)
                FBTrace.sysout("Host could not be converted to UTF-8", exc);
        }

        // Invalid in Chromebug.
        try
        {
            location = context.window.location;
            if (!location || !location.protocol)
                return;
        }
        catch (err)
        {
            return false;
        }

        if (location.protocol.indexOf("http") != 0)
            return false;

        var rawHost = CookieUtils.makeStrippedHost(host);

        // Test the current main URI first.
        // The location isn't nsIURI, so make a fake object (aka nsIURI).
        var fakeUri = {host: location.host, path: location.pathname};
        if (this.isHostFromURI(fakeUri, rawHost, path))
            return true;

        // xxxHonza
        // If the context.cookies is not initialized, it's bad. It means that
        // neither temporary context no real context has been initialized
        // One reason is that Sript model issues panel.show in onModuleActivate
        // which consequently requests a file (double load prblem), which
        // consequently rises this cookie event.
        if (!context.cookies)
            return false;

        // Now test if the cookie doesn't belong to some of the
        // activeHosts (redirects, frames).
        var activeHosts = context.cookies.activeHosts;
        for (var activeHost in activeHosts)
        {
            if (this.isHostFromURI(activeHosts[activeHost], rawHost, path))
                return true;
        }

        return false;
    },

    isCookieFromContext: function(context, cookie)
    {
        return this.isHostFromContext(context, cookie.host, cookie.path);
    },

    onCookieChanged: function(context, cookie, action)
    {
        // If the action == "cleared" the cookie is *not* set. This action is triggered
        // when all cookies are removed (cookieManager.removeAll)
        // In such a case let's displaye the event in all contexts.
        if (cookie && !this.isCookieFromContext(context, cookie))
            return;

        if (FBTrace.DBG_COOKIES)
            FBTrace.sysout("cookies.onCookieChanged: '" + (cookie ? cookie.name : "null") +
                "', " + action);

        if (action != "cleared")
        {
            // If log into the Console tab is on, create "deleted", "added" and "changed" events.
            if (logEvents())
                this.logEvent(new CookieEvents.CookieChangedEvent(context, CookieUtils.makeCookieObject(cookie),
                    action), context, "cookie");

            // Break on cookie if "Break On" is activated or if a cookie breakpoint exist.
            Breakpoints.breakOnCookie(context, cookie, action);
        }

        switch(action)
        {
          case "deleted":
            this.onRemoveCookie(context, cookie);
            break;
          case "added":
            this.onAddCookie(context, cookie);
            break;
          case "changed":
            this.onUpdateCookie(context, cookie);
            break;
          case "cleared":
            this.onClear(context);
            return;
          case "reload":
            context.invalidatePanels(panelName);
            return;
        }
    },

    onClear: function(context)
    {
        var panel = context.getPanel(panelName);
        panel.clear();

        if (logEvents())
            this.logEvent(new CookieEvents.CookieClearedEvent(), context, "cookiesCleared");
    },

    onCookieRejected: function(context, uri)
    {
        var path = uri.path.substr(0, (uri.path.lastIndexOf("/") || 1));
        if (!this.isHostFromContext(context, uri.host, path))
            return;

        if (FBTrace.DBG_COOKIES)
            FBTrace.sysout("cookies.onCookieRejected: " + uri.spec);

        // Mark host and all its cookies as rejected.
        // xxxHonza there was an exception "context.cookies is undefined".
        var activeHost = context.cookies.activeHosts[uri.host];
        if (activeHost)
            activeHost.rejected = true;

        var receivedCookies = activeHost ? activeHost.receivedCookies : null;
        for (var i=0; receivedCookies && i<receivedCookies.length; i++)
            receivedCookies[i].cookie.rejected = true;

        // Refresh the panel asynchronously.
        context.invalidatePanels(panelName);

        // Bail out if events are not logged into the Console.
        if (!logEvents())
            return;

        // The "cookies-rejected" event is sent even if no cookies
        // from the blocked site have been actually received.
        // So, the receivedCookies array can be null.
        // Don't display anything in the console in that case,
        // there could be a lot of "Cookie Rejected" events.
        // There would be actually one for each embedded request.
        if (!receivedCookies)
            return;

        // Create group log for list of rejected cookies.
        var groupRow = Firebug.Console.openGroup(
            [new CookieEvents.CookieRejectedEvent(context, uri)],
            context, "cookiesRejected", null, true, null, true);

        // The console can be disabled (since FB 1.2).
        if (!groupRow)
            return;

        // It's closed by default.
        Css.removeClass(groupRow, "opened");
        Firebug.Console.closeGroup(context, true);

        // Create embedded table.
        CookieReps.CookieTable.render(receivedCookies, groupRow.lastChild);
    },

    onAddCookie: function(context, cookie)
    {
        var panel = context.getPanel(panelName, true);
        var repCookie = panel ? panel.findRepObject(cookie) : null;
        if (repCookie)
        {
            this.onUpdateCookie(context, cookie);
            return;
        }

        if (!panel || !panel.table)
            return;

        var repCookie = panel ? panel.findRepObject(cookie) : null;

        cookie = new Cookie(CookieUtils.makeCookieObject(cookie));

        var tbody = panel.table.lastChild;
        var parent = tbody.lastChild ? tbody.lastChild : tbody;
        var row = CookieReps.CookieRow.cookieTag.insertRows({cookies: [cookie]}, parent)[0];

        cookie.row = row;
        row.repObject = cookie;

        //xxxHonza the new cookie should respect current sorting.
    },

    onUpdateCookie: function(context, cookie)
    {
        var panel = context.getPanel(panelName, true);

        // The table doesn't have to be initialized yet.
        if (!panel || !panel.table)
            return;

        var repCookie = panel ? panel.findRepObject(cookie) : null;
        if (!repCookie)
        {
            this.onAddCookie(context, cookie);
            return;
        }

        repCookie.cookie = CookieUtils.makeCookieObject(cookie);
        repCookie.rawHost = CookieUtils.makeStrippedHost(cookie.host);

        // These are helpers so, the XML and JSON cookies don't have to be parsed
        // again and again. But we need to reset them if the value is changed.
        repCookie.json = null;
        repCookie.xml = null;

        if (FBTrace.DBG_COOKIES)
            FBTrace.sysout("cookies.onUpdateCookie: " + cookie.name, repCookie);

        var row = repCookie.row;
        var rowTemplate = CookieReps.CookieRow;

        if (Css.hasClass(row, "opened"))
        {
            var cookieInfoBody = Dom.getElementByClass(row.nextSibling, "cookieInfoBody");

            // Invalidate content of all tabs.
            cookieInfoBody.valuePresented = false;
            cookieInfoBody.rawValuePresented = false;
            cookieInfoBody.xmlPresented = false;
            cookieInfoBody.jsonPresented = false;

            // Update tabs visibility and content of the selected tab.
            rowTemplate.updateTabs(cookieInfoBody, repCookie, context);
            rowTemplate.updateInfo(cookieInfoBody, repCookie, context);
        }

        rowTemplate.updateRow(repCookie, context);
    },

    onRemoveCookie: function(context, cookie)
    {
        var panel = context.getPanel(panelName, true);
        var repCookie = panel ? panel.findRepObject(cookie) : null;
        if (!repCookie)
            return;

        // Remove cookie from UI.
        var row = repCookie.row;
        var parent = repCookie.row.parentNode;

        if (Css.hasClass(repCookie.row, "opened"))
            parent.removeChild(row.nextSibling);

        if (!parent)
            return;

        parent.removeChild(repCookie.row);
    },

    logEvent: function(eventObject, context, className)
    {
        // xxxHonza: if the cookie is changed befor initContext, the log in
        // console is lost.
        Firebug.Console.log(eventObject, context, className, null, true);
    }
});

// ********************************************************************************************* //
// Helpers

function logEvents()
{
    return Options.get("cookies.logEvents");
}

// ********************************************************************************************* //

return CookieObserver;

// ********************************************************************************************* //
});

<|endoftext|>


<commit_before>var FileBrowser = {
    // this is set automatically
    admin_media_prefix: '',
    // change this
    thumb_prefix: 'thumb_',
    no_thumb: 'filebrowser/img/no_thumb.gif',

    init: function() {
        // Deduce admin_media_prefix by looking at the <script>s in the
        // current document and finding the URL of *this* module.
        var scripts = document.getElementsByTagName('script');
        for (var i=0; i<scripts.length; i++) {
            if (scripts[i].src.match(/AddFileBrowser/)) {
                var idx = scripts[i].src.indexOf('filebrowser/js/AddFileBrowser');
                FileBrowser.admin_media_prefix = scripts[i].src.substring(0, idx);
                break;
            }
        }
    },
    // show FileBrowser
    show: function(id, href, close_func) {
        // var id2=String(id).split(".").join("___");
        var id2=String(id).replace(/\-/g,"____").split(".").join("___");
        FBWindow = window.open(href, String(id2), 'height=600,width=1000,resizable=yes,scrollbars=yes');
        FBWindow.focus();
        if (close_func) {
            FBWindow.onbeforeunload = close_func;
        }
    }
}

function addEvent( obj, type, fn ) {
    if ( obj.attachEvent ) {
        obj['e'+type+fn] = fn;
        obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
        obj.attachEvent( 'on'+type, obj[type+fn] );
    } else
        obj.addEventListener( type, fn, false );
}

addEvent(window, 'load', FileBrowser.init);

<commit_msg>Renamed function "addEvent" as it overrides django admin core.js addEvent, and does not work properly in IE9<commit_after>var FileBrowser = {
    // this is set automatically
    admin_media_prefix: '',
    // change this
    thumb_prefix: 'thumb_',
    no_thumb: 'filebrowser/img/no_thumb.gif',

    init: function() {
        // Deduce admin_media_prefix by looking at the <script>s in the
        // current document and finding the URL of *this* module.
        var scripts = document.getElementsByTagName('script');
        for (var i=0; i<scripts.length; i++) {
            if (scripts[i].src.match(/AddFileBrowser/)) {
                var idx = scripts[i].src.indexOf('filebrowser/js/AddFileBrowser');
                FileBrowser.admin_media_prefix = scripts[i].src.substring(0, idx);
                break;
            }
        }
    },
    // show FileBrowser
    show: function(id, href, close_func) {
        // var id2=String(id).split(".").join("___");
        var id2=String(id).replace(/\-/g,"____").split(".").join("___");
        FBWindow = window.open(href, String(id2), 'height=600,width=1000,resizable=yes,scrollbars=yes');
        FBWindow.focus();
        if (close_func) {
            FBWindow.onbeforeunload = close_func;
        }
    }
}

function addEventFB( obj, type, fn ) {
    if ( obj.attachEvent ) {
        obj['e'+type+fn] = fn;
        obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
        obj.attachEvent( 'on'+type, obj[type+fn] );
    } else
        obj.addEventListener( type, fn, false );
}

addEventFB(window, 'load', FileBrowser.init);

<|endoftext|>


<commit_before>'use strict';

angular.module('myApp.config', ['ngRoute'])

    .config(['$routeProvider', function($routeProvider) {
        $routeProvider.when('/config', {
            templateUrl: 'views/config/config.html',
            controller: 'ConfigController',
            title: 'Configuration'
        });
    }])

    .controller('ConfigController', ['$scope', 'ApiClientService', function($scope, ApiClientService) {
        $scope.taskType = 'file';
        $scope.sequenceStart = 0;
        $scope.sequenceStop = 100;

        ApiClientService.getProviders();
    }]);<commit_msg>Removed API call (json invalid at the moment)<commit_after>'use strict';

angular.module('myApp.config', ['ngRoute'])

    .config(['$routeProvider', function($routeProvider) {
        $routeProvider.when('/config', {
            templateUrl: 'views/config/config.html',
            controller: 'ConfigController',
            title: 'Configuration'
        });
    }])

    .controller('ConfigController', ['$scope', 'ApiClientService', function($scope, ApiClientService) {
        $scope.taskType = 'file';
        $scope.sequenceStart = 0;
        $scope.sequenceStop = 100;

        // Call ApiClientService here to fetch available resources
    }]);<|endoftext|>