<commit_before>///// FIXME: Use path._rings instead of path._latlngs???
///// FIXME: Panic if this._map doesn't exist when called.
///// FIXME: Implement snakeOut()
///// FIXME: Implement layerGroup.snakeIn() / Out()
L.Polyline.include({

	// Hi-res timestamp indicating when the last calculations for vertices and
	// distance took place.
	_snakingTimestamp: 0,

	// How many rings and vertices we've already visited
	// Yeah, yeah, "rings" semantically only apply to polygons, but L.Polyline
	// internally uses that nomenclature.
	_snakingRings: 0,
	_snakingVertices: 0,

	// Distance to draw (in screen pixels) since the last vertex
	_snakingDistance: 0,

	// Flag
	_snaking: false,

	/// TODO: accept a 'map' parameter, fall back to addTo() in case
	/// performance.now is not available.
	snakeIn: function(){

		if (this._snaking) { return; }

		if ( !('performance' in window) ||
		     !('now' in window.performance) ||
		     !this._map) {
			return;
		}

		this._snaking = true;
		this._snakingTime = performance.now();
		this._snakingVertices = this._snakingRings = this._snakingDistance = 0;

		if (!this._snakeLatLngs) {
			this._snakeLatLngs = L.LineUtil.isFlat(this._latlngs) ?
				[ this._latlngs ] :
				this._latlngs ;
		}

		// Init with just the first (0th) vertex in a new ring
		// Twice because the first thing that this._snake is is chop the head.
		this._latlngs = [[ this._snakeLatLngs[0][0], this._snakeLatLngs[0][0] ]];

		this._update();
		this._snake();
		this.fire('snakestart');
		return this;
	},

	_snake: function(){
		var now = performance.now();
		var timeDdiff = now - this._snakingTime;	// In milliseconds
		timeDdiff = (timeDdiff === 0 ? 0.001 : timeDdiff) // Avoids low time resolution issues in some browsers
		var forward = timeDdiff * this.options.snakingSpeed / 1000;	// In pixels
		this._snakingTime = now;

		// Chop the head from the previous frame
		this._latlngs[ this._snakingRings ].pop();

		return this._snakeForward(forward);
	},

	_snakeForward: function(forward) {
		// If polyline has been removed from the map stop _snakeForward
		if (!this._map) return;
		// Calculate distance from current vertex to next vertex
		var currPoint = this._map.latLngToContainerPoint(
			this._snakeLatLngs[ this._snakingRings ][ this._snakingVertices ]);
		var nextPoint = this._map.latLngToContainerPoint(
			this._snakeLatLngs[ this._snakingRings ][ this._snakingVertices + 1 ]);

		var distance = currPoint.distanceTo(nextPoint);

		if (this._snakingDistance + forward > distance) {
			// Jump to next vertex
			this._snakingVertices++;
			this._latlngs[ this._snakingRings ].push( this._snakeLatLngs[ this._snakingRings ][ this._snakingVertices ] );

			if (this._snakingVertices >= this._snakeLatLngs[ this._snakingRings ].length - 1 ) {
				if (this._snakingRings >= this._snakeLatLngs.length - 1 ) {
					return this._snakeEnd();
				} else {
					this._snakingVertices = 0;
					this._snakingRings++;
					this._latlngs[ this._snakingRings ] = [
						this._snakeLatLngs[ this._snakingRings ][ this._snakingVertices ]
					];
				}
			}
			this._snakingDistance -= distance;
			return this._snakeForward(forward);
		}

		this._snakingDistance += forward;

		var percent = this._snakingDistance / distance;

		var headPoint = nextPoint.multiplyBy(percent).add(
			currPoint.multiplyBy( 1 - percent )
		);

		// Put a new head in place.
		var headLatLng = this._map.containerPointToLatLng(headPoint);
		this._latlngs[ this._snakingRings ].push(headLatLng);

		this.setLatLngs(this._latlngs);
		this.fire('snake');
		L.Util.requestAnimFrame(this._snake, this);
	},
	_snakeEnd: function() {
		this.setLatLngs(this._snakeLatLngs);
		this._snaking = false;
		this.fire('snakeend');
	}
});

L.Polyline.mergeOptions({
	snakingSpeed: 200	// In pixels/sec
});

L.LayerGroup.include({

	_snakingLayers: [],
	_snakingLayersDone: 0,

	snakeIn: function() {
		if ( !('performance' in window) ||
		     !('now' in window.performance) ||
		     !this._map ||
		     this._snaking) {
			return;
		}

		this._snaking = true;
		this._snakingLayers = [];
		this._snakingLayersDone = 0;
		for (var key in this._layers) {
			if (this._layers.hasOwnProperty(key)) {
				this._snakingLayers.push(this._layers[key]);
			}
		}
		this.clearLayers();

		this.fire('snakestart');
		return this._snakeNext();
	},

	_snakeNext: function() {
		if (this._snakingLayersDone >= this._snakingLayers.length) {
			this.fire('snakeend');
			this._snaking = false;
			return;
		}

		var currentLayer = this._snakingLayers[this._snakingLayersDone];

		this._snakingLayersDone++;

		this.addLayer(currentLayer);
		if ('snakeIn' in currentLayer) {
			currentLayer.once('snakeend', function(){
				setTimeout(this._snakeNext.bind(this), this.options.snakingPause);
			}, this);
			currentLayer.snakeIn();
		} else {
			setTimeout(this._snakeNext.bind(this), this.options.snakingPause);
		}

		this.fire('snake');
		return this;
	}
});

L.LayerGroup.mergeOptions({
	snakingPause: 200
});
<commit_msg>cleans up SnakeAnim lib file, adds attribution<commit_after>// "THE BEER-WARE LICENSE": ivan@sanchezortega.es wrote this file. As long as
// you retain this notice you can do whatever you want with this stuff. If we
// meet some day, and you think this stuff is worth it, you can buy me a beer
// in return.
///// FIXME: Use path._rings instead of path._latlngs???
///// FIXME: Panic if this._map doesn't exist when called.
///// FIXME: Implement snakeOut()
L.Polyline.include({
	// Hi-res timestamp indicating when the last calculations for vertices and
	// distance took place.
	_snakingTimestamp: 0,

	// How many rings and vertices we've already visited
	// Yeah, yeah, "rings" semantically only apply to polygons, but L.Polyline
	// internally uses that nomenclature.
	_snakingRings: 0,
	_snakingVertices: 0,

	// Distance to draw (in screen pixels) since the last vertex
	_snakingDistance: 0,

	// Flag
	_snaking: false,

	/// TODO: accept a 'map' parameter, fall back to addTo() in case
	/// performance.now is not available.
	snakeIn: function(){
		if (this._snaking) { return; }

		if ( !('performance' in window) ||
		     !('now' in window.performance) ||
		     !this._map) {
			return;
		}

		this._snaking = true;
		this._snakingTime = performance.now();
		this._snakingVertices = this._snakingRings = this._snakingDistance = 0;

		if (!this._snakeLatLngs) {
			this._snakeLatLngs = L.LineUtil.isFlat(this._latlngs) ?
				[ this._latlngs ] :
				this._latlngs ;
		}

		// Init with just the first (0th) vertex in a new ring
		// Twice because the first thing that this._snake does is chop the head.
		this._latlngs = [[ this._snakeLatLngs[0][0], this._snakeLatLngs[0][0] ]];

		this._update();
		this._snake();
		this.fire('snakestart');
		return this;
	},

	_snake: function(){
		var now = performance.now();
		var timeDdiff = now - this._snakingTime;	// In milliseconds
		timeDdiff = (timeDdiff === 0 ? 0.001 : timeDdiff) // Avoids low time resolution issues in some browsers
		var forward = timeDdiff * this.options.snakingSpeed / 1000;	// In pixels
		this._snakingTime = now;

		// Chop the head from the previous frame
		this._latlngs[ this._snakingRings ].pop();

		return this._snakeForward(forward);
	},

	_snakeForward: function(forward) {
		// If polyline has been removed from the map stop _snakeForward
		if (!this._map) return;
		// Calculate distance from current vertex to next vertex
		var currPoint = this._map.latLngToContainerPoint(
			this._snakeLatLngs[ this._snakingRings ][ this._snakingVertices ]);
		var nextPoint = this._map.latLngToContainerPoint(
			this._snakeLatLngs[ this._snakingRings ][ this._snakingVertices + 1 ]);

		var distance = currPoint.distanceTo(nextPoint);

		if (this._snakingDistance + forward > distance) {
			// Jump to next vertex
			this._snakingVertices++;
			this._latlngs[ this._snakingRings ].push( this._snakeLatLngs[ this._snakingRings ][ this._snakingVertices ] );

			if (this._snakingVertices >= this._snakeLatLngs[ this._snakingRings ].length - 1 ) {
				if (this._snakingRings >= this._snakeLatLngs.length - 1 ) {
					return this._snakeEnd();
				} else {
					this._snakingVertices = 0;
					this._snakingRings++;
					this._latlngs[ this._snakingRings ] = [
						this._snakeLatLngs[ this._snakingRings ][ this._snakingVertices ]
					];
				}
			}
			this._snakingDistance -= distance;
			return this._snakeForward(forward);
		}

		this._snakingDistance += forward;

		var percent = this._snakingDistance / distance;

		var headPoint = nextPoint.multiplyBy(percent).add(
			currPoint.multiplyBy( 1 - percent )
		);

		// Put a new head in place.
		var headLatLng = this._map.containerPointToLatLng(headPoint);
		this._latlngs[ this._snakingRings ].push(headLatLng);

		this.setLatLngs(this._latlngs);
		this.fire('snake');
		L.Util.requestAnimFrame(this._snake, this);
	},
	_snakeEnd: function() {
		this.setLatLngs(this._snakeLatLngs);
		this._snaking = false;
		this.fire('snakeend');
	}
});

L.Polyline.mergeOptions({
	snakingSpeed: 200	// In pixels/sec
});

L.LayerGroup.include({
	_snakingLayers: [],
	_snakingLayersDone: 0,

	snakeIn: function() {
		if ( !('performance' in window) ||
		     !('now' in window.performance) ||
		     !this._map ||
		     this._snaking) {
			return;
		}

		this._snaking = true;
		this._snakingLayers = [];
		this._snakingLayersDone = 0;
		for (var key in this._layers) {
			if (this._layers.hasOwnProperty(key)) {
				this._snakingLayers.push(this._layers[key]);
			}
		}
		this.clearLayers();

		this.fire('snakestart');
		return this._snakeNext();
	},

	_snakeNext: function() {
		if (this._snakingLayersDone >= this._snakingLayers.length) {
			this.fire('snakeend');
			this._snaking = false;
			return;
		}

		var currentLayer = this._snakingLayers[this._snakingLayersDone];
		this._snakingLayersDone++;

		this.addLayer(currentLayer);
		if ('snakeIn' in currentLayer) {
			currentLayer.once('snakeend', function(){
				setTimeout(this._snakeNext.bind(this), this.options.snakingPause);
			}, this);
			currentLayer.snakeIn();
		} else {
			setTimeout(this._snakeNext.bind(this), this.options.snakingPause);
		}

		this.fire('snake');
		return this;
	}
});

L.LayerGroup.mergeOptions({
	snakingPause: 200
});
<|endoftext|>


<commit_before>Ext.define('icc.view.idatabase.Collection.Dashboard', {
	extend: 'Ext.panel.Panel',
	alias: 'widget.idatabaseCollectionDashboard',
	frame: false,
	border: false,
	resizeTabs: false,
	enableTabScroll: true,
	autoScroll : true,
	layout: {
		type: 'table',
		columns: 3,
		tableAttrs: {
			style: {
				width: '100%'
			}
		},
		tdAttrs: {
			style: 'padding: 10px;'
		}
	},
	defaults: {
		frame: false,
		height: 350
	},
	renderLayout: false,
	renderDashboard: true,
	initComponent: function() {
		Ext.apply(this, {});
		this.callParent(arguments);
	},
	listeners: {
		afterlayout: function(panel) {
			if (!panel.renderLayout) {
				var columns = 3;
				var width = panel.getWidth();
				if (width >= 1000) {
					columns = 3;
				} else if (width >= 400 && width < 1000) {
					columns = 2;
				} else {
					columns = 1;
				}
				panel.layout.columns = columns;
				panel.renderLayout = true;
				panel.renderDashboard = false;
				panel.doLayout();
				return true;
			}

			if (!panel.renderDashboard) {
				panel.renderDashboard = true;
				var columns = panel.layout.columns;
				var width = Math.floor((panel.getWidth() - 50) / columns);
				Ext.Ajax.request({
					url: '/idatabase/dashboard/index',
					params: {
						__PROJECT_ID__: panel.__PROJECT_ID__
					},
					success: function(response) {
						var result = Ext.JSON.decode(response.responseText);
						if (Ext.isArray(result)) {
							Ext.Array.forEach(result, function(items, index, allTtems) {
								if (Ext.isArray(items['__DATAS__'])) {

									var store = Ext.create('Ext.data.Store', {
										fields: ["_id", "value"],
										data: items['__DATAS__']
									});
									var title = items.name;
									var seriesType = items.seriesType;
									var yAxisTitle = items.yAxisTitle;
									var yAxisType = items.yAxisType;
									var xAxisTitle = items.xAxisTitle;
									var type = {
										sum: '求和',
										avg: '均值',
										count: '计数',
										max: '最大值',
										min: '最小值',
										unique: '唯一值',
										median: '中位数',
										variance: '方差',
										standard: '标准差'
									};

									if (seriesType !== 'pie') {
										var chart = Ext.create('Ext.chart.Chart', {
											style: 'background:#fff',
											store: store,
											width: width,
											height: 300,
											axes: [{
												type: 'Numeric',
												minimum: 0,
												position: 'left',
												fields: ['value'],
												title: yAxisTitle,
												minorTickSteps: 1,
												grid: {
													odd: {
														opacity: 1,
														fill: '#ddd',
														stroke: '#bbb',
														'stroke-width': 0.5
													}
												}
											}, {
												type: 'Category',
												position: 'bottom',
												fields: ['_id'],
												title: xAxisTitle
											}],
											series: [{
												type: seriesType,
												axis: 'left',
												highlight: false,
												xField: '_id',
												yField: 'value',
												tips: {
													trackMouse: true,
													width: 'auto',
													height: 30,
													minHeight: 30,
													renderer: function(storeItem, item) {
														this.setTitle(storeItem.get('_id') + '的' + type[yAxisType] + ':' + storeItem.get('value'));
													}
												}
											}]
										});
									} else {
										var chart = Ext.create('Ext.chart.Chart', {
											animate: true,
											store: store,
											title: items.name,
											shadow: true,
											width: width,
											height: 300,
											legend: {
												position: 'right'
											},
											insetPadding: 10,
											theme: 'Base:gradients',
											series: [{
												type: 'pie',
												field: 'value',
												showInLegend: true,
												donut: true,
												tips: {
													trackMouse: true,
													width: 150,
													height: 28,
													renderer: function(storeItem, item) {
														var total = 0;
														store.each(function(rec) {
															total += rec.get('value');
														});
														this.setTitle(storeItem.get('_id') + ': ' + Math.round(storeItem.get('value') / total * 100, 2) + '%');
													}
												},
												highlight: {
													segment: {
														margin: 20
													}
												},
												label: {
													field: '_id',
													display: 'rotate',
													contrast: true,
													font: '18px Arial'
												}
											}]
										});
									}
									panel.add({
										title: title,
										xtype: 'panel',
										width: width,
										height: 350,
										items: [chart]
									});
								}
							});
						}
					}
				});
			}
			return false;
		}
	}
});<commit_msg>修正统计显示错误的问题<commit_after>Ext.define('icc.view.idatabase.Collection.Dashboard', {
	extend: 'Ext.panel.Panel',
	alias: 'widget.idatabaseCollectionDashboard',
	frame: false,
	border: false,
	resizeTabs: false,
	enableTabScroll: true,
	autoScroll : true,
	layout: {
		type: 'table',
		columns: 3,
		tableAttrs: {
			style: {
				width: '100%'
			}
		},
		tdAttrs: {
			style: 'padding: 10px;'
		}
	},
	defaults: {
		frame: false,
		height: 350
	},
	renderLayout: false,
	renderDashboard: true,
	initComponent: function() {
		Ext.apply(this, {});
		this.callParent(arguments);
	},
	listeners: {
		afterlayout: function(panel) {
			if (!panel.renderLayout) {
				var columns = 3;
				var width = panel.getWidth();
				if (width >= 1000) {
					columns = 3;
				} else if (width >= 400 && width < 1000) {
					columns = 2;
				} else {
					columns = 1;
				}
				panel.layout.columns = columns;
				panel.renderLayout = true;
				panel.renderDashboard = false;
				panel.doLayout();
				return true;
			}

			if (!panel.renderDashboard) {
				panel.renderDashboard = true;
				var columns = panel.layout.columns;
				var width = Math.floor((panel.getWidth() - 50) / columns);
				Ext.Ajax.request({
					url: '/idatabase/dashboard/index',
					params: {
						__PROJECT_ID__: panel.__PROJECT_ID__
					},
					success: function(response) {
						var result = Ext.JSON.decode(response.responseText);
						if (Ext.isArray(result)) {
							Ext.Array.forEach(result, function(items, index, allTtems) {
								if (Ext.isArray(items['__DATAS__'])) {

									var store = Ext.create('Ext.data.Store', {
										fields: ["_id", "value"],
										data: items['__DATAS__']
									});
									var title = items.name;
									var seriesType = items.seriesType;
									var yAxisTitle = items.yAxisTitle;
									var yAxisType = items.yAxisType;
									var xAxisTitle = items.xAxisTitle;
									var type = {
										sum: '求和',
										avg: '均值',
										count: '计数',
										max: '最大值',
										min: '最小值',
										unique: '唯一值',
										distinct: '唯一值',
										median: '中位数',
										variance: '方差',
										standard: '标准差'
									};

									if (seriesType !== 'pie') {
										var chart = Ext.create('Ext.chart.Chart', {
											style: 'background:#fff',
											store: store,
											width: width,
											height: 300,
											axes: [{
												type: 'Numeric',
												minimum: 0,
												position: 'left',
												fields: ['value'],
												title: yAxisTitle,
												minorTickSteps: 1,
												grid: {
													odd: {
														opacity: 1,
														fill: '#ddd',
														stroke: '#bbb',
														'stroke-width': 0.5
													}
												}
											}, {
												type: 'Category',
												position: 'bottom',
												fields: ['_id'],
												title: xAxisTitle
											}],
											series: [{
												type: seriesType,
												axis: 'left',
												highlight: false,
												xField: '_id',
												yField: 'value',
												tips: {
													trackMouse: true,
													width: 'auto',
													maxWidth : 300,
													//height: 30,
													//minHeight: 30,
													renderer: function(storeItem, item) {
														this.setTitle(storeItem.get('_id') + '的' + type[yAxisType] + ':' + storeItem.get('value'));
													}
												}
											}]
										});
									} else {
										var chart = Ext.create('Ext.chart.Chart', {
											animate: true,
											store: store,
											title: items.name,
											shadow: true,
											width: width,
											height: 300,
											legend: {
												position: 'right'
											},
											insetPadding: 10,
											theme: 'Base:gradients',
											series: [{
												type: 'pie',
												field: 'value',
												showInLegend: true,
												donut: true,
												tips: {
													trackMouse: true,
													width: 'auto',
													maxWidth : 300,
													//height: 28,
													renderer: function(storeItem, item) {
														var total = 0;
														store.each(function(rec) {
															total += rec.get('value');
														});
														this.setTitle(storeItem.get('_id') + ': ' + Math.round(storeItem.get('value') / total * 100, 2) + '% ('+storeItem.get('value')+')');
													}
												},
												highlight: {
													segment: {
														margin: 20
													}
												},
												label: {
													field: '_id',
													display: 'rotate',
													contrast: true,
													font: '18px Arial'
												}
											}]
										});
									}
									panel.add({
										title: title,
										xtype: 'panel',
										width: width,
										height: 350,
										items: [chart]
									});
								}
							});
						}
					}
				});
			}
			return false;
		}
	}
});<|endoftext|>


<commit_before>/**
 * Clarify.
 *
 * Copyright (C) 2012 Roger Dudler <roger.dudler@gmail.com>
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */
(function($) {
    Tc.Module.LayerColor = Tc.Module.extend({

        active: false,
        drag: false,
        hover: false,

        on: function(callback) {
            var that = this;

            $('.btn-color').bind('click', function(e) {
                if (that.active) {
                    that.deactivate();
                } else {
                    that.sandbox.getModuleById($('.modLayerModule').data('id')).deactivate();
                    that.sandbox.getModuleById($('.modLayerComment').data('id')).deactivate();
                    that.sandbox.getModuleById($('.modLayerMeasure').data('id')).deactivate();
                    that.sandbox.getModuleById($('.modLayerTypography').data('id')).deactivate();
                    that.activate();
                }
            });
            callback();
        },

        load: function() {
            var that = this;
            var screen = $('.modScreen').data('screen');
            $.ajax({
                url: "/api/color/get/" + screen,
                dataType: 'json',
                success: function(data){
                    $.each(data, function(key, color) {
                        that.addColor(color, false);
                    });
                }
            });
        },

        activate: function() {
            var that = this;
            this.active = true;
            var colors = $('.color');
            $.each(colors, function(key, color) {
                that.addLibraryColor(color);
            });

            var screen = $('.modScreen');
            $('.btn-color').addClass('active');

            $('.modColorLibrary').show();
            $('.modScreen').eyedrop({
                'display': true,
                pick: function(x, y, color) {
                    if (that.drag || that.hover) {
                        return;
                    }
                    $.ajax({
                        url: "/api/color/add/" + screen.data('screen') + "/" + x + "/" + y + "/" + color.r + "/" + color.g + "/" + color.b + "/" + color.a + "/" + encodeURIComponent(color.hex.substring(1)),
                        dataType: 'json',
                        success: function(data){
                            if (data.result == 'NEW') {
                                var box = $('');
                                box.css('backgroundColor', color.hex);
                                $('.modColorLibrary').append(box);
                                box.tooltip();
                                that.addLibraryColor(box);
                            }
                            that.addColor(data, true);
                        }
                    });
                }
            });
            this.load();
        },

        deactivate: function() {
            this.active = false;
            this.$ctx.empty();
            $('.modColorLibrary').hide();
            $('.modScreen').unbind('click mousemove mouseup mousedown mouseenter mouseleave');
            $('.modScreen').css('cursor', 'auto');
            $('.btn-color').removeClass('active');
            $('.picker').hide();
        },

        addLibraryColor: function(color) {
            var that = this;
            $(color).css('backgroundColor', '#' + $(color).data('color'));
            $(color).draggable({
                helper: "clone",
                revert: "true",
                cursorAt: {top: 0, left: -20},
                stop: function(e) {
                    var offset = $('.modScreen').offset();
                    var x = e.pageX - offset.left;
                    var y = e.pageY - offset.top;
                    $.ajax({
                        url: "/api/color/add/" + $('.modScreen').data('screen') + "/" + x + "/" + y + "/" + $(color).data('id'),
                        dataType: 'json',
                        success: function(data){
                            that.addColor(data, true);
                        }
                    });
                }
            });
        },

        addColor: function(color, fade) {
            var that = this;
            var label = color.name;
            var hex = '#' + color.hex;
            if (!label) {
                label = hex;
            }
            var $meta = $('' + label + '
#' + color.hex + '');
            $meta.on('click', function() {
                var $link = $(this);
                var data = { 'hex': hex.toUpperCase(), 'name': label };
                var modal = that.sandbox.getModuleById($('.modModal').data('id'));
                modal.open('color-edit', data, function() {
                    var $name = $(this).closest('.modal').find('.fld-name');
                    var $hex = $(this).closest('.modal').find('.fld-hex');
                    $.ajax({
                        url: "/api/color/update/" + color.id + "/" + $hex.val().substring(1,7) + "/" + encodeURIComponent($name.val()),
                        dataType: 'json',
                        type: 'POST',
                        success: function(data){
                            $link.find('.name').text($name.val());
                            $link.find('.hex').text($hex.val());
                            modal.cancel();
                        }
                    });
                });
                return false;
            });
            var element = $('

');
            element.append($meta);
            element.css({
                left: color.x + 'px',
                top: color.y + 'px',
                position: 'absolute'
            });
            $('.p', element).css('backgroundColor', '#' + color.hex);

            element.bind('click', function(e) {
                e.stopPropagation();
                return false;
            })

            // show / hide picker on hover
            element.hover(
                function(){
                    $('.picker').hide();
                    that.hover = true;
                },
                function(){
                    $('.picker').show();
                    that.hover = false;
                }
            );

            // delete on double click
            element.bind('dblclick', function(e) {
                $.ajax({
                    url: "/api/color/remove/" + color.id,
                    dataType: 'json',
                    success: function(data){
                        element.remove();
                        if (data.remove > 0) {
                            $('.color-' + data.remove).remove();
                        }
                    }
                });
                that.hover = false;
                e.stopPropagation();
                return false;
            });

            // draw element
            this.$ctx.append(element);
            if (fade) {
                element.fadeIn('fast');
            } else {
                element.show();
            }
        }
    });
})(Tc.$);<commit_msg>color edit modal fix.<commit_after>/**
 * Clarify.
 *
 * Copyright (C) 2012 Roger Dudler <roger.dudler@gmail.com>
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */
(function($) {
    Tc.Module.LayerColor = Tc.Module.extend({

        active: false,
        drag: false,
        hover: false,

        on: function(callback) {
            var that = this;

            $('.btn-color').bind('click', function(e) {
                if (that.active) {
                    that.deactivate();
                } else {
                    that.sandbox.getModuleById($('.modLayerModule').data('id')).deactivate();
                    that.sandbox.getModuleById($('.modLayerComment').data('id')).deactivate();
                    that.sandbox.getModuleById($('.modLayerMeasure').data('id')).deactivate();
                    that.sandbox.getModuleById($('.modLayerTypography').data('id')).deactivate();
                    that.activate();
                }
            });
            callback();
        },

        load: function() {
            var that = this;
            var screen = $('.modScreen').data('screen');
            $.ajax({
                url: "/api/color/get/" + screen,
                dataType: 'json',
                success: function(data){
                    $.each(data, function(key, color) {
                        that.addColor(color, false);
                    });
                }
            });
        },

        activate: function() {
            var that = this;
            this.active = true;
            var colors = $('.color');
            $.each(colors, function(key, color) {
                that.addLibraryColor(color);
            });

            var screen = $('.modScreen');
            $('.btn-color').addClass('active');

            $('.modColorLibrary').show();
            $('.modScreen').eyedrop({
                'display': true,
                pick: function(x, y, color) {
                    if (that.drag || that.hover) {
                        return;
                    }
                    $.ajax({
                        url: "/api/color/add/" + screen.data('screen') + "/" + x + "/" + y + "/" + color.r + "/" + color.g + "/" + color.b + "/" + color.a + "/" + encodeURIComponent(color.hex.substring(1)),
                        dataType: 'json',
                        success: function(data){
                            if (data.result == 'NEW') {
                                var box = $('');
                                box.css('backgroundColor', color.hex);
                                $('.modColorLibrary').append(box);
                                box.tooltip();
                                that.addLibraryColor(box);
                            }
                            that.addColor(data, true);
                        }
                    });
                }
            });
            this.load();
        },

        deactivate: function() {
            this.active = false;
            this.$ctx.empty();
            $('.modColorLibrary').hide();
            $('.modScreen').unbind('click mousemove mouseup mousedown mouseenter mouseleave');
            $('.modScreen').css('cursor', 'auto');
            $('.btn-color').removeClass('active');
            $('.picker').hide();
        },

        addLibraryColor: function(color) {
            var that = this;
            $(color).css('backgroundColor', '#' + $(color).data('color'));
            $(color).draggable({
                helper: "clone",
                revert: "true",
                cursorAt: {top: 0, left: -20},
                stop: function(e) {
                    var offset = $('.modScreen').offset();
                    var x = e.pageX - offset.left;
                    var y = e.pageY - offset.top;
                    $.ajax({
                        url: "/api/color/add/" + $('.modScreen').data('screen') + "/" + x + "/" + y + "/" + $(color).data('id'),
                        dataType: 'json',
                        success: function(data){
                            that.addColor(data, true);
                        }
                    });
                }
            });
        },

        addColor: function(color, fade) {
            var that = this;
            var label = color.name;
            var hex = '#' + color.hex;
            if (!label) {
                label = hex;
            }
            var $meta = $('' + label + '
#' + color.hex + '');
            $meta.on('click', function() {
                var $link = $(this);
                var data = { 'hex': $(this).data('hex').toUpperCase(), 'name': $(this).data('name') };
                var modal = that.sandbox.getModuleById($('.modModal').data('id'));
                modal.open('color-edit', data, function() {
                    var $name = $(this).closest('.modal').find('.fld-name');
                    var $hex = $(this).closest('.modal').find('.fld-hex');
                    $.ajax({
                        url: "/api/color/update/" + color.id + "/" + $hex.val().substring(1,7) + "/" + encodeURIComponent($name.val()),
                        dataType: 'json',
                        type: 'POST',
                        success: function(data){
                            $link.parent().find('.p').css('backgroundColor', $hex.val());
                            $link.find('.name').text($name.val());
                            $link.find('.hex').text($hex.val());
                            $link.data('name', $name.val());
                            $link.data('hex', $hex.val());
                            modal.cancel();
                        }
                    });
                });
                return false;
            });
            var element = $('

');
            element.append($meta);
            element.css({
                left: color.x + 'px',
                top: color.y + 'px',
                position: 'absolute'
            });
            $('.p', element).css('backgroundColor', '#' + color.hex);

            element.bind('click', function(e) {
                e.stopPropagation();
                return false;
            })

            // show / hide picker on hover
            element.hover(
                function(){
                    $('.picker').hide();
                    that.hover = true;
                },
                function(){
                    $('.picker').show();
                    that.hover = false;
                }
            );

            // delete on double click
            element.bind('dblclick', function(e) {
                $.ajax({
                    url: "/api/color/remove/" + color.id,
                    dataType: 'json',
                    success: function(data){
                        element.remove();
                        if (data.remove > 0) {
                            $('.color-' + data.remove).remove();
                        }
                    }
                });
                that.hover = false;
                e.stopPropagation();
                return false;
            });

            // draw element
            this.$ctx.append(element);
            if (fade) {
                element.fadeIn('fast');
            } else {
                element.show();
            }
        }
    });
})(Tc.$);<|endoftext|>


<commit_before>'use strict';

/*
* Handles the actual work of calling the REST endpoint to authenticate the user
* */
angular.module('admin').factory('AuthService', ['$http',
    function($http)
    {
        var authService = {}

        authService.login = function(credentials)
        {
            return $http
                .post('/auth/signin', credentials)
                .then(function(response)
                {
                    return response.data;
                });
        }

        return authService;
    }
]);<commit_msg>clean up some jslint warnings.<commit_after>'use strict';

/*
* Handles the actual work of calling the REST endpoint to authenticate the user
* */
angular.module('admin').factory('AuthService', ['$http',
    function($http)
    {
        var authService = {};

        authService.login = function(credentials)
        {
            return $http
                .post('/auth/signin', credentials)
                .then(function(response)
                {
                    return response.data;
                });
        };

        return authService;
    }
]);<|endoftext|>


<commit_before>/*
Copyright [2009-2014] EMBL-European Bioinformatics Institute
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
     http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/**
 * RNAcentral metadata search Angular.js app.
 */

; // concatenation safeguard

/**
 * Make it possible to include underscore as a dependency.
 */
var underscore = angular.module('underscore', []);
underscore.factory('_', function() {
    return window._;
});

/**
 * Create RNAcentral app.
 */
var rnaMetasearch = angular.module('rnacentralApp', ['chieffancypants.loadingBar', 'underscore']);

/**
 * html5mode removes hashtags from urls.
 */
rnaMetasearch.config(['$locationProvider', function($locationProvider) {
    $locationProvider.html5Mode(true);
}]);

/**
 * Service for passing data between controllers.
 */
rnaMetasearch.service('results', ['_', '$http', '$location', '$window', function(_, $http, $location, $window) {
    var result = {
        hitCount: null,
        entries: [],
        facets: []
    }
    var show_results = false; // hide results section at first
    var search_in_progress = false;

    var search_config = {
        ebeye_base_url: 'http://ash-4.ebi.ac.uk:8080/ebisearch/ws/rest/rnacentral',
        rnacentral_base_url: get_base_url(),
        fields: ['description', 'active', 'length'],
        facetfields: ['expert_db', 'rna_type', 'TAXONOMY'], // will be displayed in this order
        facetcount: 30,
        page_size: 15,
        max_facet_count: 1000,
    };
    var page_size = search_config.page_size; // set to the default value

    var query_urls = {
        'ebeye_search': search_config.ebeye_base_url +
                        '?query={QUERY}' +
                        '&format=json' +
                        '&fields=' + search_config.fields.join() +
                        '&facetcount=' + search_config.facetcount +
                        '&facetfields=' + search_config.facetfields.join() +
                        '&size={SIZE}' +
                        '&start=0',
        'proxy': search_config.rnacentral_base_url +
                 '/api/internal/ebeye?url={EBEYE_URL}',
        'get_more_facet_values': search_config.ebeye_base_url +
                                 '?query={QUERY}' +
                                 '&format=json' +
                                 '&facetcount=' + search_config.max_facet_count +
                                 '&facetfields={FACET_ID}' +
                                 '&size=0', // retrieve just facets
    };

    /**
     * Calculate base url for production and development environments.
     */
    function get_base_url() {
        var base_url = $location.protocol() + '://' + $location.host();
        var port = $location.port();
        if (port !== '') {
            base_url += ':' + port
        }
        return base_url;
    };

    /**
     * Process deeply nested json objects like this:
     * { "field" : [ {"id": "description", "values": {"value": "description_value"}} ] }
     * into key-value pairs like this:
     * {"description": "description_value"}
     */
    var preprocess_results = function(data) {
        result.hitCount = data.hitCount;
        result.entries = data.entries;
        // sort facets the same way as in config
        result.facets = _.sortBy(data.facets, function(facet){
            return _.indexOf(search_config.facetfields, facet.id);
        });
    };

    /**
     * Format urls and execute remote request.
     */
    var execute_ebeye_search = function(url) {
        search_in_progress = true;
        $http({
            url: url,
            method: 'GET'
        }).success(function(data) {
            preprocess_results(data);
            search_in_progress = false;
        }).error(function(){
            search_in_progress = false;
        });
    };

    /**
     * Launch EBeye search
     */
    this.search = function(query, new_page_size) {
        // display results section
        show_results = true;
        // update page title
        $window.document.title = 'Search: ' + query;

        if (typeof(new_page_size) == "undefined") {
            // if unspecified, use default
            page_size = search_config.page_size;
            // initial search, display spinner
            result.hitCount = null;
        } else {
            // load_more_results search, use supplied new_page_size value
            page_size = new_page_size;
        }

        var ebeye_url = query_urls.ebeye_search.replace('{QUERY}', query).replace('{SIZE}', page_size);
        var url = query_urls.proxy.replace('{EBEYE_URL}', encodeURIComponent(ebeye_url));
        execute_ebeye_search(url);
    };

    /**
     * Increment `page_size` and retrieve all entries from the server.
     * The new entries will be added to the results list.
     */
    this.load_more_results = function() {
        page_size += search_config.page_size;
        query = $location.search().q;
        this.search(query, page_size);
    };

    this.load_more_facets = function(facet_id) {
        var query = $location.search().q;
        var ebeye_url = query_urls.get_more_facet_values.replace('{QUERY}', query).replace('{FACET_ID}', facet_id);
        var url = query_urls.proxy.replace('{EBEYE_URL}', encodeURIComponent(ebeye_url)) ;
        $http({
            url: url,
            method: 'GET'
        }).success(function(data) {
            // find where to insert new data
            var facet_num = _.indexOf(_.map(result.facets, function(facet){
                return facet['id'] === facet_id;
            }), true);
            result.facets[facet_num].facetValues = data.facets.facet.facetValues;
        });
    };

    this.get_page_size = function() {
        return page_size;
    };

    this.get_status = function() {
        return show_results;
    };

    this.set_status = function() {
        show_results = true;
    };

    this.get_results = function() {
        return result;
    };

    this.get_max_facet_count = function() {
        return search_config.max_facet_count;
    };

    this.get_search_in_progress = function() {
        return search_in_progress;
    };

}]);

rnaMetasearch.controller('MainContent', ['$scope', '$anchorScroll', '$location', 'results', function($scope, $anchorScroll, $location, results) {
    /**
     * Enables scrolling to anchor tags.
     * Title
     */
    $scope.scrollTo = function(id) {
        $location.hash(id);
        $anchorScroll();
    };

    /**
     * Watch show_results in order to hide non-search-related content
     * when a search is initiated.
     */
    $scope.$watch(function () { return results.get_status(); }, function (newValue, oldValue) {
        if (newValue != null) {
            $scope.show_results = newValue;
        }
    });

}]);

/**
 * Results display controller
 * Responsible for visualising search results.
 */
rnaMetasearch.controller('ResultsListCtrl', ['$scope', '$location', 'results', function($scope, $location, results) {

    $scope.page_size = results.get_page_size(); // know when to show Load more button
    $scope.max_facet_count = results.get_max_facet_count();
    $scope.search_in_progress = results.get_search_in_progress();

    /**
     * Refresh results data.
     */
    $scope.$watch(function () { return results.get_results(); }, function (newValue, oldValue) {
        if (newValue != null) {
            $scope.result = newValue;
        }
    });

    /**
     * Monitor show_results changes.
     */
    $scope.$watch(function () { return results.get_status(); }, function (newValue, oldValue) {
        if (newValue != null) {
            $scope.show_results = newValue;
        }
    });

    /**
     * Monitor page_size changes.
     */
    $scope.$watch(function () { return results.get_page_size(); }, function (newValue, oldValue) {
        if (newValue != oldValue) {
            $scope.page_size = newValue;
        }
    });

    /**
     * Monitor search_in_progress changes.
     */
    $scope.$watch(function () { return results.get_search_in_progress(); }, function (newValue, oldValue) {
        if (newValue != oldValue) {
            $scope.search_in_progress = newValue;
        }
    });

    /**
     * Fired when "Load more" button is clicked.
     */
    $scope.load_more_results = function() {
        results.load_more_results();
    };

    $scope.load_more_facets = function(facet_id) {
        results.load_more_facets(facet_id);
    };

    /**
     * Repeat a search with a facet enabled.
     */
    $scope.facet_search = function(facet_id, facet_value) {
        var query = $location.search().q;
        var new_query = query + ' AND ' + facet_id + ':"' + facet_value + '"';
        $location.search('q', new_query);
    };

    /**
     * Calculate the number of currently displayed items.
     */
    $scope.displayed_items = function() {
        return Math.min($scope.page_size, $scope.result.hitCount);
    };

    /**
     * Show/hide search facets to save screen space.
     * Uses jQuery for simplicity.
     * Activated only on mobile devices.
     */
    $scope.toggle_facets = function() {
        var facets = $('.metasearch-facets');
        facets.toggleClass('hidden-xs', !facets.hasClass('hidden-xs'));
        $('#toggle-facets').text(function(i, text){
          return text === "Show facets" ? "Hide facets" : "Show facets";
        });
    };

}]);

/**
 * Query controller
 * Responsible for the search box in the header.
 */
rnaMetasearch.controller('QueryCtrl', ['$scope', '$location', 'results', function($scope, $location, results) {

    $scope.query = {
        text: '',
        submitted: false
    };

    /**
     * Control browser navigation buttons.
     */
    $scope.$watch(function () { return $location.url(); }, function (newUrl, oldUrl) {
        // url has changed
        if (newUrl !== oldUrl) {
            if (newUrl.indexOf('/search') == -1) {
                // a non-search url, load that page
                window.location.href = newUrl;
            } else {
                // the new url is a search result page, launch that search
                $scope.query.text = $location.search().q;
                results.search($location.search().q);
                $scope.query.submitted = false;
            }
        }
    });

    /**
     * To launch a new search, change browser url,
     * which will automatically trigger a new search because the url changes
     * are watched.
     */
    $scope.search = function(query) {
        $location.url('/search' + '?q=' + query);
    }

    /**
     * Called when the form is submitted.
     */
    $scope.submit_query = function() {
        $scope.query.submitted = true;
        if ($scope.queryForm.text.$invalid) {
            return;
        }
        $scope.search($scope.query.text);
    };

    /**
     * Check if the url contains a query when the controller is first created
     * and initiate a search if necessary.
     */
    (function () {
        if ($location.url().indexOf("/search?q=") > -1) {
            // a search result page, launch a new search
            $scope.query.text = $location.search().q;
            results.search($location.search().q);
        }
    })();

}]);
<commit_msg>Minor refactoring and comments<commit_after>/*
Copyright [2009-2014] EMBL-European Bioinformatics Institute
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
     http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/**
 * RNAcentral metadata search Angular.js app.
 */

; // concatenation safeguard

/**
 * Make it possible to include underscore as a dependency.
 */
var underscore = angular.module('underscore', []);
underscore.factory('_', function() {
    return window._;
});

/**
 * Create RNAcentral app.
 */
var rnaMetasearch = angular.module('rnacentralApp', ['chieffancypants.loadingBar', 'underscore']);

/**
 * html5mode removes hashtags from urls.
 */
rnaMetasearch.config(['$locationProvider', function($locationProvider) {
    $locationProvider.html5Mode(true);
}]);

/**
 * Service for passing data between controllers.
 */
rnaMetasearch.service('results', ['_', '$http', '$location', '$window', function(_, $http, $location, $window) {
    var result = {
        hitCount: null,
        entries: [],
        facets: []
    }
    var show_results = false; // hide results section at first
    var search_in_progress = false;

    var search_config = {
        ebeye_base_url: 'http://ash-4.ebi.ac.uk:8080/ebisearch/ws/rest/rnacentral',
        rnacentral_base_url: get_base_url(),
        fields: ['description', 'active', 'length'],
        facetfields: ['expert_db', 'rna_type', 'TAXONOMY'], // will be displayed in this order
        facetcount: 30,
        page_size: 15,
        max_facet_count: 1000,
    };
    var page_size = search_config.page_size; // set to the default value

    var query_urls = {
        'ebeye_search': search_config.ebeye_base_url +
                        '?query={QUERY}' +
                        '&format=json' +
                        '&fields=' + search_config.fields.join() +
                        '&facetcount=' + search_config.facetcount +
                        '&facetfields=' + search_config.facetfields.join() +
                        '&size={SIZE}' +
                        '&start=0',
        'proxy': search_config.rnacentral_base_url +
                 '/api/internal/ebeye?url={EBEYE_URL}',
        'get_more_facet_values': search_config.ebeye_base_url +
                                 '?query={QUERY}' +
                                 '&format=json' +
                                 '&facetcount=' + search_config.max_facet_count +
                                 '&facetfields={FACET_ID}' +
                                 '&size=0', // retrieve just facets
    };

    /**
     * Calculate base url for production and development environments.
     */
    function get_base_url() {
        var base_url = $location.protocol() + '://' + $location.host();
        var port = $location.port();
        if (port !== '') {
            base_url += ':' + port
        }
        return base_url;
    };

    /**
     * Pre-process the data received from the server.
     */
    var preprocess_results = function(data) {
        result = data;
        // sort facets the same way as in config
        result.facets = _.sortBy(result.facets, function(facet){
            return _.indexOf(search_config.facetfields, facet.id);
        });
    };

    /**
     * Format urls and execute remote request.
     */
    var execute_ebeye_search = function(url) {
        search_in_progress = true;
        $http({
            url: url,
            method: 'GET'
        }).success(function(data) {
            preprocess_results(data);
            search_in_progress = false;
        }).error(function(){
            search_in_progress = false;
        });
    };

    /**
     * Launch EBeye search
     */
    this.search = function(query, new_page_size) {
        // display results section
        show_results = true;
        // update page title
        $window.document.title = 'Search: ' + query;

        if (typeof(new_page_size) == "undefined") {
            // if unspecified, use default
            page_size = search_config.page_size;
            // initial search, display spinner
            result.hitCount = null;
        } else {
            // load_more_results search, use supplied new_page_size value
            page_size = new_page_size;
        }

        var ebeye_url = query_urls.ebeye_search.replace('{QUERY}', query).replace('{SIZE}', page_size);
        var url = query_urls.proxy.replace('{EBEYE_URL}', encodeURIComponent(ebeye_url));
        execute_ebeye_search(url);
    };

    /**
     * Increment `page_size` and retrieve all entries from the server.
     * The new entries will be added to the results list.
     */
    this.load_more_results = function() {
        page_size += search_config.page_size;
        query = $location.search().q;
        this.search(query, page_size);
    };

    this.load_more_facets = function(facet_id) {
        var query = $location.search().q;
        var ebeye_url = query_urls.get_more_facet_values.replace('{QUERY}', query).replace('{FACET_ID}', facet_id);
        var url = query_urls.proxy.replace('{EBEYE_URL}', encodeURIComponent(ebeye_url)) ;
        $http({
            url: url,
            method: 'GET'
        }).success(function(data) {
            // find where to insert new data
            var facet_num = _.indexOf(_.map(result.facets, function(facet){
                return facet['id'] === facet_id;
            }), true);
            result.facets[facet_num].facetValues = data.facets.facet.facetValues;
        });
    };

    this.get_page_size = function() {
        return page_size;
    };

    this.get_status = function() {
        return show_results;
    };

    this.set_status = function() {
        show_results = true;
    };

    this.get_results = function() {
        return result;
    };

    this.get_max_facet_count = function() {
        return search_config.max_facet_count;
    };

    this.get_search_in_progress = function() {
        return search_in_progress;
    };

}]);

rnaMetasearch.controller('MainContent', ['$scope', '$anchorScroll', '$location', 'results', function($scope, $anchorScroll, $location, results) {
    /**
     * Enables scrolling to anchor tags.
     * Title
     */
    $scope.scrollTo = function(id) {
        $location.hash(id);
        $anchorScroll();
    };

    /**
     * Watch show_results in order to hide non-search-related content
     * when a search is initiated.
     */
    $scope.$watch(function () { return results.get_status(); }, function (newValue, oldValue) {
        if (newValue != null) {
            $scope.show_results = newValue;
        }
    });

}]);

/**
 * Results display controller
 * Responsible for visualising search results.
 */
rnaMetasearch.controller('ResultsListCtrl', ['$scope', '$location', 'results', function($scope, $location, results) {

    $scope.page_size = results.get_page_size(); // know when to show Load more button
    $scope.max_facet_count = results.get_max_facet_count();
    $scope.search_in_progress = results.get_search_in_progress();

    /**
     * Refresh results data.
     */
    $scope.$watch(function () { return results.get_results(); }, function (newValue, oldValue) {
        if (newValue != null) {
            $scope.result = newValue;
        }
    });

    /**
     * Monitor show_results changes.
     */
    $scope.$watch(function () { return results.get_status(); }, function (newValue, oldValue) {
        if (newValue != null) {
            $scope.show_results = newValue;
        }
    });

    /**
     * Monitor page_size changes.
     */
    $scope.$watch(function () { return results.get_page_size(); }, function (newValue, oldValue) {
        if (newValue != oldValue) {
            $scope.page_size = newValue;
        }
    });

    /**
     * Monitor search_in_progress changes.
     */
    $scope.$watch(function () { return results.get_search_in_progress(); }, function (newValue, oldValue) {
        if (newValue != oldValue) {
            $scope.search_in_progress = newValue;
        }
    });

    /**
     * Fired when "Load more" button is clicked.
     */
    $scope.load_more_results = function() {
        results.load_more_results();
    };

    $scope.load_more_facets = function(facet_id) {
        results.load_more_facets(facet_id);
    };

    /**
     * Repeat a search with a facet enabled.
     */
    $scope.facet_search = function(facet_id, facet_value) {
        var query = $location.search().q;
        var new_query = query + ' AND ' + facet_id + ':"' + facet_value + '"';
        $location.search('q', new_query);
    };

    /**
     * Calculate the number of currently displayed items.
     */
    $scope.displayed_items = function() {
        return Math.min($scope.page_size, $scope.result.hitCount);
    };

    /**
     * Show/hide search facets to save screen space.
     * Uses jQuery for simplicity.
     * Activated only on mobile devices.
     */
    $scope.toggle_facets = function() {
        var facets = $('.metasearch-facets');
        facets.toggleClass('hidden-xs', !facets.hasClass('hidden-xs'));
        $('#toggle-facets').text(function(i, text){
          return text === "Show facets" ? "Hide facets" : "Show facets";
        });
    };

}]);

/**
 * Query controller
 * Responsible for the search box in the header.
 */
rnaMetasearch.controller('QueryCtrl', ['$scope', '$location', 'results', function($scope, $location, results) {

    $scope.query = {
        text: '',
        submitted: false
    };

    /**
     * Control browser navigation buttons.
     */
    $scope.$watch(function () { return $location.url(); }, function (newUrl, oldUrl) {
        // url has changed
        if (newUrl !== oldUrl) {
            if (newUrl.indexOf('/search') == -1) {
                // a non-search url, load that page
                window.location.href = newUrl;
            } else {
                // the new url is a search result page, launch that search
                $scope.query.text = $location.search().q;
                results.search($location.search().q);
                $scope.query.submitted = false;
            }
        }
    });

    /**
     * To launch a new search, change browser url,
     * which will automatically trigger a new search because the url changes
     * are watched.
     */
    $scope.search = function(query) {
        $location.url('/search' + '?q=' + query);
    }

    /**
     * Called when the form is submitted.
     */
    $scope.submit_query = function() {
        $scope.query.submitted = true;
        if ($scope.queryForm.text.$invalid) {
            return;
        }
        $scope.search($scope.query.text);
    };

    /**
     * Check if the url contains a query when the controller is first created
     * and initiate a search if necessary.
     */
    (function () {
        if ($location.url().indexOf("/search?q=") > -1) {
            // a search result page, launch a new search
            $scope.query.text = $location.search().q;
            results.search($location.search().q);
        }
    })();

}]);
<|endoftext|>


<commit_before>/*
 * Copyright 2016 SimplifyOps, Inc. (http://simplifyops.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//= require knockout.min
//= require knockout-mapping
//= require knockout-onenter
//= require ko/binding-url-path-param
//= require ko/binding-message-template
//= require ko/binding-popover
//= require jquery.waypoints.min
//= require menu/project-model

function HomeData(data) {
    var self = this;
    self.baseUrl = data.baseUrl;
    self.summaryUrl = data.summaryUrl;
    self.projectNamesUrl = data.projectNamesUrl;
    self.loaded = ko.observable(data.loaded?true:false);
    self.jobCount = ko.observable(0);
    self.execCount = ko.observable(data.execCount||0);
    self.totalFailedCount = ko.observable(data.totalFailedCount||0);
    self.projectNames = ko.observableArray(data.projectNames || []);
    self.projectNamesTotal = ko.observable(data.projectNamesTotal || 0);
    self.loadedProjectNames = ko.observable(false);
    self.projects = ko.observableArray([]);
    self.projects.extend({rateLimit: 500});

    self.recentUsers = ko.observableArray(data.recentUsers||[]);
    self.recentProjects = ko.observableArray(data.recentProjects||[]);
    self.frameworkNodeName = ko.observable(null);
    self.doRefresh = ko.observable(false);
    self.doPaging = ko.observable(false);
    self.pagingMax = ko.observable(20);
    self.pagingRepeatMax = ko.observable(20);
    self.pagingDelay = ko.observable(2000);
    self.pagingOffset = ko.observable(0);
    self.refreshDelay = ko.observable(30000);
    self.search=ko.observable(null);

    //batch of project data to load
    self.batchList=ko.observableArray([]);
    self.batchList.extend({ rateLimit: 500 });
    self.batches=ko.observableArray([]);

    self.recentUsersCount = ko.pureComputed(function () {
        return self.recentUsers().length;
    });
    self.recentProjectsCount = ko.pureComputed(function () {
        return self.recentProjects().length;
    });
    self.searchedProjects=ko.pureComputed(function(){
        "use strict";
        var search=self.search();
        var names=self.projectNames();
        if(null==search){
            return names;
        }
        var regex;
        if (search.charAt(0) === '/' && search.charAt(search.length - 1) === '/') {
            regex = new RegExp(search.substring(1, search.length - 1),'i');
        }else{
            //simple match which is case-insensitive, escaping special regex chars
            regex = new RegExp(search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'),'i');
        }
        return ko.utils.arrayFilter(names,function(val,ndx){
            var proj = self.projectForName(val);
            var label = proj.label();
            return val.match(regex) || label && label.match(regex);
        });
    });
    self.searchedProjectsCount = ko.pureComputed(function () {
        return self.searchedProjects().length;
    });
    self.projectCount = ko.pureComputed(function () {
        return self.projectNames().length;
    });
    self.projectsByName = ko.pureComputed(function () {
        var obj = {};
        ko.utils.arrayForEach(self.projects(), function (elem, ndx) {
            obj[ko.unwrap(elem.name)] = elem;
        });
        return obj;
    });
    self.searchProjectsByName = ko.pureComputed(function () {
        var obj = {};
        ko.utils.arrayForEach(self.searchedProjects(), function (elem, ndx) {
            obj[ko.unwrap(elem.name)] = elem;
        });
        return obj;
    });
    self.projectInSearch=function(name){
        "use strict";
        return !self.search() || self.searchProjectsByName()[name]!=null;
    };
    self.prototypeProject = new Project({page: 'projectList'});
    self.projectForName = function (name) {
        var projectsByName = self.projectsByName()[name];
        if(null==projectsByName){
            return self.prototypeProject;
        }
        return projectsByName;
    };
    self.mapping = {
        'projects': {
            key: function (data) {
                return ko.utils.unwrapObservable(data.name);
            },
            create: function (data) {
                "use strict";
                return new Project(options.data);
            },
            update: function (options) {
                var updateArray = [];
                var found = options.parent.projectForName(options.data.name);
                if (found) {
                    return ko.mapping.fromJS(options.data, {}, found);
                } else {
                    return ko.mapping.fromJS(options.data, {}, {});
                }
            }
        }
    };
    self.loadSummary = function () {
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.summaryUrl, {}),
            success: function (data, status, jqxhr) {

                ko.mapping.fromJS(data, self.mapping, self);
                self.loaded(true);

                if (self.doRefresh()) {
                    setTimeout(self.loadSummary, self.refreshDelay());
                }
            }
        });
    };
    self.loadProjects = function (projs) {
        for (var i = 0; i < projs.length; i++) {
            var newproj = projs[i];
            var found = self.projectForName(newproj.name);
            if (found && found.name()==newproj.name) {
                ko.mapping.fromJS(newproj, null, found);
                found.loaded(true);
            } else {
                self.projects.push(
                    new Project(jQuery.extend(newproj, {loaded: true, page: 'projectList'}))
                );
            }
        }
    };
    self.load = function (refresh) {
        var params = {};//refresh?{refresh:true}:{};
        if (self.doPaging()) {
            jQuery.extend(params, {
                offset: self.pagingOffset(),
                max: self.pagingMax()
            });
            self.pagingMax(self.pagingRepeatMax());
        }
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.baseUrl, params),
            success: function (data, status, jqxhr) {
                if (data.projects) {
                    self.loadProjects(data.projects);
                }
                // ko.mapping.fromJS(data, self.mapping, self);
                if (self.doPaging() && data.nextoffset) {
                    self.pagingOffset(data.nextoffset);
                    if (self.pagingOffset() === -1) {
                        self.pagingOffset(0);
                    } else {
                        setTimeout(function(){self.load(true);}, self.pagingDelay());
                    }
                }
            }
        });
    };
    self.pullBatch=function(){
        "use strict";
        //pull up to max number of items from batchList
        var items=self.batchList.splice(0,self.pagingMax());
        if(items.length>0) {
            self.batches.push(items);
        }
    };
    self.batchList.subscribe(function(newValue){
        "use strict";
        if(newValue.length>0){
            setTimeout(self.pullBatch,100);
        }
    });
    self.batches.subscribe(function(newValue){
        if(!self.batchLoading && newValue.length>0){
            self.batchLoading=true;
            setTimeout(self.loadBatch,100);
        }
    });
    self.clearBatchLoad=function(){
        "use strict";

        self.batchList([]);
        self.batches([]);
    };
    self.search.subscribe(self.clearBatchLoad);
    self.batchLoading=false;
    self.loadBatch = function () {
        self.batchLoading=true;
        var projects=self.batches.shift();
        if(null==projects || projects.length<1){
            self.batchLoading=false;
            return;
        }
        var params = {projects:projects.join(',')};//refresh?{refresh:true}:{};
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.baseUrl, params),
            success: function (data, status, jqxhr) {
                if (data.projects) {
                    self.loadProjects(data.projects);
                }
                //...
                if(self.batches().length>0){
                    self.loadBatch();
                }else{
                    self.batchLoading=false;
                }
            }
        });
    };

    /**
     * bound via the ko/binding-waypoints knockout binding
     * example:
     * <span data-bind="waypoints: $root.waypointHandler" >
     */
    self.waypointHandler=function(){
        "use strict";
        var projectName = jQuery(this.element).data('project');
        if(!self.projectForName(projectName).loaded()) {
            self.batchList.push(projectName);
        }

        this.destroy();
    };
    //initial setup
    self.beginLoad = function () {

        if (self.doRefresh()) {
            setTimeout(self.loadSummary, self.refreshDelay());
        }
    };
    self.loadProjectNames = function () {
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.projectNamesUrl, {}),
            success: function (data, status, jqxhr) {
                self.projectNames(data.projectNames);
                self.projectNamesTotal(data.projectNames.length);
                self.loadedProjectNames(true);
            }
        });
    };
    self.init = function () {
        self.beginLoad();
        if (self.projectCount() != self.projectNamesTotal()) {
            self.loadProjectNames();
        }
    };
}
var _waypointBatchTimer;
function batchInitWaypoints(arr,handler,count){
    "use strict";
    var arr2=arr.splice(0,count);
    if(arr2.length>0) {
        jQuery(arr2).waypoint(handler, {context:'#main-panel',offset: '100%'});
        if (arr.length > 0) {
            _waypointBatchTimer=setTimeout(function(){batchInitWaypoints(arr, handler,count);}, 1500);
        }
    }
}
function initWaypoints(homedata,reset){
    "use strict";
    if(reset){
        if(_waypointBatchTimer){
            clearTimeout(_waypointBatchTimer);
            _waypointBatchTimer=null;
        }
        Waypoint.destroyAll();
    }

    batchInitWaypoints(jQuery('.project_list_item[data-project]'),homedata.waypointHandler,50);
}

/**
 * START page init
 */
var homedata;
function init() {
    // ko.options.deferUpdates = true;
    var pageparams = loadJsonData('homeDataPagingParams') || {};
    var projectNamesData = loadJsonData('projectNamesData');
    if (projectNamesData.projectNames == null) {
        projectNamesData.projectNames = [];
    }
    var statsdata = loadJsonData('statsData') || {};
    homedata = new HomeData(jQuery.extend({
        baseUrl: appLinks.menuHomeAjax,
        summaryUrl: appLinks.menuHomeSummaryAjax,
        projectNamesUrl: appLinks.menuProjectNamesAjax,
        projectNames: projectNamesData.projectNames.sort(),
        projectNamesTotal: projectNamesData.projectNamesTotal || 0
    },statsdata));
    homedata.loadedProjectNames(projectNamesData.projectNames.length == projectNamesData.projectNamesTotal);
    ko.applyBindings(homedata);

    homedata.pagingMax(pageparams.pagingInitialMax || 15);
    homedata.pagingRepeatMax(pageparams.pagingRepeatMax || 50);
    homedata.doRefresh(pageparams.summaryRefresh != null ? pageparams.summaryRefresh : true);
    homedata.refreshDelay(pageparams.refreshDelay || 60000);
    homedata.doPaging(pageparams.doPaging != null ? pageparams.doPaging : true);
    homedata.pagingDelay(pageparams.pagingDelay || 2000);
    homedata.searchedProjects.subscribe(function(val){
        "use strict";
        //when search results change, refresh waypoints
        ko.tasks.schedule(function(){initWaypoints(homedata,true);});
    });
    if(homedata.loadedProjectNames()){
        //load waypoints manually
        initWaypoints(homedata);
    }
    homedata.loaded.subscribe(Waypoint.refreshAll);
    homedata.projects.subscribe(Waypoint.refreshAll);
    homedata.init();
}
jQuery(init);
<commit_msg>cleanup js<commit_after>/*
 * Copyright 2016 SimplifyOps, Inc. (http://simplifyops.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//= require knockout.min
//= require knockout-mapping
//= require knockout-onenter
//= require ko/binding-url-path-param
//= require ko/binding-message-template
//= require ko/binding-popover
//= require jquery.waypoints.min
//= require menu/project-model

function HomeData(data) {
    var self = this;
    self.baseUrl = data.baseUrl;
    self.summaryUrl = data.summaryUrl;
    self.projectNamesUrl = data.projectNamesUrl;
    self.loaded = ko.observable(data.loaded?true:false);
    self.jobCount = ko.observable(0);
    self.execCount = ko.observable(data.execCount||0);
    self.totalFailedCount = ko.observable(data.totalFailedCount||0);
    self.projectNames = ko.observableArray(data.projectNames || []);
    self.projectNamesTotal = ko.observable(data.projectNamesTotal || 0);
    self.loadedProjectNames = ko.observable(false);
    self.projects = ko.observableArray([]);
    self.projects.extend({rateLimit: 500});

    self.recentUsers = ko.observableArray(data.recentUsers||[]);
    self.recentProjects = ko.observableArray(data.recentProjects||[]);
    self.frameworkNodeName = ko.observable(null);
    self.doRefresh = ko.observable(false);
    self.doPaging = ko.observable(false);
    self.pagingMax = ko.observable(20);
    self.pagingRepeatMax = ko.observable(20);
    self.pagingDelay = ko.observable(2000);
    self.pagingOffset = ko.observable(0);
    self.refreshDelay = ko.observable(30000);
    self.search=ko.observable(null);

    //batch of project data to load
    self.batchList=ko.observableArray([]);
    self.batchList.extend({ rateLimit: 500 });
    self.batches=ko.observableArray([]);

    self.recentUsersCount = ko.pureComputed(function () {
        return self.recentUsers().length;
    });
    self.recentProjectsCount = ko.pureComputed(function () {
        return self.recentProjects().length;
    });
    self.searchedProjects=ko.pureComputed(function(){
        "use strict";
        var search=self.search();
        var names=self.projectNames();
        if(null==search){
            return names;
        }
        var regex;
        if (search.charAt(0) === '/' && search.charAt(search.length - 1) === '/') {
            regex = new RegExp(search.substring(1, search.length - 1),'i');
        }else{
            //simple match which is case-insensitive, escaping special regex chars
            regex = new RegExp(search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'),'i');
        }
        return ko.utils.arrayFilter(names,function(val,ndx){
            var proj = self.projectForName(val);
            var label = proj.label();
            return val.match(regex) || label && label.match(regex);
        });
    });
    self.searchedProjectsCount = ko.pureComputed(function () {
        return self.searchedProjects().length;
    });
    self.projectCount = ko.pureComputed(function () {
        return self.projectNames().length;
    });
    self.projectsByName = ko.pureComputed(function () {
        var obj = {};
        ko.utils.arrayForEach(self.projects(), function (elem, ndx) {
            obj[ko.unwrap(elem.name)] = elem;
        });
        return obj;
    });
    self.searchProjectsByName = ko.pureComputed(function () {
        var obj = {};
        ko.utils.arrayForEach(self.searchedProjects(), function (elem, ndx) {
            obj[ko.unwrap(elem.name)] = elem;
        });
        return obj;
    });
    self.projectInSearch=function(name){
        "use strict";
        return !self.search() || self.searchProjectsByName()[name]!=null;
    };
    self.prototypeProject = new Project({page: 'projectList'});
    self.projectForName = function (name) {
        var projectsByName = self.projectsByName()[name];
        if(null==projectsByName){
            return self.prototypeProject;
        }
        return projectsByName;
    };
    self.mapping = {
        'projects': {
            key: function (data) {
                return ko.utils.unwrapObservable(data.name);
            },
            create: function (data) {
                "use strict";
                return new Project(options.data);
            },
            update: function (options) {
                var updateArray = [];
                var found = options.parent.projectForName(options.data.name);
                if (found) {
                    return ko.mapping.fromJS(options.data, {}, found);
                } else {
                    return ko.mapping.fromJS(options.data, {}, {});
                }
            }
        }
    };
    self.loadSummary = function () {
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.summaryUrl, {}),
            success: function (data, status, jqxhr) {

                ko.mapping.fromJS(data, self.mapping, self);
                self.loaded(true);

                if (self.doRefresh()) {
                    setTimeout(self.loadSummary, self.refreshDelay());
                }
            }
        });
    };
    self.loadProjects = function (projs) {
        for (var i = 0; i < projs.length; i++) {
            var newproj = projs[i];
            var found = self.projectForName(newproj.name);
            if (found && found.name() === newproj.name) {
                ko.mapping.fromJS(newproj, null, found);
                found.loaded(true);
            } else {
                self.projects.push(
                    new Project(jQuery.extend(newproj, {loaded: true, page: 'projectList'}))
                );
            }
        }
    };
    self.load = function (refresh) {
        var params = {};//refresh?{refresh:true}:{};
        if (self.doPaging()) {
            jQuery.extend(params, {
                offset: self.pagingOffset(),
                max: self.pagingMax()
            });
            self.pagingMax(self.pagingRepeatMax());
        }
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.baseUrl, params),
            success: function (data, status, jqxhr) {
                if (data.projects) {
                    self.loadProjects(data.projects);
                }
                // ko.mapping.fromJS(data, self.mapping, self);
                if (self.doPaging() && data.nextoffset) {
                    self.pagingOffset(data.nextoffset);
                    if (self.pagingOffset() === -1) {
                        self.pagingOffset(0);
                    } else {
                        setTimeout(function(){self.load(true);}, self.pagingDelay());
                    }
                }
            }
        });
    };
    self.pullBatch=function(){
        "use strict";
        //pull up to max number of items from batchList
        var items=self.batchList.splice(0,self.pagingMax());
        if(items.length>0) {
            self.batches.push(items);
        }
    };
    self.batchList.subscribe(function(newValue){
        "use strict";
        if(newValue.length>0){
            setTimeout(self.pullBatch,100);
        }
    });
    self.batches.subscribe(function(newValue){
        if(!self.batchLoading && newValue.length>0){
            self.batchLoading=true;
            setTimeout(self.loadBatch,100);
        }
    });
    self.clearBatchLoad=function(){
        "use strict";

        self.batchList([]);
        self.batches([]);
    };
    self.search.subscribe(self.clearBatchLoad);
    self.batchLoading=false;
    self.loadBatch = function () {
        self.batchLoading=true;
        var projects=self.batches.shift();
        if(null==projects || projects.length<1){
            self.batchLoading=false;
            return;
        }
        var params = {projects:projects.join(',')};//refresh?{refresh:true}:{};
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.baseUrl, params),
            success: function (data, status, jqxhr) {
                if (data.projects) {
                    self.loadProjects(data.projects);
                }
                //...
                if(self.batches().length>0){
                    self.loadBatch();
                }else{
                    self.batchLoading=false;
                }
            }
        });
    };

    /**
     * bound via the ko/binding-waypoints knockout binding
     * example:
     * <span data-bind="waypoints: $root.waypointHandler" >
     */
    self.waypointHandler=function(){
        "use strict";
        var projectName = jQuery(this.element).data('project');
        if(!self.projectForName(projectName).loaded()) {
            self.batchList.push(projectName);
        }

        this.destroy();
    };
    //initial setup
    self.beginLoad = function () {

        if (self.doRefresh()) {
            setTimeout(self.loadSummary, self.refreshDelay());
        }
    };
    self.loadProjectNames = function () {
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.projectNamesUrl, {}),
            success: function (data, status, jqxhr) {
                self.projectNames(data.projectNames);
                self.projectNamesTotal(data.projectNames.length);
                self.loadedProjectNames(true);
            }
        });
    };
    self.init = function () {
        self.beginLoad();
        if (self.projectCount() != self.projectNamesTotal()) {
            self.loadProjectNames();
        }
    };
}
var _waypointBatchTimer;
function batchInitWaypoints(arr,handler,count){
    "use strict";
    var arr2=arr.splice(0,count);
    if(arr2.length>0) {
        jQuery(arr2).waypoint(handler, {context:'#main-panel',offset: '100%'});
        if (arr.length > 0) {
            _waypointBatchTimer=setTimeout(function(){batchInitWaypoints(arr, handler,count);}, 1500);
        }
    }
}
function initWaypoints(homedata,reset){
    "use strict";
    if(reset){
        if(_waypointBatchTimer){
            clearTimeout(_waypointBatchTimer);
            _waypointBatchTimer=null;
        }
        Waypoint.destroyAll();
    }

    batchInitWaypoints(jQuery('.project_list_item[data-project]'),homedata.waypointHandler,50);
}

/**
 * START page init
 */
var homedata;
function init() {
    // ko.options.deferUpdates = true;
    var pageparams = loadJsonData('homeDataPagingParams') || {};
    var projectNamesData = loadJsonData('projectNamesData');
    if (projectNamesData.projectNames == null) {
        projectNamesData.projectNames = [];
    }
    var statsdata = loadJsonData('statsData') || {};
    homedata = new HomeData(jQuery.extend({
        baseUrl: appLinks.menuHomeAjax,
        summaryUrl: appLinks.menuHomeSummaryAjax,
        projectNamesUrl: appLinks.menuProjectNamesAjax,
        projectNames: projectNamesData.projectNames.sort(),
        projectNamesTotal: projectNamesData.projectNamesTotal || 0
    },statsdata));
    homedata.loadedProjectNames(projectNamesData.projectNames.length === projectNamesData.projectNamesTotal);
    ko.applyBindings(homedata);

    homedata.pagingMax(pageparams.pagingInitialMax || 15);
    homedata.pagingRepeatMax(pageparams.pagingRepeatMax || 50);
    homedata.doRefresh(pageparams.summaryRefresh != null ? pageparams.summaryRefresh : true);
    homedata.refreshDelay(pageparams.refreshDelay || 60000);
    homedata.doPaging(pageparams.doPaging != null ? pageparams.doPaging : true);
    homedata.pagingDelay(pageparams.pagingDelay || 2000);
    homedata.searchedProjects.subscribe(function(val){
        "use strict";
        //when search results change, refresh waypoints
        ko.tasks.schedule(function(){initWaypoints(homedata,true);});
    });
    if(homedata.loadedProjectNames()){
        //load waypoints manually
        initWaypoints(homedata);
    }
    homedata.loaded.subscribe(Waypoint.refreshAll);
    homedata.projects.subscribe(Waypoint.refreshAll);
    homedata.init();
}
jQuery(init);
<|endoftext|>


<commit_before>(function() {

    var socket = SocketIO.connect('media');
    var objects = [];
    var lastResult = null;

    function readdir() {

        var dir = $scope.dir;
        var query = '';

        if (dir.location.length) {
            $location.search('location', dir.location);
        } else {
            $location.search('location', null);
        }

        objects = [];
        lastResult = null;
        $scope.objectsOnDemand.numLoaded_ = 0;
        $scope.objectsOnDemand.toLoad_ = 0;
        $scope.objectsOnDemand.fetchMoreItems_(1);

    }

    $scope.refresh = readdir;

    socket.on('files:upload:complete', readdir);
    socket.on('file:upload:complete', readdir);

    //---------------------------------------------------

    $scope.objectsOnDemand = {
        numLoaded_: 0,
        toLoad_: 0,
        getItemAtIndex: function(index) {
            if (index > this.numLoaded_) {
                this.fetchMoreItems_(index);
                return null;
            }
            return objects[index];
        },
        getLength: function() {
            return this.numLoaded_ + 1;
        },
        fetchMoreItems_: function(index) {
            var self = this;
            var marker = null;
            if (lastResult) {
                if (lastResult.truncated) {
                    marker = lastResult.nextMarker;
                } else {
                    return;
                }
            }

            if (!this.toLoad_) {
                this.toLoad_ = 1;
                return;
            }

            if (this.toLoad_ < index) {
                this.toLoad_ += 20;

                $rootScope.loadingMain = true;

                var params = {};

                if ($scope.dir.location) {
                    params.dir = $scope.dir.location;
                }
                if (marker) {
                    params.marker = marker
                }

                Media.list(params)
                    .$promise
                    .then(function(result) {

                        lastResult = result;

                        for (var _index in result.objects) {
                            var object = result.objects[_index];
                            MediaPreview.set(object);
                        }

                        $rootScope.loadingMain = false;
                        $scope.count = result.count;
                        objects = objects.concat(result.objects);

                        if ($scope.onObjects) {
                            $scope.onObjects(objects);
                        }

                        self.numLoaded_ = objects.length;
                    });

            }
        }
    };

    //---------------------------------------------------
    $scope.isLoadingMore = function(object) {
        return !object &&
            (
                $scope.objectsOnDemand.numLoaded_ === 0 ||
                $scope.objectsOnDemand.numLoaded_ < $scope.count
            );
    };
    //---------------------------------------------------

    $scope.newFolder = function(file) {

        var confirm = $mdDialog.prompt()
            .title('New Folder')
            .textContent('Enter the name of the folder you want to create.')
            .placeholder('Name')
            .ok('Create')
            .cancel('Cancel');

        $mdDialog.show(confirm).then(function(name) {
            Media.newFolder({
                    dir: $scope.dir.location,
                    name: name
                })
                .$promise
                .then(readdir);
        });

    };

    $scope.objectClick = function(object) {

        switch (object.type) {
            case 'folder':
                $scope.openFolder(object);
                break;
            default:
                $scope.openObject(object);
                break;

        }
    };

    $scope.toolbarClick = function($event) {
        $event.stopPropagation();
    };

    $scope.isFolder = function(object) {
        return object.type == 'folder';
    };

    $scope.openObject = $scope.openObject || function(object) {
        $mdDialog.open({
            partial: partialFile,
            data: {
                apiMedia: apiMedia,
                Media: Media,
                MediaPreview: MediaPreview,
                location: object.location,
                onChange: function(file) {
                    $scope.refresh();
                }
            }
        });
    };

    $scope.uploadFiles = function(objects, errFiles) {

        if (errFiles && errFiles.length) {
            console.error(errFiles);
        }

        if (objects && objects.length) {
            Upload.upload({
                url: agneta.url(apiMedia + 'upload-files'),
                data: {
                    dir: $scope.dir.location,
                    objects: objects
                },
                arrayKey: ''
            }).then(function(response) {}, function(response) {
                if (response.status > 0)
                    $scope.errorMsg = response.status + ': ' + response.data;
            }, function(evt) {
                $scope.uploadProgress = Math.min(100, parseInt(100.0 *
                    evt.loaded / evt.total));
            });

        }
    };
})();
<commit_msg>Portal.media: Prevent duplicate media list request<commit_after>(function() {

    var socket = SocketIO.connect('media');
    var objects = [];
    var lastResult = null;
    var loadmoreCount = 20;

    function readdir() {

        var dir = $scope.dir;
        var query = '';

        if (dir.location.length) {
            $location.search('location', dir.location);
        } else {
            $location.search('location', null);
        }

        objects = [];
        lastResult = null;
        $scope.objectsOnDemand.numLoaded_ = 0;
        $scope.objectsOnDemand.toLoad_ = 0;
        $scope.objectsOnDemand.fetchMoreItems_(1);

    }

    $scope.refresh = readdir;

    socket.on('files:upload:complete', readdir);
    socket.on('file:upload:complete', readdir);

    //---------------------------------------------------

    $scope.objectsOnDemand = {
        numLoaded_: 0,
        toLoad_: 0,
        getItemAtIndex: function(index) {
            if (index > this.numLoaded_) {
                this.fetchMoreItems_(index);
                return null;
            }
            return objects[index];
        },
        getLength: function() {
            return this.numLoaded_ + 1;
        },
        fetchMoreItems_: function(index) {
            var self = this;
            var marker = null;
            if (lastResult) {
                if (lastResult.truncated) {
                    marker = lastResult.nextMarker;
                } else {
                    return;
                }
            }

            if (!this.toLoad_) {
                this.toLoad_ = 1;
                return;
            }

            if (!this.toLoad_) {
                this.toLoad_ = 1;
                return;
            }

            if (this.toLoad_ - this.numLoaded_ > loadmoreCount) {
                return;
            }

            if (this.toLoad_ < index) {
                this.toLoad_ += loadmoreCount;

                $rootScope.loadingMain = true;

                var params = {};

                if ($scope.dir.location) {
                    params.dir = $scope.dir.location;
                }
                if (marker) {
                    params.marker = marker
                }

                console.warn('fetchMoreItems_', index, this.numLoaded_, this.toLoad_);

                Media.list(params)
                    .$promise
                    .then(function(result) {

                        lastResult = result;

                        for (var _index in result.objects) {
                            var object = result.objects[_index];
                            MediaPreview.set(object);
                        }

                        $rootScope.loadingMain = false;
                        $scope.count = result.count;
                        objects = objects.concat(result.objects);

                        if ($scope.onObjects) {
                            $scope.onObjects(objects);
                        }

                        self.numLoaded_ = objects.length;
                    });

            }
        }
    };

    //---------------------------------------------------
    $scope.isLoadingMore = function(object) {
        return !object &&
            (
                $scope.objectsOnDemand.numLoaded_ === 0 ||
                $scope.objectsOnDemand.numLoaded_ < $scope.count
            );
    };
    //---------------------------------------------------

    $scope.newFolder = function(file) {

        var confirm = $mdDialog.prompt()
            .title('New Folder')
            .textContent('Enter the name of the folder you want to create.')
            .placeholder('Name')
            .ok('Create')
            .cancel('Cancel');

        $mdDialog.show(confirm).then(function(name) {
            Media.newFolder({
                    dir: $scope.dir.location,
                    name: name
                })
                .$promise
                .then(readdir);
        });

    };

    $scope.objectClick = function(object) {

        switch (object.type) {
            case 'folder':
                $scope.openFolder(object);
                break;
            default:
                $scope.openObject(object);
                break;

        }
    };

    $scope.toolbarClick = function($event) {
        $event.stopPropagation();
    };

    $scope.isFolder = function(object) {
        return object.type == 'folder';
    };

    $scope.openObject = $scope.openObject || function(object) {
        $mdDialog.open({
            partial: partialFile,
            data: {
                apiMedia: apiMedia,
                Media: Media,
                MediaPreview: MediaPreview,
                location: object.location,
                onChange: function(file) {
                    $scope.refresh();
                }
            }
        });
    };

    $scope.uploadFiles = function(objects, errFiles) {

        if (errFiles && errFiles.length) {
            console.error(errFiles);
        }

        if (objects && objects.length) {
            Upload.upload({
                url: agneta.url(apiMedia + 'upload-files'),
                data: {
                    dir: $scope.dir.location,
                    objects: objects
                },
                arrayKey: ''
            }).then(function(response) {}, function(response) {
                if (response.status > 0)
                    $scope.errorMsg = response.status + ': ' + response.data;
            }, function(evt) {
                $scope.uploadProgress = Math.min(100, parseInt(100.0 *
                    evt.loaded / evt.total));
            });

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