<commit_before>jsio('from shared.javascript import Class, map, bind, blockCallback')
jsio('from net.interfaces import Server')
jsio('import shared.keys')

exports = Class(Server, function(supr) {

	this.init = function(connectionCtor, storeEngine) {
		supr(this, 'init');
		this._storeEngine = storeEngine
		this._store = this._storeEngine.getStore()

		this._uniqueId = 0
		this._connectionCtor = connectionCtor;
	}

	var connectionId = 0 // TODO Each server will need a unique id as well to make each connection id globally unique
	this.buildProtocol = function() {
		return new this._connectionCtor('c' + connectionId++, this._storeEngine)
	}

/*******************************
 * Connection request handlers *
 *******************************/
	this.getListItems = function(listKey, from, to, callback) {
		if (!to) { to = -1 } // grab the entire list if no end index is specified
		this._store.getListItems(listKey, from, to, bind(this, function(err, items) {
			if (err) { throw logger.error('could not retrieve list range', listKey, from, to, err) }
			callback(items)
		}))
	}

	this.retrieveStateMutation = function(key, type, callback) {
		switch(type) {
			case 'BYTES':
				this._retrieveBytes(key, function(json) {
					callback({ op: 'set', args: [json] })
				})
				break

			case 'SET':
				this.retrieveSet(key, function(members) {
					callback({ op: 'sadd', args: members })
				})
				break

			default:
				throw logger.error('could not retrieve state mutation of unknown type', type, key)
		}
	}

	this._retrieveBytes = function(key, callback) {
		this._store.getBytes(key, function(err, value) {
			if (err) { throw logger.error('could not retrieve BYTES for key', key, err) }
			callback(value)
		})
	}

	this.retrieveSet = function(key, callback) {
		this._store.getMembers(key, bind(this, function(err, members) {
			if (err) { throw logger.error('could not retrieve set members', key, err) }
			callback(members)
		}))

	}

	this.createItem = function(itemProperties, origConnection, callback) {
		this._store.increment(shared.keys.uniqueIdKey, bind(this, function(err, newItemID) {
			if (err) { throw logger.error('Could not increment unique item id counter', err) }

			var doCallback = blockCallback(bind(this, callback, newItemID), { throwErr: true, fireOnce: true })

			for (var propName in itemProperties) {
				var value = itemProperties[propName]
					mutation = { id: newItemID, property: propName, op: 'set', args: [value] }
				this.mutateItem(mutation, origConnection, doCallback.addBlock())
			}

			doCallback.tryNow()
		}))
	}

	this.mutateItem = function(mutation, originConnection, callback) {
		var key = shared.keys.getItemPropertyKey(mutation.id, mutation.property),
			operation = mutation.op,
			args = Array.prototype.slice.call(mutation.args, 0)
			connId = originConnection ? originConnection.getId() : '',
			mutationBuffer = connId.length + connId + JSON.stringify(mutation)

		if (connId.length > 9) {
			throw logger.error("Connection ID is longer than 9 digits! Parsing this connection ID won't work")
		}

		args.unshift(key)
		logger.log('Apply and publish mutation', operation, args)
		if (callback) { args.push(callback) }
		this._store.handleMutation(operation, args)

		// TODO clients should subscribe against pattern channels,
		//	e.g. for item props *:1@type:* and for prop channels *:#type:*
		//	mutations then come with a single publication channel,
		//	e.g. :1@type:#type: for a mutation that changes the type of item 1
		// var propChannel = shared.keys.getPropertyChannel(propName)

		this._store.publish(key, mutationBuffer)
		// this._store.publish(propChannel, mutationBuffer)
	}
})

<commit_msg>Add comma to avoid global declaration of connId and mutationBuffer<commit_after>jsio('from shared.javascript import Class, map, bind, blockCallback')
jsio('from net.interfaces import Server')
jsio('import shared.keys')

exports = Class(Server, function(supr) {

	this.init = function(connectionCtor, storeEngine) {
		supr(this, 'init');
		this._storeEngine = storeEngine
		this._store = this._storeEngine.getStore()

		this._uniqueId = 0
		this._connectionCtor = connectionCtor;
	}

	var connectionId = 0 // TODO Each server will need a unique id as well to make each connection id globally unique
	this.buildProtocol = function() {
		return new this._connectionCtor('c' + connectionId++, this._storeEngine)
	}

/*******************************
 * Connection request handlers *
 *******************************/
	this.getListItems = function(listKey, from, to, callback) {
		if (!to) { to = -1 } // grab the entire list if no end index is specified
		this._store.getListItems(listKey, from, to, bind(this, function(err, items) {
			if (err) { throw logger.error('could not retrieve list range', listKey, from, to, err) }
			callback(items)
		}))
	}

	this.retrieveStateMutation = function(key, type, callback) {
		switch(type) {
			case 'BYTES':
				this._retrieveBytes(key, function(json) {
					callback({ op: 'set', args: [json] })
				})
				break

			case 'SET':
				this.retrieveSet(key, function(members) {
					callback({ op: 'sadd', args: members })
				})
				break

			default:
				throw logger.error('could not retrieve state mutation of unknown type', type, key)
		}
	}

	this._retrieveBytes = function(key, callback) {
		this._store.getBytes(key, function(err, value) {
			if (err) { throw logger.error('could not retrieve BYTES for key', key, err) }
			callback(value)
		})
	}

	this.retrieveSet = function(key, callback) {
		this._store.getMembers(key, bind(this, function(err, members) {
			if (err) { throw logger.error('could not retrieve set members', key, err) }
			callback(members)
		}))

	}

	this.createItem = function(itemProperties, origConnection, callback) {
		this._store.increment(shared.keys.uniqueIdKey, bind(this, function(err, newItemID) {
			if (err) { throw logger.error('Could not increment unique item id counter', err) }

			var doCallback = blockCallback(bind(this, callback, newItemID), { throwErr: true, fireOnce: true })

			for (var propName in itemProperties) {
				var value = itemProperties[propName]
					mutation = { id: newItemID, property: propName, op: 'set', args: [value] }
				this.mutateItem(mutation, origConnection, doCallback.addBlock())
			}

			doCallback.tryNow()
		}))
	}

	// this.deleteItem = function(itemID, callback) {
	// 	this._store.delete(itemID, function(err) {
	// 		if (err) { throw logger.error('Could not delete item ' + itemID, err) }
	// 		callback()
	// 	})
	// }

	this.mutateItem = function(mutation, originConnection, callback) {
		var key = shared.keys.getItemPropertyKey(mutation.id, mutation.property),
			operation = mutation.op,
			args = Array.prototype.slice.call(mutation.args, 0),
			connId = originConnection ? originConnection.getId() : '',
			mutationBuffer = connId.length + connId + JSON.stringify(mutation)

		if (connId.length > 9) {
			throw logger.error("Connection ID is longer than 9 digits! Parsing this connection ID won't work")
		}

		args.unshift(key)
		logger.log('Apply and publish mutation', operation, args)
		if (callback) { args.push(callback) }
		this._store.handleMutation(operation, args)

		// TODO clients should subscribe against pattern channels,
		//	e.g. for item props *:1@type:* and for prop channels *:#type:*
		//	mutations then come with a single publication channel,
		//	e.g. :1@type:#type: for a mutation that changes the type of item 1
		// var propChannel = shared.keys.getPropertyChannel(propName)

		this._store.publish(key, mutationBuffer)
		// this._store.publish(propChannel, mutationBuffer)
	}
})

<|endoftext|>


<commit_before>var Sheets2sqlite = function(db, workbookId, tablesToProcess) {
    this.db = db;
    this.tablesToProcess = tablesToProcess;
    this.tables = [];
    this.control = {
        reqs: 0,
        reqOk: false,
        resps: 0,

        ok: function() {
            return (this.reqOk && (this.reqs == this.resps));
        },

        reset: function() {
            this.reqs = 0;
            this.resps = 0;
            this.reqOk = false;
        }
    };

    this.url = '//spreadsheets.google.com/feeds/worksheets/' + workbookId + '/public/values?alt=json';
};

Sheets2sqlite.prototype.start = function(done) {
    this.done = done;
    var that = this;

    $.ajax({
        url: this.url
    }).done(function(workbookData) {
        for(var i=0; i<workbookData.feed.entry.length; i++) {
            var entry = workbookData.feed.entry[i];
            var item = { name : entry.title.$t, link : entry.link[1].href.replace('https:', '') + '?alt=json' };

            that.control.reqs++;
            (function(name, link) {
                $.ajax({
                    url: link
                }).done(function(worksheetData) {
                    that.processWorksheetData(name, worksheetData);
                });
            }) (item.name, item.link);
        }
        that.control.reqOk = true;
    });
};

Sheets2sqlite.prototype.processWorksheetData = function(tableName, worksheetData) {
    this.control.resps++;
    if($.inArray(tableName, this.tablesToProcess) >= 0) {
        var table = this.createTable(tableName, worksheetData);
        this.insertData(table, worksheetData);
        this.tables.push(table);
    }

    if(this.control.ok()) {
        this.loadData(this.tables);
        this.done();
        this.control.reset();
    }
};

Sheets2sqlite.prototype.createTable = function(tableName, worksheetData) {
    var columns = [];
    var table = {
        name: tableName,
        fkCount: false,
        validColumns: [],
        regularIndexes: [],
        uniqueIndexes: [],
        createSQL: function() {
            var sSQL = 'CREATE TABLE ' + this.name + ' (';
            for(var i=0; i<this.columns.length; i++) {
                var column = this.columns[i];
                sSQL += column.name + ' ' + column.type;
                if(column.name == 'id') sSQL += ' primary key';
                if(i+1 != this.columns.length || this.fkCount > 0) {
                    sSQL += ', ';
                }
            }

            var tempFkCount = 0;
            if(this.fkCount > 0) {
                for(var i=0; i<this.columns.length; i++) {
                    var column = this.columns[i];
                    if(column.fk !== '') {
                        tempFkCount++;
                        sSQL += 'FOREIGN KEY(' + column.name + ') REFERENCES ' + column.fk;
                        if(tempFkCount != this.fkCount) {
                            sSQL += ', ';
                        } else {
                            break;
                        }
                    }
                }
            }

            sSQL += ');';

            for(var i=0; i<this.regularIndexes.length; i++) {
                var index = this.regularIndexes[i];
                sSQL += this.indexSQL(index, false);
            }

            for(var i=0; i<this.uniqueIndexes.length; i++) {
                var index = this.uniqueIndexes[i];
                sSQL += this.indexSQL(index, true);
            }

            return sSQL;
        },
        indexSQL: function(index, unique) {
            var temp = 'CREATE ' + (unique ? 'UNIQUE ' : '') + 'INDEX IF NOT EXISTS ';
            temp += index.name;
            temp += ' ON ';
            temp += this.name;

            var indexNames = [];
            for(var i=0; i<index.columns.length; i++) {
                indexNames.push(index.columns[i].name);
            }

            temp += ' (' + indexNames.join(', ') + ');';

            return temp;
        },
        insertSQL: function() {
            var sSQL = '';
            for(var j=0; j<this.rows.length; j++) {
                var row = this.rows[j];
                var sSQLData = '';

                sSQL += 'INSERT INTO ' + this.name + '(';
                for(var i=0; i<this.columns.length; i++) {
                    var col = this.columns[i];
                    sSQL += col.name;

                    if(col.type.toLowerCase() == 'text') {
                        sSQLData += '\'' + escape(row.cells[i]) + '\'';
                    } else {
                        var value = escape(row.cells[i]);
                        if(value === '') {
                            value = 'NULL';
                        }
                        sSQLData += value;

                    }

                    if(i+1 != this.columns.length) {
                        sSQL += ', ';
                        sSQLData += ', ';
                    }
                }
                sSQL += ') VALUES (' + sSQLData + ');';
            }

            return sSQL;
        },
        getRegularIndex: function(indexName) {
            return this.getIndex(this.regularIndexes, indexName);
        },
        getUniqueIndex: function(indexName) {
            return this.getIndex(this.uniqueIndexes, indexName);
        },
        getIndex: function(indexes, indexName) {
            for(var i=0; i<indexes; i++) {
                var index = indexes[i];
                if(index.name == indexName) {
                    return index;
                }
            }
            return null;
        }
    };

    for(var i=0; i<worksheetData.feed.entry.length; i++) {
        var item = worksheetData.feed.entry[i];

        if(item.gs$cell.row == '1') {
            var pos = parseInt(item.gs$cell.col, 10) - 1;
            var value = item.gs$cell.$t;
            var name = value.substring(0, value.indexOf('(')).trim();
            var type = value.substring(value.indexOf('(') + 1, value.indexOf(')')).trim();

            var column = {
                pos: pos,
                name: name,
                type: type,
                fk: ''
            };

            columns.push(column);
            table.validColumns.push(pos);
        } else if(item.gs$cell.row == '2') {
            var pos = parseInt(item.gs$cell.col, 10) - 1;
            var column = columns[table.validColumns.indexOf(pos)];
            var value = item.gs$cell.$t;

            if(value !== '') {
                var indexes = value.split(',');
                for(var j=0; j<indexes.length; j++) {
                    var index = indexes[j].trim();
                    if(index.toLowerCase().indexOf('fk_') >= 0) {
                        table.fkCount++;
                        column.fk = index.substring(3, index.length);
                    } else if(index.toLowerCase().indexOf('in_') >= 0) {
                        var regularIndex = table.getRegularIndex(index.toLowerCase());

                        if(regularIndex === null) {
                            regularIndex = {
                                name: index.toLowerCase(),
                                columns: []
                            };

                            table.regularIndexes.push(regularIndex);
                        }

                        regularIndex.columns.push(column);
                    } else if(index.toLowerCase().indexOf('un_') >= 0) {
                        var uniqueIndex = table.getUniqueIndex(index.toLowerCase());

                        if(uniqueIndex === null) {
                            uniqueIndex = {
                                name: index.toLowerCase(),
                                columns: []
                            };

                            table.uniqueIndexes.push(uniqueIndex);
                        }

                        uniqueIndex.columns.push(column);
                    }
                }
            }
        } else {
            break;
        }
    }

    table.columns = columns;

    return table;
};

Sheets2sqlite.prototype.insertData = function(table, worksheetData) {
    var rows = [];

    var linhaInicial = 3;

    for(var i=0; i<worksheetData.feed.entry.length; i++) {
        var item = worksheetData.feed.entry[i];
        var col = parseInt(item.gs$cell.col, 10) - 1;
        var row = parseInt(item.gs$cell.row, 10) - linhaInicial;

        if(row < 0) {
            continue;
        }

        if(col === 0) {
            rows.push({
                row: row,
                cells: []
            });
        }

        if(table.validColumns.indexOf(col) >= 0) {
            var line = rows[row];
            line.cells.push(item.gs$cell.$t);
        }
    }

    table.rows = rows;
};

Sheets2sqlite.prototype.loadData = function(tables) {
    for(var i=0; i<tables.length; i++) {
        var table = tables[i];

        console.log('createSQL:', table.createSQL());
        console.log('insertSQL:', table.insertSQL());

        this.db.exec(table.createSQL());
        this.db.exec(table.insertSQL());
    }
};

var escape = function(text) {
    var temp = text.replace('\'', '\'\'');
    temp = temp.replace('"', '""');
    return temp;
};

var tableCreate = function () {
    function valconcat(vals, tagName) {
        if (vals.length === 0) return '';
        var open = '<'+tagName+'>', close='</'+tagName+'>';
        return open + vals.join(close + open) + close;
    }

    return function (columns, values) {
        var tbl  = document.createElement('table');
        var html = '
' + valconcat(columns, 'th') + '
';
        var rows = values.map(function(v){ return valconcat(v, 'td'); });
        html += '
' + valconcat(rows, 'tr') + '
';
        tbl.innerHTML = html;
        return tbl;
    };
};<commit_msg>table.column fk reference<commit_after>var Sheets2sqlite = function(db, workbookId, tablesToProcess) {
    this.db = db;
    this.tablesToProcess = tablesToProcess;
    this.tables = [];
    this.control = {
        reqs: 0,
        reqOk: false,
        resps: 0,

        ok: function() {
            return (this.reqOk && (this.reqs == this.resps));
        },

        reset: function() {
            this.reqs = 0;
            this.resps = 0;
            this.reqOk = false;
        }
    };

    this.url = '//spreadsheets.google.com/feeds/worksheets/' + workbookId + '/public/values?alt=json';
};

Sheets2sqlite.prototype.start = function(done) {
    this.done = done;
    var that = this;

    $.ajax({
        url: this.url
    }).done(function(workbookData) {
        for(var i=0; i<workbookData.feed.entry.length; i++) {
            var entry = workbookData.feed.entry[i];
            var item = { name : entry.title.$t, link : entry.link[1].href.replace('https:', '') + '?alt=json' };

            that.control.reqs++;
            (function(name, link) {
                $.ajax({
                    url: link
                }).done(function(worksheetData) {
                    that.processWorksheetData(name, worksheetData);
                });
            }) (item.name, item.link);
        }
        that.control.reqOk = true;
    });
};

Sheets2sqlite.prototype.processWorksheetData = function(tableName, worksheetData) {
    this.control.resps++;
    if($.inArray(tableName, this.tablesToProcess) >= 0) {
        var table = this.createTable(tableName, worksheetData);
        this.insertData(table, worksheetData);
        this.tables.push(table);
    }

    if(this.control.ok()) {
        this.loadData(this.tables);
        this.done();
        this.control.reset();
    }
};

Sheets2sqlite.prototype.createTable = function(tableName, worksheetData) {
    var columns = [];
    var table = {
        name: tableName,
        fkCount: false,
        validColumns: [],
        regularIndexes: [],
        uniqueIndexes: [],
        createSQL: function() {
            var sSQL = 'CREATE TABLE ' + this.name + ' (';
            for(var i=0; i<this.columns.length; i++) {
                var column = this.columns[i];
                sSQL += column.name + ' ' + column.type;
                if(column.name == 'id') sSQL += ' primary key';
                if(i+1 != this.columns.length || this.fkCount > 0) {
                    sSQL += ', ';
                }
            }

            var tempFkCount = 0;
            if(this.fkCount > 0) {
                for(var i=0; i<this.columns.length; i++) {
                    var column = this.columns[i];
                    if(column.fk !== '') {
                        tempFkCount++;
                        sSQL += 'FOREIGN KEY(' + column.name + ') REFERENCES ' + column.fk;
                        if(tempFkCount != this.fkCount) {
                            sSQL += ', ';
                        } else {
                            break;
                        }
                    }
                }
            }

            sSQL += ');';

            for(var i=0; i<this.regularIndexes.length; i++) {
                var index = this.regularIndexes[i];
                sSQL += this.indexSQL(index, false);
            }

            for(var i=0; i<this.uniqueIndexes.length; i++) {
                var index = this.uniqueIndexes[i];
                sSQL += this.indexSQL(index, true);
            }

            return sSQL;
        },
        indexSQL: function(index, unique) {
            var temp = 'CREATE ' + (unique ? 'UNIQUE ' : '') + 'INDEX IF NOT EXISTS ';
            temp += index.name;
            temp += ' ON ';
            temp += this.name;

            var indexNames = [];
            for(var i=0; i<index.columns.length; i++) {
                indexNames.push(index.columns[i].name);
            }

            temp += ' (' + indexNames.join(', ') + ');';

            return temp;
        },
        insertSQL: function() {
            var sSQL = '';
            for(var j=0; j<this.rows.length; j++) {
                var row = this.rows[j];
                var sSQLData = '';

                sSQL += 'INSERT INTO ' + this.name + '(';
                for(var i=0; i<this.columns.length; i++) {
                    var col = this.columns[i];
                    sSQL += col.name;

                    if(col.type.toLowerCase() == 'text') {
                        sSQLData += '\'' + escape(row.cells[i]) + '\'';
                    } else {
                        var value = escape(row.cells[i]);
                        if(value === '') {
                            value = 'NULL';
                        }
                        sSQLData += value;

                    }

                    if(i+1 != this.columns.length) {
                        sSQL += ', ';
                        sSQLData += ', ';
                    }
                }
                sSQL += ') VALUES (' + sSQLData + ');';
            }

            return sSQL;
        },
        getRegularIndex: function(indexName) {
            return this.getIndex(this.regularIndexes, indexName);
        },
        getUniqueIndex: function(indexName) {
            return this.getIndex(this.uniqueIndexes, indexName);
        },
        getIndex: function(indexes, indexName) {
            for(var i=0; i<indexes; i++) {
                var index = indexes[i];
                if(index.name == indexName) {
                    return index;
                }
            }
            return null;
        }
    };

    for(var i=0; i<worksheetData.feed.entry.length; i++) {
        var item = worksheetData.feed.entry[i];

        if(item.gs$cell.row == '1') {
            var pos = parseInt(item.gs$cell.col, 10) - 1;
            var value = item.gs$cell.$t;
            var name = value.substring(0, value.indexOf('(')).trim();
            var type = value.substring(value.indexOf('(') + 1, value.indexOf(')')).trim();

            var column = {
                pos: pos,
                name: name,
                type: type,
                fk: ''
            };

            columns.push(column);
            table.validColumns.push(pos);
        } else if(item.gs$cell.row == '2') {
            var pos = parseInt(item.gs$cell.col, 10) - 1;
            var column = columns[table.validColumns.indexOf(pos)];
            var value = item.gs$cell.$t;

            if(value !== '') {
                var indexes = value.split(',');
                for(var j=0; j<indexes.length; j++) {
                    var index = indexes[j].trim();
                    if(index.toLowerCase().indexOf('fk_') >= 0) {
                        table.fkCount++;
                        //column.fk = index.substring(3, index.length);
                        column.fk = index.substring(index.indexOf('(') + 1, index.indexOf(')')).replace('.', '(') + ')';
                    } else if(index.toLowerCase().indexOf('in_') >= 0) {
                        var regularIndex = table.getRegularIndex(index.toLowerCase());

                        if(regularIndex === null) {
                            regularIndex = {
                                name: index.toLowerCase(),
                                columns: []
                            };

                            table.regularIndexes.push(regularIndex);
                        }

                        regularIndex.columns.push(column);
                    } else if(index.toLowerCase().indexOf('un_') >= 0) {
                        var uniqueIndex = table.getUniqueIndex(index.toLowerCase());

                        if(uniqueIndex === null) {
                            uniqueIndex = {
                                name: index.toLowerCase(),
                                columns: []
                            };

                            table.uniqueIndexes.push(uniqueIndex);
                        }

                        uniqueIndex.columns.push(column);
                    }
                }
            }
        } else {
            break;
        }
    }

    table.columns = columns;

    return table;
};

Sheets2sqlite.prototype.insertData = function(table, worksheetData) {
    var rows = [];

    var linhaInicial = 3;

    for(var i=0; i<worksheetData.feed.entry.length; i++) {
        var item = worksheetData.feed.entry[i];
        var col = parseInt(item.gs$cell.col, 10) - 1;
        var row = parseInt(item.gs$cell.row, 10) - linhaInicial;

        if(row < 0) {
            continue;
        }

        if(col === 0) {
            rows.push({
                row: row,
                cells: []
            });
        }

        if(table.validColumns.indexOf(col) >= 0) {
            var line = rows[row];
            line.cells.push(item.gs$cell.$t);
        }
    }

    table.rows = rows;
};

Sheets2sqlite.prototype.loadData = function(tables) {
    for(var i=0; i<tables.length; i++) {
        var table = tables[i];

        console.log('createSQL:', table.createSQL());
        console.log('insertSQL:', table.insertSQL());

        this.db.exec(table.createSQL());
        this.db.exec(table.insertSQL());
    }
};

var escape = function(text) {
    var temp = text.replace('\'', '\'\'');
    temp = temp.replace('"', '""');
    return temp;
};

var tableCreate = function () {
    function valconcat(vals, tagName) {
        if (vals.length === 0) return '';
        var open = '<'+tagName+'>', close='</'+tagName+'>';
        return open + vals.join(close + open) + close;
    }

    return function (columns, values) {
        var tbl  = document.createElement('table');
        var html = '
' + valconcat(columns, 'th') + '
';
        var rows = values.map(function(v){ return valconcat(v, 'td'); });
        html += '
' + valconcat(rows, 'tr') + '
';
        tbl.innerHTML = html;
        return tbl;
    };
};<|endoftext|>


<commit_before>// Copyright (c) 2015-2016, Exa Analytics Development Team
// Distributed under the terms of the Apache License 2.0
/*""""
Exa-Three.js Adapter
=====================
Description
*/
var widgets = require("jupyter-js-widgets");
var _ = require("underscore");
var THREE = require("three");
window.THREE = THREE;    // Allows importing three/*
require("./threejs/renderers/CanvasRenderer.js");
var Detector = require("./threejs/Detector.js");

var $ = require("jquery");

var base = require("./foo/base.js");

// The DOM object is what is actually displayed in the (Jupyter) notebook
var RendererModel = base.createWidgetModel("Renderer", {"value": "renderer model"});

class RendererView extends widgets.DOMWidgetView {
    render() {
        this.value_changed();
        this.model.on("change:value", this.value_changed, this);
    }

    value_changed() {
        this.el.textContent = this.model.get("value");
    }
}

// All other objects are just Widgets
class ThreeView extends widgets.WidgetView {
}

class ThreeModel extends widgets.WidgetModel {
}

//

function generate_view(name) {
    console.log("generate_view");
//    console.log(THREE[name]);
//    console.log(THREE[name].prototype);
 //   var obj = THREE[name];
 //   console.log(obj);
    var obj1 = THREE.BoxBufferGeometry(1, 1, 1);
    console.log(obj1);

    return {};
}

function build_api() {
    console.log("building api");
    var models = {RendererModel: RendererModel};
    var views = {RendererView: RendererView};
    console.log(THREE);
    //for (var attribute in THREE) {
    //    if (THREE.hasOwnProperty(attribute)) {
    //        console.log(attribute);
    //    }
    //}
    var attributes = generate_view("BoxGeometry");

    return _.extend({}, models, views);
}

module.exports = build_api();
<commit_msg>minor<commit_after>// Copyright (c) 2015-2016, Exa Analytics Development Team
// Distributed under the terms of the Apache License 2.0
/*""""
Exa-Three.js Adapter
=====================
Description
*/
var widgets = require("jupyter-js-widgets");
var _ = require("underscore");
var THREE = require("three");
window.THREE = THREE;    // Allows importing three/*
require("./threejs/renderers/CanvasRenderer.js");
var Detector = require("./threejs/Detector.js");

var $ = require("jquery");

var base = require("./foo/base.js");

// The DOM object is what is actually displayed in the (Jupyter) notebook
var RendererModel = base.createWidgetModel("Renderer", {"value": "renderer model"});

class RendererView extends widgets.DOMWidgetView {
    render() {
        this.value_changed();
        this.model.on("change:value", this.value_changed, this);
    }

    value_changed() {
        this.el.textContent = this.model.get("value");
    }
}

// All other objects are just Widgets
class ThreeView extends widgets.WidgetView {
}

class ThreeModel extends widgets.WidgetModel {
}

//

function generate_view(name) {
    console.log("generate_view");
//    console.log(THREE[name]);
//    console.log(THREE[name].prototype);
 //   var obj = THREE[name];
 //   console.log(obj);

    return {};
}

function build_api() {
    console.log("building api");
    var models = {RendererModel: RendererModel};
    var views = {RendererView: RendererView};
    console.log(THREE);
    //for (var attribute in THREE) {
    //    if (THREE.hasOwnProperty(attribute)) {
    //        console.log(attribute);
    //    }
    //}
    var obj = THREE.BoxGeometry();
    console.log(obj);
    //var attributes = generate_view("BoxGeometry");

    return _.extend({}, models, views);
}

module.exports = build_api();
<|endoftext|>


<commit_before>/**
 * Created by dat on 4/5/17.
 */
var hic = (function (hic) {

    hic.TrackRenderer = function (browser, size, $container, trackRenderPair, trackPair, axis, order) {

        this.browser = browser;

        this.trackRenderPair = trackRenderPair;

        this.track = trackPair[axis];

        this.id = _.uniqueId('trackRenderer_');
        this.axis = axis;
        this.initializationHelper($container, size, order);
    };

    hic.TrackRenderer.prototype.initializationHelper = function ($container, size, order) {

        var self = this,
            str,
            doShowLabelAndGear,
            $x_track_label,
            $x_track_menu_container;

        // track canvas container
        this.$viewport = ('x' === this.axis) ? $('
') : $('
');
        if (size.width) {
            this.$viewport.width(size.width);
        }
        if (size.height) {
            this.$viewport.height(size.height);
        }
        $container.append(this.$viewport);
        this.$viewport.css( { order:order } );

        // canvas
        this.$canvas = $('<canvas>');
        this.$viewport.append(this.$canvas);
        this.ctx = this.$canvas.get(0).getContext("2d");

        if ('x' === this.axis) {

            // label
            this.$label = $('
');
            str = this.track.name || 'untitled';
            this.$label.text(str);

            // note the pre-existing state of track labels/gear. hide/show accordingly.
            $x_track_label = $container.find(this.$label);
            doShowLabelAndGear = (0 === _.size($x_track_label)) ? true : $x_track_label.is(':visible');

            this.$viewport.append(this.$label);
        }

        // track spinner container
        this.$spinner = ('x' === this.axis) ? $('
') : $('
');
        this.$viewport.append(this.$spinner);

        // throbber
        // size: see $hic-viewport-spinner-size in .scss files
        this.throbber = Throbber({color: 'rgb(64, 64, 64)', size: 32, padding: 7});
        this.throbber.appendTo(this.$spinner.get(0));
        this.stopSpinner();

        if ('x' === this.axis) {

            this.$menu_container = $('
');
            this.$viewport.append(this.$menu_container);

            this.$menu_button = $('');
            this.$menu_container.append(this.$menu_button);

            this.$menu_button.click(function (e) {
                e.stopPropagation();
                igv.popover.presentTrackGearMenu(e.pageX, e.pageY, self);
            });

            this.$viewport.on('click', function (e) {

                e.stopPropagation();

                // self.$label.toggle();
                // self.$menu_container.toggle();

                $container.find('.x-track-label').toggle();
                $container.find('.x-track-menu-container').toggle();
            });

            if (doShowLabelAndGear) {
                this.$label.show();
                this.$menu_container.show();
            } else {
                this.$label.hide();
                this.$menu_container.hide();
            }

        }

        // compatibility with igv menus
        this.track.trackView = this;
        this.track.trackView.trackDiv = this.$viewport.get(0);

        this.configTrackTransforms();

    };

    hic.TrackRenderer.prototype.configTrackTransforms = function () {

        this.canvasTransform = ('y' === this.axis) ? hic.reflectionRotationWithContext : hic.identityTransformWithContext;

        this.labelReflectionTransform = ('y' === this.axis) ? hic.reflectionAboutYAxisAtOffsetWithContext : function (context, exe) { /* nuthin */
        };

    };

    hic.TrackRenderer.prototype.syncCanvas = function () {

        this.tile = null;

        this.$canvas.width(this.$viewport.width());
        this.$canvas.attr('width', this.$viewport.width());

        this.$canvas.height(this.$viewport.height());
        this.$canvas.attr('height', this.$viewport.height());

        igv.graphics.fillRect(this.ctx, 0, 0, this.$canvas.width(), this.$canvas.height(), {fillStyle: igv.rgbColor(255, 255, 255)});
    };

    hic.TrackRenderer.prototype.setColor = function (color) {

        _.each(this.trackRenderPair, function (trackRenderer) {
            trackRenderer.tile = undefined;
            trackRenderer.track.color = color;
        });

        this.browser.renderTrackXY(this.trackRenderPair);
    };

    hic.TrackRenderer.prototype.dataRange = function () {
        return this.track.dataRange ? this.track.dataRange : undefined;
    };

    hic.TrackRenderer.prototype.setDataRange = function (min, max, autoscale) {

        _.each(this.trackRenderPair, function (trackRenderer) {
            trackRenderer.tile = undefined;
            trackRenderer.track.dataRange = {min: min, max: max};
            trackRenderer.track.autscale = autoscale;
        });

        this.browser.renderTrackXY(this.trackRenderPair);

    };

    hic.TrackRenderer.prototype.repaint = function () {

        var self = this,
            lengthPixel,
            lengthBP,
            startBP,
            endBP,
            genomicState,
            chrName;

        genomicState = _.mapObject(self.browser.genomicState(), function (val) {
            return _.isObject(val) ? val[self.axis] : val;
        });

        if (/*this.$zoomInNotice &&*/ self.track.visibilityWindow && self.track.visibilityWindow > 0) {

            if ((genomicState.bpp * Math.max(self.$canvas.width(), self.$canvas.height()) > self.track.visibilityWindow) /*|| ('all' === genomicState.chromosome.name && !self.track.supportsWholeGenome)*/) {

                self.tile = undefined;
                self.ctx.clearRect(0, 0, self.$canvas.width(), self.$canvas.height());

                self.stopSpinner();
                // self.$zoomInNotice.show();

                return;

            } else {
                // self.$zoomInNotice.hide();
            }

        } // if (/*this.$zoomInNotice &&*/ self.track.visibilityWindow && self.track.visibilityWindow > 0)

        chrName = genomicState.chromosome.name;

        if (self.tile && self.tile.containsRange(chrName, genomicState.startBP, genomicState.endBP, genomicState.bpp)) {
            self.drawTileWithGenomicState(self.tile, genomicState);
            return;

        } else {

            // Expand the requested range so we can pan a bit without reloading
            lengthPixel = 3 * Math.max(self.$canvas.width(), self.$canvas.height());

            lengthBP = Math.round(genomicState.bpp * lengthPixel);

            startBP = Math.max(0, Math.round(genomicState.startBP - lengthBP / 3));

            endBP = startBP + lengthBP;

            if (self.loading) { //&& self.loading.start === startBP && self.loading.end === endBP) {
                return;
            } else {

                self.loading =
                {
                    start: startBP,
                    end: endBP
                };

                self.startSpinner();
                self.track
                    .getFeatures(genomicState.chromosome.name, startBP, endBP, genomicState.bpp)
                    .then(function (features) {

                        var buffer,
                            ctx;

                        self.loading = false;

                        self.stopSpinner();

                        buffer = document.createElement('canvas');
                        buffer.width = 'x' === self.axis ? lengthPixel : self.$canvas.width();
                        buffer.height = 'x' === self.axis ? self.$canvas.height() : lengthPixel;
                        ctx = buffer.getContext("2d");

                        if (features) {

                            self.canvasTransform(ctx);

                            self.drawConfiguration =
                            {
                                features: features,

                                context: ctx,

                                pixelWidth: lengthPixel,
                                pixelHeight: Math.min(buffer.width, buffer.height),

                                bpStart: startBP,
                                bpEnd: endBP,

                                bpPerPixel: genomicState.bpp,

                                genomicState: genomicState,

                                viewportContainerX: (genomicState.startBP - startBP) / genomicState.bpp,

                                viewportContainerWidth: Math.max(self.$canvas.width(), self.$canvas.height()),

                                labelTransform: self.labelReflectionTransform
                            };

                            self.track.draw(self.drawConfiguration);

                        } else {
                            ctx.clearRect(0, 0, self.$canvas.width(), self.$canvas.height());
                        }

                        self.tile = new Tile(chrName, startBP, endBP, genomicState.bpp, buffer);

                        self.repaint();

                    })
                    .catch(function (error) {

                        self.stopSpinner();
                        self.loading = false;
                        throw new Error(error);
                    });

            }
        }

    };

    hic.TrackRenderer.prototype.drawTileWithGenomicState = function (tile, genomicState) {

        if (tile) {

            this.ctx.clearRect(0, 0, this.$canvas.width(), this.$canvas.height());

            this.offsetPixel = Math.round((tile.startBP - genomicState.startBP) / genomicState.bpp);
            if ('x' === this.axis) {
                this.ctx.drawImage(tile.buffer, this.offsetPixel, 0);
            } else {
                this.ctx.drawImage(tile.buffer, 0, this.offsetPixel);
            }

            // this.ctx.save();
            // this.ctx.restore();
        }
    };

    hic.TrackRenderer.prototype.startSpinner = function () {
        this.$spinner.show();
        this.throbber.start();
    };

    hic.TrackRenderer.prototype.stopSpinner = function () {
        // this.startSpinner();
        this.throbber.stop();
        this.$spinner.hide();
    };

    hic.TrackRenderer.prototype.isLoading = function () {
        return !(undefined === this.loading);
    };

    Tile = function (chr, startBP, endBP, bpp, buffer) {
        this.chr = chr;
        this.startBP = startBP;
        this.endBP = endBP;
        this.bpp = bpp;
        this.buffer = buffer;
    };

    Tile.prototype.containsRange = function (chr, startBP, endBP, bpp) {
        return this.bpp === bpp && startBP >= this.startBP && endBP <= this.endBP && chr === this.chr;
    };

    return hic;

})(hic || {});
<commit_msg>disable tile blasting when synching track canvas<commit_after>/**
 * Created by dat on 4/5/17.
 */
var hic = (function (hic) {

    hic.TrackRenderer = function (browser, size, $container, trackRenderPair, trackPair, axis, order) {

        this.browser = browser;

        this.trackRenderPair = trackRenderPair;

        this.track = trackPair[axis];

        this.id = _.uniqueId('trackRenderer_');
        this.axis = axis;
        this.initializationHelper($container, size, order);
    };

    hic.TrackRenderer.prototype.initializationHelper = function ($container, size, order) {

        var self = this,
            str,
            doShowLabelAndGear,
            $x_track_label,
            $x_track_menu_container;

        // track canvas container
        this.$viewport = ('x' === this.axis) ? $('
') : $('
');
        if (size.width) {
            this.$viewport.width(size.width);
        }
        if (size.height) {
            this.$viewport.height(size.height);
        }
        $container.append(this.$viewport);
        this.$viewport.css( { order:order } );

        // canvas
        this.$canvas = $('<canvas>');
        this.$viewport.append(this.$canvas);
        this.ctx = this.$canvas.get(0).getContext("2d");

        if ('x' === this.axis) {

            // label
            this.$label = $('
');
            str = this.track.name || 'untitled';
            this.$label.text(str);

            // note the pre-existing state of track labels/gear. hide/show accordingly.
            $x_track_label = $container.find(this.$label);
            doShowLabelAndGear = (0 === _.size($x_track_label)) ? true : $x_track_label.is(':visible');

            this.$viewport.append(this.$label);
        }

        // track spinner container
        this.$spinner = ('x' === this.axis) ? $('
') : $('
');
        this.$viewport.append(this.$spinner);

        // throbber
        // size: see $hic-viewport-spinner-size in .scss files
        this.throbber = Throbber({color: 'rgb(64, 64, 64)', size: 32, padding: 7});
        this.throbber.appendTo(this.$spinner.get(0));
        this.stopSpinner();

        if ('x' === this.axis) {

            this.$menu_container = $('
');
            this.$viewport.append(this.$menu_container);

            this.$menu_button = $('');
            this.$menu_container.append(this.$menu_button);

            this.$menu_button.click(function (e) {
                e.stopPropagation();
                igv.popover.presentTrackGearMenu(e.pageX, e.pageY, self);
            });

            this.$viewport.on('click', function (e) {

                e.stopPropagation();

                // self.$label.toggle();
                // self.$menu_container.toggle();

                $container.find('.x-track-label').toggle();
                $container.find('.x-track-menu-container').toggle();
            });

            if (doShowLabelAndGear) {
                this.$label.show();
                this.$menu_container.show();
            } else {
                this.$label.hide();
                this.$menu_container.hide();
            }

        }

        // compatibility with igv menus
        this.track.trackView = this;
        this.track.trackView.trackDiv = this.$viewport.get(0);

        this.configTrackTransforms();

    };

    hic.TrackRenderer.prototype.configTrackTransforms = function () {

        this.canvasTransform = ('y' === this.axis) ? hic.reflectionRotationWithContext : hic.identityTransformWithContext;

        this.labelReflectionTransform = ('y' === this.axis) ? hic.reflectionAboutYAxisAtOffsetWithContext : function (context, exe) { /* nuthin */
        };

    };

    hic.TrackRenderer.prototype.syncCanvas = function () {

      //  this.tile = null;

        this.$canvas.width(this.$viewport.width());
        this.$canvas.attr('width', this.$viewport.width());

        this.$canvas.height(this.$viewport.height());
        this.$canvas.attr('height', this.$viewport.height());

        igv.graphics.fillRect(this.ctx, 0, 0, this.$canvas.width(), this.$canvas.height(), {fillStyle: igv.rgbColor(255, 255, 255)});
    };

    hic.TrackRenderer.prototype.setColor = function (color) {

        _.each(this.trackRenderPair, function (trackRenderer) {
            trackRenderer.tile = undefined;
            trackRenderer.track.color = color;
        });

        this.browser.renderTrackXY(this.trackRenderPair);
    };

    hic.TrackRenderer.prototype.dataRange = function () {
        return this.track.dataRange ? this.track.dataRange : undefined;
    };

    hic.TrackRenderer.prototype.setDataRange = function (min, max, autoscale) {

        _.each(this.trackRenderPair, function (trackRenderer) {
            trackRenderer.tile = undefined;
            trackRenderer.track.dataRange = {min: min, max: max};
            trackRenderer.track.autscale = autoscale;
        });

        this.browser.renderTrackXY(this.trackRenderPair);

    };

    hic.TrackRenderer.prototype.repaint = function () {

        var self = this,
            lengthPixel,
            lengthBP,
            startBP,
            endBP,
            genomicState,
            chrName;

        genomicState = _.mapObject(self.browser.genomicState(), function (val) {
            return _.isObject(val) ? val[self.axis] : val;
        });

        if (/*this.$zoomInNotice &&*/ self.track.visibilityWindow && self.track.visibilityWindow > 0) {

            if ((genomicState.bpp * Math.max(self.$canvas.width(), self.$canvas.height()) > self.track.visibilityWindow) /*|| ('all' === genomicState.chromosome.name && !self.track.supportsWholeGenome)*/) {

                self.tile = undefined;
                self.ctx.clearRect(0, 0, self.$canvas.width(), self.$canvas.height());

                self.stopSpinner();
                // self.$zoomInNotice.show();

                return;

            } else {
                // self.$zoomInNotice.hide();
            }

        } // if (/*this.$zoomInNotice &&*/ self.track.visibilityWindow && self.track.visibilityWindow > 0)

        chrName = genomicState.chromosome.name;

        if (self.tile && self.tile.containsRange(chrName, genomicState.startBP, genomicState.endBP, genomicState.bpp)) {
            self.drawTileWithGenomicState(self.tile, genomicState);
            return;

        } else {

            // Expand the requested range so we can pan a bit without reloading
            lengthPixel = 3 * Math.max(self.$canvas.width(), self.$canvas.height());

            lengthBP = Math.round(genomicState.bpp * lengthPixel);

            startBP = Math.max(0, Math.round(genomicState.startBP - lengthBP / 3));

            endBP = startBP + lengthBP;

            if (self.loading) { //&& self.loading.start === startBP && self.loading.end === endBP) {
                return;
            } else {

                self.loading =
                {
                    start: startBP,
                    end: endBP
                };

                self.startSpinner();
                self.track
                    .getFeatures(genomicState.chromosome.name, startBP, endBP, genomicState.bpp)
                    .then(function (features) {

                        var buffer,
                            ctx;

                        self.loading = false;

                        self.stopSpinner();

                        buffer = document.createElement('canvas');
                        buffer.width = 'x' === self.axis ? lengthPixel : self.$canvas.width();
                        buffer.height = 'x' === self.axis ? self.$canvas.height() : lengthPixel;
                        ctx = buffer.getContext("2d");

                        if (features) {

                            self.canvasTransform(ctx);

                            self.drawConfiguration =
                            {
                                features: features,

                                context: ctx,

                                pixelWidth: lengthPixel,
                                pixelHeight: Math.min(buffer.width, buffer.height),

                                bpStart: startBP,
                                bpEnd: endBP,

                                bpPerPixel: genomicState.bpp,

                                genomicState: genomicState,

                                viewportContainerX: (genomicState.startBP - startBP) / genomicState.bpp,

                                viewportContainerWidth: Math.max(self.$canvas.width(), self.$canvas.height()),

                                labelTransform: self.labelReflectionTransform
                            };

                            self.track.draw(self.drawConfiguration);

                        } else {
                            ctx.clearRect(0, 0, self.$canvas.width(), self.$canvas.height());
                        }

                        self.tile = new Tile(chrName, startBP, endBP, genomicState.bpp, buffer);

                        self.repaint();

                    })
                    .catch(function (error) {

                        self.stopSpinner();
                        self.loading = false;
                        throw new Error(error);
                    });

            }
        }

    };

    hic.TrackRenderer.prototype.drawTileWithGenomicState = function (tile, genomicState) {

        if (tile) {

            this.ctx.clearRect(0, 0, this.$canvas.width(), this.$canvas.height());

            this.offsetPixel = Math.round((tile.startBP - genomicState.startBP) / genomicState.bpp);
            if ('x' === this.axis) {
                this.ctx.drawImage(tile.buffer, this.offsetPixel, 0);
            } else {
                this.ctx.drawImage(tile.buffer, 0, this.offsetPixel);
            }

            // this.ctx.save();
            // this.ctx.restore();
        }
    };

    hic.TrackRenderer.prototype.startSpinner = function () {
        this.$spinner.show();
        this.throbber.start();
    };

    hic.TrackRenderer.prototype.stopSpinner = function () {
        // this.startSpinner();
        this.throbber.stop();
        this.$spinner.hide();
    };

    hic.TrackRenderer.prototype.isLoading = function () {
        return !(undefined === this.loading);
    };

    Tile = function (chr, startBP, endBP, bpp, buffer) {
        this.chr = chr;
        this.startBP = startBP;
        this.endBP = endBP;
        this.bpp = bpp;
        this.buffer = buffer;
    };

    Tile.prototype.containsRange = function (chr, startBP, endBP, bpp) {
        return this.bpp === bpp && startBP >= this.startBP && endBP <= this.endBP && chr === this.chr;
    };

    return hic;

})(hic || {});
<|endoftext|>


<commit_before>(function ($, Drupal) {
	Drupal.behaviors.trunc_tooltip = {
		attach: function(context, settings) {
			var _this = this;

			if(Drupal.settings.trunc_tooltip) {
				$(settings.trunc_tooltip.selectors).once('truncate-tooltip-processed').each(function(idx, el) {
					el.addEventListener('mouseover', _this, false);
					el.addEventListener('mouseout', _this, false);
				});
			}
		},
		toolTip: null,
		buildToolTipSpan: function() {
			var toolTip = document.createElement('span'),
					_this = this;

			window.requestAnimationFrame(function() {
				toolTip.style.position = 'absolute';
				toolTip.style.zIndex = 999;
				toolTip.style.display = 'inline-block';
				toolTip.className += 'truncate-tooltip';
			});

			return toolTip;
		},
		handleEvent: function(e) {
			var el = e.target,
					text = el.innerHTML,
					bodyTag,
					posX = e.pageX + 5,
					posY = e.pageY + 5,
					_this = this;

			if(!_this.toolTip) {
					_this.toolTip = _this.buildToolTipSpan();
			}

			bodyTag = document.getElementsByTagName('body')[0];

			switch(e.type) {
				case 'mouseover':
					window.requestAnimationFrame(function() {
						_this.toolTip.style.top = posY + 'px';
						_this.toolTip.style.left = posX + 'px';
						_this.toolTip.innerHTML = text;
						bodyTag.appendChild(_this.toolTip);
					});
					break;
				case 'mouseout':
					window.requestAnimationFrame(function() {
						_this.toolTip.remove();
					});
					break
			}
		},
	};
})(jQuery, Drupal);<commit_msg>Readded check for el size<commit_after>(function ($, Drupal) {
	Drupal.behaviors.trunc_tooltip = {
		attach: function(context, settings) {
			var _this = this;

			if(Drupal.settings.trunc_tooltip) {
				$(settings.trunc_tooltip.selectors).once('truncate-tooltip-processed').each(function(idx, el) {
					el.addEventListener('mouseover', _this, false);
					el.addEventListener('mouseout', _this, false);
				});
			}
		},
		toolTip: null,
		buildToolTipSpan: function() {
			var toolTip = document.createElement('span'),
					_this = this;

			window.requestAnimationFrame(function() {
				toolTip.style.position = 'absolute';
				toolTip.style.zIndex = 999;
				toolTip.style.display = 'inline-block';
				toolTip.className += 'truncate-tooltip';
			});

			return toolTip;
		},
		handleEvent: function(e) {
			var el = e.target,
					text = el.innerHTML,
					bodyTag,
					posX = e.pageX + 5,
					posY = e.pageY + 5,
					_this = this;

			if(!_this.toolTip) {
					_this.toolTip = _this.buildToolTipSpan();
			}

			bodyTag = document.getElementsByTagName('body')[0];

			if(el.scrollWidth > el.clientWidth) {
				switch(e.type) {
					case 'mouseover':
						window.requestAnimationFrame(function() {
							_this.toolTip.style.top = posY + 'px';
							_this.toolTip.style.left = posX + 'px';
							_this.toolTip.innerHTML = text;
							bodyTag.appendChild(_this.toolTip);
						});
						break;
					case 'mouseout':
						window.requestAnimationFrame(function() {
							_this.toolTip.remove();
						});
						break
				}
			}
		},
	};
})(jQuery, Drupal);<|endoftext|>


<commit_before>/**
 * Mail
 *
 * This file is licensed under the Affero General Public License version 3 or
 * later. See the COPYING file.
 *
 * @author Christoph Wurst <christoph@winzerhof-wurst.at>
 * @copyright Christoph Wurst 2015, 2016
 */

define(function(require) {
	'use strict';

	var Handlebars = require('handlebars');
	var Marionette = require('marionette');
	var OC = require('OC');
	var Radio = require('radio');
	var FolderView = require('views/folder');
	var AccountTemplate = require('text!templates/account.html');

	var SHOW_COLLAPSED = Object.seal([
		'inbox',
		'flagged',
		'drafts'
	]);

	return Marionette.CompositeView.extend({
		collection: null,
		model: null,
		template: Handlebars.compile(AccountTemplate),
		templateHelpers: function() {
			var toggleCollapseMessage = this.collapsed ? t('mail', 'Show all folders') : t('mail', 'Collapse folders');
			return {
				isUnifiedInbox: this.model.get('accountId') === -1,
				toggleCollapseMessage: toggleCollapseMessage,
				hasMenu: this.model.get('accountId') !== -1,
				hasFolders: this.collection.length > 0
			};
		},
		collapsed: true,
		events: {
			'click .account-toggle-collapse': 'toggleCollapse',
			'click .app-navigation-entry-utils-menu-button button': 'toggleMenu',
			'click @ui.deleteButton': 'onDelete',
			'click @ui.settingsButton': 'showAccountSettings',
			'click @ui.email': 'onClick'
		},
		ui: {
			'email': '.mail-account-email',
			'menu': 'div.app-navigation-entry-menu',
			'deleteButton': 'button[class^="icon-delete"]',
			'settingsButton': 'button[class^="icon-rename"]'
		},
		// 'active' is needed to show the dotdotdot menu
		className: 'navigation-account',
		childView: FolderView,
		childViewContainer: '#mail_folders',
		menuShown: false,
		initialize: function(options) {
			this.model = options.model;
			this.collection = this.model.folders;
		},
		filter: function(child) {
			if (!this.collapsed) {
				return true;
			}
			var specialRole = child.get('specialRole');
			return SHOW_COLLAPSED.indexOf(specialRole) !== -1;
		},
		toggleCollapse: function() {
			this.collapsed = !this.collapsed;
			this.render();
		},
		toggleMenu: function(e) {
			e.preventDefault();
			this.menuShown = !this.menuShown;
			this.toggleMenuClass();
		},
		toggleMenuClass: function() {
			this.ui.menu.toggleClass('open', this.menuShown);
		},
		onDelete: function(e) {
			e.stopPropagation();

			this.ui.deleteButton.removeClass('icon-delete').addClass('icon-loading-small');

			var account = this.model;

			$.ajax(OC.generateUrl('/apps/mail/accounts/{accountId}'), {
				data: {accountId: account.get('accountId')},
				type: 'DELETE',
				success: function() {
					// Delete cached message lists
					require('cache').removeAccount(account);

					// reload the complete page
					// TODO should only reload the app nav/content
					window.location.reload();
				},
				error: function() {
					OC.Notification.show(t('mail', 'Error while deleting account.'));
				}
			});
		},
		onClick: function(e) {
			e.preventDefault();
			if (this.model.folders.length > 0) {
				var accountId = this.model.get('accountId');
				var folderId = this.model.folders.first().get('id');
				Radio.navigation.trigger('folder', accountId, folderId);
			}
		},
		onShow: function() {
			this.listenTo(Radio.ui, 'document:click', function(event) {
				var target = $(event.target);
				if (!this.$el.is(target.closest('.navigation-account'))) {
					// Click was not triggered by this element -> close menu
					this.menuShown = false;
					this.toggleMenuClass();
				}
			});
		},
		showAccountSettings: function(e) {
			this.toggleMenu(e);
			Radio.navigation.trigger('accountsettings', this.model.get('accountId'));

		}
	});
});
<commit_msg>also show Sent folder by default, fix #176<commit_after>/**
 * Mail
 *
 * This file is licensed under the Affero General Public License version 3 or
 * later. See the COPYING file.
 *
 * @author Christoph Wurst <christoph@winzerhof-wurst.at>
 * @copyright Christoph Wurst 2015, 2016
 */

define(function(require) {
	'use strict';

	var Handlebars = require('handlebars');
	var Marionette = require('marionette');
	var OC = require('OC');
	var Radio = require('radio');
	var FolderView = require('views/folder');
	var AccountTemplate = require('text!templates/account.html');

	var SHOW_COLLAPSED = Object.seal([
		'inbox',
		'flagged',
		'drafts',
		'sent'
	]);

	return Marionette.CompositeView.extend({
		collection: null,
		model: null,
		template: Handlebars.compile(AccountTemplate),
		templateHelpers: function() {
			var toggleCollapseMessage = this.collapsed ? t('mail', 'Show all folders') : t('mail', 'Collapse folders');
			return {
				isUnifiedInbox: this.model.get('accountId') === -1,
				toggleCollapseMessage: toggleCollapseMessage,
				hasMenu: this.model.get('accountId') !== -1,
				hasFolders: this.collection.length > 0
			};
		},
		collapsed: true,
		events: {
			'click .account-toggle-collapse': 'toggleCollapse',
			'click .app-navigation-entry-utils-menu-button button': 'toggleMenu',
			'click @ui.deleteButton': 'onDelete',
			'click @ui.settingsButton': 'showAccountSettings',
			'click @ui.email': 'onClick'
		},
		ui: {
			'email': '.mail-account-email',
			'menu': 'div.app-navigation-entry-menu',
			'deleteButton': 'button[class^="icon-delete"]',
			'settingsButton': 'button[class^="icon-rename"]'
		},
		// 'active' is needed to show the dotdotdot menu
		className: 'navigation-account',
		childView: FolderView,
		childViewContainer: '#mail_folders',
		menuShown: false,
		initialize: function(options) {
			this.model = options.model;
			this.collection = this.model.folders;
		},
		filter: function(child) {
			if (!this.collapsed) {
				return true;
			}
			var specialRole = child.get('specialRole');
			return SHOW_COLLAPSED.indexOf(specialRole) !== -1;
		},
		toggleCollapse: function() {
			this.collapsed = !this.collapsed;
			this.render();
		},
		toggleMenu: function(e) {
			e.preventDefault();
			this.menuShown = !this.menuShown;
			this.toggleMenuClass();
		},
		toggleMenuClass: function() {
			this.ui.menu.toggleClass('open', this.menuShown);
		},
		onDelete: function(e) {
			e.stopPropagation();

			this.ui.deleteButton.removeClass('icon-delete').addClass('icon-loading-small');

			var account = this.model;

			$.ajax(OC.generateUrl('/apps/mail/accounts/{accountId}'), {
				data: {accountId: account.get('accountId')},
				type: 'DELETE',
				success: function() {
					// Delete cached message lists
					require('cache').removeAccount(account);

					// reload the complete page
					// TODO should only reload the app nav/content
					window.location.reload();
				},
				error: function() {
					OC.Notification.show(t('mail', 'Error while deleting account.'));
				}
			});
		},
		onClick: function(e) {
			e.preventDefault();
			if (this.model.folders.length > 0) {
				var accountId = this.model.get('accountId');
				var folderId = this.model.folders.first().get('id');
				Radio.navigation.trigger('folder', accountId, folderId);
			}
		},
		onShow: function() {
			this.listenTo(Radio.ui, 'document:click', function(event) {
				var target = $(event.target);
				if (!this.$el.is(target.closest('.navigation-account'))) {
					// Click was not triggered by this element -> close menu
					this.menuShown = false;
					this.toggleMenuClass();
				}
			});
		},
		showAccountSettings: function(e) {
			this.toggleMenu(e);
			Radio.navigation.trigger('accountsettings', this.model.get('accountId'));

		}
	});
});
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

const VerticalTimeline = ({
  animate,
  className,
  layout,
  lineColor,
  children,
}) => {
  document.documentElement.style.setProperty('--line-color', lineColor);
  return (
    <div
      className={classNames(className, 'vertical-timeline', {
        'vertical-timeline--animate': animate,
        'vertical-timeline--two-columns': layout === '2-columns',
        'vertical-timeline--one-column-left':
          layout === '1-column' || layout === '1-column-left',
        'vertical-timeline--one-column-right': layout === '1-column-right',
      })}
    >
      {children}
    </div>
  );
};

VerticalTimeline.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(PropTypes.node),
    PropTypes.node,
  ]).isRequired,
  className: PropTypes.string,
  animate: PropTypes.bool,
  layout: PropTypes.oneOf([
    '1-column-left',
    '1-column',
    '2-columns',
    '1-column-right',
  ]),
  lineColor: PropTypes.string,
};

VerticalTimeline.defaultProps = {
  animate: true,
  className: '',
  layout: '2-columns',
  lineColor: '#FFF',
};

export default VerticalTimeline;
<commit_msg>Fix for SSR/SGR<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

const VerticalTimeline = ({
  animate,
  className,
  layout,
  lineColor,
  children,
}) => {
  if (typeof window === 'object') {
    document.documentElement.style.setProperty('--line-color', lineColor);
  }
  return (
    <div
      className={classNames(className, 'vertical-timeline', {
        'vertical-timeline--animate': animate,
        'vertical-timeline--two-columns': layout === '2-columns',
        'vertical-timeline--one-column-left':
          layout === '1-column' || layout === '1-column-left',
        'vertical-timeline--one-column-right': layout === '1-column-right',
      })}
    >
      {children}
    </div>
  );
};

VerticalTimeline.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(PropTypes.node),
    PropTypes.node,
  ]).isRequired,
  className: PropTypes.string,
  animate: PropTypes.bool,
  layout: PropTypes.oneOf([
    '1-column-left',
    '1-column',
    '2-columns',
    '1-column-right',
  ]),
  lineColor: PropTypes.string,
};

VerticalTimeline.defaultProps = {
  animate: true,
  className: '',
  layout: '2-columns',
  lineColor: '#FFF',
};

export default VerticalTimeline;
<|endoftext|>


<commit_before>var svg = {};
var vis = {};
var processInputMapping = {};
var processOutputMapping = {};
var isVariableOfMapping = {};
var outputByMapping = {};
var workflowURI = localStorage.getItem("workflow-uri");
getGraphJSON(workflowURI, function(res) {
    renderVisualization(res, false);
});

var renderVisualization = function (res, isArtifact) {
    document.getElementById('workflow-name').innerHTML
        = localStorage.getItem('workflow-label');
    d3.select("svg").remove();
    d3.select('.visualization-container').append('svg');
    var results = res['results']['bindings'];
    var processNodeIndices = {};
    var putNodeIndices = {};
    processInputMapping = {};
    processOutputMapping = {};
    isVariableOfMapping = {};
    outputByMapping = {};

    /*
        @params: string processName, string inputName
        - inserts the inputName to the list of inputs that the processName maps
        to within the object processInputMapping
    */
    var addInputProcess = function(processName, inputName) {
        processInputMapping[processName] = processInputMapping[processName] || [];
        processInputMapping[processName].push(inputName);
    }

    /*
        @params: string processName, string outputName
        - inserts the outputName to the list of outputs that the processName maps
        to within the object processOutputMapping
    */
    var addOutputProcess = function(processName, outputName) {
        processOutputMapping[processName] = processOutputMapping[processName] || [];
        processOutputMapping[processName].push(outputName);
    }

    var mapInputToProcess = function(inputName, processName) {
        isVariableOfMapping[inputName] = isVariableOfMapping[inputName] || [];

        isVariableOfMapping[inputName].push(processName);
    }

    var mapOutputFromProcess = function(outputName, processName) {
        outputByMapping[outputName] = outputByMapping[outputName] || [];

        outputByMapping[outputName].push(processName);
    }

    /*
        @params: dagreD3 graph
        - pulls from JSON result and sets nodes according to whether or not they are labeled as inputs, outputs, or processes
    */
    var mapNodesEdges = function(graph) {
        var j = 0;
        for (var i = 0; i < results.length; i++) {
            //get URI of step from JSON
            var step = results[i].hasOwnProperty('step') ? results[i]['step']['value'] : null;

            //add step to processNodeIndices if the step hasn't been added yet
            if (processNodeIndices[step] == null) {
                processNodeIndices[step] = j;
                //get readable display for step name
                var stepToDisplay = stripNameFromURI(step);
                stepToDisplay = stepToDisplay.substring(0, stepToDisplay.lastIndexOf('node')) == '' ? stepToDisplay : stepToDisplay.substring(0, stepToDisplay.lastIndexOf('node'));
                vis.setNode(j, {
                    shape: 'process',
                    label: stepToDisplay,
                    labelStyle: "fill: #000",
                    style: "fill: #FFCC99;",
                    uri: step,
                    type: 'process'
                });
                j++;
            }
            if (results[i].hasOwnProperty('input')) {
                //get URI of input from JSON
                var input = results[i]['input']['value'];
                if (putNodeIndices[input] == null) {
                    putNodeIndices[input] = j;
                    //get readable display for input name
                    var inputToDisplay = stripNameFromURI(input);
                    vis.setNode(j, {
                        label: inputToDisplay,
                        labelStyle: 'fill: #FFF',
                        shape: 'customEllipse',
                        style: 'fill: #003366;',
                        uri: input,
                        type: 'input'
                    });
                    j++;
                }
                addInputProcess(step, input);
                mapInputToProcess(input, step);
            } else if (results[i].hasOwnProperty('output')) {
                //get URI of output from JSON
                var output = results[i]['output']['value'];
                if (putNodeIndices[output] == null) {
                    putNodeIndices[output] = j;
                    //get readable display for output name
                    var outputToDisplay = stripNameFromURI(output);
                    vis.setNode(j, {
                        label: outputToDisplay,
                        labelStyle: "fill: #FFF",
                        shape: 'customEllipse',
                        style: "fill: #003366;",
                        uri: output,
                        type: 'output'
                    });
                    j++;
                }
                addOutputProcess(step, output);
                mapOutputFromProcess(output, step);
            }
        }
        setGraphEdges(vis);
    }

    /*
        @params: dagreD3 vis
        - connects nodes to each other via node numbers from processInputMapping
        and processOutputMapping
    */
    var setGraphEdges = function (vis) {
        for (var process in processInputMapping) {
            for (var i = 0; i < processInputMapping[process].length; i++) {
                vis.setEdge(putNodeIndices[processInputMapping[process][i]], processNodeIndices[process], {
                    style: "stroke: #000; fill:none"
                });
            }
        }

        for (var process in processOutputMapping) {
            for (var i = 0; i < processOutputMapping[process].length; i++) {
                vis.setEdge(processNodeIndices[process], putNodeIndices[processOutputMapping[process][i]], {
                    style: "stroke: #000; fill:none"
                });
            }
        }
        if (!isArtifact)
            formatInputs(vis, renderGraph);
        else {
//            addArtifacts()
            renderGraph(vis);
        }
    }

    var renderGraph = function(vis) {
        // Create the renderer
        var render = new dagreD3.render();

        // Add dimensions to nodes if there are any
        addDimensions(render);
        // Set up an SVG group so that we can translate the final graph.
        svg = d3.select("svg").attr('width','75%').attr('height','100%'), svgGroup = svg.append("g");

        // Set up zoom support
        var zoom = d3.behavior.zoom().on("zoom", function() {
            svgGroup.attr("transform", "translate(" + d3.event.translate + ")" +
                                        "scale(" + d3.event.scale + ")");
        });
        svg.call(zoom);

        // Run the renderer. This is what draws the final graph.
        render(svgGroup, vis);

        //centers graph and calculates top margin of graph based on screen size
        var xCenterOffset = (document.getElementsByClassName('visualization-container')[0].clientWidth / 2 - vis.graph().width) / 2;
        var yTopMargin = screen.height * .05;
        var scale = .75;
        zoom.translate([xCenterOffset, 20])
            .scale(scale)
            .event(svg);
        svg.attr('height', vis.graph().height * scale + yTopMargin);

        setupNodeOnClick(svg, vis);
    }

    /*

    */
    var formatInputs = function(vis, callback) {
        getInputs(workflowURI, function (inputs) {
            for (var i = 0; i < inputs.length; i++) {
                var nodeIndex = putNodeIndices[inputs[i].input.value];
                var newLabel = vis.node(nodeIndex).label;
                var newURI = vis.node(nodeIndex).uri;
                vis.setNode(nodeIndex, {
                    label: newLabel,
                    labelStyle: "fill: #FFF",
                    shape: 'customInputEllipse',
                    style: "fill: #336633;",
                    uri: newURI,
                    type: 'input'
                });
            }
            callback(vis);
        })
    }

    /*
        renders graph
    */
    vis = new dagreD3.graphlib.Graph()
        .setGraph({
            nodesep: 10,
            ranksep: 20,
        })
        .setDefaultEdgeLabel(function() {
            return {}
        });

    mapNodesEdges(vis);
}

var highlightHandler = function (checkbox) {
    console.log(checkbox.checked);
    highlightInputs(checkbox.checked);
}

var highlightInputs = function(checked) {
    if (checked) {
    } else {
        // make an array of objects- the objects contain a process URI

        // how can I know which checkbox is checked to highlight inputs?
    }
}

var addArtifacts = function(artifacts) {
    var select = document.getElementById("selection");

    var first = document.createElement("option");
    first.textContent = 'Select execution artifact';
    select.appendChild(first);
    for(var i = 0; i < artifacts.length; i++) {
        var opt = artifacts[i];
        var el = document.createElement("option");
        el.textContent = stripNameFromURI(opt.execution.value);
        el.value = opt.execution.value;
        select.appendChild(el);
    }

    select.addEventListener('change', function() {
        if (select.selectedIndex == 0)
            return;
        localStorage.setItem('workflow-uri', select.options[select.selectedIndex].value);
        getExecutionArtifacts(select.options[select.selectedIndex].value, function(res, executionID) {
            renderVisualization(res, true);
            getExecutionDetails(executionID, function(res) {
                setWorkflowMetadata(res);
            })
        })
    })
}

/*
    @params: d3 svg
    - setup on click process for each node
*/
var setupNodeOnClick = function (svg, vis) {
    //setup on click listeners for every node
    svg.selectAll("g.node").on('click', function(id) {
        var node = vis.node(id);
        if(d3.select(this).style('opacity') == 0.7) {
            d3.select(this).style('opacity','1.0');
            // TODO: remove chart of info for node, since it is being 'unselected'
        }
        else {
            d3.select(this).style('opacity', '0.7');
            // TODO: add chart of info for input/output nodes, since they are being 'selected'
            if (node.type == 'process') {
                addProcessInfo(node.uri, processInputMapping[node.uri], processOutputMapping[node.uri]);
            } else if (node.type == 'input') {
                addVariableInfo(node.uri, isVariableOfMapping[node.uri], outputByMapping[node.uri]);

            } else if (node.type == 'output') {
                addVariableInfo(node.uri, isVariableOfMapping[node.uri], outputByMapping[node.uri]);
            }
        }
    });
}

/*
    @params: string URI
    @return: a parsed, human-readable substring of the URI
*/
var stripNameFromURI = function(uri) {
    if (uri.indexOf('CE_') <= -1) {
        return uri.substring(uri.lastIndexOf('/')+1, uri.length-13).toLowerCase();
    }
    return uri.substring(uri.lastIndexOf('CE_')+3, uri.length).toLowerCase();
}

var addDimensions = function(render) {
    render.shapes().customEllipse = function(parent, bbox, node) {
        var rx = bbox.width/2,
            ry = bbox.height/2,
            shapeSvg = parent.insert("ellipse", ":first-child")
            .attr('x', -bbox.width/2)
            .attr('y', -bbox.height/2)
            .attr('rx', rx)
            .attr('ry', ry)
            .attr('style', 'fill: #003366');
        if (node.dimensions > 1) {
            for (var i = 1; i < node.dimensions; i++) {
                shapeSvg = parent.insert("ellipse", ":first-child")
                .attr('x', -bbox.width/2)
                .attr('y', -bbox.height/2)
                .attr('rx', rx)
                .attr('ry', ry)
                .attr('style', "fill: #FFF; stroke: #003366")
                .attr('transform', 'translate(' + 0 + ',' + (bbox.height/10)*i + ')' + 'scale(' + '1.0' + ')');
            }

            shapeSvg = parent.insert("ellipse", ":first-child")
                .attr('x', -bbox.width/2)
                .attr('y', -bbox.height/2)
                .attr('rx', rx)
                .attr('ry', ry)
                .attr('transform', 'translate(' + 0 + ',' + (bbox.height/10)*(node.dimensions) + ')' + 'scale(' + '1.0' + ')');
                node.style = "fill: #FFF; stroke: #003366";
        }

        node.intersect = function(point) {
            return dagreD3.intersect.ellipse(node, rx, ry, point);
        };
        return shapeSvg;
    };

    render.shapes().customInputEllipse = function(parent, bbox, node) {
        var rx = bbox.width/2,
            ry = bbox.height/2,
            shapeSvg = parent.insert("ellipse", ":first-child")
            .attr('x', -bbox.width/2)
            .attr('y', -bbox.height/2)
            .attr('rx', rx)
            .attr('ry', ry)
            .attr('style', 'fill: #336633');

        if (node.dimensions > 1) {
            for (var i = 1; i < node.dimensions; i++) {
                shapeSvg = parent.insert("ellipse", ":first-child")
                .attr('x', -bbox.width/2)
                .attr('y', -bbox.height/2)
                .attr('rx', rx)
                .attr('ry', ry)
                .attr('style', "fill: #FFF; stroke: #336633")
                .attr('transform', 'translate(' + 3*i + ',' + (bbox.height/10)*i + ')' + 'scale(' + '1.0' + ')');
            }
            shapeSvg = parent.insert("ellipse", ":first-child")
                .attr('x', -bbox.width/2)
                .attr('y', -bbox.height/2)
                .attr('rx', rx)
                .attr('ry', ry)
                .attr('transform', 'translate(' + 3*(node.dimensions) + ',' + (bbox.height/10)*(node.dimensions) + ')' + 'scale(' + '1.0' + ')');
                node.style = "fill: #FFF; stroke: #336633";
        }

        node.intersect = function(point) {
            return dagreD3.intersect.ellipse(node, rx, ry, point);
        };
        return shapeSvg;
    };

    render.shapes().process = function(parent, bbox, node) {
        var width = bbox.width,
            height = bbox.height,
            shapeSvg = parent.insert('rect', ':first-child')
                .attr('rx', node.rx)
                .attr('ry', node.ry)
                .attr('x', -width/2)
                .attr('y', -height/2)
                .attr('width', width)
                .attr('height', height)
                .attr('style', 'fill: #FFCC99;');

        for (var i = 1; i < node.dimensions; i++) {
            shapeSvg = parent.insert('rect', ':first-child')
                .attr('rx', node.rx)
                .attr('ry', node.ry)
                .attr('x', -width/2 + (5*i))
                .attr('y', -height/2 + (5*i))
                .attr('width', width)
                .attr('height', height)
                .attr('style', 'fill: #FFCC99;');
        }
        node.intersect = function(point) {
            return dagreD3.intersect.rect(node, point);
        }
        return shapeSvg;
    }
}<commit_msg>specify input output for addVariableInfo<commit_after>var svg = {};
var vis = {};
var processInputMapping = {};
var processOutputMapping = {};
var isVariableOfMapping = {};
var outputByMapping = {};
var workflowURI = localStorage.getItem("workflow-uri");
getGraphJSON(workflowURI, function(res) {
    renderVisualization(res, false);
});

var renderVisualization = function (res, isArtifact) {
    document.getElementById('workflow-name').innerHTML
        = localStorage.getItem('workflow-label');
    d3.select("svg").remove();
    d3.select('.visualization-container').append('svg');
    var results = res['results']['bindings'];
    var processNodeIndices = {};
    var putNodeIndices = {};
    processInputMapping = {};
    processOutputMapping = {};
    isVariableOfMapping = {};
    outputByMapping = {};

    /*
        @params: string processName, string inputName
        - inserts the inputName to the list of inputs that the processName maps
        to within the object processInputMapping
    */
    var addInputProcess = function(processName, inputName) {
        processInputMapping[processName] = processInputMapping[processName] || [];
        processInputMapping[processName].push(inputName);
    }

    /*
        @params: string processName, string outputName
        - inserts the outputName to the list of outputs that the processName maps
        to within the object processOutputMapping
    */
    var addOutputProcess = function(processName, outputName) {
        processOutputMapping[processName] = processOutputMapping[processName] || [];
        processOutputMapping[processName].push(outputName);
    }

    var mapInputToProcess = function(inputName, processName) {
        isVariableOfMapping[inputName] = isVariableOfMapping[inputName] || [];

        isVariableOfMapping[inputName].push(processName);
    }

    var mapOutputFromProcess = function(outputName, processName) {
        outputByMapping[outputName] = outputByMapping[outputName] || [];

        outputByMapping[outputName].push(processName);
    }

    /*
        @params: dagreD3 graph
        - pulls from JSON result and sets nodes according to whether or not they are labeled as inputs, outputs, or processes
    */
    var mapNodesEdges = function(graph) {
        var j = 0;
        for (var i = 0; i < results.length; i++) {
            //get URI of step from JSON
            var step = results[i].hasOwnProperty('step') ? results[i]['step']['value'] : null;

            //add step to processNodeIndices if the step hasn't been added yet
            if (processNodeIndices[step] == null) {
                processNodeIndices[step] = j;
                //get readable display for step name
                var stepToDisplay = stripNameFromURI(step);
                stepToDisplay = stepToDisplay.substring(0, stepToDisplay.lastIndexOf('node')) == '' ? stepToDisplay : stepToDisplay.substring(0, stepToDisplay.lastIndexOf('node'));
                vis.setNode(j, {
                    shape: 'process',
                    label: stepToDisplay,
                    labelStyle: "fill: #000",
                    style: "fill: #FFCC99;",
                    uri: step,
                    type: 'process'
                });
                j++;
            }
            if (results[i].hasOwnProperty('input')) {
                //get URI of input from JSON
                var input = results[i]['input']['value'];
                if (putNodeIndices[input] == null) {
                    putNodeIndices[input] = j;
                    //get readable display for input name
                    var inputToDisplay = stripNameFromURI(input);
                    vis.setNode(j, {
                        label: inputToDisplay,
                        labelStyle: 'fill: #FFF',
                        shape: 'customEllipse',
                        style: 'fill: #003366;',
                        uri: input,
                        type: 'input'
                    });
                    j++;
                }
                addInputProcess(step, input);
                mapInputToProcess(input, step);
            } else if (results[i].hasOwnProperty('output')) {
                //get URI of output from JSON
                var output = results[i]['output']['value'];
                if (putNodeIndices[output] == null) {
                    putNodeIndices[output] = j;
                    //get readable display for output name
                    var outputToDisplay = stripNameFromURI(output);
                    vis.setNode(j, {
                        label: outputToDisplay,
                        labelStyle: "fill: #FFF",
                        shape: 'customEllipse',
                        style: "fill: #003366;",
                        uri: output,
                        type: 'output'
                    });
                    j++;
                }
                addOutputProcess(step, output);
                mapOutputFromProcess(output, step);
            }
        }
        setGraphEdges(vis);
    }

    /*
        @params: dagreD3 vis
        - connects nodes to each other via node numbers from processInputMapping
        and processOutputMapping
    */
    var setGraphEdges = function (vis) {
        for (var process in processInputMapping) {
            for (var i = 0; i < processInputMapping[process].length; i++) {
                vis.setEdge(putNodeIndices[processInputMapping[process][i]], processNodeIndices[process], {
                    style: "stroke: #000; fill:none"
                });
            }
        }

        for (var process in processOutputMapping) {
            for (var i = 0; i < processOutputMapping[process].length; i++) {
                vis.setEdge(processNodeIndices[process], putNodeIndices[processOutputMapping[process][i]], {
                    style: "stroke: #000; fill:none"
                });
            }
        }
        if (!isArtifact)
            formatInputs(vis, renderGraph);
        else {
//            addArtifacts()
            renderGraph(vis);
        }
    }

    var renderGraph = function(vis) {
        // Create the renderer
        var render = new dagreD3.render();

        // Add dimensions to nodes if there are any
        addDimensions(render);
        // Set up an SVG group so that we can translate the final graph.
        svg = d3.select("svg").attr('width','75%').attr('height','100%'), svgGroup = svg.append("g");

        // Set up zoom support
        var zoom = d3.behavior.zoom().on("zoom", function() {
            svgGroup.attr("transform", "translate(" + d3.event.translate + ")" +
                                        "scale(" + d3.event.scale + ")");
        });
        svg.call(zoom);

        // Run the renderer. This is what draws the final graph.
        render(svgGroup, vis);

        //centers graph and calculates top margin of graph based on screen size
        var xCenterOffset = (document.getElementsByClassName('visualization-container')[0].clientWidth / 2 - vis.graph().width) / 2;
        var yTopMargin = screen.height * .05;
        var scale = .75;
        zoom.translate([xCenterOffset, 20])
            .scale(scale)
            .event(svg);
        svg.attr('height', vis.graph().height * scale + yTopMargin);

        setupNodeOnClick(svg, vis);
    }

    /*

    */
    var formatInputs = function(vis, callback) {
        getInputs(workflowURI, function (inputs) {
            for (var i = 0; i < inputs.length; i++) {
                var nodeIndex = putNodeIndices[inputs[i].input.value];
                var newLabel = vis.node(nodeIndex).label;
                var newURI = vis.node(nodeIndex).uri;
                vis.setNode(nodeIndex, {
                    label: newLabel,
                    labelStyle: "fill: #FFF",
                    shape: 'customInputEllipse',
                    style: "fill: #336633;",
                    uri: newURI,
                    type: 'input'
                });
            }
            callback(vis);
        })
    }

    /*
        renders graph
    */
    vis = new dagreD3.graphlib.Graph()
        .setGraph({
            nodesep: 10,
            ranksep: 20,
        })
        .setDefaultEdgeLabel(function() {
            return {}
        });

    mapNodesEdges(vis);
}

var highlightHandler = function (checkbox) {
    console.log(checkbox.checked);
    highlightInputs(checkbox.checked);
}

var highlightInputs = function(checked) {
    if (checked) {
    } else {
        // make an array of objects- the objects contain a process URI

        // how can I know which checkbox is checked to highlight inputs?
    }
}

var addArtifacts = function(artifacts) {
    var select = document.getElementById("selection");

    var first = document.createElement("option");
    first.textContent = 'Select execution artifact';
    select.appendChild(first);
    for(var i = 0; i < artifacts.length; i++) {
        var opt = artifacts[i];
        var el = document.createElement("option");
        el.textContent = stripNameFromURI(opt.execution.value);
        el.value = opt.execution.value;
        select.appendChild(el);
    }

    select.addEventListener('change', function() {
        if (select.selectedIndex == 0)
            return;
        localStorage.setItem('workflow-uri', select.options[select.selectedIndex].value);
        getExecutionArtifacts(select.options[select.selectedIndex].value, function(res, executionID) {
            renderVisualization(res, true);
            getExecutionDetails(executionID, function(res) {
                setWorkflowMetadata(res);
            })
        })
    })
}

/*
    @params: d3 svg
    - setup on click process for each node
*/
var setupNodeOnClick = function (svg, vis) {
    //setup on click listeners for every node
    svg.selectAll("g.node").on('click', function(id) {
        var node = vis.node(id);
        if(d3.select(this).style('opacity') == 0.7) {
            d3.select(this).style('opacity','1.0');
            // TODO: remove chart of info for node, since it is being 'unselected'
        }
        else {
            d3.select(this).style('opacity', '0.7');
            // TODO: add chart of info for input/output nodes, since they are being 'selected'
            if (node.type == 'process') {
                addProcessInfo(node.uri, processInputMapping[node.uri], processOutputMapping[node.uri]);
            } else if (node.type == 'input') {
                addVariableInfo(node.uri, isVariableOfMapping[node.uri], outputByMapping[node.uri], 'input');

            } else if (node.type == 'output') {
                addVariableInfo(node.uri, isVariableOfMapping[node.uri], outputByMapping[node.uri], 'output');
            }
        }
    });
}

/*
    @params: string URI
    @return: a parsed, human-readable substring of the URI
*/
var stripNameFromURI = function(uri) {
    if (uri.indexOf('CE_') <= -1) {
        return uri.substring(uri.lastIndexOf('/')+1, uri.length-13).toLowerCase();
    }
    return uri.substring(uri.lastIndexOf('CE_')+3, uri.length).toLowerCase();
}

var addDimensions = function(render) {
    render.shapes().customEllipse = function(parent, bbox, node) {
        var rx = bbox.width/2,
            ry = bbox.height/2,
            shapeSvg = parent.insert("ellipse", ":first-child")
            .attr('x', -bbox.width/2)
            .attr('y', -bbox.height/2)
            .attr('rx', rx)
            .attr('ry', ry)
            .attr('style', 'fill: #003366');
        if (node.dimensions > 1) {
            for (var i = 1; i < node.dimensions; i++) {
                shapeSvg = parent.insert("ellipse", ":first-child")
                .attr('x', -bbox.width/2)
                .attr('y', -bbox.height/2)
                .attr('rx', rx)
                .attr('ry', ry)
                .attr('style', "fill: #FFF; stroke: #003366")
                .attr('transform', 'translate(' + 0 + ',' + (bbox.height/10)*i + ')' + 'scale(' + '1.0' + ')');
            }

            shapeSvg = parent.insert("ellipse", ":first-child")
                .attr('x', -bbox.width/2)
                .attr('y', -bbox.height/2)
                .attr('rx', rx)
                .attr('ry', ry)
                .attr('transform', 'translate(' + 0 + ',' + (bbox.height/10)*(node.dimensions) + ')' + 'scale(' + '1.0' + ')');
                node.style = "fill: #FFF; stroke: #003366";
        }

        node.intersect = function(point) {
            return dagreD3.intersect.ellipse(node, rx, ry, point);
        };
        return shapeSvg;
    };

    render.shapes().customInputEllipse = function(parent, bbox, node) {
        var rx = bbox.width/2,
            ry = bbox.height/2,
            shapeSvg = parent.insert("ellipse", ":first-child")
            .attr('x', -bbox.width/2)
            .attr('y', -bbox.height/2)
            .attr('rx', rx)
            .attr('ry', ry)
            .attr('style', 'fill: #336633');

        if (node.dimensions > 1) {
            for (var i = 1; i < node.dimensions; i++) {
                shapeSvg = parent.insert("ellipse", ":first-child")
                .attr('x', -bbox.width/2)
                .attr('y', -bbox.height/2)
                .attr('rx', rx)
                .attr('ry', ry)
                .attr('style', "fill: #FFF; stroke: #336633")
                .attr('transform', 'translate(' + 3*i + ',' + (bbox.height/10)*i + ')' + 'scale(' + '1.0' + ')');
            }
            shapeSvg = parent.insert("ellipse", ":first-child")
                .attr('x', -bbox.width/2)
                .attr('y', -bbox.height/2)
                .attr('rx', rx)
                .attr('ry', ry)
                .attr('transform', 'translate(' + 3*(node.dimensions) + ',' + (bbox.height/10)*(node.dimensions) + ')' + 'scale(' + '1.0' + ')');
                node.style = "fill: #FFF; stroke: #336633";
        }

        node.intersect = function(point) {
            return dagreD3.intersect.ellipse(node, rx, ry, point);
        };
        return shapeSvg;
    };

    render.shapes().process = function(parent, bbox, node) {
        var width = bbox.width,
            height = bbox.height,
            shapeSvg = parent.insert('rect', ':first-child')
                .attr('rx', node.rx)
                .attr('ry', node.ry)
                .attr('x', -width/2)
                .attr('y', -height/2)
                .attr('width', width)
                .attr('height', height)
                .attr('style', 'fill: #FFCC99;');

        for (var i = 1; i < node.dimensions; i++) {
            shapeSvg = parent.insert('rect', ':first-child')
                .attr('rx', node.rx)
                .attr('ry', node.ry)
                .attr('x', -width/2 + (5*i))
                .attr('y', -height/2 + (5*i))
                .attr('width', width)
                .attr('height', height)
                .attr('style', 'fill: #FFCC99;');
        }
        node.intersect = function(point) {
            return dagreD3.intersect.rect(node, point);
        }
        return shapeSvg;
    }
}<|endoftext|>