<commit_before>/* eslint-env node */
/* eslint-disable no-console */

import pth from 'path'
import shell from 'shelljs'
import chalk from 'chalk'
import fs from 'fs'
import PhenylModuleGraph from './lib/phenyl-module-graph.js'
import type { PackageJSONsByName } from './lib/phenyl-module-graph.js'
import type { BumpType } from './lib/phenyl-module-graph'

const rootPath = pth.dirname(__dirname)

class CLI {
  constructor() {
    const rootPackageJson = require(rootPath + '/package.json')
    const packageJsonsByName = loadPackageJsons(rootPath + '/modules')
    const examplePackageJsonsByName = loadPackageJsons(rootPath + '/examples')
    this.graph = new PhenylModuleGraph(rootPath, rootPackageJson, packageJsonsByName, examplePackageJsonsByName)
  }

  bump(moduleName: string, bumpType: BumpType) {
    const phenylModulesByName = this.graph.bumpVersion(moduleName, bumpType)
    Object.keys(phenylModulesByName).forEach(name => {
      const phenylModule = phenylModulesByName[name]
      const pathToModule = __dirname + `/../modules/${name}`
      const packagejson = JSON.parse(fs.readFileSync(pathToModule + '/package.json', 'utf-8'))
      const oldVersion = packagejson.version
      const newVersion = phenylModule.version
      packagejson.version = newVersion
      fs.writeFileSync(pathToModule + '/package.json', JSON.stringify(packagejson, null, '  '), 'utf-8')

      if (bumpType === 'patch') {
        this.commitAndTag(oldVersion, newVersion, moduleName, pathToModule)
        this.publish(`v${newVersion}`)
      }
    })
  }

  createGitTag(moduleName, version) {
    return `${moduleName}-v${version}`
  }

  commitAndTag(oldVersion: string, newVersion: string, moduleName: string, pathToModule: string) {
    shell.exec(`git commit -am ':bookmark: Release ${moduleName}'`)
    shell.exec('git push origin master')
    const oldTag = this.createGitTag(moduleName, oldVersion)
    const newTag = this.createGitTag(moduleName, newVersion)

    const releaseNote = shell.exec(`git log --oneline --no-merges ${oldTag}...master ${pathToModule}`).stdout
    shell.exec(`git tag -a ${newTag} -m ${releaseNote}`)
    shell.exec(`git push origin ${newTag}`)
  }

  publish(tag: string) {
    shell.exec(`npm publish --tag ${tag}`)
  }

  clean() {
    this.graph.phenylModules.forEach(phenylModule => {
      const { name, modulePath } = phenylModule
      console.log(chalk.cyan(`\n[${name}] start clean`))
      shell.rm('-rf', `${modulePath}/node_modules`, `${modulePath}/dist`, `${modulePath}/package-lock.json`)
      console.log(chalk.green(`[${name}] ✓ clean done`))
    })

    this.graph.exampleModules.forEach(exampleModule => {
      const { name, modulePath } = exampleModule
      console.log(chalk.cyan(`\n[${name}] start clean`))
      shell.rm('-rf', `${modulePath}/node_modules`, `${modulePath}/dist`, `${modulePath}/package-lock.json`)
      console.log(chalk.green(`[${name}] ✓ clean done`))
    })
  }

  test() {
    const failedModules = []

    this.graph.phenylModules.forEach(phenylModule => {
      const { name, modulePath, scripts } = phenylModule
      console.log(chalk.cyan(`\n[${name}] start test`))

      if (scripts && Object.keys(scripts).includes('test')) {
        shell.cd(modulePath)
        if (shell.exec('npm test --color always').code !== 0) {
          failedModules.push(name)
        }
        shell.cd(rootPath)
      }
      else {
        shell.echo(`no test specified in ${name}`)
      }
    })

    console.log(
      chalk.cyan('-------------------\n') +
      chalk.cyan('test summary\n') +
      chalk.cyan('-------------------')
    )

    if (failedModules.length > 0) {
      console.log(
        chalk.red('☓ Tests failed in The following modules\n') +
        '\n' +
        failedModules.join('\n')
      )
      process.exit(1)
    } else {
      console.log(chalk.green('✓ Tests passed in all modules!'))
    }
  }

  load() {
    this.graph.phenylModules.forEach(installSubModules)
    this.graph.exampleModules.forEach(installSubModules)
  }

  build() {
    this.graph.phenylModules.forEach(phenylModule => {
      const { modulePath } = phenylModule
      shell.exec(`BABEL_ENV=build babel ${modulePath}/src -d ${modulePath}/dist`)
    })
  }
}

const cli = new CLI()

const command = process.argv[2]
const moduleName = process.argv[3]

switch(command) {
  case 'build':
    cli.build()
    break
  case 'load':
    cli.load()
    break
  case 'test':
    cli.test()
    break
  case 'clean':
    cli.clean()
    break
  case 'bump:major':
    if (!moduleName) throw new Error('specify moduleName to bump version')
    cli.bump(moduleName, 'major')
    break
  case 'bump:minor':
    if (!moduleName) throw new Error('specify moduleName to bump version')
    cli.bump(moduleName, 'minor')
    break
  case 'bump:patch':
    if (!moduleName) throw new Error('specify moduleName to bump version')
    cli.bump(moduleName, 'patch')
    break
  default:
    throw new Error(`unknown command: ${command}`)
}

function loadPackageJsons(path: string): PackageJSONsByName {
  const moduleNames = fs.readdirSync(path).filter(moduleName => fs.statSync(path + '/' + moduleName).isDirectory())
  const packageJsonsByName = {}
  moduleNames.forEach(moduleName => {
    // $FlowIssue(load-package.json)
    packageJsonsByName[moduleName] = require(`${path}/${moduleName}/package.json`)
  })
  return packageJsonsByName
}

function installSubModules(phenylModule) {
  const { name, modulePath } = phenylModule
  console.log(chalk.cyan(`[${name}] start install.`))

  const { dependingModuleNames, commonModuleNames } = phenylModule
  dependingModuleNames.forEach(dependingModuleName => {
    const dependingModulePath = `${rootPath}/modules/${dependingModuleName}`
    const relative = pth.relative(modulePath + '/node_modules', dependingModulePath)

    shell.mkdir('-p', `${modulePath}/node_modules`)
    shell.cd(`${modulePath}/node_modules`)
    shell.ln('-sf', relative, `${dependingModuleName}`)
    shell.cd(rootPath)
  })

  commonModuleNames.forEach(commonModuleName => {
    shell.mkdir('-p', `${modulePath}/node_modules`)
    shell.cd(`${modulePath}/node_modules`)
    shell.ln('-sf', `../../../node_modules/${commonModuleName}`, `${commonModuleName}`)
    shell.cd(rootPath)
  })

  shell.mkdir('-p', `${modulePath}/node_modules/.bin`)
  shell.cd(`${modulePath}/node_modules/.bin`)
  shell.ln('-sf', '../../../../node_modules/.bin/kocha', 'kocha')

  shell.cd(modulePath)
  shell.exec('npm install --color always --loglevel=error')
  shell.rm('-f', `${modulePath}/package-lock.json`)
  shell.cd(rootPath)
  console.log(chalk.green(`[${name}] ✓ install done.\n`))
}
<commit_msg>Don't release in bump:patch<commit_after>/* eslint-env node */
/* eslint-disable no-console */

import pth from 'path'
import shell from 'shelljs'
import chalk from 'chalk'
import fs from 'fs'
import PhenylModuleGraph from './lib/phenyl-module-graph.js'
import type { PackageJSONsByName } from './lib/phenyl-module-graph.js'
import type { BumpType } from './lib/phenyl-module-graph'

const rootPath = pth.dirname(__dirname)

class CLI {
  constructor() {
    const rootPackageJson = require(rootPath + '/package.json')
    const packageJsonsByName = loadPackageJsons(rootPath + '/modules')
    const examplePackageJsonsByName = loadPackageJsons(rootPath + '/examples')
    this.graph = new PhenylModuleGraph(rootPath, rootPackageJson, packageJsonsByName, examplePackageJsonsByName)
  }

  bump(moduleName: string, bumpType: BumpType) {
    const phenylModulesByName = this.graph.bumpVersion(moduleName, bumpType)
    Object.keys(phenylModulesByName).forEach(name => {
      const phenylModule = phenylModulesByName[name]
      const pathToModule = __dirname + `/../modules/${name}`
      const packagejson = JSON.parse(fs.readFileSync(pathToModule + '/package.json', 'utf-8'))
      const oldVersion = packagejson.version
      const newVersion = phenylModule.version
      packagejson.version = newVersion
      fs.writeFileSync(pathToModule + '/package.json', JSON.stringify(packagejson, null, '  '), 'utf-8')
    })
  }

  createGitTag(moduleName, version) {
    return `${moduleName}-v${version}`
  }

  commitAndTag(oldVersion: string, newVersion: string, moduleName: string, pathToModule: string) {
    shell.exec(`git commit -am ':bookmark: Release ${moduleName}'`)
    shell.exec('git push origin master')
    const oldTag = this.createGitTag(moduleName, oldVersion)
    const newTag = this.createGitTag(moduleName, newVersion)

    const releaseNote = shell.exec(`git log --oneline --no-merges ${oldTag}...master ${pathToModule}`).stdout
    shell.exec(`git tag -a ${newTag} -m ${releaseNote}`)
    shell.exec(`git push origin ${newTag}`)
  }

  publish(tag: string) {
    shell.exec(`npm publish --tag ${tag}`)
  }

  clean() {
    this.graph.phenylModules.forEach(phenylModule => {
      const { name, modulePath } = phenylModule
      console.log(chalk.cyan(`\n[${name}] start clean`))
      shell.rm('-rf', `${modulePath}/node_modules`, `${modulePath}/dist`, `${modulePath}/package-lock.json`)
      console.log(chalk.green(`[${name}] ✓ clean done`))
    })

    this.graph.exampleModules.forEach(exampleModule => {
      const { name, modulePath } = exampleModule
      console.log(chalk.cyan(`\n[${name}] start clean`))
      shell.rm('-rf', `${modulePath}/node_modules`, `${modulePath}/dist`, `${modulePath}/package-lock.json`)
      console.log(chalk.green(`[${name}] ✓ clean done`))
    })
  }

  test() {
    const failedModules = []

    this.graph.phenylModules.forEach(phenylModule => {
      const { name, modulePath, scripts } = phenylModule
      console.log(chalk.cyan(`\n[${name}] start test`))

      if (scripts && Object.keys(scripts).includes('test')) {
        shell.cd(modulePath)
        if (shell.exec('npm test --color always').code !== 0) {
          failedModules.push(name)
        }
        shell.cd(rootPath)
      }
      else {
        shell.echo(`no test specified in ${name}`)
      }
    })

    console.log(
      chalk.cyan('-------------------\n') +
      chalk.cyan('test summary\n') +
      chalk.cyan('-------------------')
    )

    if (failedModules.length > 0) {
      console.log(
        chalk.red('☓ Tests failed in The following modules\n') +
        '\n' +
        failedModules.join('\n')
      )
      process.exit(1)
    } else {
      console.log(chalk.green('✓ Tests passed in all modules!'))
    }
  }

  load() {
    this.graph.phenylModules.forEach(installSubModules)
    this.graph.exampleModules.forEach(installSubModules)
  }

  build() {
    this.graph.phenylModules.forEach(phenylModule => {
      const { modulePath } = phenylModule
      shell.exec(`BABEL_ENV=build babel ${modulePath}/src -d ${modulePath}/dist`)
    })
  }
}

const cli = new CLI()

const command = process.argv[2]
const moduleName = process.argv[3]

switch(command) {
  case 'build':
    cli.build()
    break
  case 'load':
    cli.load()
    break
  case 'test':
    cli.test()
    break
  case 'clean':
    cli.clean()
    break
  case 'bump:major':
    if (!moduleName) throw new Error('specify moduleName to bump version')
    cli.bump(moduleName, 'major')
    break
  case 'bump:minor':
    if (!moduleName) throw new Error('specify moduleName to bump version')
    cli.bump(moduleName, 'minor')
    break
  case 'bump:patch':
    if (!moduleName) throw new Error('specify moduleName to bump version')
    cli.bump(moduleName, 'patch')
    break
  default:
    throw new Error(`unknown command: ${command}`)
}

function loadPackageJsons(path: string): PackageJSONsByName {
  const moduleNames = fs.readdirSync(path).filter(moduleName => fs.statSync(path + '/' + moduleName).isDirectory())
  const packageJsonsByName = {}
  moduleNames.forEach(moduleName => {
    // $FlowIssue(load-package.json)
    packageJsonsByName[moduleName] = require(`${path}/${moduleName}/package.json`)
  })
  return packageJsonsByName
}

function installSubModules(phenylModule) {
  const { name, modulePath } = phenylModule
  console.log(chalk.cyan(`[${name}] start install.`))

  const { dependingModuleNames, commonModuleNames } = phenylModule
  dependingModuleNames.forEach(dependingModuleName => {
    const dependingModulePath = `${rootPath}/modules/${dependingModuleName}`
    const relative = pth.relative(modulePath + '/node_modules', dependingModulePath)

    shell.mkdir('-p', `${modulePath}/node_modules`)
    shell.cd(`${modulePath}/node_modules`)
    shell.ln('-sf', relative, `${dependingModuleName}`)
    shell.cd(rootPath)
  })

  commonModuleNames.forEach(commonModuleName => {
    shell.mkdir('-p', `${modulePath}/node_modules`)
    shell.cd(`${modulePath}/node_modules`)
    shell.ln('-sf', `../../../node_modules/${commonModuleName}`, `${commonModuleName}`)
    shell.cd(rootPath)
  })

  shell.mkdir('-p', `${modulePath}/node_modules/.bin`)
  shell.cd(`${modulePath}/node_modules/.bin`)
  shell.ln('-sf', '../../../../node_modules/.bin/kocha', 'kocha')

  shell.cd(modulePath)
  shell.exec('npm install --color always --loglevel=error')
  shell.rm('-f', `${modulePath}/package-lock.json`)
  shell.cd(rootPath)
  console.log(chalk.green(`[${name}] ✓ install done.\n`))
}
<|endoftext|>


<commit_before>'use strict';

var glob = require('glob');
var path = require('path');
var fs = require('fs');

var makeTree = function (files) {
	var tree = {};

	for (var i = 0; i < files.length; i++) {
		var file = files[i];
		var parts = file.split('/');
		var branch = tree;
		for (var j = 0; j < parts.length; j++) {
			var part = parts[j];
			if (j === parts.length - 1) {
				branch[part] = file;
				break;
			}
			if (!branch[part]) {
				branch[part] = {};
			}
			branch = branch[part];
		}
	}

	return tree;
};

var printTree = function (tree) {
	var ret = '
\n';

	for (var branch in tree) {
		var link = tree[branch];
		ret += '
';
		if (typeof link === 'string') {
			ret += '' + branch + '';
		} else {
			ret += branch;
			ret += printTree(link);
		}
		ret += '
\n';
	}

	ret += '
\n';

	return ret;
};

exports.getFiles = function (path, callback) {
	return glob(path + '/**/!(index).html', function (err, files) {
		return callback(err, files);
	});
};

exports.getFilesSync = function (path) {
	return glob.sync(path + '/**/!(index).html');
};

exports.run = function (rootPath, title) {
	var files = exports.getFilesSync(rootPath);
	files = files.filter(function (fileName) {
		return fileName.indexOf('carousel') === -1;
	});

	for (var i = 0; i < files.length; i++) {
		var file = files[i];
		files[i] = path.relative(rootPath, file);
	}

	var tree = makeTree(files);

	var content = '';

	content += [
		'',
		'',
		'<title>' + title + '</title>',
		'<link rel="stylesheet" type="text/css" href="style.css">',
		'',
		'',
		'
',
		'
Contents
'
	].join('\n');

	content += printTree(tree);

	content += [
		'
',
		'',
		''
	].join('\n');

	fs.writeFileSync(path.resolve(rootPath + '/index.html'), content);
};
<commit_msg>Fixed small toc generation bug<commit_after>'use strict';

var glob = require('glob');
var path = require('path');
var fs = require('fs');

var makeTree = function (files) {
	var tree = {};

	for (var i = 0; i < files.length; i++) {
		var file = files[i];
		var parts = file.split('/');
		var branch = tree;
		for (var j = 0; j < parts.length; j++) {
			var part = parts[j];
			if (j === parts.length - 1) {
				branch[part] = file;
				break;
			}
			if (!branch[part]) {
				branch[part] = {};
			}
			branch = branch[part];
		}
	}

	return tree;
};

var printTree = function (tree) {
	var ret = '
\n';

	for (var branch in tree) {
		var link = tree[branch];
		ret += '
';
		if (typeof link === 'string') {
			ret += '' + branch + '';
		} else {
			ret += branch;
			ret += printTree(link);
		}
		ret += '
\n';
	}

	ret += '
\n';

	return ret;
};

exports.getFiles = function (path, callback) {
	return glob(path + '/**/!(index).html', function (err, files) {
		return callback(err, files);
	});
};

exports.getFilesSync = function (path) {
	return glob.sync(path + '/**/!(index).html');
};

exports.run = function (rootPath, title) {
	var files = exports.getFilesSync(rootPath);
	files = files.filter(function (fileName) {
		return fileName.indexOf('carousel') === -1;
	});

	for (var i = 0; i < files.length; i++) {
		var file = files[i];
		files[i] = path.relative(rootPath, file).replace(/\\/g, '/');
	}

	var tree = makeTree(files);

	var content = '';

	content += [
		'',
		'',
		'<title>' + title + '</title>',
		'<link rel="stylesheet" type="text/css" href="style.css">',
		'',
		'',
		'
',
		'
Contents
'
	].join('\n');

	content += printTree(tree);

	content += [
		'
',
		'',
		''
	].join('\n');

	fs.writeFileSync(path.resolve(rootPath + '/index.html'), content);
};
<|endoftext|>


<commit_before>var check_code = "";
var startTime;
var endTime;

function _init_() {
    var height = $("#mainContent").height();
    var width = $(window).width();
    $("#info").css("height",height+"px");
    $(".well").css("height",height+"px");
    $(".header").css("width",width+"px");
}

var se, m = 0, h = 0, s = 0, ss = 1;

function second(){
    if((ss%200)==0){
        s += 1;
        ss = 1;
    }
    if(s>0 && (s%60)==0){
        m += 1;
        s = 0;
    }
    if(m>0 && (m%60)==0){
        h += 1;
        m = 0;
    }
    t = h + ":" + m + ":" + s;
    $("#time").replaceWith("
" + t + "
");
    ss+=1;
}
function startclock(){se=setInterval("second()",1);}
function stopclock(){clearInterval(se);ss=1;m=h=s=0;}

var action = {
    "start" : function() {
                  var tmp;
                  $.ajax({
                      type     : "get",
                      url      : "/workStart",
                      success  : function(data) {
                          if (data != "failed"){
                              check_code = data;
                              alert("工作已开始，请结束时点击按钮，否则后果自负。");
                              tmp = true;
                          }
                          else {
                              alert("开始失败，请重新尝试!");
                              tmp = false;
                          }
                      },
                      error    : function() {
                          alert("无法链接服务器！");
                          tmp = false;
                      },
                      dataType : 'text',
                      async    : false,
                  });
                  return tmp;
              },
    "end"   : function(dt) {
                  var tmp;
                  dt["checkCode"] = check_code;
                  $.ajax({
                      type     : "get",
                      url      : "/workEnd",
                      data     : dt,
                      success  : function(data) {
                          if (data != "failed"){
                              alert("工作已结束，辛苦了！");
                              tmp = true;
                          }
                          else {
                              alert("失败，请重新尝试！");
                              tmp = false;
                          }
                      },
                      error    : function() {
                          alert("无法链接服务器！");
                          tmp = false;
                      },
                      dataType : 'text',
                      async    : false,
                  });
                  return tmp;
              }
}

$(document).ready(function(){
    _init_();
    var now_date = new Date();
    $("#date").replaceWith("" + now_date.toLocaleDateString() + "	");
    $("#now-time").replaceWith("" + now_date.toLocaleTimeString() + "	");
    $('#str-btn').on('click', function(e, data) {
        var tmp = action["start"]();
        if (tmp) {
            startclock();
            startTime = new Date();
            $("#status").replaceWith("已开始	");
        }
    });
    $('#end-btn').on('click', function(e, data) {
        if (check_code == "") {
            alert("工作还未开始！请先点击开始工作！");
            return;
        }
        $('#myModal').modal('show');
        $('#submit').on('click',function(){
            var data = {};
            texts = $(":textarea",$('myModal'));
            selects = $(":select",$('myModal'));
            for(i = 0; i < texts.length; i++){
                data[texts[i].attr("name")] = texts[i].attr("value");
            }
            for(i = 0; i < selects.length; i++){
                data[selects[i].attr("name")] = selects[i].attr("value");
            }
            if (data['cls'] == ""){
                alert("结束工作失败，请填写好工作日志！");
                return;
            }
            else {
                endTime = new Date();
                data["st_time"] = startTime;
                data["ed_time"] = endTime;
                data["month"] = endTime.getMonth() + 1;
				data["year"] = endTime.getFullYear();
				data["day"] = endTime.getDay() + 1;
                var sh = startTime.getHours();
                var sm = startTime.getMinutes();
                var eh = endTime.getHours();
                var em = endTime.getMinutes();
                var hour = eh - sh;
                if (em - sm >= 40) hour ++;
                else if (em - sm < -20) hour --;
                data["hour"] = hour;
            }
            var tmp = action["end"](data);
            if (tmp) {
                check_code = "";
                stopclock();
                $("#time").replaceWith("
0:0:0
");
                $("#status").replaceWith("未开始	");
            }
            else {
                alert("结束工作失败，请再次尝试！");
            }
        });
    });
<<<<<<>>>>>> 637085a6275c409d3573feb666485f114373713d
});

<commit_msg>Update workPage.js<commit_after>var check_code = "";
var startTime;
var endTime;

function _init_() {
    var height = $("#mainContent").height();
    var width = $(window).width();
    $("#info").css("height",height+"px");
    $(".well").css("height",height+"px");
    $(".header").css("width",width+"px");
}

var se, m = 0, h = 0, s = 0, ss = 1;

function second(){
    if((ss%200)==0){
        s += 1;
        ss = 1;
    }
    if(s>0 && (s%60)==0){
        m += 1;
        s = 0;
    }
    if(m>0 && (m%60)==0){
        h += 1;
        m = 0;
    }
    t = h + ":" + m + ":" + s;
    $("#time").replaceWith("
" + t + "
");
    ss+=1;
}
function startclock(){se=setInterval("second()",1);}
function stopclock(){clearInterval(se);ss=1;m=h=s=0;}

var action = {
    "start" : function() {
                  var tmp;
                  $.ajax({
                      type     : "get",
                      url      : "/workStart",
                      success  : function(data) {
                          if (data != "failed"){
                              check_code = data;
                              alert("工作已开始，请结束时点击按钮，否则后果自负。");
                              tmp = true;
                          }
                          else {
                              alert("开始失败，请重新尝试!");
                              tmp = false;
                          }
                      },
                      error    : function() {
                          alert("无法链接服务器！");
                          tmp = false;
                      },
                      dataType : 'text',
                      async    : false,
                  });
                  return tmp;
              },
    "end"   : function(dt) {
                  var tmp;
                  dt["checkCode"] = check_code;
                  $.ajax({
                      type     : "get",
                      url      : "/workEnd",
                      data     : dt,
                      success  : function(data) {
                          if (data != "failed"){
                              alert("工作已结束，辛苦了！");
                              tmp = true;
                          }
                          else {
                              alert("失败，请重新尝试！");
                              tmp = false;
                          }
                      },
                      error    : function() {
                          alert("无法链接服务器！");
                          tmp = false;
                      },
                      dataType : 'text',
                      async    : false,
                  });
                  return tmp;
              }
}

$(document).ready(function(){
    _init_();
    var now_date = new Date();
    $("#date").replaceWith("" + now_date.toLocaleDateString() + "	");
    $("#now-time").replaceWith("" + now_date.toLocaleTimeString() + "	");
    $('#str-btn').on('click', function(e, data) {
        var tmp = action["start"]();
        if (tmp) {
            startclock();
            startTime = new Date();
            $("#status").replaceWith("已开始	");
        }
    });
    $('#end-btn').on('click', function(e, data) {
        if (check_code == "") {
            alert("工作还未开始！请先点击开始工作！");
            return;
        }
        $('#myModal').modal('show');
        $('#submit').on('click',function(){
            var data = {};
            texts = $(":textarea",$('myModal'));
            selects = $(":select",$('myModal'));
            for(i = 0; i < texts.length; i++){
                data[texts[i].attr("name")] = texts[i].attr("value");
            }
            for(i = 0; i < selects.length; i++){
                data[selects[i].attr("name")] = selects[i].attr("value");
            }
            if (data['cls'] == ""){
                alert("结束工作失败，请填写好工作日志！");
                return;
            }
            else {
                endTime = new Date();
                data["st_time"] = startTime;
                data["ed_time"] = endTime;
                data["month"] = endTime.getMonth() + 1;
				data["year"] = endTime.getFullYear();
				data["day"] = endTime.getDay() + 1;
                var sh = startTime.getHours();
                var sm = startTime.getMinutes();
                var eh = endTime.getHours();
                var em = endTime.getMinutes();
                var hour = eh - sh;
                if (em - sm >= 40) hour ++;
                else if (em - sm < -20) hour --;
                data["hour"] = hour;
            }
            var tmp = action["end"](data);
            if (tmp) {
                check_code = "";
                stopclock();
                $("#time").replaceWith("
0:0:0
");
                $("#status").replaceWith("未开始	");
            }
            else {
                alert("结束工作失败，请再次尝试！");
            }
        });
    });
    window.onbeforeunload = function(){
	return "如果于工作状态离开，将产生不可预计的后果！";
    };
});

<|endoftext|>


<commit_before>#!/usr/bin/env node
//
// Run the tests

var lib = require('../lib')
  , util = require('util'), I = util.inspect
  , assert = require('assert')
  , request = require('request')
  ;

var XX_MEANS_EXCLUDE = process.env.xx ? false : true; // Set to false to run *only* the xx tests.
var TESTS = require('./all');
var LOG = lib.log4js().getLogger('tests');
LOG.setLevel(lib.LOG_LEVEL);

//
// Runner
//

var errors = [];
var count = { pass: 0
            , timeout: 0
            , fail: 0
            , skip: 0
            , inc: function(type) {
                     this[type] += 1
                     var symbol = type[0].toUpperCase().replace(/P/, '.');
                     process.stdout.write(symbol);
                     return run();
                   }
            }

function run() {
  var test = TESTS.shift();
  if(!test)
    return complete();

  var starts_with_xx = /^xx/.test(test.name);
  if( XX_MEANS_EXCLUDE ? starts_with_xx : !starts_with_xx )
    return count.inc('skip');

  function done(er) {
    if(er === 'timeout') {
      errors.push(new Error('Timeout: ' + test.name));
      return count.inc('timeout');
    }

    clearTimeout(test.timer);
    if(er) {
      errors.push(er);
      return count.inc('fail');
    }

    return count.inc('pass');
  }

  var timeout = 2500;
  test.timer = setTimeout(function() { done('timeout') }, timeout);

  // This is pretty convenient. Simply throw an error and we'll assume it pertains to this unit test.
  process.removeAllListeners('uncaughtException');
  process.on('uncaughtException', function(er) { return done(er); })

  LOG.debug('Test: ' + test.name);
  test(done);
}

function complete() {
  process.stdout.write('\n\n');
  errors.forEach(function(er) {
    var stack = er.stack;
    if(er.expected || er.actual)
      stack = "expected=" + util.inspect(er.expected) + ' actual=' + util.inspect(er.actual) + '\n' + stack;

    console.error(stack);
  })

  console.log('Done: pass:' + count.pass + ' fail:' + count.fail + ' timeout:' + count.timeout + ' skip:' + count.skip);
}

run();

//
// Utilities
//

if(! assert.member)
  assert.member = function(elem, list, message) {
    var is_member = false;
    list.forEach(function(list_elem) {
      if(list_elem === elem)
        is_member = true;
    })

    if(!is_member)
      throw new Error(message || "");
  }

if(! assert.any)
  assert.any = function(list, message, pred) {
    for(var a = 0; a < list.length; a++)
      if(pred.call(null, list[a]))
        return true;
    throw new Error(message || "assert.any");
  }

if(! assert.none)
  assert.none = function(list, message, pred) {
    for(var a = 0; a < list.length; a++)
      if(pred.call(null, list[a]))
        throw new Error(message || "assert.none");
    return true;
  }

if(! assert.func)
  assert.func = function(obj, message) {
    if(typeof obj !== 'function')
      throw new Error(message || "assert.func");
  }

if(! assert.almost)
  assert.almost = function(actual, expected, message) {
    var delta = Math.abs(actual - expected);
    var margin = delta / expected;
    if(margin > 0.01)
      throw new Error(message || "assert.almost");
  }
<commit_msg>Support decorators<commit_after>#!/usr/bin/env node
//
// Run the tests

var lib = require('../lib')
  , util = require('util'), I = util.inspect
  , assert = require('assert')
  , request = require('request')
  ;

var XX_MEANS_EXCLUDE = process.env.xx ? false : true; // Set to false to run *only* the xx tests.
var TESTS = require('./all');
var LOG = lib.log4js().getLogger('tests');
LOG.setLevel(lib.LOG_LEVEL);

//
// Runner
//

var errors = [];
var count = { pass: 0
            , timeout: 0
            , fail: 0
            , skip: 0
            , inc: function(type) {
                     this[type] += 1
                     var symbol = type[0].toUpperCase().replace(/P/, '.');
                     process.stdout.write(symbol);
                     return run();
                   }
            }

var decoration = {};
TESTS = TESTS.reduce(function(so_far, obj) {
  if(typeof obj === 'function') {
    so_far.push(obj);
    lib.copy(decoration, obj);
    decoration = {};
  } else {
    lib.copy(obj, decoration);
  }
  return so_far;
}, []);

function run() {
  var test = TESTS.shift();
  if(!test)
    return complete();

  var starts_with_xx = /^xx/.test(test.name);
  if( XX_MEANS_EXCLUDE ? starts_with_xx : !starts_with_xx )
    return count.inc('skip');

  var timeout = test.timeout || 250;
  var start_at = new Date;
  function done(er) {
    if(er === 'timeout') {
      errors.push(new Error('Timeout: ' + test.name));
      return count.inc('timeout');
    }

    clearTimeout(test.timer);
    if(er) {
      errors.push(er);
      return count.inc('fail');
    }

    var end_at = new Date;
    var duration = end_at - start_at;
    if(duration > (timeout * 0.80))
      LOG.warn('Long processing time: ' + test.name);

    return count.inc('pass');
  }

  test.timer = setTimeout(function() { done('timeout') }, timeout);

  // This is pretty convenient. Simply throw an error and we'll assume it pertains to this unit test.
  process.removeAllListeners('uncaughtException');
  process.on('uncaughtException', function(er) { return done(er); })

  LOG.debug('Test: ' + test.name);
  test(done);
}

function complete() {
  process.stdout.write('\n\n');
  errors.forEach(function(er) {
    var stack = er.stack;
    if(er.expected || er.actual)
      stack = "expected=" + util.inspect(er.expected) + ' actual=' + util.inspect(er.actual) + '\n' + stack;

    console.error(stack);
  })

  console.log('Done: pass:' + count.pass + ' fail:' + count.fail + ' timeout:' + count.timeout + ' skip:' + count.skip);
}

run();

//
// Utilities
//

if(! assert.member)
  assert.member = function(elem, list, message) {
    var is_member = false;
    list.forEach(function(list_elem) {
      if(list_elem === elem)
        is_member = true;
    })

    if(!is_member)
      throw new Error(message || "");
  }

if(! assert.any)
  assert.any = function(list, message, pred) {
    for(var a = 0; a < list.length; a++)
      if(pred.call(null, list[a]))
        return true;
    throw new Error(message || "assert.any");
  }

if(! assert.none)
  assert.none = function(list, message, pred) {
    for(var a = 0; a < list.length; a++)
      if(pred.call(null, list[a]))
        throw new Error(message || "assert.none");
    return true;
  }

if(! assert.func)
  assert.func = function(obj, message) {
    if(typeof obj !== 'function')
      throw new Error(message || "assert.func");
  }

if(! assert.almost)
  assert.almost = function(actual, expected, message) {
    var delta = Math.abs(actual - expected);
    var margin = delta / expected;
    if(margin > 0.05)
      throw new Error(message || "assert.almost");
  }
<|endoftext|>


<commit_before>module.exports = homeCtrl = {};

homeCtrl.default = function(req, res, next) {
  res.render('index', {
    title: 'Nouson Bright'
  });
  // next();
};
<commit_msg>change title from the home ctrl<commit_after>module.exports = homeCtrl = {};

homeCtrl.default = function(req, res, next) {

  res.render('index', {
    title: 'Fondi'
  });
  // next();
};
<|endoftext|>


<commit_before>
function WebGLViewer(divID) {

  self = this;

  this.divID = divID;
  this.divID_jQuery = '#' + divID;

  this.divWidth = $(this.divID_jQuery).width();
  this.divHeight = $(this.divID_jQuery).height();

  this.neurons = [];

  var camera, scene, renderer, grid_lines, scale, controls;
  var mouseX = 0, mouseY = 0;
  var project_id = project.id;
  var stack_id = project.focusedStack.id;

  /* transform coordinates from CATMAID coordinate system
     to WebGL coordinate system: x->x, y->y+dy, z->-z
    */
  var transform_coordinates = function ( point ) {
    return [point[0],-point[1]+dimension.y*resolution.y,-point[2] ];
  }

  var resolution = project.focusedStack.resolution;
      dimension = project.focusedStack.dimension;
      translation = project.focusedStack.translation;

  var connectivity_types = new Array('neurite', 'presynaptic_to', 'postsynaptic_to');

  init();
  animate();
  debugaxes();
  draw_grid();

  function init() {
    container = document.getElementById(self.divID);
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera( 75, self.divWidth / self.divHeight, 1, 3000 );
    controls = new THREE.TrackballControls( camera, container );
    controls.rotateSpeed = 1.0;
    controls.zoomSpeed = 1.2;
    controls.panSpeed = 0.8;
    controls.noZoom = false;
    controls.noPan = false;
    controls.staticMoving = true;
    controls.dynamicDampingFactor = 0.3;

    renderer = new THREE.WebGLRenderer();
    //renderer = new THREE.CanvasRenderer();
    renderer.setSize( self.divWidth, self.divHeight );

    // Follow size
    // THREEx.WindowResize(renderer, camera);

    container.appendChild( renderer.domElement )

    var x_middle = (dimension.x*resolution.x)/2.0 + translation.x,
        y_middle = (dimension.y*resolution.y)/2.0 + translation.y,
        z_middle = (dimension.z*resolution.z)/2.0 + translation.z;

    scale = 50./dimension.x;

    var coord = transform_coordinates([x_middle, y_middle, z_middle]);

    create_stackboundingbox(
            coord[0]*scale,
            coord[1]*scale,
            coord[2]*scale,
            dimension.x*resolution.x*scale,
            dimension.y*resolution.y*scale,
            dimension.z*resolution.z*scale
    );

    controls.target = new THREE.Vector3(coord[0]*scale,coord[1]*scale,coord[2]*scale);

  }

  var Skeleton = function( skeleton_data )
  {
    this.translate = function( dx, dy, dz )
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        if( dx ) {
          this.actor[connectivity_types[i]].translateX( dx );
        }
        if( dy ) {
          this.actor[connectivity_types[i]].translateY( dy );
        }
        if( dz ) {
          this.actor[connectivity_types[i]].translateZ( dz );
        }
      }
    }

    this.updateCompositeActor = function()
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        this.actor[connectivity_types[i]] = new THREE.Line( this.geometry[connectivity_types[i]],
            this.line_material[connectivity_types[i]], THREE.LinePieces );
      }
    }

    this.removeActorFromScene = function()
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        scene.removeObject( this.actor[connectivity_types[i]] );
      }
    }

    this.addCompositeActorToScene = function()
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        scene.add( this.actor[connectivity_types[i]] );
      }
    }

    var type, from_vector, to_vector;

    this.line_material = new Object();
    this.geometry = new Object();
    this.actor = new Object();

    this.geometry[connectivity_types[0]] = new THREE.Geometry();
    this.geometry[connectivity_types[1]] = new THREE.Geometry();
    this.geometry[connectivity_types[2]] = new THREE.Geometry();

    this.line_material[connectivity_types[0]] = new THREE.LineBasicMaterial( { color: 0xffff00, opacity: 1.0, linewidth: 3 } );
    this.line_material[connectivity_types[1]] = new THREE.LineBasicMaterial( { color: 0xff0000, opacity: 1.0, linewidth: 6 } )
    this.line_material[connectivity_types[2]] = new THREE.LineBasicMaterial( { color: 0x0000ff, opacity: 1.0, linewidth: 6 } )

    this.original_vertices = skeleton_data.vertices;
    this.original_connectivity = skeleton_data.connectivity;
    this.id = skeleton_data.id;
    this.baseName = skeleton_data.baseName;

    for (var fromkey in this.original_connectivity) {
      var to = this.original_connectivity[fromkey];
      for (var tokey in to) {

        type = connectivity_types[connectivity_types.indexOf(this.original_connectivity[fromkey][tokey]['type'])];
        var fv=transform_coordinates([
                 this.original_vertices[fromkey]['x'],
                 this.original_vertices[fromkey]['y'],
                 this.original_vertices[fromkey]['z']
            ]);
        from_vector = new THREE.Vector3(fv[0], fv[1], fv[2] );

        // transform
        from_vector.multiplyScalar( scale );

        this.geometry[type].vertices.push( new THREE.Vertex( from_vector ) );

        var tv=transform_coordinates([
                 this.original_vertices[tokey]['x'],
                 this.original_vertices[tokey]['y'],
                 this.original_vertices[tokey]['z']
            ]);
        to_vector = new THREE.Vector3(tv[0], tv[1], tv[2] );

        // transform
        // to_vector.add( translate_x, translate_y, translate_z );
        to_vector.multiplyScalar( scale );

        this.geometry[type].vertices.push( new THREE.Vertex( to_vector ) );
      }
    }

    this.updateCompositeActor();

  }

  // array of skeletons
  var skeletons = new Object();

  // active node geometry
  var active_node;

  this.fullscreenWebGL = function()
  {
    var divID = 'viewer-3d-webgl-canvas';
    if( THREEx.FullScreen.activated() ){
        THREEx.FullScreen.cancel();
    } else {
        THREEx.FullScreen.request(document.getElementById(divID));
    };
  }

  this.createActiveNode = function( x, y, z)
  {
    sphere = new THREE.SphereGeometry( 30, 32, 32, 1 );
    active_node = new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0x00ff00 } ) );
    active_node.scale.set( 0.05, 0.05, 0.05 );
    active_node.position.set( x,y,z );
    scene.add( active_node );
  }

  this.removeActiveNode = function() {
    if(active_node) {
      scene.removeObject( active_node );
      active_node = null;
    }
  }

  this.updateActiveNode = function( x, y, z )
  {
    if(!active_node) {
      this.createActiveNode( 0, 0, 0 );
    }
    var co = transform_coordinates( [
      translation.x + ((x) / project.focusedStack.scale) * resolution.x,
      translation.y + ((y) / project.focusedStack.scale) * resolution.y,
      translation.z + z * resolution.z]
    );
    active_node.position.set( co[0]*scale, co[1]*scale, co[2]*scale );
  }

  // add skeleton to scene
  this.addSkeleton = function( skeleton_id, skeleton_data )
  {
    var deleted=false;
    if( skeletons.hasOwnProperty(skeleton_id) ){
      // remove skeleton and refetch
      skeletons[skeleton_id].removeActorFromScene();
      delete skeletons[skeleton_id];
      deleted=true;
    }
    skeleton_data['id'] = skeleton_id;
    skeletons[skeleton_id] = new Skeleton( skeleton_data );
    if(!deleted) {
      self.addToSkeletonList( skeletons[skeleton_id] );
    }
    skeletons[skeleton_id].addCompositeActorToScene();
    return true;
  }

  // remove skeleton from scence
  this.removeSkeleton = function( skeleton_id )
  {
    if( !skeletons.hasOwnProperty(skeleton_id) ){
        alert("Skeleton "+skeleton_id+" does not exist. Cannot remove it!");
        return;
    } else {
        skeletons[skeleton_id].removeActorFromScene();
        delete skeletons[skeleton_id];
        return true;
    }
  }

  function create_stackboundingbox(x, y, z, dx, dy, dz)
  {
    // console.log('bouding box', x, y, z, dx, dy, dz);
    var gg = new THREE.CubeGeometry( dx, dy, dz );
    var mm = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
    var mesh = new THREE.Mesh( gg, mm );
    mesh.position.set(x, y, z);
    scene.add( mesh );
    // update camera
    camera.position.x = x;
    camera.position.y = y;
    camera.position.z = 200;
  }

  function debugaxes() {
    var object = new THREE.Axes();
    object.position.set( -1, -1, 0 );
    object.scale.x = object.scale.y = object.scale.z = 0.1;
    scene.add( object );
  }

  function draw_grid() {
    // Grid
    var line_material = new THREE.LineBasicMaterial( { color: 0xffffff, opacity: 0.2 } ),
      geometry = new THREE.Geometry(),
      floor = 0, step = 25;
    for ( var i = 0; i <= 40; i ++ ) {
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( - 500, floor, i * step - 500 ) ) );
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3(   500, floor, i * step - 500 ) ) );
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( i * step - 500, floor, -500 ) ) );
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( i * step - 500, floor,  500 ) ) );

    }
    grid_lines = new THREE.Line( geometry, line_material, THREE.LinePieces );
    scene.add( grid_lines );
  }

  function animate() {
    requestAnimationFrame( animate );
    render();
  }
/*
  function onDocumentMouseMove(event) {
    mouseX = ( event.clientX - self.divWidth );
    mouseY = ( event.clientY - self.divHeight );
  }*/

  function render() {
    controls.update();
    renderer.clear();
    renderer.render( scene, camera );
  }

  this.addToSkeletonList = function ( skeleton ) {
    var newElement = $('<li/>'),
        linkElement, enclosingObject = this;
    newElement.attr('id', '3d-object-' + skeleton.baseName );
    newElement.text(skeleton.baseName + ' ');
    linkElement = $('<a/>');
    linkElement.attr('href', '#');
    linkElement.text("(remove)");
    enclosingObject = this;
    linkElement.click(function (e) {
      self.removeSkeleton( skeleton.id );
      newElement.remove();
    });
    newElement.append(linkElement);
    $('#view-3d-webgl-object-list').append(newElement);
  };

  this.addFromCATMAID = function (projectID, skeletonID, neuronName) {
    if( skeletonID !== undefined )
    {
        jQuery.ajax({
          //url: "../../model/export.skeleton.json.php",
          url: "dj/"+projectID+"/skeleton/" + skeletonID + "/json",
          type: "GET",
          dataType: "json",
          success: function (skeleton_data) {
            skeleton_data['baseName'] = neuronName;
            self.addSkeleton( parseInt(skeletonID), skeleton_data );
          }
        });
    }
  };

  this.toString = function () {
    return "WebGL Viewer(" + this.divID + ")";
  };

}

function nameFromCATMAIDInfo(info) {
  return info.skeleton_name + ' [' + info.neuron_name + ']';
}

function addNeuronFromCATMAID(divID, info) {

  var divID_jQuery = '#' + divID;

  if (!$(divID_jQuery).data('viewer')) {
    $(divID_jQuery).data('viewer', new WebGLViewer(divID));
  }

  $(divID_jQuery).data('viewer').addFromCATMAID(info.project_id, info.skeleton_id, nameFromCATMAIDInfo(info));
}

function createWebGLViewerFromCATMAID(divID) {

  var divID_jQuery = '#' + divID;

  if (!$(divID_jQuery).data('viewer')) {
    $(divID_jQuery).data('viewer', new WebGLViewer(divID));
  }
}

function update3DWebGLViewATN() {
  var atn = SkeletonAnnotations.getActiveNodePosition();

  var divID = 'viewer-3d-webgl-canvas';
  var divID_jQuery = '#' + divID;

  if (!$(divID_jQuery).data('viewer')) {
    $(divID_jQuery).data('viewer', new WebGLViewer(divID));
  }

  if (!atn) {
    alert("You must have an active node selected to add its skeleton to the 3D WebGL View.");
    $(divID_jQuery).data('viewer').removeActiveNode();
    return;
  }

  $(divID_jQuery).data('viewer').updateActiveNode( atn.x, atn.y, atn.z );

}

function addSkeletonTo3DWebGLView(project_id, skeleton_id, skeleton_name, neuron_name) {
  var e = new Object();
  e['project_id'] = project_id;
  e['skeleton_id'] = skeleton_id;
  e['skeleton_name'] = skeleton_name;
  e['neuron_name'] = neuron_name;
  addNeuronFromCATMAID('viewer-3d-webgl-canvas', e);
}

function fullscreenWebGL() {
  var divID = 'viewer-3d-webgl-canvas';
  var divID_jQuery = '#' + divID;
  $(divID_jQuery).data('viewer').fullscreenWebGL();
}

function addTo3DWebGLView() {
  var atn_id = SkeletonAnnotations.getActiveNodeId();
  if (!atn_id) {
    alert("You must have an active node selected to add its skeleton to the 3D WebGL View.");
    return;
  }
  if (SkeletonAnnotations.getActiveNodeType() != "treenode") {
    alert("You can only add skeletons to the 3D WebGL View at the moment - please select a node of a skeleton.");
    return;
  }
  requestQueue.register('model/treenode.info.php', 'POST', {
    pid: project.id,
    tnid: atn_id
  }, function (status, text, xml) {
    if (status == 200) {
      var e = eval("(" + text + ")");
      if (e.error) {
        alert(e.error);
      } else {
        e['project_id'] = project.id;
        addNeuronFromCATMAID('viewer-3d-webgl-canvas', e);
      }
    } else {
      alert("Bad status code " + status + " mapping treenode ID to skeleton and neuron");
    }
    return true;
  });
}
<commit_msg>Test for color picking for neuron colors<commit_after>
function WebGLViewer(divID) {

  self = this;

  this.divID = divID;
  this.divID_jQuery = '#' + divID;

  this.divWidth = $(this.divID_jQuery).width();
  this.divHeight = $(this.divID_jQuery).height();

  this.neurons = [];

  var camera, scene, renderer, grid_lines, scale, controls;
  var mouseX = 0, mouseY = 0;
  var project_id = project.id;
  var stack_id = project.focusedStack.id;

  /* transform coordinates from CATMAID coordinate system
     to WebGL coordinate system: x->x, y->y+dy, z->-z
    */
  var transform_coordinates = function ( point ) {
    return [point[0],-point[1]+dimension.y*resolution.y,-point[2] ];
  }

  var resolution = project.focusedStack.resolution;
      dimension = project.focusedStack.dimension;
      translation = project.focusedStack.translation;

  var connectivity_types = new Array('neurite', 'presynaptic_to', 'postsynaptic_to');

  init();
  animate();
  debugaxes();
  draw_grid();

  function init() {
    container = document.getElementById(self.divID);
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera( 75, self.divWidth / self.divHeight, 1, 3000 );
    controls = new THREE.TrackballControls( camera, container );
    controls.rotateSpeed = 1.0;
    controls.zoomSpeed = 1.2;
    controls.panSpeed = 0.8;
    controls.noZoom = false;
    controls.noPan = false;
    controls.staticMoving = true;
    controls.dynamicDampingFactor = 0.3;

    renderer = new THREE.WebGLRenderer();
    //renderer = new THREE.CanvasRenderer();
    renderer.setSize( self.divWidth, self.divHeight );

    // Follow size
    // THREEx.WindowResize(renderer, camera);

    container.appendChild( renderer.domElement )

    var x_middle = (dimension.x*resolution.x)/2.0 + translation.x,
        y_middle = (dimension.y*resolution.y)/2.0 + translation.y,
        z_middle = (dimension.z*resolution.z)/2.0 + translation.z;

    scale = 50./dimension.x;

    var coord = transform_coordinates([x_middle, y_middle, z_middle]);

    create_stackboundingbox(
            coord[0]*scale,
            coord[1]*scale,
            coord[2]*scale,
            dimension.x*resolution.x*scale,
            dimension.y*resolution.y*scale,
            dimension.z*resolution.z*scale
    );

    controls.target = new THREE.Vector3(coord[0]*scale,coord[1]*scale,coord[2]*scale);

  }

  var Skeleton = function( skeleton_data )
  {
    this.translate = function( dx, dy, dz )
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        if( dx ) {
          this.actor[connectivity_types[i]].translateX( dx );
        }
        if( dy ) {
          this.actor[connectivity_types[i]].translateY( dy );
        }
        if( dz ) {
          this.actor[connectivity_types[i]].translateZ( dz );
        }
      }
    }

    this.changeColor = function( value )
    {
      console.log("setter value", value, parseInt(value));
      this.actor[connectivity_types[0]].material.color.setHex( value );
    }

    this.updateCompositeActor = function()
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        this.actor[connectivity_types[i]] = new THREE.Line( this.geometry[connectivity_types[i]],
            this.line_material[connectivity_types[i]], THREE.LinePieces );
      }
    }

    this.removeActorFromScene = function()
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        scene.removeObject( this.actor[connectivity_types[i]] );
      }
    }

    this.addCompositeActorToScene = function()
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        scene.add( this.actor[connectivity_types[i]] );
      }
    }

    var type, from_vector, to_vector;

    this.line_material = new Object();
    this.geometry = new Object();
    this.actor = new Object();

    this.geometry[connectivity_types[0]] = new THREE.Geometry();
    this.geometry[connectivity_types[1]] = new THREE.Geometry();
    this.geometry[connectivity_types[2]] = new THREE.Geometry();

    this.line_material[connectivity_types[0]] = new THREE.LineBasicMaterial( { color: 0xffff00, opacity: 1.0, linewidth: 3 } );
    this.line_material[connectivity_types[1]] = new THREE.LineBasicMaterial( { color: 0xff0000, opacity: 1.0, linewidth: 6 } )
    this.line_material[connectivity_types[2]] = new THREE.LineBasicMaterial( { color: 0x0000ff, opacity: 1.0, linewidth: 6 } )

    this.original_vertices = skeleton_data.vertices;
    this.original_connectivity = skeleton_data.connectivity;
    this.id = skeleton_data.id;
    this.baseName = skeleton_data.baseName;

    for (var fromkey in this.original_connectivity) {
      var to = this.original_connectivity[fromkey];
      for (var tokey in to) {

        type = connectivity_types[connectivity_types.indexOf(this.original_connectivity[fromkey][tokey]['type'])];
        var fv=transform_coordinates([
                 this.original_vertices[fromkey]['x'],
                 this.original_vertices[fromkey]['y'],
                 this.original_vertices[fromkey]['z']
            ]);
        from_vector = new THREE.Vector3(fv[0], fv[1], fv[2] );

        // transform
        from_vector.multiplyScalar( scale );

        this.geometry[type].vertices.push( new THREE.Vertex( from_vector ) );

        var tv=transform_coordinates([
                 this.original_vertices[tokey]['x'],
                 this.original_vertices[tokey]['y'],
                 this.original_vertices[tokey]['z']
            ]);
        to_vector = new THREE.Vector3(tv[0], tv[1], tv[2] );

        // transform
        // to_vector.add( translate_x, translate_y, translate_z );
        to_vector.multiplyScalar( scale );

        this.geometry[type].vertices.push( new THREE.Vertex( to_vector ) );
      }
    }

    this.updateCompositeActor();

  }

  // array of skeletons
  var skeletons = new Object();

  // active node geometry
  var active_node;

  this.fullscreenWebGL = function()
  {
    var divID = 'viewer-3d-webgl-canvas';
    if( THREEx.FullScreen.activated() ){
        THREEx.FullScreen.cancel();
    } else {
        THREEx.FullScreen.request(document.getElementById(divID));
    };
  }

  this.createActiveNode = function( x, y, z)
  {
    sphere = new THREE.SphereGeometry( 30, 32, 32, 1 );
    active_node = new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0x00ff00 } ) );
    active_node.scale.set( 0.05, 0.05, 0.05 );
    active_node.position.set( x,y,z );
    scene.add( active_node );
  }

  this.removeActiveNode = function() {
    if(active_node) {
      scene.removeObject( active_node );
      active_node = null;
    }
  }

  this.updateActiveNode = function( x, y, z )
  {
    if(!active_node) {
      this.createActiveNode( 0, 0, 0 );
    }
    var co = transform_coordinates( [
      translation.x + ((x) / project.focusedStack.scale) * resolution.x,
      translation.y + ((y) / project.focusedStack.scale) * resolution.y,
      translation.z + z * resolution.z]
    );
    active_node.position.set( co[0]*scale, co[1]*scale, co[2]*scale );
  }

  // add skeleton to scene
  this.addSkeleton = function( skeleton_id, skeleton_data )
  {
    var deleted=false;
    if( skeletons.hasOwnProperty(skeleton_id) ){
      // remove skeleton and refetch
      skeletons[skeleton_id].removeActorFromScene();
      delete skeletons[skeleton_id];
      deleted=true;
    }
    skeleton_data['id'] = skeleton_id;
    skeletons[skeleton_id] = new Skeleton( skeleton_data );
    if(!deleted) {
      self.addToSkeletonList( skeletons[skeleton_id] );
    }
    skeletons[skeleton_id].addCompositeActorToScene();
    return true;
  }

  this.changeSkeletonColor = function( skeleton_id, value )
  {
    if( !skeletons.hasOwnProperty(skeleton_id) ){
        alert("Skeleton "+skeleton_id+" does not exist. Cannot change color it!");
        return;
    } else {
        skeletons[skeleton_id].changeColor( value );
        return true;
    }

  }

  // remove skeleton from scence
  this.removeSkeleton = function( skeleton_id )
  {
    if( !skeletons.hasOwnProperty(skeleton_id) ){
        alert("Skeleton "+skeleton_id+" does not exist. Cannot remove it!");
        return;
    } else {
        skeletons[skeleton_id].removeActorFromScene();
        delete skeletons[skeleton_id];
        return true;
    }
  }

  function create_stackboundingbox(x, y, z, dx, dy, dz)
  {
    // console.log('bouding box', x, y, z, dx, dy, dz);
    var gg = new THREE.CubeGeometry( dx, dy, dz );
    var mm = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
    var mesh = new THREE.Mesh( gg, mm );
    mesh.position.set(x, y, z);
    scene.add( mesh );
    // update camera
    camera.position.x = x;
    camera.position.y = y;
    camera.position.z = 200;
  }

  function debugaxes() {
    var object = new THREE.Axes();
    object.position.set( -1, -1, 0 );
    object.scale.x = object.scale.y = object.scale.z = 0.1;
    scene.add( object );
  }

  function draw_grid() {
    // Grid
    var line_material = new THREE.LineBasicMaterial( { color: 0xffffff, opacity: 0.2 } ),
      geometry = new THREE.Geometry(),
      floor = 0, step = 25;
    for ( var i = 0; i <= 40; i ++ ) {
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( - 500, floor, i * step - 500 ) ) );
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3(   500, floor, i * step - 500 ) ) );
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( i * step - 500, floor, -500 ) ) );
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( i * step - 500, floor,  500 ) ) );

    }
    grid_lines = new THREE.Line( geometry, line_material, THREE.LinePieces );
    scene.add( grid_lines );
  }

  function animate() {
    requestAnimationFrame( animate );
    render();
  }
/*
  function onDocumentMouseMove(event) {
    mouseX = ( event.clientX - self.divWidth );
    mouseY = ( event.clientY - self.divHeight );
  }*/

  function render() {
    controls.update();
    renderer.clear();
    renderer.render( scene, camera );
  }

  this.addToSkeletonList = function ( skeleton ) {
    var newElement = $('<li/>'),
        linkElement, enclosingObject = this;
    newElement.attr('id', '3d-object-' + skeleton.baseName );
    newElement.text(skeleton.baseName + ' ');
    linkElement = $('<a/>');
    linkElement.attr('href', '#');
    linkElement.text("(remove)");
    enclosingObject = this;
    linkElement.click(function (e) {
      self.removeSkeleton( skeleton.id );
      newElement.remove();
    });
    newElement.append(linkElement);

    colorElement = $('<input/>');
    colorElement.attr('type', 'text');
    colorElement.attr('id', 'skeleton_'+skeleton.id );
    colorElement.attr('value', '#ffff000' );
    colorElement.keyup(function (e) {
      // TODO: fix
      console.log("color", e, this, this.value );
      // if enter
      self.changeSkeletonColor( skeleton.id, this.value );
    });
    newElement.append(colorElement);

    $('#view-3d-webgl-object-list').append(newElement);
  };

  this.addFromCATMAID = function (projectID, skeletonID, neuronName) {
    if( skeletonID !== undefined )
    {
        jQuery.ajax({
          //url: "../../model/export.skeleton.json.php",
          url: "dj/"+projectID+"/skeleton/" + skeletonID + "/json",
          type: "GET",
          dataType: "json",
          success: function (skeleton_data) {
            skeleton_data['baseName'] = neuronName;
            self.addSkeleton( parseInt(skeletonID), skeleton_data );
          }
        });
    }
  };

  this.toString = function () {
    return "WebGL Viewer(" + this.divID + ")";
  };

}

function nameFromCATMAIDInfo(info) {
  return info.skeleton_name + ' [' + info.neuron_name + ']';
}

function addNeuronFromCATMAID(divID, info) {

  var divID_jQuery = '#' + divID;

  if (!$(divID_jQuery).data('viewer')) {
    $(divID_jQuery).data('viewer', new WebGLViewer(divID));
  }

  $(divID_jQuery).data('viewer').addFromCATMAID(info.project_id, info.skeleton_id, nameFromCATMAIDInfo(info));
}

function createWebGLViewerFromCATMAID(divID) {

  var divID_jQuery = '#' + divID;

  if (!$(divID_jQuery).data('viewer')) {
    $(divID_jQuery).data('viewer', new WebGLViewer(divID));
  }
}

function update3DWebGLViewATN() {
  var atn = SkeletonAnnotations.getActiveNodePosition();

  var divID = 'viewer-3d-webgl-canvas';
  var divID_jQuery = '#' + divID;

  if (!$(divID_jQuery).data('viewer')) {
    $(divID_jQuery).data('viewer', new WebGLViewer(divID));
  }

  if (!atn) {
    alert("You must have an active node selected to add its skeleton to the 3D WebGL View.");
    $(divID_jQuery).data('viewer').removeActiveNode();
    return;
  }

  $(divID_jQuery).data('viewer').updateActiveNode( atn.x, atn.y, atn.z );

}

function addSkeletonTo3DWebGLView(project_id, skeleton_id, skeleton_name, neuron_name) {
  var e = new Object();
  e['project_id'] = project_id;
  e['skeleton_id'] = skeleton_id;
  e['skeleton_name'] = skeleton_name;
  e['neuron_name'] = neuron_name;
  addNeuronFromCATMAID('viewer-3d-webgl-canvas', e);
}

function fullscreenWebGL() {
  var divID = 'viewer-3d-webgl-canvas';
  var divID_jQuery = '#' + divID;
  $(divID_jQuery).data('viewer').fullscreenWebGL();
}

function addTo3DWebGLView() {
  var atn_id = SkeletonAnnotations.getActiveNodeId();
  if (!atn_id) {
    alert("You must have an active node selected to add its skeleton to the 3D WebGL View.");
    return;
  }
  if (SkeletonAnnotations.getActiveNodeType() != "treenode") {
    alert("You can only add skeletons to the 3D WebGL View at the moment - please select a node of a skeleton.");
    return;
  }
  requestQueue.register('model/treenode.info.php', 'POST', {
    pid: project.id,
    tnid: atn_id
  }, function (status, text, xml) {
    if (status == 200) {
      var e = eval("(" + text + ")");
      if (e.error) {
        alert(e.error);
      } else {
        e['project_id'] = project.id;
        addNeuronFromCATMAID('viewer-3d-webgl-canvas', e);
      }
    } else {
      alert("Bad status code " + status + " mapping treenode ID to skeleton and neuron");
    }
    return true;
  });
}
<|endoftext|>


<commit_before>
function WebGLViewer(divID) {

  self = this;

  this.divID = divID;
  this.divID_jQuery = '#' + divID;

  this.divWidth = $(this.divID_jQuery).width();
  this.divHeight = $(this.divID_jQuery).height();

  this.neurons = [];

  var camera, scene, renderer, grid_lines, scale, controls;
  var mouseX = 0, mouseY = 0;
  var project_id = project.id;
  var stack_id = project.focusedStack.id;

  /* transform coordinates from CATMAID coordinate system
     to WebGL coordinate system: x->x, y->y+dy, z->-z
    */
  var transform_coordinates = function ( point ) {
    return [point[0],-point[1]+dimension.y*resolution.y,-point[2] ];
  }

  var resolution = project.focusedStack.resolution;
      dimension = project.focusedStack.dimension;
      translation = project.focusedStack.translation;

  var connectivity_types = new Array('neurite', 'presynaptic_to', 'postsynaptic_to');

  init();
  animate();
  debugaxes();
  draw_grid();

  function init() {
    container = document.getElementById(self.divID);
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera( 75, self.divWidth / self.divHeight, 1, 3000 );
    controls = new THREE.TrackballControls( camera );
    controls.rotateSpeed = 1.0;
    controls.zoomSpeed = 1.2;
    controls.panSpeed = 0.8;
    controls.noZoom = false;
    controls.noPan = false;
    controls.staticMoving = true;
    controls.dynamicDampingFactor = 0.3;

    renderer = new THREE.WebGLRenderer();
    //renderer = new THREE.CanvasRenderer();
    renderer.setSize( self.divWidth, self.divHeight );

    // Follow size
    // THREEx.WindowResize(renderer, camera);

    container.appendChild( renderer.domElement );
    container.addEventListener( 'mousemove', onDocumentMouseMove, false );

    var x_middle = (dimension.x*resolution.x)/2.0 + translation.x,
        y_middle = (dimension.y*resolution.y)/2.0 + translation.y,
        z_middle = (dimension.z*resolution.z)/2.0 + translation.z;

    scale = 50./dimension.x;

    var coord = transform_coordinates([x_middle, y_middle, z_middle]);

    create_stackboundingbox(
            coord[0]*scale,
            coord[1]*scale,
            coord[2]*scale,
            dimension.x*resolution.x*scale,
            dimension.y*resolution.y*scale,
            dimension.z*resolution.z*scale
    );

    controls.target = new THREE.Vector3(coord[0]*scale,coord[1]*scale,coord[2]*scale);

  }

  var Skeleton = function( skeleton_data )
  {
    this.translate = function( dx, dy, dz )
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        if( dx ) {
          this.actor[connectivity_types[i]].translateX( dx );
        }
        if( dy ) {
          this.actor[connectivity_types[i]].translateY( dy );
        }
        if( dz ) {
          this.actor[connectivity_types[i]].translateZ( dz );
        }
      }
    }

    this.updateCompositeActor = function()
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        this.actor[connectivity_types[i]] = new THREE.Line( this.geometry[connectivity_types[i]],
            this.line_material[connectivity_types[i]], THREE.LinePieces );
      }
    }

    this.removeActorFromScene = function()
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        scene.removeObject( this.actor[connectivity_types[i]] );
      }
    }

    this.addCompositeActorToScene = function()
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        scene.add( this.actor[connectivity_types[i]] );
      }
    }

    var type, from_vector, to_vector;

    this.line_material = new Object();
    this.geometry = new Object();
    this.actor = new Object();

    this.geometry[connectivity_types[0]] = new THREE.Geometry();
    this.geometry[connectivity_types[1]] = new THREE.Geometry();
    this.geometry[connectivity_types[2]] = new THREE.Geometry();

    this.line_material[connectivity_types[0]] = new THREE.LineBasicMaterial( { color: 0xffff00, opacity: 1.0, linewidth: 3 } );
    this.line_material[connectivity_types[1]] = new THREE.LineBasicMaterial( { color: 0xff0000, opacity: 1.0, linewidth: 6 } )
    this.line_material[connectivity_types[2]] = new THREE.LineBasicMaterial( { color: 0x0000ff, opacity: 1.0, linewidth: 6 } )

    this.original_vertices = skeleton_data.vertices;
    this.original_connectivity = skeleton_data.connectivity;
    this.id = skeleton_data.id;
    this.baseName = skeleton_data.baseName;

    for (var fromkey in this.original_connectivity) {
      var to = this.original_connectivity[fromkey];
      for (var tokey in to) {

        type = connectivity_types[connectivity_types.indexOf(this.original_connectivity[fromkey][tokey]['type'])];
        var fv=transform_coordinates([
                 this.original_vertices[fromkey]['x'],
                 this.original_vertices[fromkey]['y'],
                 this.original_vertices[fromkey]['z']
            ]);
        from_vector = new THREE.Vector3(fv[0], fv[1], fv[2] );

        // transform
        from_vector.multiplyScalar( scale );

        this.geometry[type].vertices.push( new THREE.Vertex( from_vector ) );

        var tv=transform_coordinates([
                 this.original_vertices[tokey]['x'],
                 this.original_vertices[tokey]['y'],
                 this.original_vertices[tokey]['z']
            ]);
        to_vector = new THREE.Vector3(tv[0], tv[1], tv[2] );

        // transform
        // to_vector.add( translate_x, translate_y, translate_z );
        to_vector.multiplyScalar( scale );

        this.geometry[type].vertices.push( new THREE.Vertex( to_vector ) );
      }
    }

    this.updateCompositeActor();

  }

  // array of skeletons
  var skeletons = new Object();

  // active node geometry
  var active_node;

  this.fullscreenWebGL = function()
  {
    var divID = 'viewer-3d-webgl-canvas';
    if( THREEx.FullScreen.activated() ){
        THREEx.FullScreen.cancel();
    } else {
        THREEx.FullScreen.request(document.getElementById(divID));
    };
  }

  this.createActiveNode = function( x, y, z)
  {
    sphere = new THREE.SphereGeometry( 30, 32, 32, 1 );
    active_node = new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0x00ff00 } ) );
    active_node.scale.set( 0.05, 0.05, 0.05 );
    active_node.position.set( x,y,z );
    scene.add( active_node );
  }

  this.removeActiveNode = function() {
    if(active_node) {
      scene.removeObject( active_node );
      active_node = null;
    }
  }

  this.updateActiveNode = function( x, y, z )
  {
    if(!active_node) {
      this.createActiveNode( 0, 0, 0 );
    }
    var co = transform_coordinates( [
      translation.x + ((x) / project.focusedStack.scale) * resolution.x,
      translation.y + ((y) / project.focusedStack.scale) * resolution.y,
      translation.z + z * resolution.z]
    );
    active_node.position.set( co[0]*scale, co[1]*scale, co[2]*scale );
  }

  // add skeleton to scene
  this.addSkeleton = function( skeleton_id, skeleton_data )
  {
    var deleted=false;
    if( skeletons.hasOwnProperty(skeleton_id) ){
      // remove skeleton and refetch
      skeletons[skeleton_id].removeActorFromScene();
      delete skeletons[skeleton_id];
      deleted=true;
    }
    skeleton_data['id'] = skeleton_id;
    skeletons[skeleton_id] = new Skeleton( skeleton_data );
    if(!deleted) {
      self.addToSkeletonList( skeletons[skeleton_id] );
    }
    skeletons[skeleton_id].addCompositeActorToScene();
    return true;
  }

  // remove skeleton from scence
  this.removeSkeleton = function( skeleton_id )
  {
    if( !skeletons.hasOwnProperty(skeleton_id) ){
        alert("Skeleton "+skeleton_id+" does not exist. Cannot remove it!");
        return;
    } else {
        skeletons[skeleton_id].removeActorFromScene();
        delete skeletons[skeleton_id];
        return true;
    }
  }

  function create_stackboundingbox(x, y, z, dx, dy, dz)
  {
    console.log('bouding box', x, y, z, dx, dy, dz);
    var gg = new THREE.CubeGeometry( dx, dy, dz );
    var mm = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
    var mesh = new THREE.Mesh( gg, mm );
    mesh.position.set(x, y, z);
    scene.add( mesh );
    // update camera
    camera.position.x = x;
    camera.position.y = y;
    camera.position.z = 200;
  }

  function debugaxes() {
    var object = new THREE.Axes();
    object.position.set( -1, -1, 0 );
    object.scale.x = object.scale.y = object.scale.z = 0.1;
    scene.add( object );
  }

  function draw_grid() {
    // Grid
    var line_material = new THREE.LineBasicMaterial( { color: 0xffffff, opacity: 0.2 } ),
      geometry = new THREE.Geometry(),
      floor = 0, step = 25;
    for ( var i = 0; i <= 40; i ++ ) {
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( - 500, floor, i * step - 500 ) ) );
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3(   500, floor, i * step - 500 ) ) );
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( i * step - 500, floor, -500 ) ) );
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( i * step - 500, floor,  500 ) ) );

    }
    grid_lines = new THREE.Line( geometry, line_material, THREE.LinePieces );
    scene.add( grid_lines );
  }

  function animate() {
    requestAnimationFrame( animate );
    render();
  }

  function onDocumentMouseMove(event) {
    mouseX = ( event.clientX - self.divWidth );
    mouseY = ( event.clientY - self.divHeight );
  }

  function render() {
    controls.update();
    renderer.clear();
    renderer.render( scene, camera );
  }

  this.addToSkeletonList = function ( skeleton ) {
    var newElement = $('<li/>'),
        linkElement, enclosingObject = this;
    newElement.attr('id', '3d-object-' + skeleton.baseName );
    newElement.text(skeleton.baseName + ' ');
    linkElement = $('<a/>');
    linkElement.attr('href', '#');
    linkElement.text("(remove)");
    enclosingObject = this;
    linkElement.click(function (e) {
      self.removeSkeleton( skeleton.id );
      newElement.remove();
    });
    newElement.append(linkElement);
    $('#view-3d-webgl-object-list').append(newElement);
  };

  this.addFromCATMAID = function (projectID, skeletonID, neuronName) {
    if( skeletonID !== undefined )
    {
        jQuery.ajax({
          //url: "../../model/export.skeleton.json.php",
          url: "dj/"+projectID+"/skeleton/" + skeletonID + "/json",
          type: "GET",
          dataType: "json",
          success: function (skeleton_data) {
            skeleton_data['baseName'] = neuronName;
            self.addSkeleton( parseInt(skeletonID), skeleton_data );
          }
        });
    }
  };

  this.toString = function () {
    return "WebGL Viewer(" + this.divID + ")";
  };

}

function nameFromCATMAIDInfo(info) {
  return info.skeleton_name + ' [' + info.neuron_name + ']';
}

function addNeuronFromCATMAID(divID, info) {

  var divID_jQuery = '#' + divID;

  if (!$(divID_jQuery).data('viewer')) {
    $(divID_jQuery).data('viewer', new WebGLViewer(divID));
  }

  $(divID_jQuery).data('viewer').addFromCATMAID(info.project_id, info.skeleton_id, nameFromCATMAIDInfo(info));
}

function createWebGLViewerFromCATMAID(divID) {

  var divID_jQuery = '#' + divID;

  if (!$(divID_jQuery).data('viewer')) {
    $(divID_jQuery).data('viewer', new WebGLViewer(divID));
  }
}

function update3DWebGLViewATN() {
  var atn = SkeletonAnnotations.getActiveNodePosition();

  var divID = 'viewer-3d-webgl-canvas';
  var divID_jQuery = '#' + divID;

  if (!$(divID_jQuery).data('viewer')) {
    $(divID_jQuery).data('viewer', new WebGLViewer(divID));
  }

  if (!atn) {
    alert("You must have an active node selected to add its skeleton to the 3D WebGL View.");
    $(divID_jQuery).data('viewer').removeActiveNode();
    return;
  }

  $(divID_jQuery).data('viewer').updateActiveNode( atn.x, atn.y, atn.z );

}

function addSkeletonTo3DWebGLView(project_id, skeleton_id, skeleton_name, neuron_name) {
  var e = new Object();
  e['project_id'] = project_id;
  e['skeleton_id'] = skeleton_id;
  e['skeleton_name'] = skeleton_name;
  e['neuron_name'] = neuron_name;
  addNeuronFromCATMAID('viewer-3d-webgl-canvas', e);
}

function fullscreenWebGL() {
  var divID = 'viewer-3d-webgl-canvas';
  var divID_jQuery = '#' + divID;
  $(divID_jQuery).data('viewer').fullscreenWebGL();
}

function addTo3DWebGLView() {
  var atn_id = SkeletonAnnotations.getActiveNodeId();
  if (!atn_id) {
    alert("You must have an active node selected to add its skeleton to the 3D WebGL View.");
    return;
  }
  if (SkeletonAnnotations.getActiveNodeType() != "treenode") {
    alert("You can only add skeletons to the 3D WebGL View at the moment - please select a node of a skeleton.");
    return;
  }
  requestQueue.register('model/treenode.info.php', 'POST', {
    pid: project.id,
    tnid: atn_id
  }, function (status, text, xml) {
    if (status == 200) {
      var e = eval("(" + text + ")");
      if (e.error) {
        alert(e.error);
      } else {
        e['project_id'] = project.id;
        addNeuronFromCATMAID('viewer-3d-webgl-canvas', e);
      }
    } else {
      alert("Bad status code " + status + " mapping treenode ID to skeleton and neuron");
    }
    return true;
  });
}
<commit_msg>Fix problem when mouse events added to the document not the canvas DOM element<commit_after>
function WebGLViewer(divID) {

  self = this;

  this.divID = divID;
  this.divID_jQuery = '#' + divID;

  this.divWidth = $(this.divID_jQuery).width();
  this.divHeight = $(this.divID_jQuery).height();

  this.neurons = [];

  var camera, scene, renderer, grid_lines, scale, controls;
  var mouseX = 0, mouseY = 0;
  var project_id = project.id;
  var stack_id = project.focusedStack.id;

  /* transform coordinates from CATMAID coordinate system
     to WebGL coordinate system: x->x, y->y+dy, z->-z
    */
  var transform_coordinates = function ( point ) {
    return [point[0],-point[1]+dimension.y*resolution.y,-point[2] ];
  }

  var resolution = project.focusedStack.resolution;
      dimension = project.focusedStack.dimension;
      translation = project.focusedStack.translation;

  var connectivity_types = new Array('neurite', 'presynaptic_to', 'postsynaptic_to');

  init();
  animate();
  debugaxes();
  draw_grid();

  function init() {
    container = document.getElementById(self.divID);
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera( 75, self.divWidth / self.divHeight, 1, 3000 );
    controls = new THREE.TrackballControls( camera, container );
    controls.rotateSpeed = 1.0;
    controls.zoomSpeed = 1.2;
    controls.panSpeed = 0.8;
    controls.noZoom = false;
    controls.noPan = false;
    controls.staticMoving = true;
    controls.dynamicDampingFactor = 0.3;

    renderer = new THREE.WebGLRenderer();
    //renderer = new THREE.CanvasRenderer();
    renderer.setSize( self.divWidth, self.divHeight );

    // Follow size
    // THREEx.WindowResize(renderer, camera);

    container.appendChild( renderer.domElement )

    var x_middle = (dimension.x*resolution.x)/2.0 + translation.x,
        y_middle = (dimension.y*resolution.y)/2.0 + translation.y,
        z_middle = (dimension.z*resolution.z)/2.0 + translation.z;

    scale = 50./dimension.x;

    var coord = transform_coordinates([x_middle, y_middle, z_middle]);

    create_stackboundingbox(
            coord[0]*scale,
            coord[1]*scale,
            coord[2]*scale,
            dimension.x*resolution.x*scale,
            dimension.y*resolution.y*scale,
            dimension.z*resolution.z*scale
    );

    controls.target = new THREE.Vector3(coord[0]*scale,coord[1]*scale,coord[2]*scale);

  }

  var Skeleton = function( skeleton_data )
  {
    this.translate = function( dx, dy, dz )
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        if( dx ) {
          this.actor[connectivity_types[i]].translateX( dx );
        }
        if( dy ) {
          this.actor[connectivity_types[i]].translateY( dy );
        }
        if( dz ) {
          this.actor[connectivity_types[i]].translateZ( dz );
        }
      }
    }

    this.updateCompositeActor = function()
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        this.actor[connectivity_types[i]] = new THREE.Line( this.geometry[connectivity_types[i]],
            this.line_material[connectivity_types[i]], THREE.LinePieces );
      }
    }

    this.removeActorFromScene = function()
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        scene.removeObject( this.actor[connectivity_types[i]] );
      }
    }

    this.addCompositeActorToScene = function()
    {
      for ( var i=0; i<connectivity_types.length; ++i ) {
        scene.add( this.actor[connectivity_types[i]] );
      }
    }

    var type, from_vector, to_vector;

    this.line_material = new Object();
    this.geometry = new Object();
    this.actor = new Object();

    this.geometry[connectivity_types[0]] = new THREE.Geometry();
    this.geometry[connectivity_types[1]] = new THREE.Geometry();
    this.geometry[connectivity_types[2]] = new THREE.Geometry();

    this.line_material[connectivity_types[0]] = new THREE.LineBasicMaterial( { color: 0xffff00, opacity: 1.0, linewidth: 3 } );
    this.line_material[connectivity_types[1]] = new THREE.LineBasicMaterial( { color: 0xff0000, opacity: 1.0, linewidth: 6 } )
    this.line_material[connectivity_types[2]] = new THREE.LineBasicMaterial( { color: 0x0000ff, opacity: 1.0, linewidth: 6 } )

    this.original_vertices = skeleton_data.vertices;
    this.original_connectivity = skeleton_data.connectivity;
    this.id = skeleton_data.id;
    this.baseName = skeleton_data.baseName;

    for (var fromkey in this.original_connectivity) {
      var to = this.original_connectivity[fromkey];
      for (var tokey in to) {

        type = connectivity_types[connectivity_types.indexOf(this.original_connectivity[fromkey][tokey]['type'])];
        var fv=transform_coordinates([
                 this.original_vertices[fromkey]['x'],
                 this.original_vertices[fromkey]['y'],
                 this.original_vertices[fromkey]['z']
            ]);
        from_vector = new THREE.Vector3(fv[0], fv[1], fv[2] );

        // transform
        from_vector.multiplyScalar( scale );

        this.geometry[type].vertices.push( new THREE.Vertex( from_vector ) );

        var tv=transform_coordinates([
                 this.original_vertices[tokey]['x'],
                 this.original_vertices[tokey]['y'],
                 this.original_vertices[tokey]['z']
            ]);
        to_vector = new THREE.Vector3(tv[0], tv[1], tv[2] );

        // transform
        // to_vector.add( translate_x, translate_y, translate_z );
        to_vector.multiplyScalar( scale );

        this.geometry[type].vertices.push( new THREE.Vertex( to_vector ) );
      }
    }

    this.updateCompositeActor();

  }

  // array of skeletons
  var skeletons = new Object();

  // active node geometry
  var active_node;

  this.fullscreenWebGL = function()
  {
    var divID = 'viewer-3d-webgl-canvas';
    if( THREEx.FullScreen.activated() ){
        THREEx.FullScreen.cancel();
    } else {
        THREEx.FullScreen.request(document.getElementById(divID));
    };
  }

  this.createActiveNode = function( x, y, z)
  {
    sphere = new THREE.SphereGeometry( 30, 32, 32, 1 );
    active_node = new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0x00ff00 } ) );
    active_node.scale.set( 0.05, 0.05, 0.05 );
    active_node.position.set( x,y,z );
    scene.add( active_node );
  }

  this.removeActiveNode = function() {
    if(active_node) {
      scene.removeObject( active_node );
      active_node = null;
    }
  }

  this.updateActiveNode = function( x, y, z )
  {
    if(!active_node) {
      this.createActiveNode( 0, 0, 0 );
    }
    var co = transform_coordinates( [
      translation.x + ((x) / project.focusedStack.scale) * resolution.x,
      translation.y + ((y) / project.focusedStack.scale) * resolution.y,
      translation.z + z * resolution.z]
    );
    active_node.position.set( co[0]*scale, co[1]*scale, co[2]*scale );
  }

  // add skeleton to scene
  this.addSkeleton = function( skeleton_id, skeleton_data )
  {
    var deleted=false;
    if( skeletons.hasOwnProperty(skeleton_id) ){
      // remove skeleton and refetch
      skeletons[skeleton_id].removeActorFromScene();
      delete skeletons[skeleton_id];
      deleted=true;
    }
    skeleton_data['id'] = skeleton_id;
    skeletons[skeleton_id] = new Skeleton( skeleton_data );
    if(!deleted) {
      self.addToSkeletonList( skeletons[skeleton_id] );
    }
    skeletons[skeleton_id].addCompositeActorToScene();
    return true;
  }

  // remove skeleton from scence
  this.removeSkeleton = function( skeleton_id )
  {
    if( !skeletons.hasOwnProperty(skeleton_id) ){
        alert("Skeleton "+skeleton_id+" does not exist. Cannot remove it!");
        return;
    } else {
        skeletons[skeleton_id].removeActorFromScene();
        delete skeletons[skeleton_id];
        return true;
    }
  }

  function create_stackboundingbox(x, y, z, dx, dy, dz)
  {
    // console.log('bouding box', x, y, z, dx, dy, dz);
    var gg = new THREE.CubeGeometry( dx, dy, dz );
    var mm = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
    var mesh = new THREE.Mesh( gg, mm );
    mesh.position.set(x, y, z);
    scene.add( mesh );
    // update camera
    camera.position.x = x;
    camera.position.y = y;
    camera.position.z = 200;
  }

  function debugaxes() {
    var object = new THREE.Axes();
    object.position.set( -1, -1, 0 );
    object.scale.x = object.scale.y = object.scale.z = 0.1;
    scene.add( object );
  }

  function draw_grid() {
    // Grid
    var line_material = new THREE.LineBasicMaterial( { color: 0xffffff, opacity: 0.2 } ),
      geometry = new THREE.Geometry(),
      floor = 0, step = 25;
    for ( var i = 0; i <= 40; i ++ ) {
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( - 500, floor, i * step - 500 ) ) );
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3(   500, floor, i * step - 500 ) ) );
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( i * step - 500, floor, -500 ) ) );
      geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( i * step - 500, floor,  500 ) ) );

    }
    grid_lines = new THREE.Line( geometry, line_material, THREE.LinePieces );
    scene.add( grid_lines );
  }

  function animate() {
    requestAnimationFrame( animate );
    render();
  }
/*
  function onDocumentMouseMove(event) {
    mouseX = ( event.clientX - self.divWidth );
    mouseY = ( event.clientY - self.divHeight );
  }*/

  function render() {
    controls.update();
    renderer.clear();
    renderer.render( scene, camera );
  }

  this.addToSkeletonList = function ( skeleton ) {
    var newElement = $('<li/>'),
        linkElement, enclosingObject = this;
    newElement.attr('id', '3d-object-' + skeleton.baseName );
    newElement.text(skeleton.baseName + ' ');
    linkElement = $('<a/>');
    linkElement.attr('href', '#');
    linkElement.text("(remove)");
    enclosingObject = this;
    linkElement.click(function (e) {
      self.removeSkeleton( skeleton.id );
      newElement.remove();
    });
    newElement.append(linkElement);
    $('#view-3d-webgl-object-list').append(newElement);
  };

  this.addFromCATMAID = function (projectID, skeletonID, neuronName) {
    if( skeletonID !== undefined )
    {
        jQuery.ajax({
          //url: "../../model/export.skeleton.json.php",
          url: "dj/"+projectID+"/skeleton/" + skeletonID + "/json",
          type: "GET",
          dataType: "json",
          success: function (skeleton_data) {
            skeleton_data['baseName'] = neuronName;
            self.addSkeleton( parseInt(skeletonID), skeleton_data );
          }
        });
    }
  };

  this.toString = function () {
    return "WebGL Viewer(" + this.divID + ")";
  };

}

function nameFromCATMAIDInfo(info) {
  return info.skeleton_name + ' [' + info.neuron_name + ']';
}

function addNeuronFromCATMAID(divID, info) {

  var divID_jQuery = '#' + divID;

  if (!$(divID_jQuery).data('viewer')) {
    $(divID_jQuery).data('viewer', new WebGLViewer(divID));
  }

  $(divID_jQuery).data('viewer').addFromCATMAID(info.project_id, info.skeleton_id, nameFromCATMAIDInfo(info));
}

function createWebGLViewerFromCATMAID(divID) {

  var divID_jQuery = '#' + divID;

  if (!$(divID_jQuery).data('viewer')) {
    $(divID_jQuery).data('viewer', new WebGLViewer(divID));
  }
}

function update3DWebGLViewATN() {
  var atn = SkeletonAnnotations.getActiveNodePosition();

  var divID = 'viewer-3d-webgl-canvas';
  var divID_jQuery = '#' + divID;

  if (!$(divID_jQuery).data('viewer')) {
    $(divID_jQuery).data('viewer', new WebGLViewer(divID));
  }

  if (!atn) {
    alert("You must have an active node selected to add its skeleton to the 3D WebGL View.");
    $(divID_jQuery).data('viewer').removeActiveNode();
    return;
  }

  $(divID_jQuery).data('viewer').updateActiveNode( atn.x, atn.y, atn.z );

}

function addSkeletonTo3DWebGLView(project_id, skeleton_id, skeleton_name, neuron_name) {
  var e = new Object();
  e['project_id'] = project_id;
  e['skeleton_id'] = skeleton_id;
  e['skeleton_name'] = skeleton_name;
  e['neuron_name'] = neuron_name;
  addNeuronFromCATMAID('viewer-3d-webgl-canvas', e);
}

function fullscreenWebGL() {
  var divID = 'viewer-3d-webgl-canvas';
  var divID_jQuery = '#' + divID;
  $(divID_jQuery).data('viewer').fullscreenWebGL();
}

function addTo3DWebGLView() {
  var atn_id = SkeletonAnnotations.getActiveNodeId();
  if (!atn_id) {
    alert("You must have an active node selected to add its skeleton to the 3D WebGL View.");
    return;
  }
  if (SkeletonAnnotations.getActiveNodeType() != "treenode") {
    alert("You can only add skeletons to the 3D WebGL View at the moment - please select a node of a skeleton.");
    return;
  }
  requestQueue.register('model/treenode.info.php', 'POST', {
    pid: project.id,
    tnid: atn_id
  }, function (status, text, xml) {
    if (status == 200) {
      var e = eval("(" + text + ")");
      if (e.error) {
        alert(e.error);
      } else {
        e['project_id'] = project.id;
        addNeuronFromCATMAID('viewer-3d-webgl-canvas', e);
      }
    } else {
      alert("Bad status code " + status + " mapping treenode ID to skeleton and neuron");
    }
    return true;
  });
}
<|endoftext|>