<commit_before>angular.module('ot.directive.entity', [
    'ot.service.core',
    'ot.service.event',
    'ot.service.task'
])
    .directive('otEntityImage', function () {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.entityImage.tpl.html',
            transclude: true,
            scope: {
                entity: '=',
                link: '@',
                title: '@'
            }
        };
    })
    .directive('otEntityDisabled', function ($http, ot) {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.entityDisabled.tpl.html',
            transclude: true,
            scope: {
                entity: '=',
                callback: '&'
            },
            controller: function ($scope) {
                $scope.enableEntity = function (entity) {
                    ot.pageCall($http.put(entity._enable, entity)).then(function () {
                        entity.disabled = false;
                    }).then($scope.callback);
                };
            }
        };
    })
    .directive('otEntityEvents', function ($http, $log, ot, otEventService, otTaskService) {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.entityEvents.tpl.html',
            scope: {
                entity: '='
            },
            link: function (scope) {
                scope.eventsLoaded = false;
                scope.renderEvent = otEventService.renderEvent;
                scope.renderSince = function (eventTime) {
                    return moment(eventTime).fromNow();
                };
                scope.$watch('entity', function () {
                    if (scope.entity && scope.entity._events) {
                        scope.events = [];
                        // loadEvents(scope.entity._events);
                    }
                });
                scope.moreEvents = function () {
                    if (!scope.eventsLoaded) {
                        loadEvents(scope.entity._events);
                    } else if (scope.eventsResource.pagination.next) {
                        otTaskService.stop('events');
                        loadEvents(scope.eventsResource.pagination.next);
                    }
                };

                otTaskService.register('events', function () {
                    if (scope.entity && scope.entity._events) {
                        scope.events = [];
                        loadEvents(scope.entity._events);
                    }
                }, 60000);

                function loadEvents(uri) {
                    $log.debug("[events] From URI = " + uri);
                    scope.loadingEvents = true;
                    ot.call($http.get(uri)).then(function (events) {
                        scope.eventsResource = events;
                        scope.events = scope.events.concat(events.resources);
                        scope.more = (events.resources.length > 0);
                        scope.eventsLoaded = true;
                    }).finally(function () {
                        scope.loadingEvents = false;
                    });
                }
            }
        };
    })
    .directive('otEntityDecorations', function ($http, ot) {
        function updateEntityDecorations(scope, entity) {
            ot.call($http.get(entity._decorations)).then(function (decorations) {
                scope.decorations = decorations.resources;
            });
        }

        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.entityDecorations.tpl.html',
            scope: {
                entity: '='
            },
            link: function (scope) {
                scope.$watch('entity', function () {
                    if (scope.entity) {
                        updateEntityDecorations(scope, scope.entity);
                    }
                });
            }
        };
    })
    .directive('otEntityEmbeddedDecorations', function ($http, ot) {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.entityDecorations.tpl.html',
            scope: {
                decorations: '='
            }
        };
    })
    .directive('otEntityExtra', function ($http, ot) {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.entityExtra.tpl.html',
            scope: {
                entity: '='
            },
            link: function (scope) {
                scope.$watch('entity', function () {
                    if (scope.entity && scope.entity._extra) {
                        scope.infosLoading = true;
                        ot.call($http.get(scope.entity._extra)).then(function (infos) {
                            scope.infosLoading = false;
                            scope.infos = infos;
                        });
                    }
                });
            }
        };
    })
    .directive('otBuildPromotionRuns', function ($modal) {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.buildPromotionRuns.tpl.html',
            scope: {
                promotionRuns: '='
            },
            controller: function ($scope) {
                $scope.displayPromotionRuns = function (promotionRun) {
                    $modal.open({
                        templateUrl: 'app/dialog/dialog.promotionRuns.tpl.html',
                        controller: 'otDialogPromotionRuns',
                        resolve: {
                            config: function () {
                                return {
                                    build: promotionRun.build,
                                    promotionLevel: promotionRun.promotionLevel,
                                    uri: promotionRun._all
                                };
                            }
                        }
                    });
                };
            }
        };
    })
    .directive('otValidationRunStatus', function () {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.validationRunStatus.tpl.html',
            scope: {
                status: '='
            }
        };
    })
    .directive('otValidationStampRunView', function () {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.validationStampRunView.tpl.html',
            scope: {
                validationStampRunView: '='
            }
        };
    })
    .directive('otValidationRunStatusNone', function () {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.validationRunStatusNone.tpl.html'
        };
    })
    .directive('otSignature', function () {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.signature.tpl.html',
            scope: {
                value: '=',
                user: '=',
                time: '='
            }
        };
    })
;<commit_msg>#551 Disabling automated loading of events<commit_after>angular.module('ot.directive.entity', [
    'ot.service.core',
    'ot.service.event',
    'ot.service.task'
])
    .directive('otEntityImage', function () {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.entityImage.tpl.html',
            transclude: true,
            scope: {
                entity: '=',
                link: '@',
                title: '@'
            }
        };
    })
    .directive('otEntityDisabled', function ($http, ot) {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.entityDisabled.tpl.html',
            transclude: true,
            scope: {
                entity: '=',
                callback: '&'
            },
            controller: function ($scope) {
                $scope.enableEntity = function (entity) {
                    ot.pageCall($http.put(entity._enable, entity)).then(function () {
                        entity.disabled = false;
                    }).then($scope.callback);
                };
            }
        };
    })
    .directive('otEntityEvents', function ($http, $log, ot, otEventService, otTaskService) {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.entityEvents.tpl.html',
            scope: {
                entity: '='
            },
            link: function (scope) {
                scope.eventsLoaded = false;
                scope.renderEvent = otEventService.renderEvent;
                scope.renderSince = function (eventTime) {
                    return moment(eventTime).fromNow();
                };
                scope.$watch('entity', function () {
                    if (scope.entity && scope.entity._events) {
                        scope.events = [];
                        // loadEvents(scope.entity._events);
                    }
                });
                scope.moreEvents = function () {
                    if (!scope.eventsLoaded) {
                        loadEvents(scope.entity._events);
                    } else if (scope.eventsResource.pagination.next) {
                        otTaskService.stop('events');
                        loadEvents(scope.eventsResource.pagination.next);
                    }
                };

                function loadEvents(uri) {
                    $log.debug("[events] From URI = " + uri);
                    scope.loadingEvents = true;
                    ot.call($http.get(uri)).then(function (events) {
                        scope.eventsResource = events;
                        scope.events = scope.events.concat(events.resources);
                        scope.more = (events.resources.length > 0);
                        scope.eventsLoaded = true;
                    }).finally(function () {
                        scope.loadingEvents = false;
                    });
                }
            }
        };
    })
    .directive('otEntityDecorations', function ($http, ot) {
        function updateEntityDecorations(scope, entity) {
            ot.call($http.get(entity._decorations)).then(function (decorations) {
                scope.decorations = decorations.resources;
            });
        }

        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.entityDecorations.tpl.html',
            scope: {
                entity: '='
            },
            link: function (scope) {
                scope.$watch('entity', function () {
                    if (scope.entity) {
                        updateEntityDecorations(scope, scope.entity);
                    }
                });
            }
        };
    })
    .directive('otEntityEmbeddedDecorations', function ($http, ot) {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.entityDecorations.tpl.html',
            scope: {
                decorations: '='
            }
        };
    })
    .directive('otEntityExtra', function ($http, ot) {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.entityExtra.tpl.html',
            scope: {
                entity: '='
            },
            link: function (scope) {
                scope.$watch('entity', function () {
                    if (scope.entity && scope.entity._extra) {
                        scope.infosLoading = true;
                        ot.call($http.get(scope.entity._extra)).then(function (infos) {
                            scope.infosLoading = false;
                            scope.infos = infos;
                        });
                    }
                });
            }
        };
    })
    .directive('otBuildPromotionRuns', function ($modal) {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.buildPromotionRuns.tpl.html',
            scope: {
                promotionRuns: '='
            },
            controller: function ($scope) {
                $scope.displayPromotionRuns = function (promotionRun) {
                    $modal.open({
                        templateUrl: 'app/dialog/dialog.promotionRuns.tpl.html',
                        controller: 'otDialogPromotionRuns',
                        resolve: {
                            config: function () {
                                return {
                                    build: promotionRun.build,
                                    promotionLevel: promotionRun.promotionLevel,
                                    uri: promotionRun._all
                                };
                            }
                        }
                    });
                };
            }
        };
    })
    .directive('otValidationRunStatus', function () {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.validationRunStatus.tpl.html',
            scope: {
                status: '='
            }
        };
    })
    .directive('otValidationStampRunView', function () {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.validationStampRunView.tpl.html',
            scope: {
                validationStampRunView: '='
            }
        };
    })
    .directive('otValidationRunStatusNone', function () {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.validationRunStatusNone.tpl.html'
        };
    })
    .directive('otSignature', function () {
        return {
            restrict: 'E',
            templateUrl: 'app/directive/directive.signature.tpl.html',
            scope: {
                value: '=',
                user: '=',
                time: '='
            }
        };
    })
;<|endoftext|>


<commit_before>// BRICOLEUR

var conf = require('./__conf.json')
var through = require('through')
var proc = process.title // node or browser
var interface = {}
var api

module.exports = function bricoleur (data) {

  var WILDS = {}

  WILDS['_'] = function (i,o) { // _ PROCESS

  }
  WILDS['^'] = function (i,o) { // ^ LIBRARY

  }
  WILDS['*'] = function (i,o) { // * MODULE

  }
  WILDS['#'] = function (i,o) { // # CONNECT

  }

  var filter = {
    put: function (d) {
      var path = d.key.split(':')

    },
    del: function (d) {
      var path = d.key.split(':')

    }
  }

  var liveStream = data.liveStream({old:false})

  liveStream.on('data', function dataFilter {
    if (filter[d.type]) filter[d.type](d)
  })

  return api
}

interface.ls = function (result) {
  // show active modules and connections
  for (module in WILDS['_']) {

  }
}
interface.search = function (pattern, result) {
  var res = []
  var ks = data.createKeyStream()
  ks.on('data', function (d) {
    var path = d.split(':')
    if (pattern[1] === path[1]) res.push(d)
  })
  ks.on('end', function () {
    result(res)
  })
}

api = through(function input (d) {
  interface[d.cmd](d, function (res) {
    self.emit('data', res)
  })
}, function end () {
  this.emit('end')
}, {autoDestroy:false})
<commit_msg>fix syntax err in brico dataFilter fn<commit_after>// BRICOLEUR

var conf = require('./__conf.json')
var through = require('through')
var proc = process.title // node or browser
var interface = {}

module.exports = function bricoleur (data) {

  var WILDS = {}

  WILDS['_'] = function (i,o) { // _ PROCESS

  }
  WILDS['^'] = function (i,o) { // ^ LIBRARY

  }
  WILDS['*'] = function (i,o) { // * MODULE

  }
  WILDS['#'] = function (i,o) { // # CONNECT

  }

  var liveStream = data.liveStream({old:false})

  liveStream.on('data', function dataFilter (d) {
    if (filter[d.type]) filter[d.type](d)
  })

  var filter = {
    put: function (d) {
      var path = d.key.split(':')

    },
    del: function (d) {
      var path = d.key.split(':')

    }
  }

  // use an event emitter?
  // interface = require('events').EventEmitter
  interface.ls = function (result) {// show active modules and connections
    for (module in WILDS['_']) {

    }
  }
  interface.search = function (pattern, result) {
    var res = []
    var ks = data.createKeyStream()
    ks.on('data', function (d) {
      var path = d.split(':')
      if (pattern[1] === path[1]) res.push(d)
    })
    ks.on('end', function () {
      result(res)
    })
  }

  // STREAM --> EVENT EMITTER

  var api = through(function input (d) {
    var self = this
    interface[d.cmd](d, function (res) {
      self.emit('data', res)
    })
  }, function end () {
    this.emit('end')
  }, {autoDestroy:false})

  return api
}
<|endoftext|>


<commit_before>'use strict';

var mean = require('meanio');
var fs = require('fs');
var http = require('http');
var request = require('request')
var Tabletop = require('tabletop');
var config=mean.config.clean;

var rizerData={}

/* Splits data into separate paragraphs*/
function splitParagraphs(source){
	var splitGraphs = '';

	var paragraphs = (source===null) ? '' : source;
	paragraphs = paragraphs.split('\n')

	for (var i = 0; i<paragraphs.length; i++){
		splitGraphs += '
' + paragraphs[i] + '
';
	}
	return splitGraphs
}

function renderLiveJson() {

}

function buildRizers(apiStr,profileStr,profileObj) {
	/* if we're using a flat file, we'll have profileStr
	   if we're coming from tableTop, we'll have profileObj
	   did it that way because tableTop wasn't nicely stringify-ing
	*/

	/**** PROFILE JSON ****/
	var allProfileJson;
	if (profileObj) {
		allProfileJson=profileObj;
	} else {
		allProfileJson=JSON.parse(profileStr);
	}
	//console.log("ALL PROFILES JSON IS " + allProfileJson)
	var profilesById = {};
	for (var i=0; i < allProfileJson.length; i++) {
		var oneProfile = allProfileJson[i];
		profilesById[oneProfile.id] = oneProfile;
	}

	/**** API JSON ****/
	var allRizerJson = JSON.parse(apiStr).accounts;
	var rizersById = {};
	for (i = 0; i < allRizerJson.length; i++) {
		var oneRizer = allRizerJson[i];
		rizersById[oneRizer.id] = oneRizer;
		oneRizer.profile = profilesById[oneRizer.id];
		oneRizer.location = oneRizer.city_name + ', ' + oneRizer.country_name;

		oneRizer.rize_summary = splitParagraphs(oneRizer.rize_summary);

		//Trying to split the categories into an array and return the first value
		oneRizer.categories = (oneRizer.categories === null) ? '' : oneRizer.categories;
		oneRizer.categories = oneRizer.categories.split(', ');
		oneRizer.categories = oneRizer.categories[0];

		oneRizer.person = false;
		if (oneRizer.account_type === 'Person') {
			oneRizer.person = true;
		} else {
			//Add the preferred profile image
			//Order should be Spreadsheet -> Twitter -> Facebook
			oneRizer.profile_image = '';

			if (oneRizer.twitter.profile_image_url_https !== null){
				oneRizer.profile_image = oneRizer.twitter.profile_image_url_https;
			} else if (oneRizer.facebook.profile_image !== null){
				oneRizer.profile_image = oneRizer.facebook.profile_image;
			} else {
				//add a column to the spreadsheet for a fallback image/logo
			}
		}
	}

	return {allRizerJson:allRizerJson, rizersById:rizersById} ;
}

module.exports = function(System){

	function loadRizerDataLive() {
		request(config.accounts_api_URL, function (error, response, body) {
			if (!error && response.statusCode == 200) {
				rizerData.apiStr=body;
				console.log("requesting spreadsheet from " + config.spreadsheet_URL);
				var options = {
					key: config.spreadsheet_URL,
					postProcess: function(element) {
						element["timestamp"] = Date.parse( element["date"] );
					},
					callback: function(data) {
						rizerData.profileObj=data["profiles"].elements;
						rizerData.rd=buildRizers(rizerData.apiStr,"",rizerData.profileObj);

						console.log("LIVE DATA HAS FINISHED LOADING FOR THE APP!")
					}
				};
				Tabletop.init(options);

			}
		});
	}

	function loadRizerDataDisk() {
		var profileStr=fs.readFileSync( process.cwd() + config.profileFlatPath);
		var apiStr=fs.readFileSync( process.cwd() + config.apiFlatPath );

		rizerData.rd=buildRizers(apiStr,profileStr);
		console.log("DISK DATA LOADED!")
	}

	//PICK YOUR POISON - LOAD FROM DISK OR FROM API/SPREADSHEET
	if (config.useLiveData) {
		loadRizerDataLive();
	} else {
		loadRizerDataDisk();
	}

	return {
		render:function(req,res){
			res.render('index',{ locals: { config: System.config.clean }});
		},
		aggregatedList:function(req,res) {
			res.send(res.locals.aggregatedassets);
		},
		showAll:function(req,res){
			console.log('RETURNING RIZER JSON');
		//	if(process.env.NODE_ENV == "development") {
			if (rizerData && rizerData.rd && rizerData.rd.allRizerJson) {
				res.json(rizerData.rd.allRizerJson);
			} else {
				res.json({});
			}
			//renderLiveJson();
		},
		showOne:function(req,res) {
			console.log('returning one rizer');
			if (rizerData && rizerData.rd && rizerData.rd.rizersById) {
				var oneRizer=rizerData.rd.rizersById[req.params.id];
				res.json(oneRizer);
			} else {
				res.json({});
			}
		}
	};
};

<commit_msg>Use spreadsheet profileImage as the default profile image.<commit_after>'use strict';

var mean = require('meanio');
var fs = require('fs');
var http = require('http');
var request = require('request')
var Tabletop = require('tabletop');
var config=mean.config.clean;

var rizerData={}

/* Splits data into separate paragraphs*/
function splitParagraphs(source){
	var splitGraphs = '';

	var paragraphs = (source===null) ? '' : source;
	paragraphs = paragraphs.split('\n')

	for (var i = 0; i<paragraphs.length; i++){
		splitGraphs += '
' + paragraphs[i] + '
';
	}
	return splitGraphs
}

function renderLiveJson() {

}

function buildRizers(apiStr,profileStr,profileObj) {
	/* if we're using a flat file, we'll have profileStr
	   if we're coming from tableTop, we'll have profileObj
	   did it that way because tableTop wasn't nicely stringify-ing
	*/

	/**** PROFILE JSON ****/
	var allProfileJson;
	if (profileObj) {
		allProfileJson=profileObj;
	} else {
		allProfileJson=JSON.parse(profileStr);
	}
	//console.log("ALL PROFILES JSON IS " + allProfileJson)
	var profilesById = {};
	for (var i=0; i < allProfileJson.length; i++) {
		var oneProfile = allProfileJson[i];
		profilesById[oneProfile.id] = oneProfile;
	}

	/**** API JSON ****/
	var allRizerJson = JSON.parse(apiStr).accounts;
	var rizersById = {};
	for (i = 0; i < allRizerJson.length; i++) {
		var oneRizer = allRizerJson[i];
		rizersById[oneRizer.id] = oneRizer;
		oneRizer.profile = profilesById[oneRizer.id];
		oneRizer.location = oneRizer.city_name + ', ' + oneRizer.country_name;

		oneRizer.rize_summary = splitParagraphs(oneRizer.rize_summary);

		//Trying to split the categories into an array and return the first value
		oneRizer.categories = (oneRizer.categories === null) ? '' : oneRizer.categories;
		oneRizer.categories = oneRizer.categories.split(', ');
		oneRizer.categories = oneRizer.categories[0];

		//Add responsive featured image base.
		/*
		oneRizer.profile.image_base = oneRizer.profile.image;
		oneRizer.profile.image_base = oneRizer.profile.image_base.replace(".jpeg", "");
		*/

		oneRizer.person = false;
		if (oneRizer.account_type === 'Person') {
			oneRizer.person = true;
		} else {
		}

		//Order should be Spreadsheet -> Twitter -> Facebook
		oneRizer.profile_image = '';

		if (oneRizer.profile.profileImage != ""){
			oneRizer.profile_image = oneRizer.profile.profileImage;
		} else if (oneRizer.twitter.profile_image_url_https !== null){
			oneRizer.profile_image = oneRizer.twitter.profile_image_url_https;
		} else if (oneRizer.facebook.profile_image !== null){
			oneRizer.profile_image = oneRizer.facebook.profile_image;
		} else {
			//add a column to the spreadsheet for a fallback image/logo
		}

	}

	return {allRizerJson:allRizerJson, rizersById:rizersById} ;
}

module.exports = function(System){

	function loadRizerDataLive() {
		request(config.accounts_api_URL, function (error, response, body) {
			if (!error && response.statusCode == 200) {
				rizerData.apiStr=body;
				console.log("requesting spreadsheet from " + config.spreadsheet_URL);
				var options = {
					key: config.spreadsheet_URL,
					postProcess: function(element) {
						element["timestamp"] = Date.parse( element["date"] );
					},
					callback: function(data) {
						rizerData.profileObj=data["profiles"].elements;
						rizerData.rd=buildRizers(rizerData.apiStr,"",rizerData.profileObj);

						console.log("LIVE DATA HAS FINISHED LOADING FOR THE APP!")
					}
				};
				Tabletop.init(options);

			}
		});
	}

	function loadRizerDataDisk() {
		var profileStr=fs.readFileSync( process.cwd() + config.profileFlatPath);
		var apiStr=fs.readFileSync( process.cwd() + config.apiFlatPath );

		rizerData.rd=buildRizers(apiStr,profileStr);
		console.log("DISK DATA LOADED!")
	}

	//PICK YOUR POISON - LOAD FROM DISK OR FROM API/SPREADSHEET
	if (config.useLiveData) {
		loadRizerDataLive();
	} else {
		loadRizerDataDisk();
	}

	return {
		render:function(req,res){
			res.render('index',{ locals: { config: System.config.clean }});
		},
		aggregatedList:function(req,res) {
			res.send(res.locals.aggregatedassets);
		},
		showAll:function(req,res){
			console.log('RETURNING RIZER JSON');
		//	if(process.env.NODE_ENV == "development") {
			if (rizerData && rizerData.rd && rizerData.rd.allRizerJson) {
				res.json(rizerData.rd.allRizerJson);
			} else {
				res.json({});
			}
			//renderLiveJson();
		},
		showOne:function(req,res) {
			console.log('returning one rizer');
			if (rizerData && rizerData.rd && rizerData.rd.rizersById) {
				var oneRizer=rizerData.rd.rizersById[req.params.id];
				res.json(oneRizer);
			} else {
				res.json({});
			}
		}
	};
};

<|endoftext|>


<commit_before>import mode from './mode'
import login from './login'
import items from './items'
import shelf from './shelf'

export {
  mode,
  login,
  items,
  shelf,
}
<commit_msg>:fire: remove<commit_after><|endoftext|>


<commit_before>(function() {

angular.module("Genoverse", []).directive("genoverse", genoverse);

    function genoverse() {
        return {
            restrict: 'E',
            scope: false,
            template:
                "
" +
                "
" +
                "        " +
                "        View in Ensembl" +
                "        |" +
                "            UCSC" +
                "        " +
                "
" +
                "

" +
                "
",
            link: function(scope, element, attrs) {

                // Initialization
                // --------------

                render();

                // set Genoverse -> Angular data flow
                var genoverseToAngularWatches = setGenoverseToAngularWatches();

                // set Angular -> Genoverse data flow
                setAngularToGenoverseWatches(genoverseToAngularWatches);

                // these need to be re-attached on every re-creation of browser
                registerGenoverseEvents();

                // resize genoverse on browser width changes - attach once only
                window.onresize(setGenoverseWidth);

                // Functions/methods
                // -----------------

                function render() {
                    console.log("scope.genome in render = ", scope.genome);
                    var genoverseConfig = {
                        container: element.find('#genoverse'),
                        chr: scope.chromosome,
                        species: scope.genome.species,
                        showUrlCoords: false, // do not show genomic coordinates in the url
                        plugins: ['controlPanel', 'resizer', 'fileDrop'],
                        tracks: [
                            Genoverse.Track.Scalebar,
                            Genoverse.Track.extend({
                                name: 'Sequence',
                                model: configureGenoverseModel('ensemblSequence'),
                                view: Genoverse.Track.View.Sequence,
                                controller: Genoverse.Track.Controller.Sequence,
                                resizable: 'auto',
                                100000: false,
                            }),
                            Genoverse.Track.extend({
                                name: 'Genes',
                                info: 'Ensembl API genes',
                                labels: true,
                                model: configureGenoverseModel('ensemblGene'),
                                view: Genoverse.Track.View.Gene.Ensembl,
                                controller: Genoverse.Track.Controller.Ensembl,
                            }),
                            Genoverse.Track.extend({
                                name: 'Transcripts',
                                info: 'Ensembl API transcripts',
                                labels: true,
                                model: configureGenoverseModel('ensemblTranscript'),
                                view: Genoverse.Track.View.Transcript.Ensembl,
                                controller: Genoverse.Track.Controller.Ensembl,
                            }),
                            Genoverse.Track.extend({
                                name: 'RNAcentral',
                                id: 'RNAcentral',
                                info: 'Unique RNAcentral Sequences',
                                labels: true,
                                model: configureGenoverseModel('rnacentral'),
                                view: Genoverse.Track.View.Transcript.Ensembl,
                                controller: Genoverse.Track.Controller.Ensembl,
                            })
                        ]
                    };

                    // configure karyotype display
                    if (isKaryotypeAvailable(scope.genome.species)) {
                        genoverseConfig.plugins.push('karyotype');
                        genoverseConfig.genome = 'grch38'; // determine dynamically when more karyotypes are available
                    } else {
                        genoverseConfig.chromosomeSize = Math.pow(10, 20); // should be greater than any chromosome size
                    }

                    scope.browser = new Genoverse(genoverseConfig);

                    // karyotype is available only for a limited number of species,
                    // so a placeholder div is used to replace the karyotype div
                    // to keep the display consistent
                    if (!isKaryotypeAvailable(urlencodeSpecies(scope.genome.species))) {
                        element.find(".gv_wrapper").prepend(
                            "
" +
                            "
Karyotype display is not available
" +
                            "
"
                        );
                    }

                    setGenoverseWidth();
                }

                function setGenoverseToAngularWatches() {
                    var speciesWatch = scope.$watch('browser.species', function(newValue, oldValue) {
                        scope.genome = getGenomeByName(newValue);
                    });

                    var chrWatch = scope.$watch('browser.chr', function(newValue, oldValue) {
                        scope.chromosome = newValue;
                    });

                    var startWatch = scope.$watch('browser.start', function(newValue, oldValue) {
                        scope.start = newValue;
                    });

                    var endWatch = scope.$watch('browser.end', function(newValue, oldValue) {
                        scope.end = newValue;
                    });

                    return [speciesWatch, chrWatch, startWatch, endWatch];
                }

                function setAngularToGenoverseWatches(genoverseToAngularWatches) {
                    scope.$watch('start', function(newValue, oldValue) {
                        scope.browser.setRange(newValue, scope.end, true);
                    });

                    scope.$watch('end', function(newValue, oldValue) {
                        scope.browser.setRange(scope.start, newValue, true);
                    });

                    scope.$watch('genome', function(newValue, oldValue) {
                        // destroy the old instance of browser and callbacks/watches
                        genoverseToAngularWatches.forEach(function (element) { element(); }); // clear the old watches
                        element.find('#genoverse').html(''); // clear the innerHtml of directive
                        delete scope.browser; // clear old instance of browser

                        // create a new instance of browser and set the new watches for it
                        render();
                        registerGenoverseEvents();
                        setGenoverseToAngularWatches();
                    });

                    scope.$watch('chromosome', function(newValue, oldValue) {
                        // destroy the old instance of browser and callback/watches
                        genoverseToAngularWatches.forEach(function (element) { element(); }); // clear the old watches
                        element.find('#genoverse').html(''); // clear the innerHtml of directive
                        delete scope.browser; // clear old instance of browser

                        // create a new instance of browser and set the new watches for it
                        render();
                        registerGenoverseEvents();
                        setGenoverseToAngularWatches();
                    })
                }

                /**
                 * Each Genoverse model is configured with an organism-specific url.
                 * In addition, a new RNAcentral models that's mimicking Ensembl API is defined.
                 */
                function configureGenoverseModel(modelType) {
                    var model, url;
                    var endpoint = getEnsemblOrEnsemblgenomesEndpoint(urlencodeSpecies(scope.genome.species));

                    if (modelType === 'ensemblGene') {
                        // Ensembl Gene track
                        url = '//__ENDPOINT__/overlap/region/__SPECIES__/__CHR__:__START__-__END__?feature=gene;content-type=application/json'.replace('__ENDPOINT__', endpoint).replace('__SPECIES__', urlencodeSpecies(scope.genome.species));
                        model = Genoverse.Track.Model.Gene.Ensembl.extend({ url: url });
                    }
                    else if (modelType === 'ensemblTranscript') {
                        // Ensembl Transcript track
                        url = '//__ENDPOINT__/overlap/region/__SPECIES__/__CHR__:__START__-__END__?feature=transcript;feature=exon;feature=cds;content-type=application/json'.replace('__ENDPOINT__', endpoint).replace('__SPECIES__', urlencodeSpecies(scope.genome.species));
                        model = Genoverse.Track.Model.Transcript.Ensembl.extend({ url: url });
                    }
                    else if (modelType === 'ensemblSequence') {
                        // Ensembl sequence view
                        url = '//__ENDPOINT__/sequence/region/__SPECIES__/__CHR__:__START__-__END__?content-type=text/plain'.replace('__ENDPOINT__', endpoint).replace('__SPECIES__', urlencodeSpecies(scope.genome.species));
                        model = Genoverse.Track.Model.Sequence.Ensembl.extend({ url: url });
                    }
                    else if (modelType === 'rnacentral') {
                        // custom RNAcentral track
                        if (!window.location.origin) { window.location.origin = window.location.protocol + "//" + window.location.host + '/'; }

                        url = window.location.origin + '/api/v1/overlap/region/__SPECIES__/__CHR__:__START__-__END__'.replace('__SPECIES__', urlencodeSpecies(scope.genome.species));
                        model = Genoverse.Track.Model.Gene.Ensembl.extend({
                            url: url,
                            parseData: function (data) {
                                for (var i = 0; i < data.length; i++) {
                                    var feature = data[i];

                                    if (feature.feature_type === 'transcript' && !this.featuresById[feature.ID]) {
                                        feature.id    = feature.ID;
                                        feature.label = feature.external_name;
                                        feature.exons = [];
                                        feature.cds   = [];

                                        this.insertFeature(feature);
                                    }
                                    else if (feature.feature_type === 'exon' && this.featuresById[feature.Parent]) {
                                        feature.id = feature.ID;

                                        if (!this.featuresById[feature.Parent].exons[feature.id]) {
                                            this.featuresById[feature.Parent].exons.push(feature);
                                            this.featuresById[feature.Parent].exons[feature.id] = feature;
                                        }
                                    }
                                }
                            }
                        });
                    }

                  return model;
                }

                /**
                 * Dynamically choose whether to use E! or EG REST API based on species.
                 * If species not in E!, use EG.
                 * Ensembl species list: http://www.ensembl.org/info/about/species.html
                 */
                function getEnsemblOrEnsemblgenomesEndpoint(species) {
                    var ensemblSpecies = [
                        "ailuropoda_melanoleuca",
                        "anas_platyrhynchos",
                        "anolis_carolinensis",
                        "astyanax_mexicanus",
                        "bos_taurus",
                        "callithrix_jacchus",
                        "canis_lupus_familiaris",
                        "cavia_porcellus",
                        "ceratotherium_simum_simum",
                        "chlorocebus_sabaeus",
                        "choloepus_hoffmanni",
                        "chrysemys_picta_bellii",
                        "ciona_intestinalis",
                        "ciona_savignyi",
                        "cricetulus_griseus",
                        "danio_rerio",
                        "dasypus_novemcinctus",
                        "dipodomys_ordii",
                        "drosophila_melanogaster",
                        "echinops_telfairi",
                        "equus_caballus",
                        "erinaceus_europaeus",
                        "felis_catus",
                        "ficedula_albicollis",
                        "gadus_morhua",
                        "gallus_gallus",
                        "gasterosteus_aculeatus",
                        "gorilla_gorilla_gorilla",
                        "heterocephalus_glaber",
                        "homo_sapiens",
                        "ictidomys_tridecemlineatus",
                        "latimeria_chalumnae",
                        "lepisosteus_oculatus",
                        "loxodonta_africana",
                        "macaca_fascicularis",
                        "macaca_mulatta",
                        "macropus_eugenii",
                        "meleagris_gallopavo",
                        "melopsittacus_undulatus",
                        "microcebus_murinus",
                        "microtus_ochrogaster",
                        "monodelphis_domestica",
                        "mus_musculus",
                        "mustela_putorius_furo",
                        "myotis_lucifugus",
                        "nomascus_leucogenys",
                        "ochotona_princeps",
                        "oreochromis_niloticus",
                        "ornithorhynchus_anatinus",
                        "orycteropus_afer_afer",
                        "oryctolagus_cuniculus",
                        "oryzias_latipes",
                        "otolemur_garnettii",
                        "ovis_aries",
                        "pan_troglodytes",
                        "papio_anubis",
                        "papio_hamadryas",
                        "pelodiscus_sinensis",
                        "petromyzon_marinus",
                        "poecilia_formosa",
                        "pongo_abelii",
                        "procavia_capensis",
                        "pteropus_vampyrus",
                        "rattus_norvegicus",
                        "saimiri_boliviensis",
                        "sarcophilus_harrisii",
                        "sorex_araneus",
                        "sus_scrofa",
                        "sus_scrofa_map",
                        "taeniopygia_guttata",
                        "takifugu_rubripes",
                        "tarsius_syrichta",
                        "tetraodon_nigroviridis",
                        "tupaia_belangeri",
                        "tursiops_truncatus",
                        "vicugna_pacos",
                        "xenopus_tropicalis",
                        "xiphophorus_maculatus"
                    ];
                    // "saccharomyces_cerevisiae", "caenorhabditis_elegans"];
                    // "saccharomyces_cerevisiae", "caenorhabditis_elegans" could use either E! or EG

                    return ensemblSpecies.indexOf(species) > -1 ? 'rest.ensembl.org' : 'rest.ensemblgenomes.org';
                }

                /**
                 * Determine if karyotype information is available for this species.
                 */
                function isKaryotypeAvailable(species) {
                    return speciesSupported(species) && chromosomeSizeAvailable();
                }

                function speciesSupported(species) {
                    var supportedSpecies = ["homo_sapiens"]; // TODO: support more species
                    return supportedSpecies.indexOf(species) !== -1;
                }

                /**
                 * Get a list of chromosomes from the karyotype object and determine
                 * whether the size of the displayed region is known.
                 * Some RNAs are defined on scaffolds or other non-chromosomal objects
                 * for which the size is not stored in the karyotype object.
                 */
                function chromosomeSizeAvailable() {
                    var chromosomes = [];
                    for (var key in grch38) { // TODO: WHERE IS THIS grch38 VARIABLE DEFINED? IS IT GLOBAL?
                        chromosomes.push(key);
                    }
                    return chromosomes.indexOf(scope.chromosome.toString())
                }

                /**
                 * Register custom Genoverse events.
                 */
                function registerGenoverseEvents() {
                    // resize tracks after load
                    scope.browser.on({
                        // this event is called, whenever the user updates the browser viewport location
                        afterSetRange: function () {

                            // let angular update its model in response to coordinates change
                            if (!scope.$$phase) scope.$apply(); // anti-pattern, but no other way to use FRP in angular

                            // expand the tracks by programmatically clicking the resizer button
                            setTimeout(function() {
                                element.find('.genoverse-wrap .resizer').click();
                            }, 1000);
                        }
                    });
                }

                /**
                 * Maximize Genoverse container width.
                 */
                function setGenoverseWidth() {
                    var w = element.find('.container').width();
                    element.find('.wrap').width(w);
                    element.find('#genoverse').width(w);
                }

                // Helper functions
                // ----------------

                /**
                 * Returns an object from genomes Array by its species name or null, if not found.
                 * @param name {string} e.g. "Homo sapiens" or "homo_sapiens" (like in url) or "human" (synonym)
                 * @returns {Object or null} element of genomes Array
                 */
                function getGenomeByName(name) {
                    name = name.replace(/_/g, ' '); // if name was urlencoded, replace '_' with whitespaces

                    for (var i = 0; i < genomes.length; i++) {
                        if (name.toLowerCase() == genomes[i].name.toLowerCase()) { // test scientific name
                            return genomes[i];
                        }
                        else { // if name is not a scientific name, may be it's a synonym?
                            var synonyms = []; // convert all synonyms to lower case to make case-insensitive comparison

                            genomes[i].synonyms.forEach(function(synonym) {
                                synonyms.push(synonym.toLowerCase());
                            });

                            if (synonyms.indexOf(name.toLowerCase()) > -1) return genomes[i];
                        }
                    }

                    return null; // if no match found, return null
                }

                /**
                 * Replaces whitespaces with underscores in scientific names of species.
                 * @param species (string} - scientific name of a species with whitespaces, e.g. Homo Sapiens
                 * @returns {string} - scientific name of species with whitespaces replaces with underscores
                 */
                function urlencodeSpecies(species) {
                    // Canis familiaris is a special case
                    if (species == 'Canis familiaris') { species = 'Canis lupus familiaris'; }
                    return species.replace(/ /g, '_').toLowerCase();
                }
            }
        };
    }

})();<commit_msg> #94 Minor fix in JSDoc.<commit_after>(function() {

angular.module("Genoverse", []).directive("genoverse", genoverse);

    function genoverse() {
        return {
            restrict: 'E',
            scope: false,
            template:
                "
" +
                "
" +
                "        " +
                "        View in Ensembl" +
                "        |" +
                "            UCSC" +
                "        " +
                "
" +
                "

" +
                "
",
            link: function(scope, element, attrs) {

                // Initialization
                // --------------

                render();

                // set Genoverse -> Angular data flow
                var genoverseToAngularWatches = setGenoverseToAngularWatches();

                // set Angular -> Genoverse data flow
                setAngularToGenoverseWatches(genoverseToAngularWatches);

                // these need to be re-attached on every re-creation of browser
                registerGenoverseEvents();

                // resize genoverse on browser width changes - attach once only
                window.onresize(setGenoverseWidth);

                // Functions/methods
                // -----------------

                function render() {
                    console.log("scope.genome in render = ", scope.genome);
                    var genoverseConfig = {
                        container: element.find('#genoverse'),
                        chr: scope.chromosome,
                        species: scope.genome.species,
                        showUrlCoords: false, // do not show genomic coordinates in the url
                        plugins: ['controlPanel', 'resizer', 'fileDrop'],
                        tracks: [
                            Genoverse.Track.Scalebar,
                            Genoverse.Track.extend({
                                name: 'Sequence',
                                model: configureGenoverseModel('ensemblSequence'),
                                view: Genoverse.Track.View.Sequence,
                                controller: Genoverse.Track.Controller.Sequence,
                                resizable: 'auto',
                                100000: false,
                            }),
                            Genoverse.Track.extend({
                                name: 'Genes',
                                info: 'Ensembl API genes',
                                labels: true,
                                model: configureGenoverseModel('ensemblGene'),
                                view: Genoverse.Track.View.Gene.Ensembl,
                                controller: Genoverse.Track.Controller.Ensembl,
                            }),
                            Genoverse.Track.extend({
                                name: 'Transcripts',
                                info: 'Ensembl API transcripts',
                                labels: true,
                                model: configureGenoverseModel('ensemblTranscript'),
                                view: Genoverse.Track.View.Transcript.Ensembl,
                                controller: Genoverse.Track.Controller.Ensembl,
                            }),
                            Genoverse.Track.extend({
                                name: 'RNAcentral',
                                id: 'RNAcentral',
                                info: 'Unique RNAcentral Sequences',
                                labels: true,
                                model: configureGenoverseModel('rnacentral'),
                                view: Genoverse.Track.View.Transcript.Ensembl,
                                controller: Genoverse.Track.Controller.Ensembl,
                            })
                        ]
                    };

                    // configure karyotype display
                    if (isKaryotypeAvailable(scope.genome.species)) {
                        genoverseConfig.plugins.push('karyotype');
                        genoverseConfig.genome = 'grch38'; // determine dynamically when more karyotypes are available
                    } else {
                        genoverseConfig.chromosomeSize = Math.pow(10, 20); // should be greater than any chromosome size
                    }

                    scope.browser = new Genoverse(genoverseConfig);

                    // karyotype is available only for a limited number of species,
                    // so a placeholder div is used to replace the karyotype div
                    // to keep the display consistent
                    if (!isKaryotypeAvailable(urlencodeSpecies(scope.genome.species))) {
                        element.find(".gv_wrapper").prepend(
                            "
" +
                            "
Karyotype display is not available
" +
                            "
"
                        );
                    }

                    setGenoverseWidth();
                }

                function setGenoverseToAngularWatches() {
                    var speciesWatch = scope.$watch('browser.species', function(newValue, oldValue) {
                        scope.genome = getGenomeByName(newValue);
                    });

                    var chrWatch = scope.$watch('browser.chr', function(newValue, oldValue) {
                        scope.chromosome = newValue;
                    });

                    var startWatch = scope.$watch('browser.start', function(newValue, oldValue) {
                        scope.start = newValue;
                    });

                    var endWatch = scope.$watch('browser.end', function(newValue, oldValue) {
                        scope.end = newValue;
                    });

                    return [speciesWatch, chrWatch, startWatch, endWatch];
                }

                function setAngularToGenoverseWatches(genoverseToAngularWatches) {
                    scope.$watch('start', function(newValue, oldValue) {
                        scope.browser.setRange(newValue, scope.end, true);
                    });

                    scope.$watch('end', function(newValue, oldValue) {
                        scope.browser.setRange(scope.start, newValue, true);
                    });

                    scope.$watch('genome', function(newValue, oldValue) {
                        // destroy the old instance of browser and callbacks/watches
                        genoverseToAngularWatches.forEach(function (element) { element(); }); // clear the old watches
                        element.find('#genoverse').html(''); // clear the innerHtml of directive
                        delete scope.browser; // clear old instance of browser

                        // create a new instance of browser and set the new watches for it
                        render();
                        registerGenoverseEvents();
                        setGenoverseToAngularWatches();
                    });

                    scope.$watch('chromosome', function(newValue, oldValue) {
                        // destroy the old instance of browser and callback/watches
                        genoverseToAngularWatches.forEach(function (element) { element(); }); // clear the old watches
                        element.find('#genoverse').html(''); // clear the innerHtml of directive
                        delete scope.browser; // clear old instance of browser

                        // create a new instance of browser and set the new watches for it
                        render();
                        registerGenoverseEvents();
                        setGenoverseToAngularWatches();
                    })
                }

                /**
                 * Each Genoverse model is configured with an organism-specific url.
                 * In addition, a new RNAcentral models that's mimicking Ensembl API is defined.
                 */
                function configureGenoverseModel(modelType) {
                    var model, url;
                    var endpoint = getEnsemblOrEnsemblgenomesEndpoint(urlencodeSpecies(scope.genome.species));

                    if (modelType === 'ensemblGene') {
                        // Ensembl Gene track
                        url = '//__ENDPOINT__/overlap/region/__SPECIES__/__CHR__:__START__-__END__?feature=gene;content-type=application/json'.replace('__ENDPOINT__', endpoint).replace('__SPECIES__', urlencodeSpecies(scope.genome.species));
                        model = Genoverse.Track.Model.Gene.Ensembl.extend({ url: url });
                    }
                    else if (modelType === 'ensemblTranscript') {
                        // Ensembl Transcript track
                        url = '//__ENDPOINT__/overlap/region/__SPECIES__/__CHR__:__START__-__END__?feature=transcript;feature=exon;feature=cds;content-type=application/json'.replace('__ENDPOINT__', endpoint).replace('__SPECIES__', urlencodeSpecies(scope.genome.species));
                        model = Genoverse.Track.Model.Transcript.Ensembl.extend({ url: url });
                    }
                    else if (modelType === 'ensemblSequence') {
                        // Ensembl sequence view
                        url = '//__ENDPOINT__/sequence/region/__SPECIES__/__CHR__:__START__-__END__?content-type=text/plain'.replace('__ENDPOINT__', endpoint).replace('__SPECIES__', urlencodeSpecies(scope.genome.species));
                        model = Genoverse.Track.Model.Sequence.Ensembl.extend({ url: url });
                    }
                    else if (modelType === 'rnacentral') {
                        // custom RNAcentral track
                        if (!window.location.origin) { window.location.origin = window.location.protocol + "//" + window.location.host + '/'; }

                        url = window.location.origin + '/api/v1/overlap/region/__SPECIES__/__CHR__:__START__-__END__'.replace('__SPECIES__', urlencodeSpecies(scope.genome.species));
                        model = Genoverse.Track.Model.Gene.Ensembl.extend({
                            url: url,
                            parseData: function (data) {
                                for (var i = 0; i < data.length; i++) {
                                    var feature = data[i];

                                    if (feature.feature_type === 'transcript' && !this.featuresById[feature.ID]) {
                                        feature.id    = feature.ID;
                                        feature.label = feature.external_name;
                                        feature.exons = [];
                                        feature.cds   = [];

                                        this.insertFeature(feature);
                                    }
                                    else if (feature.feature_type === 'exon' && this.featuresById[feature.Parent]) {
                                        feature.id = feature.ID;

                                        if (!this.featuresById[feature.Parent].exons[feature.id]) {
                                            this.featuresById[feature.Parent].exons.push(feature);
                                            this.featuresById[feature.Parent].exons[feature.id] = feature;
                                        }
                                    }
                                }
                            }
                        });
                    }

                  return model;
                }

                /**
                 * Dynamically choose whether to use E! or EG REST API based on species.
                 * If species not in E!, use EG.
                 * Ensembl species list: http://www.ensembl.org/info/about/species.html
                 */
                function getEnsemblOrEnsemblgenomesEndpoint(species) {
                    var ensemblSpecies = [
                        "ailuropoda_melanoleuca",
                        "anas_platyrhynchos",
                        "anolis_carolinensis",
                        "astyanax_mexicanus",
                        "bos_taurus",
                        "callithrix_jacchus",
                        "canis_lupus_familiaris",
                        "cavia_porcellus",
                        "ceratotherium_simum_simum",
                        "chlorocebus_sabaeus",
                        "choloepus_hoffmanni",
                        "chrysemys_picta_bellii",
                        "ciona_intestinalis",
                        "ciona_savignyi",
                        "cricetulus_griseus",
                        "danio_rerio",
                        "dasypus_novemcinctus",
                        "dipodomys_ordii",
                        "drosophila_melanogaster",
                        "echinops_telfairi",
                        "equus_caballus",
                        "erinaceus_europaeus",
                        "felis_catus",
                        "ficedula_albicollis",
                        "gadus_morhua",
                        "gallus_gallus",
                        "gasterosteus_aculeatus",
                        "gorilla_gorilla_gorilla",
                        "heterocephalus_glaber",
                        "homo_sapiens",
                        "ictidomys_tridecemlineatus",
                        "latimeria_chalumnae",
                        "lepisosteus_oculatus",
                        "loxodonta_africana",
                        "macaca_fascicularis",
                        "macaca_mulatta",
                        "macropus_eugenii",
                        "meleagris_gallopavo",
                        "melopsittacus_undulatus",
                        "microcebus_murinus",
                        "microtus_ochrogaster",
                        "monodelphis_domestica",
                        "mus_musculus",
                        "mustela_putorius_furo",
                        "myotis_lucifugus",
                        "nomascus_leucogenys",
                        "ochotona_princeps",
                        "oreochromis_niloticus",
                        "ornithorhynchus_anatinus",
                        "orycteropus_afer_afer",
                        "oryctolagus_cuniculus",
                        "oryzias_latipes",
                        "otolemur_garnettii",
                        "ovis_aries",
                        "pan_troglodytes",
                        "papio_anubis",
                        "papio_hamadryas",
                        "pelodiscus_sinensis",
                        "petromyzon_marinus",
                        "poecilia_formosa",
                        "pongo_abelii",
                        "procavia_capensis",
                        "pteropus_vampyrus",
                        "rattus_norvegicus",
                        "saimiri_boliviensis",
                        "sarcophilus_harrisii",
                        "sorex_araneus",
                        "sus_scrofa",
                        "sus_scrofa_map",
                        "taeniopygia_guttata",
                        "takifugu_rubripes",
                        "tarsius_syrichta",
                        "tetraodon_nigroviridis",
                        "tupaia_belangeri",
                        "tursiops_truncatus",
                        "vicugna_pacos",
                        "xenopus_tropicalis",
                        "xiphophorus_maculatus"
                    ];
                    // "saccharomyces_cerevisiae", "caenorhabditis_elegans"];
                    // "saccharomyces_cerevisiae", "caenorhabditis_elegans" could use either E! or EG

                    return ensemblSpecies.indexOf(species) > -1 ? 'rest.ensembl.org' : 'rest.ensemblgenomes.org';
                }

                /**
                 * Determine if karyotype information is available for this species.
                 */
                function isKaryotypeAvailable(species) {
                    return speciesSupported(species) && chromosomeSizeAvailable();
                }

                function speciesSupported(species) {
                    var supportedSpecies = ["homo_sapiens"]; // TODO: support more species
                    return supportedSpecies.indexOf(species) !== -1;
                }

                /**
                 * Get a list of chromosomes from the karyotype object and determine
                 * whether the size of the displayed region is known.
                 * Some RNAs are defined on scaffolds or other non-chromosomal objects
                 * for which the size is not stored in the karyotype object.
                 */
                function chromosomeSizeAvailable() {
                    var chromosomes = [];
                    for (var key in grch38) { // TODO: WHERE IS THIS grch38 VARIABLE DEFINED? IS IT GLOBAL?
                        chromosomes.push(key);
                    }
                    return chromosomes.indexOf(scope.chromosome.toString())
                }

                /**
                 * Register custom Genoverse events.
                 */
                function registerGenoverseEvents() {
                    // resize tracks after load
                    scope.browser.on({
                        // this event is called, whenever the user updates the browser viewport location
                        afterSetRange: function () {

                            // let angular update its model in response to coordinates change
                            if (!scope.$$phase) scope.$apply(); // anti-pattern, but no other way to use FRP in angular

                            // expand the tracks by programmatically clicking the resizer button
                            setTimeout(function() {
                                element.find('.genoverse-wrap .resizer').click();
                            }, 1000);
                        }
                    });
                }

                /**
                 * Maximize Genoverse container width.
                 */
                function setGenoverseWidth() {
                    var w = element.find('.container').width();
                    element.find('.wrap').width(w);
                    element.find('#genoverse').width(w);
                }

                // Helper functions
                // ----------------

                /**
                 * Returns an object from genomes Array by its species name or null, if not found.
                 * @param name {string} e.g. "Homo sapiens" or "homo_sapiens" (like in url) or "human" (synonym)
                 * @returns {Object || null} element of genomes Array
                 */
                function getGenomeByName(name) {
                    name = name.replace(/_/g, ' '); // if name was urlencoded, replace '_' with whitespaces

                    for (var i = 0; i < genomes.length; i++) {
                        if (name.toLowerCase() == genomes[i].name.toLowerCase()) { // test scientific name
                            return genomes[i];
                        }
                        else { // if name is not a scientific name, may be it's a synonym?
                            var synonyms = []; // convert all synonyms to lower case to make case-insensitive comparison

                            genomes[i].synonyms.forEach(function(synonym) {
                                synonyms.push(synonym.toLowerCase());
                            });

                            if (synonyms.indexOf(name.toLowerCase()) > -1) return genomes[i];
                        }
                    }

                    return null; // if no match found, return null
                }

                /**
                 * Replaces whitespaces with underscores in scientific names of species.
                 * @param species (string} - scientific name of a species with whitespaces, e.g. Homo Sapiens
                 * @returns {string} - scientific name of species with whitespaces replaces with underscores
                 */
                function urlencodeSpecies(species) {
                    // Canis familiaris is a special case
                    if (species == 'Canis familiaris') { species = 'Canis lupus familiaris'; }
                    return species.replace(/ /g, '_').toLowerCase();
                }
            }
        };
    }

})();<|endoftext|>


<commit_before>'use strict';

//Setting up route
angular.module('vocabs').config(['$stateProvider',
  function($stateProvider) {
  // Vocabs state routing
  $stateProvider.
    state('listVocabs', {
  url: '/vocabs',
  templateUrl: 'modules/vocabs/views/list-vocabs.client.view.html'
    }).
    state('createVocab', {
  url: '/vocabs/create',
  templateUrl: 'modules/vocabs/views/create-vocab.client.view.html'
    }).
    state('viewVocab', {
  url: '/vocabs/:vocabId',
  templateUrl: 'modules/vocabs/views/view-vocab.client.view.html'
    }).
    state('editVocab', {
  url: '/vocabs/:vocabId/edit',
  templateUrl: 'modules/vocabs/views/edit-vocab.client.view.html'
    });
  }
]);
<commit_msg>Fixes indentation<commit_after>'use strict';

//Setting up route
angular.module('vocabs').config(['$stateProvider',
  function($stateProvider) {
    // Vocabs state routing
    $stateProvider.
      state('listVocabs', {
        url: '/vocabs',
        templateUrl: 'modules/vocabs/views/list-vocabs.client.view.html'
      }).
      state('createVocab', {
        url: '/vocabs/create',
        templateUrl: 'modules/vocabs/views/create-vocab.client.view.html'
      }).
      state('viewVocab', {
        url: '/vocabs/:vocabId',
        templateUrl: 'modules/vocabs/views/view-vocab.client.view.html'
      }).
      state('editVocab', {
        url: '/vocabs/:vocabId/edit',
        templateUrl: 'modules/vocabs/views/edit-vocab.client.view.html'
      });
  }
]);
<|endoftext|>


<commit_before>(function($){
	$.fn.Huploadify = function(opts){
		var itemTemp = '

${fileName}上传删除
';
		var defaults = {
			fileTypeExts:'*.*',//允许上传的文件类型，格式'*.jpg;*.doc'
			uploader:'',//文件提交的地址
			auto:false,//是否开启自动上传
			method:'post',//发送请求的方式，get或post
			multi:true,//是否允许选择多个文件
			formData:null,//发送给服务端的参数，格式：{key1:value1,key2:value2}
			fileObjName:'file',//在后端接受文件的参数名称，如PHP中的$_FILES['file']
			fileSizeLimit:2048,//允许上传的文件大小，单位KB
			showUploadedPercent:true,//是否实时显示上传的百分比，如20%
			showUploadedSize:false,//是否实时显示已上传的文件大小，如1M/2M
			buttonText:'选择文件',//上传按钮上的文字
			removeTimeout: 1000,//上传完成后进度条的消失时间，单位毫秒
			itemTemplate:itemTemp,//上传队列显示的模板
			onUploadStart:null,//上传开始时的动作
			onUploadSuccess:null,//上传成功的动作
			onUploadComplete:null,//上传完成的动作
			onUploadError:null, //上传失败的动作
			onInit:null,//初始化时的动作
			onCancel:null,//删除掉某个文件后的回调函数，可传入参数file
			onClearQueue:null,//清空上传队列后的回调函数，在调用cancel并传入参数*时触发
			onDestroy:null,//在调用destroy方法时触发
			onSelect:null,//选择文件后的回调函数，可传入参数file
            onChange:null,//选择文件的事件,用于检测文件是否重复
			onQueueComplete:null//队列中的所有文件上传完成后触发
		}

		var option = $.extend(defaults,opts);

		//定义一个通用函数集合
		var F = {
			//将文件的单位由bytes转换为KB或MB，若第二个参数指定为true，则永远转换为KB
			formatFileSize : function(size,withKB){
				if (size > 1024 * 1024 && !withKB){
					size = (Math.round(size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
				}
				else{
					size = (Math.round(size * 100 / 1024) / 100).toString() + 'KB';
				}
				return size;
			},
			//将输入的文件类型字符串转化为数组,原格式为*.jpg;*.png
			getFileTypes : function(str){
				var result = [];
				var arr1 = str.split(";");
				for(var i=0, len=arr1.length; i<len; i++){
					result.push(arr1[i].split(".").pop());
				}
				return result;
			},
			////根据文件序号获取文件
			getFile : function(index,files){
				for(var i=0;i<files.length;i++){
					if(files[i].index == index){
						return files[i];
					}
				}
				return null;
			}
		};

		var returnObj = null;

		this.each(function(index, element){
			var _this = $(element);
            var instanceNumber = $('.selectbtn').length+1;
			var uploadManager = {
				container : _this,
				filteredFiles : [],//过滤后的文件数组
				init : function(){
					var inputStr = '<input id="select_btn_'+instanceNumber+'" class="selectbtn" style="display:none;" type="file" name="fileselect[]"';
					inputStr += option.multi ? ' multiple' : '';
					inputStr += ' accept="';
					inputStr += F.getFileTypes(option.fileTypeExts).join(",");
					inputStr += '"/>';
					inputStr += '';
					inputStr += option.buttonText;
					inputStr += '';
					var uploadFileListStr = '

';
					_this.append(inputStr+uploadFileListStr);

					//初始化返回的实例
					returnObj =  {
						instanceNumber : instanceNumber,
						upload : function(fileIndex){
							if(fileIndex === '*'){
								for(var i=0,len=uploadManager.filteredFiles.length;i<len;i++){
									uploadManager._uploadFile(uploadManager.filteredFiles[i]);
								}
							}
							else{
								var file = F.getFile(fileIndex,uploadManager.filteredFiles);
								file && uploadManager._uploadFile(file);
							}
						},
						cancel : function(fileIndex){
							if(fileIndex === '*'){
								var len=uploadManager.filteredFiles.length;
								for(var i=len-1;i>=0;i--){
									uploadManager._deleteFile(uploadManager.filteredFiles[i]);
								}
								option.onClearQueue && option.onClearQueue(len);
							}
							else{
								var file = F.getFile(fileIndex,uploadManager.filteredFiles);
								file && uploadManager._deleteFile(file);
							}
						},
						disable : function(instanceID){
							var parent = instanceID ? $('file_upload_'+instanceID+'-button') : $('body');
							parent.find('.uploadify-button').css('background-color','#888').off('click');
						},
						ennable : function(instanceID){
							//点击上传按钮时触发file的click事件
							var parent = instanceID ? $('file_upload_'+instanceID+'-button') : $('body');
						  	parent.find('.uploadify-button').css('background-color','#707070').on('click',function(){
								parent.find('.selectbtn').trigger('click');
							});
						},
						destroy : function(){
							uploadManager.container.html('');
							uploadManager = null;
							option.onDestroy && option.onDestroy();
						},
						settings : function(name,value){
							if(arguments.length==1){
								return option[name];
							}
							else{
								if(name=='formData'){
									option.formData = $.extend(option.formData, value);
								}
								else{
									option[name] = value;
								}
							}
						},
						Huploadify : function(){
							var method = arguments[0];
							if(method in this){
								Array.prototype.splice.call(arguments, 0, 1);
								this[method].apply(this[method], arguments);
							}
						}
					};

					//文件选择控件选择
					var fileInput = this._getInputBtn();
				  	if (fileInput.length>0) {
						fileInput.change(function(e) {
							uploadManager._getFiles(e);
					 	});
				 	}

					//点击选择文件按钮时触发file的click事件
					_this.find('.uploadify-button').on('click',function(){
						_this.find('.selectbtn').trigger('click');
					});

					option.onInit && option.onInit(returnObj);
				},
				_filter: function(files) {		//选择文件组的过滤方法
					var arr = [];
					var typeArray = F.getFileTypes(option.fileTypeExts);
					if(typeArray.length>0){
						for(var i=0,len=files.length;i<len;i++){
							var f = files[i];
							if(parseInt(F.formatFileSize(f.size,true))<=option.fileSizeLimit){
								if($.inArray('*',typeArray)>=0 || $.inArray(f.name.split('.').pop(),typeArray)>=0){
									arr.push(f);
								}
								else{
									alert('文件 "'+f.name+'" 类型不允许！');
								}
							}
							else{
								alert('文件 "'+f.name+'" 大小超出限制！');
								continue;
							}
						}
					}
					return arr;
				},
				_getInputBtn : function(){
					return _this.find('.selectbtn');
				},
				_getFileList : function(){
					return _this.find('.uploadify-queue');
				},
				//根据选择的文件，渲染DOM节点
				_renderFile : function(file){
					var $html = $(option.itemTemplate.replace(/\${fileID}/g,'fileupload_'+instanceNumber+'_'+file.index).replace(/\${fileName}/g,file.name).replace(/\${fileSize}/g,F.formatFileSize(file.size)).replace(/\${instanceID}/g,_this.attr('id')));
					//如果是非自动上传，显示上传按钮
					if(!option.auto){
						$html.find('.uploadbtn').css('display','inline-block');
					}
					uploadManager._getFileList().append($html);

					//判断是否显示已上传文件大小
					if(option.showUploadedSize){
						var num = '0KB/${fileSize}'.replace(/\${fileSize}/g,F.formatFileSize(file.size));
						$html.find('.uploadify-progress').after(num);
					}

					//判断是否显示上传百分比
					if(option.showUploadedPercent){
						var percentText = '0%';
						$html.find('.uploadify-progress').after(percentText);
					}

					//触发select动作
					option.onSelect && option.onSelect(file);

					//判断是否是自动上传
					if(option.auto){
						uploadManager._uploadFile(file);
					}
					else{
						//如果配置非自动上传，绑定上传事件
					 	$html.find('.uploadbtn').on('click',function(){
					 		if(!$(this).hasClass('.disabledbtn')){
					 			$(this).addClass('.disabledbtn');
					 			uploadManager._uploadFile(file);
					 		}
				 		});
					}

					//为删除文件按钮绑定删除文件事件
			 		$html.find('.delfilebtn').on('click',function(){
			 			if(!$(this).hasClass('.disabledbtn')){
					 		$(this).addClass('.disabledbtn');
			 				uploadManager._deleteFile(file);
			 			}
			 		});
				},
				//获取选择后的文件
                _getFiles : function(e){
                    var files = e.target.files;
                    files = uploadManager._filter(files);
                    var fileCount = _this.find('.uploadify-queue .uploadify-queue-item').length;//队列中已经有的文件个数
                    for(var i=0,len=files.length;i<len;i++){
                        if(option.onChange) {
                            option.onChange(files[i],++fileCount,uploadManager.__getFiles);
                        }else {
                            uploadManager.__getFiles(files[i],++fileCount);
                        }

                    }
                },
                __getFiles : function(file,fileCount) {
                    file.index = ++fileCount;
                    file.status = 0;//标记为未开始上传
                    uploadManager.filteredFiles.push(file);
                    var l = uploadManager.filteredFiles.length;
                    uploadManager._renderFile(uploadManager.filteredFiles[l-1]);
                },
				//删除文件
				_deleteFile : function(file){
					for (var i = 0,len=uploadManager.filteredFiles.length; i<len; i++) {
						var f = uploadManager.filteredFiles[i];
						if (f.index == file.index) {
							uploadManager.filteredFiles.splice(i,1);
							_this.find('#fileupload_'+instanceNumber+'_'+file.index).fadeOut();
							option.onCancel && option.onCancel(file);
							break;
						}
			  		}
				},
				//校正上传完成后的进度条误差
				_regulateView : function(file){
					var thisfile = _this.find('#fileupload_'+instanceNumber+'_'+file.index);
					thisfile.find('.uploadify-progress-bar').css('width','100%');
					option.showUploadedSize && thisfile.find('.uploadedsize').text(thisfile.find('.totalsize').text());
					option.showUploadedPercent && thisfile.find('.up_percent').text('100%');
				},
				onProgress : function(file, loaded, total) {
					var eleProgress = _this.find('#fileupload_'+instanceNumber+'_'+file.index+' .uploadify-progress');
					var percent = (loaded / total * 100).toFixed(2) +'%';
					if(option.showUploadedSize){
						eleProgress.nextAll('.progressnum .uploadedsize').text(F.formatFileSize(loaded));
						eleProgress.nextAll('.progressnum .totalsize').text(F.formatFileSize(total));
					}
					if(option.showUploadedPercent){
						eleProgress.nextAll('.up_percent').text(percent);
					}
					eleProgress.children('.uploadify-progress-bar').css('width',percent);
			  	},
			  	_allFilesUploaded : function(){
		  			var queueData = {
						uploadsSuccessful : 0,
						uploadsErrored : 0
					};
			  		for(var i=0,len=uploadManager.filteredFiles.length; i<len; i++){
			  			var s = uploadManager.filteredFiles[i].status;
			  			if(s===0 || s===1){
			  				queueData = false;
			  				break;
			  			}
			  			else if(s===2){
			  				queueData.uploadsSuccessful++;
			  			}
			  			else if(s===3){
			  				queueData.uploadsErrored++;
			  			}
			  		}
			  		return queueData;
			  	},
				//上传文件
				_uploadFile : function(file){
					var xhr = null;
					try{
						xhr=new XMLHttpRequest();
					}catch(e){
						xhr=ActiveXobject("Msxml12.XMLHTTP");
				  	}
				  	if(xhr.upload){
				  		// 上传中
					  	xhr.upload.onprogress = function(e) {
							uploadManager.onProgress(file, e.loaded, e.total);
						};

						xhr.onreadystatechange = function(e) {
							if(xhr.readyState == 4){
								if(xhr.status == 200){
									uploadManager._regulateView(file);
									file.status = 2;//标记为上传成功
									option.onUploadSuccess && option.onUploadSuccess(file, xhr.responseText);
									//在指定的间隔时间后删掉进度条
									setTimeout(function(){
										_this.find('#fileupload_'+instanceNumber+'_'+file.index).fadeOut();
									},option.removeTimeout);
								}
								else {
									file.status = 3;//标记为上传失败
									option.onUploadError && option.onUploadError(file, xhr.responseText);
								}
								option.onUploadComplete && option.onUploadComplete(file,xhr.responseText);

								//检测队列中的文件是否全部上传完成，执行onQueueComplete
								if(option.onQueueComplete){
									var queueData = uploadManager._allFilesUploaded();
									queueData && option.onQueueComplete(queueData);
								}

								//清除文件选择框中的已有值
								uploadManager._getInputBtn().val('');
							}
						}

						if(file.status===0){
							file.status = 1;//标记为正在上传
							option.onUploadStart && option.onUploadStart(file);
							// 开始上传
							xhr.open(option.method, option.uploader, true);
							xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
							var fd = new FormData();
							fd.append(option.fileObjName,file);
							if(option.formData){
							 	for(key in option.formData){
							  		fd.append(key,option.formData[key]);
							  	}
							}
							xhr.send(fd);
						}

				  	}
				}
			};

			uploadManager.init();
		});

		return returnObj;

	}
})(jQuery)<commit_msg>Huploadify插件解决上传重复图片不触发change事件bug,删除图片再重新选择无效bug<commit_after>(function($){
	$.fn.Huploadify = function(opts){
		var itemTemp = '

${fileName}上传删除
';
		var defaults = {
			fileTypeExts:'*.*',//允许上传的文件类型，格式'*.jpg;*.doc'
			uploader:'',//文件提交的地址
			auto:false,//是否开启自动上传
			method:'post',//发送请求的方式，get或post
			multi:true,//是否允许选择多个文件
			formData:null,//发送给服务端的参数，格式：{key1:value1,key2:value2}
			fileObjName:'file',//在后端接受文件的参数名称，如PHP中的$_FILES['file']
			fileSizeLimit:2048,//允许上传的文件大小，单位KB
			showUploadedPercent:true,//是否实时显示上传的百分比，如20%
			showUploadedSize:false,//是否实时显示已上传的文件大小，如1M/2M
			buttonText:'选择文件',//上传按钮上的文字
			removeTimeout: 1000,//上传完成后进度条的消失时间，单位毫秒
			itemTemplate:itemTemp,//上传队列显示的模板
			onUploadStart:null,//上传开始时的动作
			onUploadSuccess:null,//上传成功的动作
			onUploadComplete:null,//上传完成的动作
			onUploadError:null, //上传失败的动作
			onInit:null,//初始化时的动作
			onCancel:null,//删除掉某个文件后的回调函数，可传入参数file
			onClearQueue:null,//清空上传队列后的回调函数，在调用cancel并传入参数*时触发
			onDestroy:null,//在调用destroy方法时触发
			onSelect:null,//选择文件后的回调函数，可传入参数file
            onChange:null,//选择文件的事件,用于检测文件是否重复
			onQueueComplete:null//队列中的所有文件上传完成后触发
		}

		var option = $.extend(defaults,opts);

		//定义一个通用函数集合
		var F = {
			//将文件的单位由bytes转换为KB或MB，若第二个参数指定为true，则永远转换为KB
			formatFileSize : function(size,withKB){
				if (size > 1024 * 1024 && !withKB){
					size = (Math.round(size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
				}
				else{
					size = (Math.round(size * 100 / 1024) / 100).toString() + 'KB';
				}
				return size;
			},
			//将输入的文件类型字符串转化为数组,原格式为*.jpg;*.png
			getFileTypes : function(str){
				var result = [];
				var arr1 = str.split(";");
				for(var i=0, len=arr1.length; i<len; i++){
					result.push(arr1[i].split(".").pop());
				}
				return result;
			},
			////根据文件序号获取文件
			getFile : function(index,files){
				for(var i=0;i<files.length;i++){
					if(files[i].index == index){
						return files[i];
					}
				}
				return null;
			}
		};

		var returnObj = null;

		this.each(function(index, element){
			var _this = $(element);
            var instanceNumber = $('.selectbtn').length+1;
			var uploadManager = {
				container : _this,
				filteredFiles : [],//过滤后的文件数组
				init : function(){
					var inputStr = '<input id="select_btn_'+instanceNumber+'" class="selectbtn" style="display:none;" type="file" name="fileselect[]"';
					inputStr += option.multi ? ' multiple' : '';
					inputStr += ' accept="';
					inputStr += F.getFileTypes(option.fileTypeExts).join(",");
					inputStr += '"/>';
					inputStr += '';
					inputStr += option.buttonText;
					inputStr += '';
					var uploadFileListStr = '

';
					_this.append(inputStr+uploadFileListStr);

					//初始化返回的实例
					returnObj =  {
						instanceNumber : instanceNumber,
						upload : function(fileIndex){
							if(fileIndex === '*'){
								for(var i=0,len=uploadManager.filteredFiles.length;i<len;i++){
									uploadManager._uploadFile(uploadManager.filteredFiles[i]);
								}
							}
							else{
								var file = F.getFile(fileIndex,uploadManager.filteredFiles);
								file && uploadManager._uploadFile(file);
							}
						},
						cancel : function(fileIndex){
							if(fileIndex === '*'){
								var len=uploadManager.filteredFiles.length;
								for(var i=len-1;i>=0;i--){
									uploadManager._deleteFile(uploadManager.filteredFiles[i]);
								}
								option.onClearQueue && option.onClearQueue(len);
							}
							else{
								var file = F.getFile(fileIndex,uploadManager.filteredFiles);
								file && uploadManager._deleteFile(file);
							}
						},
						disable : function(instanceID){
							var parent = instanceID ? $('file_upload_'+instanceID+'-button') : $('body');
							parent.find('.uploadify-button').css('background-color','#888').off('click');
						},
						ennable : function(instanceID){
							//点击上传按钮时触发file的click事件
							var parent = instanceID ? $('file_upload_'+instanceID+'-button') : $('body');
						  	parent.find('.uploadify-button').css('background-color','#707070').on('click',function(){
								parent.find('.selectbtn').trigger('click');
							});
						},
						destroy : function(){
							uploadManager.container.html('');
							uploadManager = null;
							option.onDestroy && option.onDestroy();
						},
						settings : function(name,value){
							if(arguments.length==1){
								return option[name];
							}
							else{
								if(name=='formData'){
									option.formData = $.extend(option.formData, value);
								}
								else{
									option[name] = value;
								}
							}
						},
						Huploadify : function(){
							var method = arguments[0];
							if(method in this){
								Array.prototype.splice.call(arguments, 0, 1);
								this[method].apply(this[method], arguments);
							}
						}
					};

					//文件选择控件选择
					var fileInput = this._getInputBtn();
				  	if (fileInput.length>0) {
						fileInput.change(function(e) {
							uploadManager._getFiles(e);
							$(this).val('');
					 	});
				 	}

					//点击选择文件按钮时触发file的click事件
					_this.find('.uploadify-button').on('click',function(){
						_this.find('.selectbtn').trigger('click');
					});

					option.onInit && option.onInit(returnObj);
				},
				_filter: function(files) {		//选择文件组的过滤方法
					var arr = [];
					var typeArray = F.getFileTypes(option.fileTypeExts);
					if(typeArray.length>0){
						for(var i=0,len=files.length;i<len;i++){
							var f = files[i];
							if(parseInt(F.formatFileSize(f.size,true))<=option.fileSizeLimit){
								if($.inArray('*',typeArray)>=0 || $.inArray(f.name.split('.').pop(),typeArray)>=0){
									arr.push(f);
								}
								else{
									alert('文件 "'+f.name+'" 类型不允许！');
								}
							}
							else{
								alert('文件 "'+f.name+'" 大小超出限制！');
								continue;
							}
						}
					}
					return arr;
				},
				_getInputBtn : function(){
					return _this.find('.selectbtn');
				},
				_getFileList : function(){
					return _this.find('.uploadify-queue');
				},
				//根据选择的文件，渲染DOM节点
				_renderFile : function(file){
					var $html = $(option.itemTemplate.replace(/\${fileID}/g,'fileupload_'+instanceNumber+'_'+file.index).replace(/\${fileName}/g,file.name).replace(/\${fileSize}/g,F.formatFileSize(file.size)).replace(/\${instanceID}/g,_this.attr('id')));
					//如果是非自动上传，显示上传按钮
					if(!option.auto){
						$html.find('.uploadbtn').css('display','inline-block');
					}
					uploadManager._getFileList().append($html);

					//判断是否显示已上传文件大小
					if(option.showUploadedSize){
						var num = '0KB/${fileSize}'.replace(/\${fileSize}/g,F.formatFileSize(file.size));
						$html.find('.uploadify-progress').after(num);
					}

					//判断是否显示上传百分比
					if(option.showUploadedPercent){
						var percentText = '0%';
						$html.find('.uploadify-progress').after(percentText);
					}

					//触发select动作
					option.onSelect && option.onSelect(file);

					//判断是否是自动上传
					if(option.auto){
						uploadManager._uploadFile(file);
					}
					else{
						//如果配置非自动上传，绑定上传事件
					 	$html.find('.uploadbtn').on('click',function(){
					 		if(!$(this).hasClass('.disabledbtn')){
					 			$(this).addClass('.disabledbtn');
					 			uploadManager._uploadFile(file);
					 		}
				 		});
					}

					//为删除文件按钮绑定删除文件事件
			 		$html.find('.delfilebtn').on('click',function(){
			 			if(!$(this).hasClass('.disabledbtn')){
					 		$(this).addClass('.disabledbtn');
			 				uploadManager._deleteFile(file);
			 			}
			 		});
				},
				//获取选择后的文件
                _getFiles : function(e){
                    var files = e.target.files;
                    files = uploadManager._filter(files);
                    var fileCount = _this.find('.uploadify-queue .uploadify-queue-item').length;//队列中已经有的文件个数
                    for(var i=0,len=files.length;i<len;i++){
                        if(option.onChange) {
                            option.onChange(files[i],++fileCount,uploadManager.__getFiles);
                        }else {
                            uploadManager.__getFiles(files[i],++fileCount);
                        }

                    }
                },
                __getFiles : function(file,fileCount) {
                    file.index = ++fileCount;
                    file.status = 0;//标记为未开始上传
                    uploadManager.filteredFiles.push(file);
                    var l = uploadManager.filteredFiles.length;
                    uploadManager._renderFile(uploadManager.filteredFiles[l-1]);
                },
				//删除文件
				_deleteFile : function(file){
					for (var i = 0,len=uploadManager.filteredFiles.length; i<len; i++) {
						var f = uploadManager.filteredFiles[i];
						if (f.index == file.index) {
							uploadManager.filteredFiles.splice(i,1);
							_this.find('#fileupload_'+instanceNumber+'_'+file.index).fadeOut();
							option.onCancel && option.onCancel(file);
							break;
						}
			  		}
				},
				//校正上传完成后的进度条误差
				_regulateView : function(file){
					var thisfile = _this.find('#fileupload_'+instanceNumber+'_'+file.index);
					thisfile.find('.uploadify-progress-bar').css('width','100%');
					option.showUploadedSize && thisfile.find('.uploadedsize').text(thisfile.find('.totalsize').text());
					option.showUploadedPercent && thisfile.find('.up_percent').text('100%');
				},
				onProgress : function(file, loaded, total) {
					var eleProgress = _this.find('#fileupload_'+instanceNumber+'_'+file.index+' .uploadify-progress');
					var percent = (loaded / total * 100).toFixed(2) +'%';
					if(option.showUploadedSize){
						eleProgress.nextAll('.progressnum .uploadedsize').text(F.formatFileSize(loaded));
						eleProgress.nextAll('.progressnum .totalsize').text(F.formatFileSize(total));
					}
					if(option.showUploadedPercent){
						eleProgress.nextAll('.up_percent').text(percent);
					}
					eleProgress.children('.uploadify-progress-bar').css('width',percent);
			  	},
			  	_allFilesUploaded : function(){
		  			var queueData = {
						uploadsSuccessful : 0,
						uploadsErrored : 0
					};
			  		for(var i=0,len=uploadManager.filteredFiles.length; i<len; i++){
			  			var s = uploadManager.filteredFiles[i].status;
			  			if(s===0 || s===1){
			  				queueData = false;
			  				break;
			  			}
			  			else if(s===2){
			  				queueData.uploadsSuccessful++;
			  			}
			  			else if(s===3){
			  				queueData.uploadsErrored++;
			  			}
			  		}
			  		return queueData;
			  	},
				//上传文件
				_uploadFile : function(file){
					var xhr = null;
					try{
						xhr=new XMLHttpRequest();
					}catch(e){
						xhr=ActiveXobject("Msxml12.XMLHTTP");
				  	}
				  	if(xhr.upload){
				  		// 上传中
					  	xhr.upload.onprogress = function(e) {
							uploadManager.onProgress(file, e.loaded, e.total);
						};

						xhr.onreadystatechange = function(e) {
							if(xhr.readyState == 4){
								if(xhr.status == 200){
									uploadManager._regulateView(file);
									file.status = 2;//标记为上传成功
									option.onUploadSuccess && option.onUploadSuccess(file, xhr.responseText);
									//在指定的间隔时间后删掉进度条
									setTimeout(function(){
										_this.find('#fileupload_'+instanceNumber+'_'+file.index).fadeOut();
									},option.removeTimeout);
								}
								else {
									file.status = 3;//标记为上传失败
									option.onUploadError && option.onUploadError(file, xhr.responseText);
								}
								option.onUploadComplete && option.onUploadComplete(file,xhr.responseText);

								//检测队列中的文件是否全部上传完成，执行onQueueComplete
								if(option.onQueueComplete){
									var queueData = uploadManager._allFilesUploaded();
									queueData && option.onQueueComplete(queueData);
								}

								//清除文件选择框中的已有值
								uploadManager._getInputBtn().val('');
							}
						}

						if(file.status===0){
							file.status = 1;//标记为正在上传
							option.onUploadStart && option.onUploadStart(file);
							// 开始上传
							xhr.open(option.method, option.uploader, true);
							xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
							var fd = new FormData();
							fd.append(option.fileObjName,file);
							if(option.formData){
							 	for(key in option.formData){
							  		fd.append(key,option.formData[key]);
							  	}
							}
							xhr.send(fd);
						}

				  	}
				}
			};

			uploadManager.init();
		});

		return returnObj;

	}
})(jQuery)<|endoftext|>


<commit_before>const styles = require('../Style/style.js')

import React, { Component } from 'react'
import { Navigator, Text } from 'react-native'
import HomeMap from './HomeMap'
import ParkingDetails from './ParkingDetails'
import NavButton from './NavButton'

export default class Router extends Component {
  constructor(props) {
    super(props)
    this.state = {}

  	this.renderScene = this.renderScene.bind(this)
    }

    renderScene(route, navigator) {
      switch (route.name) {
        case 'HomeMap':
          return <HomeMap navigator={navigator} {...route} />
          break
        case 'Camera':
          return <Camera navigator={navigator} {...route} />
          break
        case 'ParkingDetails':
          return <ParkingDetails navigator={navigator} {...route} />
          break
      }
  	}

    leftButton (route, navigator, index, navState) {
      if (route.name !== 'HomeMap') {
        return <NavButton text="back" onPress={() => navigator.pop()}/>
      } else {
        return null
      }
    }

    rightButton (route, navigator, index, navState) {
      if (route.name !== 'HomeMap') {

      } else {
        return null
      }
    }

    render () {
    	return (
        <Navigator
    		  initialRoute = {
            {
              name: 'HomeMap',
              currentUser: this.props.currentUser,
              userToken: this.props.userToken,
              logOut: this.props.logOut,
              reanimator: this.props.reanimator
            }
          }
    		  renderScene={this.renderScene}
          navigationBar={
            <Navigator.NavigationBar
              routeMapper={{
                LeftButton: this.leftButton,
                RightButton: this.rightButton,
                Title: () => {}
              }}
            />
          }
        />
      )
    }
  }
<commit_msg>Clean up Router.js<commit_after>const styles = require('../Style/style.js')

import React, { Component } from 'react'
import { Navigator, Text } from 'react-native'
import HomeMap from './HomeMap'
import ParkingDetails from './ParkingDetails'
import NavButton from './NavButton'

export default class Router extends Component {
  constructor(props) {
    super(props)
    this.state = {}

  	this.renderScene = this.renderScene.bind(this)
    }

    renderScene(route, navigator) {
      switch (route.name) {
        case 'HomeMap':
          return <HomeMap navigator={navigator} {...route} />
          break
        case 'Camera':
          return <Camera navigator={navigator} {...route} />
          break
        case 'ParkingDetails':
          return <ParkingDetails navigator={navigator} {...route} />
          break
      }
  	}

    render () {
    	return (
        <Navigator
    		  initialRoute = {
            {
              name: 'HomeMap',
              currentUser: this.props.currentUser,
              userToken: this.props.userToken,
              logOut: this.props.logOut,
              reanimator: this.props.reanimator
            }
          }
    		  renderScene={this.renderScene}
        />
      )
    }
  }
<|endoftext|>