<commit_before>import Renderer from '../Renderer.js';

export default class VirtualDomHorizontal extends Renderer{
	constructor(table){
		super(table);

		this.leftCol = 0;
		this.rightCol = 0;
		this.scrollLeft = 0;

		this.vDomScrollPosLeft = 0;
		this.vDomScrollPosRight = 0;

		this.vDomPadLeft = 0;
		this.vDomPadRight = 0;

		this.fitDataColAvg = 0;

		this.windowBuffer = 200; //pixel margin to make column visible before it is shown on screen

		this.visibleRows = null;

		this.initialized = false;
		this.isFitData = false;

		this.columns = [];
	}

	initialize(){
		this.compatibilityCheck();
		this.layoutCheck();
		this.vertScrollListen();
	}

	compatibilityCheck(){
		var columns = this.options("columns"),
		frozen = false,
		ok = true;

		if(this.options("layout") == "fitDataTable"){
			console.warn("Horizontal Virtual DOM is not compatible with fitDataTable layout mode");
			ok = false;
		}

		if(this.options("responsiveLayout")){
			console.warn("Horizontal Virtual DOM is not compatible with responsive columns");
			ok = false;
		}

		if(this.options("rtl")){
			console.warn("Horizontal Virtual DOM is not currently compatible with RTL text direction");
			ok = false;
		}

		// if(columns){
		// 	frozen = columns.find((col) => {
		// 		return col.frozen;
		// 	});

		// 	if(frozen){
		// 		console.warn("Horizontal Virtual DOM is not compatible with frozen columns");
		// 		ok = false;
		// 	}
		// }

		// if(!ok){
		// 	options.virtualDomHoz = false;
		// }

		return ok;
	}

	layoutCheck(){
		this.isFitData = this.options("layout").startsWith('fitData');
	}

	vertScrollListen(){
		this.subscribe("scroll-vertical", this.clearVisRowCache.bind(this));
		this.subscribe("data-refreshed", this.clearVisRowCache.bind(this));
	}

	clearVisRowCache(){
		this.visibleRows = null;
	}

	//////////////////////////////////////
	///////// Public Functions ///////////
	//////////////////////////////////////

	renderColumns(row, force){
		this.dataChange();
	}

	scrollColumns(left, dir){
		if(this.scrollLeft != left){
			this.scrollLeft = left;

			this.scroll(left - (this.vDomScrollPosLeft + this.windowBuffer));
		}
	}

	calcWindowBuffer(){
		var buffer = this.elementVertical.clientWidth;

		this.table.columnManager.columnsByIndex.forEach((column) => {
			if(column.visible){
				var width = column.getWidth();

				if(width > buffer){
					buffer = width;
				}
			}
		});

		this.windowBuffer = buffer * 2;
	}

	rerenderColumns(update, blockRedraw){
		var old = {
			cols:this.columns,
			leftCol:this.leftCol,
			rightCol:this.rightCol,
		},
		colPos = 0;

		if(update && !this.initialized){
			return;
		}

		this.clear();

		this.calcWindowBuffer();

		this.scrollLeft = this.elementVertical.scrollLeft;

		this.vDomScrollPosLeft = this.scrollLeft - this.windowBuffer;
		this.vDomScrollPosRight = this.scrollLeft + this.elementVertical.clientWidth + this.windowBuffer;

		this.table.columnManager.columnsByIndex.forEach((column) => {
			var config = {},
			width;

			if(column.visible){
				if(!column.modules.frozen){
					width = column.getWidth();

					config.leftPos = colPos;
					config.rightPos = colPos + width;

					config.width = width;

					if (this.isFitData) {
						config.fitDataCheck = column.modules.vdomHoz ? column.modules.vdomHoz.fitDataCheck : true;
					}

					if((colPos + width > this.vDomScrollPosLeft) && (colPos < this.vDomScrollPosRight)){
						//column is visible

						if(this.leftCol == -1){
							this.leftCol = this.columns.length;
							this.vDomPadLeft = colPos;
						}

						this.rightCol = this.columns.length;
					}else{
						// column is hidden
						if(this.leftCol !== -1){
							this.vDomPadRight += width;
						}
					}

					this.columns.push(column);

					column.modules.vdomHoz = config;

					colPos += width;
				}
			}
		});

		this.tableElement.style.paddingLeft = this.vDomPadLeft + "px";
		this.tableElement.style.paddingRight = this.vDomPadRight + "px";

		this.initialized = true;

		if(!blockRedraw){
			if(!update || this.reinitChanged(old)){
				this.reinitializeRows();
			}
		}

		this.elementVertical.scrollLeft = this.scrollLeft;
	}

	renderRowCells(row){
		if(this.initialized){
			this.initializeRow(row);
		}else{
			row.cells.forEach((cell) => {
				row.element.appendChild(cell.getElement());
				cell.cellRendered();
			});
		}
	}

	rerenderRowCells(row, force){
		this.reinitializeRow(row, force);
	}

	reinitializeColumnWidths(columns){
		for(let i = this.leftCol; i <= this.rightCol; i++){
			this.columns[i].reinitializeWidth();
		}
	}

	//////////////////////////////////////
	//////// Internal Rendering //////////
	//////////////////////////////////////

	deinitialize(){
		this.initialized = false;
	}

	clear(){
		this.columns = [];

		this.leftCol = -1;
		this.rightCol = 0;

		this.vDomScrollPosLeft = 0;
		this.vDomScrollPosRight = 0;
		this.vDomPadLeft = 0;
		this.vDomPadRight = 0;
	}

	dataChange(){
		var change = false,
		row, rowEl;

		if(this.isFitData){
			this.table.columnManager.columnsByIndex.forEach((column) => {
				if(!column.definition.width && column.visible){
					change = true;
				}
			});

			if(change && this.table.rowManager.getDisplayRows().length){
				this.vDomScrollPosRight = this.scrollLeft + this.elementVertical.clientWidth + this.windowBuffer;

				row = this.chain("rows-sample", [1], [], () => {
					return this.table.rowManager.getDisplayRows();
				})[0];

				if(row){
					rowEl = row.getElement();

					row.generateCells();

					this.tableElement.appendChild(rowEl);

					for(let colEnd = 0; colEnd < row.cells.length; colEnd++){
						let cell = row.cells[colEnd];
						rowEl.appendChild(cell.getElement());

						cell.column.reinitializeWidth();
					}

					rowEl.parentNode.removeChild(rowEl);

					this.rerenderColumns(false, true);
				}
			}
		}else{
			if(this.options("layout") === "fitColumns"){
				this.layoutRefresh();
				this.rerenderColumns(false, true);
			}
		}
	}

	reinitChanged(old){
		var match = true;

		if(old.cols.length !== this.columns.length || old.leftCol !== this.leftCol || old.rightCol !== this.rightCol){
			return true;
		}

		old.cols.forEach((col, i) => {
			if(col !== this.columns[i]){
				match = false;
			}
		});

		return !match;
	}

	reinitializeRows(){
		var visibleRows = this.getVisibleRows(),
		otherRows = this.table.rowManager.getRows().filter(row => !visibleRows.includes(row));

		visibleRows.forEach((row) => {
			this.reinitializeRow(row, true);
		});

		otherRows.forEach((row) =>{
			row.deinitialize();
		});
	}

	getVisibleRows(){
		if (!this.visibleRows){
			this.visibleRows = this.table.rowManager.getVisibleRows();
		}

		return this.visibleRows;
	}

	scroll(diff){
		this.vDomScrollPosLeft += diff;
		this.vDomScrollPosRight += diff;

		if(Math.abs(diff) > (this.windowBuffer / 2)){
			this.rerenderColumns();
		}else{
			if(diff > 0){
				//scroll right
				this.addColRight();
				this.removeColLeft();
			}else{
				//scroll left
				this.addColLeft();
				this.removeColRight();
			}
		}
	}

	colPositionAdjust (start, end, diff){
		for(let i = start; i < end; i++){
			let column = this.columns[i];

			column.modules.vdomHoz.leftPos += diff;
			column.modules.vdomHoz.rightPos += diff;
		}
	}

	addColRight(){
		var changes = false,
		working = true;

		while(working){

			let column = this.columns[this.rightCol + 1];

			if(column){
				if(column.modules.vdomHoz.leftPos <= this.vDomScrollPosRight){
					changes = true;

					this.getVisibleRows().forEach((row) => {
						if(row.type !== "group"){
							var cell = row.getCell(column);
							row.getElement().insertBefore(cell.getElement(), row.getCell(this.columns[this.rightCol]).getElement().nextSibling);
							cell.cellRendered();
						}
					});

					this.fitDataColActualWidthCheck(column);

					this.rightCol++; // Don't move this below the >= check below

					if(this.rightCol >= (this.columns.length - 1)){
						this.vDomPadRight = 0;
					}else{
						this.vDomPadRight -= column.getWidth();
					}
				}else{
					working = false;
				}
			}else{
				working = false;
			}
		}

		if(changes){
			this.tableElement.style.paddingRight = this.vDomPadRight + "px";
		}
	}

	addColLeft(){
		var changes = false,
		working = true;

		while(working){
			let column = this.columns[this.leftCol - 1];

			if(column){
				if(column.modules.vdomHoz.rightPos >= this.vDomScrollPosLeft){
					changes = true;

					this.getVisibleRows().forEach((row) => {
						if(row.type !== "group"){
							var cell = row.getCell(column);
							row.getElement().insertBefore(cell.getElement(), row.getCell(this.columns[this.leftCol]).getElement());
							cell.cellRendered();
						}
					});

					this.leftCol--; // don't move this below the <= check below

					if(this.leftCol <= 0){ // replicating logic in addColRight
						this.vDomPadLeft = 0;
					}else{
						this.vDomPadLeft -= column.getWidth();
					}

					let diff = this.fitDataColActualWidthCheck(column);

					if(diff){
						this.scrollLeft = this.elementVertical.scrollLeft = this.elementVertical.scrollLeft + diff;
						this.vDomPadRight -= diff;
					}

				}else{
					working = false;
				}
			}else{
				working = false;
			}
		}

		if(changes){
			this.tableElement.style.paddingLeft = this.vDomPadLeft + "px";
		}
	}

	removeColRight(){
		var changes = false,
		working = true;

		while(working){
			let column = this.columns[this.rightCol];

			if(column){
				if(column.modules.vdomHoz.leftPos > this.vDomScrollPosRight){
					changes = true;

					this.getVisibleRows().forEach((row) => {
						if(row.type !== "group"){
							var cell = row.getCell(column);

							try {
								row.getElement().removeChild(cell.getElement());
							} catch (ex) {
								console.warn("Could not removeColRight", ex.message);
							}
						}
					});

					this.vDomPadRight += column.getWidth();
					this.rightCol --;
				}else{
					working = false;
				}
			}else{
				working = false;
			}
		}

		if(changes){
			this.tableElement.style.paddingRight = this.vDomPadRight + "px";
		}
	}

	removeColLeft(){
		var changes = false,
		working = true;

		while(working){
			let column = this.columns[this.leftCol];

			if(column){
				if(column.modules.vdomHoz.rightPos < this.vDomScrollPosLeft){
					changes = true;

					this.getVisibleRows().forEach((row) => {
						if(row.type !== "group"){
							var cell = row.getCell(column);

							try {
								row.getElement().removeChild(cell.getElement());
							} catch (ex) {
								console.warn("Could not removeColLeft", ex.message);
							}
						}
					});

					this.vDomPadLeft += column.getWidth();
					this.leftCol ++;
				}else{
					working = false;
				}
			}else{
				working = false;
			}
		}

		if(changes){
			this.tableElement.style.paddingLeft = this.vDomPadLeft + "px";
		}
	}

	fitDataColActualWidthCheck(column){
		var newWidth, widthDiff;

		if(column.modules.vdomHoz.fitDataCheck){
			column.reinitializeWidth();

			newWidth = column.getWidth();
			widthDiff = newWidth - column.modules.vdomHoz.width;

			if(widthDiff){
				column.modules.vdomHoz.rightPos += widthDiff;
				column.modules.vdomHoz.width = newWidth;
				this.colPositionAdjust(this.columns.indexOf(column) + 1, this.columns.length, widthDiff);
			}

			column.modules.vdomHoz.fitDataCheck = false;
		}

		return widthDiff;
	}

	initializeRow(row){
		if(row.type !== "group"){
			row.modules.vdomHoz = {
				leftCol:this.leftCol,
				rightCol:this.rightCol,
			};

			if(this.table.modules.frozenColumns){
				this.table.modules.frozenColumns.leftColumns.forEach((column) => {
					this.appendCell(row, column);
				});
			}

			for(let i = this.leftCol; i <= this.rightCol; i++){
				this.appendCell(row, this.columns[i]);
			}

			if(this.table.modules.frozenColumns){
				this.table.modules.frozenColumns.rightColumns.forEach((column) => {
					this.appendCell(row, column);
				});
			}
		}
	}

	appendCell(row, column){
		if(column && column.visible){
			let cell = row.getCell(column);

			row.getElement().appendChild(cell.getElement());
			cell.cellRendered();
		}
	}

	reinitializeRow(row, force){
		if(row.type !== "group"){
			if(force || !row.modules.vdomHoz || row.modules.vdomHoz.leftCol !== this.leftCol || row.modules.vdomHoz.rightCol !== this.rightCol){

				var rowEl = row.getElement();
				while(rowEl.firstChild) rowEl.removeChild(rowEl.firstChild);

				this.initializeRow(row);
			}
		}
	}
}<commit_msg>remove redundant code from hozvdom compatability check<commit_after>import Renderer from '../Renderer.js';

export default class VirtualDomHorizontal extends Renderer{
	constructor(table){
		super(table);

		this.leftCol = 0;
		this.rightCol = 0;
		this.scrollLeft = 0;

		this.vDomScrollPosLeft = 0;
		this.vDomScrollPosRight = 0;

		this.vDomPadLeft = 0;
		this.vDomPadRight = 0;

		this.fitDataColAvg = 0;

		this.windowBuffer = 200; //pixel margin to make column visible before it is shown on screen

		this.visibleRows = null;

		this.initialized = false;
		this.isFitData = false;

		this.columns = [];
	}

	initialize(){
		this.compatibilityCheck();
		this.layoutCheck();
		this.vertScrollListen();
	}

	compatibilityCheck(){
		if(this.options("layout") == "fitDataTable"){
			console.warn("Horizontal Virtual DOM is not compatible with fitDataTable layout mode");
		}

		if(this.options("responsiveLayout")){
			console.warn("Horizontal Virtual DOM is not compatible with responsive columns");
		}

		if(this.options("rtl")){
			console.warn("Horizontal Virtual DOM is not currently compatible with RTL text direction");
		}
	}

	layoutCheck(){
		this.isFitData = this.options("layout").startsWith('fitData');
	}

	vertScrollListen(){
		this.subscribe("scroll-vertical", this.clearVisRowCache.bind(this));
		this.subscribe("data-refreshed", this.clearVisRowCache.bind(this));
	}

	clearVisRowCache(){
		this.visibleRows = null;
	}

	//////////////////////////////////////
	///////// Public Functions ///////////
	//////////////////////////////////////

	renderColumns(row, force){
		this.dataChange();
	}

	scrollColumns(left, dir){
		if(this.scrollLeft != left){
			this.scrollLeft = left;

			this.scroll(left - (this.vDomScrollPosLeft + this.windowBuffer));
		}
	}

	calcWindowBuffer(){
		var buffer = this.elementVertical.clientWidth;

		this.table.columnManager.columnsByIndex.forEach((column) => {
			if(column.visible){
				var width = column.getWidth();

				if(width > buffer){
					buffer = width;
				}
			}
		});

		this.windowBuffer = buffer * 2;
	}

	rerenderColumns(update, blockRedraw){
		var old = {
			cols:this.columns,
			leftCol:this.leftCol,
			rightCol:this.rightCol,
		},
		colPos = 0;

		if(update && !this.initialized){
			return;
		}

		this.clear();

		this.calcWindowBuffer();

		this.scrollLeft = this.elementVertical.scrollLeft;

		this.vDomScrollPosLeft = this.scrollLeft - this.windowBuffer;
		this.vDomScrollPosRight = this.scrollLeft + this.elementVertical.clientWidth + this.windowBuffer;

		this.table.columnManager.columnsByIndex.forEach((column) => {
			var config = {},
			width;

			if(column.visible){
				if(!column.modules.frozen){
					width = column.getWidth();

					config.leftPos = colPos;
					config.rightPos = colPos + width;

					config.width = width;

					if (this.isFitData) {
						config.fitDataCheck = column.modules.vdomHoz ? column.modules.vdomHoz.fitDataCheck : true;
					}

					if((colPos + width > this.vDomScrollPosLeft) && (colPos < this.vDomScrollPosRight)){
						//column is visible

						if(this.leftCol == -1){
							this.leftCol = this.columns.length;
							this.vDomPadLeft = colPos;
						}

						this.rightCol = this.columns.length;
					}else{
						// column is hidden
						if(this.leftCol !== -1){
							this.vDomPadRight += width;
						}
					}

					this.columns.push(column);

					column.modules.vdomHoz = config;

					colPos += width;
				}
			}
		});

		this.tableElement.style.paddingLeft = this.vDomPadLeft + "px";
		this.tableElement.style.paddingRight = this.vDomPadRight + "px";

		this.initialized = true;

		if(!blockRedraw){
			if(!update || this.reinitChanged(old)){
				this.reinitializeRows();
			}
		}

		this.elementVertical.scrollLeft = this.scrollLeft;
	}

	renderRowCells(row){
		if(this.initialized){
			this.initializeRow(row);
		}else{
			row.cells.forEach((cell) => {
				row.element.appendChild(cell.getElement());
				cell.cellRendered();
			});
		}
	}

	rerenderRowCells(row, force){
		this.reinitializeRow(row, force);
	}

	reinitializeColumnWidths(columns){
		for(let i = this.leftCol; i <= this.rightCol; i++){
			this.columns[i].reinitializeWidth();
		}
	}

	//////////////////////////////////////
	//////// Internal Rendering //////////
	//////////////////////////////////////

	deinitialize(){
		this.initialized = false;
	}

	clear(){
		this.columns = [];

		this.leftCol = -1;
		this.rightCol = 0;

		this.vDomScrollPosLeft = 0;
		this.vDomScrollPosRight = 0;
		this.vDomPadLeft = 0;
		this.vDomPadRight = 0;
	}

	dataChange(){
		var change = false,
		row, rowEl;

		if(this.isFitData){
			this.table.columnManager.columnsByIndex.forEach((column) => {
				if(!column.definition.width && column.visible){
					change = true;
				}
			});

			if(change && this.table.rowManager.getDisplayRows().length){
				this.vDomScrollPosRight = this.scrollLeft + this.elementVertical.clientWidth + this.windowBuffer;

				row = this.chain("rows-sample", [1], [], () => {
					return this.table.rowManager.getDisplayRows();
				})[0];

				if(row){
					rowEl = row.getElement();

					row.generateCells();

					this.tableElement.appendChild(rowEl);

					for(let colEnd = 0; colEnd < row.cells.length; colEnd++){
						let cell = row.cells[colEnd];
						rowEl.appendChild(cell.getElement());

						cell.column.reinitializeWidth();
					}

					rowEl.parentNode.removeChild(rowEl);

					this.rerenderColumns(false, true);
				}
			}
		}else{
			if(this.options("layout") === "fitColumns"){
				this.layoutRefresh();
				this.rerenderColumns(false, true);
			}
		}
	}

	reinitChanged(old){
		var match = true;

		if(old.cols.length !== this.columns.length || old.leftCol !== this.leftCol || old.rightCol !== this.rightCol){
			return true;
		}

		old.cols.forEach((col, i) => {
			if(col !== this.columns[i]){
				match = false;
			}
		});

		return !match;
	}

	reinitializeRows(){
		var visibleRows = this.getVisibleRows(),
		otherRows = this.table.rowManager.getRows().filter(row => !visibleRows.includes(row));

		visibleRows.forEach((row) => {
			this.reinitializeRow(row, true);
		});

		otherRows.forEach((row) =>{
			row.deinitialize();
		});
	}

	getVisibleRows(){
		if (!this.visibleRows){
			this.visibleRows = this.table.rowManager.getVisibleRows();
		}

		return this.visibleRows;
	}

	scroll(diff){
		this.vDomScrollPosLeft += diff;
		this.vDomScrollPosRight += diff;

		if(Math.abs(diff) > (this.windowBuffer / 2)){
			this.rerenderColumns();
		}else{
			if(diff > 0){
				//scroll right
				this.addColRight();
				this.removeColLeft();
			}else{
				//scroll left
				this.addColLeft();
				this.removeColRight();
			}
		}
	}

	colPositionAdjust (start, end, diff){
		for(let i = start; i < end; i++){
			let column = this.columns[i];

			column.modules.vdomHoz.leftPos += diff;
			column.modules.vdomHoz.rightPos += diff;
		}
	}

	addColRight(){
		var changes = false,
		working = true;

		while(working){

			let column = this.columns[this.rightCol + 1];

			if(column){
				if(column.modules.vdomHoz.leftPos <= this.vDomScrollPosRight){
					changes = true;

					this.getVisibleRows().forEach((row) => {
						if(row.type !== "group"){
							var cell = row.getCell(column);
							row.getElement().insertBefore(cell.getElement(), row.getCell(this.columns[this.rightCol]).getElement().nextSibling);
							cell.cellRendered();
						}
					});

					this.fitDataColActualWidthCheck(column);

					this.rightCol++; // Don't move this below the >= check below

					if(this.rightCol >= (this.columns.length - 1)){
						this.vDomPadRight = 0;
					}else{
						this.vDomPadRight -= column.getWidth();
					}
				}else{
					working = false;
				}
			}else{
				working = false;
			}
		}

		if(changes){
			this.tableElement.style.paddingRight = this.vDomPadRight + "px";
		}
	}

	addColLeft(){
		var changes = false,
		working = true;

		while(working){
			let column = this.columns[this.leftCol - 1];

			if(column){
				if(column.modules.vdomHoz.rightPos >= this.vDomScrollPosLeft){
					changes = true;

					this.getVisibleRows().forEach((row) => {
						if(row.type !== "group"){
							var cell = row.getCell(column);
							row.getElement().insertBefore(cell.getElement(), row.getCell(this.columns[this.leftCol]).getElement());
							cell.cellRendered();
						}
					});

					this.leftCol--; // don't move this below the <= check below

					if(this.leftCol <= 0){ // replicating logic in addColRight
						this.vDomPadLeft = 0;
					}else{
						this.vDomPadLeft -= column.getWidth();
					}

					let diff = this.fitDataColActualWidthCheck(column);

					if(diff){
						this.scrollLeft = this.elementVertical.scrollLeft = this.elementVertical.scrollLeft + diff;
						this.vDomPadRight -= diff;
					}

				}else{
					working = false;
				}
			}else{
				working = false;
			}
		}

		if(changes){
			this.tableElement.style.paddingLeft = this.vDomPadLeft + "px";
		}
	}

	removeColRight(){
		var changes = false,
		working = true;

		while(working){
			let column = this.columns[this.rightCol];

			if(column){
				if(column.modules.vdomHoz.leftPos > this.vDomScrollPosRight){
					changes = true;

					this.getVisibleRows().forEach((row) => {
						if(row.type !== "group"){
							var cell = row.getCell(column);

							try {
								row.getElement().removeChild(cell.getElement());
							} catch (ex) {
								console.warn("Could not removeColRight", ex.message);
							}
						}
					});

					this.vDomPadRight += column.getWidth();
					this.rightCol --;
				}else{
					working = false;
				}
			}else{
				working = false;
			}
		}

		if(changes){
			this.tableElement.style.paddingRight = this.vDomPadRight + "px";
		}
	}

	removeColLeft(){
		var changes = false,
		working = true;

		while(working){
			let column = this.columns[this.leftCol];

			if(column){
				if(column.modules.vdomHoz.rightPos < this.vDomScrollPosLeft){
					changes = true;

					this.getVisibleRows().forEach((row) => {
						if(row.type !== "group"){
							var cell = row.getCell(column);

							try {
								row.getElement().removeChild(cell.getElement());
							} catch (ex) {
								console.warn("Could not removeColLeft", ex.message);
							}
						}
					});

					this.vDomPadLeft += column.getWidth();
					this.leftCol ++;
				}else{
					working = false;
				}
			}else{
				working = false;
			}
		}

		if(changes){
			this.tableElement.style.paddingLeft = this.vDomPadLeft + "px";
		}
	}

	fitDataColActualWidthCheck(column){
		var newWidth, widthDiff;

		if(column.modules.vdomHoz.fitDataCheck){
			column.reinitializeWidth();

			newWidth = column.getWidth();
			widthDiff = newWidth - column.modules.vdomHoz.width;

			if(widthDiff){
				column.modules.vdomHoz.rightPos += widthDiff;
				column.modules.vdomHoz.width = newWidth;
				this.colPositionAdjust(this.columns.indexOf(column) + 1, this.columns.length, widthDiff);
			}

			column.modules.vdomHoz.fitDataCheck = false;
		}

		return widthDiff;
	}

	initializeRow(row){
		if(row.type !== "group"){
			row.modules.vdomHoz = {
				leftCol:this.leftCol,
				rightCol:this.rightCol,
			};

			if(this.table.modules.frozenColumns){
				this.table.modules.frozenColumns.leftColumns.forEach((column) => {
					this.appendCell(row, column);
				});
			}

			for(let i = this.leftCol; i <= this.rightCol; i++){
				this.appendCell(row, this.columns[i]);
			}

			if(this.table.modules.frozenColumns){
				this.table.modules.frozenColumns.rightColumns.forEach((column) => {
					this.appendCell(row, column);
				});
			}
		}
	}

	appendCell(row, column){
		if(column && column.visible){
			let cell = row.getCell(column);

			row.getElement().appendChild(cell.getElement());
			cell.cellRendered();
		}
	}

	reinitializeRow(row, force){
		if(row.type !== "group"){
			if(force || !row.modules.vdomHoz || row.modules.vdomHoz.leftCol !== this.leftCol || row.modules.vdomHoz.rightCol !== this.rightCol){

				var rowEl = row.getElement();
				while(rowEl.firstChild) rowEl.removeChild(rowEl.firstChild);

				this.initializeRow(row);
			}
		}
	}
}<|endoftext|>


<commit_before>/*
 *  Copyright 2014 TWO SIGMA OPEN SOURCE, LLC
 *
 *  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.
 */
/**
 * Module bk.evaluatePluginManager
 */
(function() {
  'use strict';
  var module = angular.module('bk.evaluatePluginManager', ['bk.utils', 'bk.evaluatorManager']);
  module.factory('bkEvaluatePluginManager', function(bkUtils) {
      var nameToUrlMap = {};
      var plugins = {};
      var loadingInProgressPlugins = [];
      return {
        getKnownEvaluatorPlugins: function() {
          return nameToUrlMap;
        },
        addNameToUrlEntry: function(name, url) {
          nameToUrlMap[name] = url;
        },
        getEvaluatorFactory: function(nameOrUrl) {
          if (plugins[nameOrUrl]) {
            var deferred = bkUtils.newDeferred();
            plugins[nameOrUrl].getEvaluatorFactory().then(function(shellCreator) {
              deferred.resolve(shellCreator);
            });
            return deferred.promise;
          } else {
            var deferred = bkUtils.newDeferred();
            var name, url;
            if (nameToUrlMap[nameOrUrl]) {
              name = nameOrUrl;
              url = nameToUrlMap[nameOrUrl];
            } else {
              name = "";
              url = nameOrUrl;
            }
            loadingInProgressPlugins.push({
              name: name,
              url: url
            });
            bkUtils.loadModule(url, name).then(function(ex) {
              if (!_.isEmpty(ex.name)) {
                plugins[ex.name] = ex;
              }
              if (!_.isEmpty(name) && name !== ex.name) {
                plugins[name] = ex;
              }
              ex.getEvaluatorFactory().then(function(shellCreator) {
                deferred.resolve(shellCreator);
              });
            }, function(err) {
              console.error(err);
              if (_.isEmpty(name)) {
                deferred.reject("failed to load plugin: " + url);
              } else {
                deferred.reject("failed to load plugin: " + name + " at " + url);
              }
            }).finally(function() {
              loadingInProgressPlugins = _(loadingInProgressPlugins).filter(function(it) {
                return it.url !== url;
              });
            });

            return deferred.promise;
          }
        },
        createEvaluatorThenExit: function(settings) {
          var theShell;
          return this.getEvaluatorFactory(settings.plugin)
              .then(function(factory) {
                var evaluator = factory.create(settings);
                return evaluator;
              })
              .then(function(evaluator) {
                if (evaluator.exit) {
                  evaluator.exit();
                }
              })
              .then(function() {
                _(plugins).filter(function(aShell) {
                  return aShell !== theShell;
                });
              });
        }
      };
    });
})();
<commit_msg>remove unused module<commit_after>/*
 *  Copyright 2014 TWO SIGMA OPEN SOURCE, LLC
 *
 *  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.
 */
/**
 * Module bk.evaluatePluginManager
 */
(function() {
  'use strict';
  var module = angular.module('bk.evaluatePluginManager', ['bk.utils']);
  module.factory('bkEvaluatePluginManager', function(bkUtils) {
      var nameToUrlMap = {};
      var plugins = {};
      var loadingInProgressPlugins = [];
      return {
        getKnownEvaluatorPlugins: function() {
          return nameToUrlMap;
        },
        addNameToUrlEntry: function(name, url) {
          nameToUrlMap[name] = url;
        },
        getEvaluatorFactory: function(nameOrUrl) {
          if (plugins[nameOrUrl]) {
            var deferred = bkUtils.newDeferred();
            plugins[nameOrUrl].getEvaluatorFactory().then(function(shellCreator) {
              deferred.resolve(shellCreator);
            });
            return deferred.promise;
          } else {
            var deferred = bkUtils.newDeferred();
            var name, url;
            if (nameToUrlMap[nameOrUrl]) {
              name = nameOrUrl;
              url = nameToUrlMap[nameOrUrl];
            } else {
              name = "";
              url = nameOrUrl;
            }
            loadingInProgressPlugins.push({
              name: name,
              url: url
            });
            bkUtils.loadModule(url, name).then(function(ex) {
              if (!_.isEmpty(ex.name)) {
                plugins[ex.name] = ex;
              }
              if (!_.isEmpty(name) && name !== ex.name) {
                plugins[name] = ex;
              }
              ex.getEvaluatorFactory().then(function(shellCreator) {
                deferred.resolve(shellCreator);
              });
            }, function(err) {
              console.error(err);
              if (_.isEmpty(name)) {
                deferred.reject("failed to load plugin: " + url);
              } else {
                deferred.reject("failed to load plugin: " + name + " at " + url);
              }
            }).finally(function() {
              loadingInProgressPlugins = _(loadingInProgressPlugins).filter(function(it) {
                return it.url !== url;
              });
            });

            return deferred.promise;
          }
        },
        createEvaluatorThenExit: function(settings) {
          var theShell;
          return this.getEvaluatorFactory(settings.plugin)
              .then(function(factory) {
                var evaluator = factory.create(settings);
                return evaluator;
              })
              .then(function(evaluator) {
                if (evaluator.exit) {
                  evaluator.exit();
                }
              })
              .then(function() {
                _(plugins).filter(function(aShell) {
                  return aShell !== theShell;
                });
              });
        }
      };
    });
})();
<|endoftext|>


<commit_before>var Ripples = new function() {

  this.setup = function() {

    var append = ".ripple{display:block;position:absolute;background-color:rgba(0,0,0,.033);border-radius:50%;-webkit-transform:scale(0);-moz-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);-webkit-transition:opacity .3s ease-in;-moz-transition:opacity .3s ease-in;transition:opacity .3s ease-in;opacity:0;pointer-events:none}.ripple.animate{opacity:1;-webkit-animation:ripple .65s ease-in;-webkit-animation-fill-mode:forwards;-moz-animation:ripple .65s ease-in;-moz-animation-fill-mode:forwards;-o-animation:ripple .65s ease-in;-o-animation-fill-mode:forwards;animation:ripple .65s ease-in;animation-fill-mode:forwards}@-webkit-keyframes ripple{75%{opacity:1}100%{opacity:0;-webkit-transform:scale(2)}}@-moz-keyframes ripple{75%{opacity:1}100%{opacity:0;-moz-transform:scale(2)}}@-o-keyframes ripple{75%{opacity:1}100%{opacity:0;-o-transform:scale(2)}}@-ms-keyframes ripple{75%{opacity:1}100%{opacity:0;-ms-transform:scale(2)}}@keyframes ripple{75%{opacity:1}100%{opacity:0;transform:scale(2)}}";
    $("head").append("");

          var ripple = $(this).find(".ripple");

          var parent = ripple.parent();

          console.log(ripple.height()+", "+ripple.width());

          if (!ripple.height() || !ripple.width()) {
              var d = Math.max(parent.outerWidth(), parent.outerHeight());
              ripple.css({
                  height: d,
                  width: d
              });
          }

          console.log(ripple.height()+", "+ripple.width());

          var x = e.pageX - $(this).offset().left - ripple.width() / 2;
          var y = e.pageY - $(this).offset().top - ripple.height() / 2;

          ripple.css({
              top: y + 'px',
              left: x + 'px'
          }).addClass("animate");
          setTimeout(function() {
              ripple.remove();
          }, 650);
      });
  };

};<commit_msg>Code by...<commit_after>var Ripples = new function() {

  /*
  Code by Leo Ørsnes, Zeekoo.dk
  */

  this.setup = function() {

    var append = ".ripple{display:block;position:absolute;background-color:rgba(0,0,0,.033);border-radius:50%;-webkit-transform:scale(0);-moz-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);-webkit-transition:opacity .3s ease-in;-moz-transition:opacity .3s ease-in;transition:opacity .3s ease-in;opacity:0;pointer-events:none}.ripple.animate{opacity:1;-webkit-animation:ripple .65s ease-in;-webkit-animation-fill-mode:forwards;-moz-animation:ripple .65s ease-in;-moz-animation-fill-mode:forwards;-o-animation:ripple .65s ease-in;-o-animation-fill-mode:forwards;animation:ripple .65s ease-in;animation-fill-mode:forwards}@-webkit-keyframes ripple{75%{opacity:1}100%{opacity:0;-webkit-transform:scale(2)}}@-moz-keyframes ripple{75%{opacity:1}100%{opacity:0;-moz-transform:scale(2)}}@-o-keyframes ripple{75%{opacity:1}100%{opacity:0;-o-transform:scale(2)}}@-ms-keyframes ripple{75%{opacity:1}100%{opacity:0;-ms-transform:scale(2)}}@keyframes ripple{75%{opacity:1}100%{opacity:0;transform:scale(2)}}";
    $("head").append("");

          var ripple = $(this).find(".ripple");

          var parent = ripple.parent();

          console.log(ripple.height()+", "+ripple.width());

          if (!ripple.height() || !ripple.width()) {
              var d = Math.max(parent.outerWidth(), parent.outerHeight());
              ripple.css({
                  height: d,
                  width: d
              });
          }

          console.log(ripple.height()+", "+ripple.width());

          var x = e.pageX - $(this).offset().left - ripple.width() / 2;
          var y = e.pageY - $(this).offset().top - ripple.height() / 2;

          ripple.css({
              top: y + 'px',
              left: x + 'px'
          }).addClass("animate");
          setTimeout(function() {
              ripple.remove();
          }, 650);
      });
  };

};<|endoftext|>


<commit_before>/*global gettext*/
(function($) {
    'use strict';
    $(document).ready(function() {
        // Add anchor tag for Show/Hide link
        $("fieldset.collapse").each(function(i, elem) {
            // Don't hide if fields in this fieldset have errors
            if ($(elem).find("div.errors").length === 0) {
                $(elem).addClass("collapsed").find("h2").first().append(' (' + gettext("Show") +
                    ')');
            }
        });
        // Add toggle to anchor tag
        $("fieldset.collapse a.collapse-toggle").click(function(ev) {
            if ($(this).closest("fieldset").hasClass("collapsed")) {
                // Show
                $(this).text(gettext("Hide")).closest("fieldset").removeClass("collapsed").trigger("show.fieldset", [$(this).attr("id")]);
            } else {
                // Hide
                $(this).text(gettext("Show")).closest("fieldset").addClass("collapsed").trigger("hide.fieldset", [$(this).attr("id")]);
            }
            return false;
        });
    });
})(django.jQuery);
<commit_msg>Update public/admin/js/collapse.js<commit_after><|endoftext|>


<commit_before>/* Copyright (c) 2015-2016 The TagSpaces Authors. All rights reserved.
 * Use of this source code is governed by a AGPL3 license that
 * can be found in the LICENSE file. */

/* global define, Handlebars, isNode */
define(function(require, exports, module) {
  'use strict';
  console.log('Loading audiorecorder.ui.js ...');
  var TSCORE = require('tscore');
  require("webaudiorecording");
  var fileContent;
  var fileType;

  var initUI = function() {

    $('#audioRecordingConfirmButton').click(function() {
      saveAudioVideoFile();
    });

  };

  function saveAudioVideoFile() {
    var fileTags = '';
    var rawTags = $('#newFileNameTagsAudioRecorder').val().split(',');
    rawTags.forEach(function(value, index) {
      if (index === 0) {
        fileTags = value;
      } else {
        fileTags = fileTags + TSCORE.Config.getTagDelimiter() + value;
      }
    });
    if (fileTags.length > 0) {
      fileTags = TSCORE.TagUtils.beginTagContainer + fileTags + TSCORE.TagUtils.endTagContainer;
    }

    var filePath = TSCORE.currentPath + TSCORE.dirSeparator + $('#newFileNameAudioRecorder').val() + fileTags + '.' + fileType;
    TSCORE.IO.saveBinaryFilePromise(filePath, blob).then(function() {
      TSCORE.showSuccessDialog("File saved successfully.");

    }, function(error) {
      TSCORE.hideLoadingAnimation();
      TSCORE.showAlertDialog("Saving " + filePath + " failed.");
      console.error("Save to file " + filePath + " failed " + error);
    });
  }

  // Navigator.getUserMedia shim
  navigator.getUserMedia =
          navigator.getUserMedia ||
          navigator.webkitGetUserMedia ||
          navigator.mozGetUserMedia ||
          navigator.msGetUserMedia;

  // URL shim
  window.URL = window.URL || window.webkitURL;

  // audio context + .createScriptProcessor shim
  var audioContext = new AudioContext;
  if (audioContext.createScriptProcessor == null) {
    audioContext.createScriptProcessor = audioContext.createJavaScriptNode;
  }

  // Elements (jQuery objects)
  var $testToneLevel = $('#testToneLevel'),
          $microphone = $('#microphone'),
          $microphoneLevel = $('#microphoneLevel'),
  //$timeLimit = $('#time-limit'),
          $encoding = $('input[name="encoding"]'),
          $encodingOption = $('#encoding-option'),
  //$encodingProcess = $('input[name="encoding-process"]'),
  //$reportInterval = $('#report-interval'),
  //$bufferSize = $('#buffer-size'),
          $recording = $('#recording'),
          $timeDisplay = $('#time-display'),
          $record = $('#record'),
          $cancel = $('#cancel'),
          $dateTime = $('#date-time'),
          $recordingList = $('#recordingList'),
          $modalLoading = $('#modal-loading'),
          $modalProgress = $('#modal-progress'),
          $modalError = $('#modal-error');

  // Initialize input element states (required for reloading page on Firefox)
  $testToneLevel.attr('disabled', false);
  $testToneLevel[0].valueAsNumber = 0;
  $microphone.attr('disabled', false);
  $microphone[0].checked = false;
  $microphoneLevel.attr('disabled', false);
  $microphoneLevel[0].valueAsNumber = 0;
//  $timeLimit.attr('disabled', false);
//  $timeLimit[0].valueAsNumber = 3;
  $encoding.attr('disabled', false);
  $encoding[0].checked = true;
  //$encodingProcess.attr('disabled', false);
  //$encodingProcess[0].checked = true;
  //$reportInterval.attr('disabled', false);
  //$reportInterval[0].valueAsNumber = 1;
  //$bufferSize.attr('disabled', false);

  var testTone = (function() {
    var osc = audioContext.createOscillator(),
            lfo = audioContext.createOscillator(),
            ampMod = audioContext.createGain(),
            output = audioContext.createGain();
    lfo.type = 'square';
    lfo.frequency.value = 2;
    osc.connect(ampMod);
    lfo.connect(ampMod.gain);
    output.gain.value = 0.5;
    ampMod.connect(output);
    osc.start();
    lfo.start();
    return output;
  })();

  var testToneLevel = audioContext.createGain(),
          microphone = undefined,     // obtained by user click
          microphoneLevel = audioContext.createGain(),
          mixer = audioContext.createGain();
  testTone.connect(testToneLevel);
  testToneLevel.gain.value = 0;
  testToneLevel.connect(mixer);
  microphoneLevel.gain.value = 0;
  microphoneLevel.connect(mixer);
  mixer.connect(audioContext.destination);

  // Audio recorder object
  var audioRecorder = new WebAudioRecorder(mixer, {
    workerDir: 'libs/audio-record/',
    onEncoderLoading: function(recorder, encoding) {
      $modalLoading.find('.modal-title').html("Loading " + encoding.toUpperCase() + " encoder ...");
      $modalLoading.modal('show');
    },
    onEncoderLoaded: function() {
      $modalLoading.modal('hide');
    }
  });

  // Mixer levels
  $testToneLevel.on('input', function() {
    var level = $testToneLevel[0].valueAsNumber / 100;
    testToneLevel.gain.value = level * level;
  });

  $microphoneLevel.on('input', function() {
    var level = $microphoneLevel[0].valueAsNumber / 100;
    microphoneLevel.gain.value = level * level;
  });

  // Obtaining microphone input
  $microphone.click(function() {
    if (microphone == null)
      navigator.getUserMedia({audio: true},
              function(stream) {
                microphone = audioContext.createMediaStreamSource(stream);
                microphone.connect(microphoneLevel);
                $microphone.attr('disabled', true);
                $microphoneLevel.removeClass('hidden');
              },
              function(error) {
                $microphone[0].checked = false;
                audioRecorder.onError(audioRecorder, "Could not get audio input.");
              });
  });

  // Recording time limit
  function plural(n) {
    return n > 1 ? "s" : "";
  }

  /*$timeLimit.on('input', function() {
   var min = $timeLimit[0].valueAsNumber;
   $('#time-limit-text').html("" + min + " minute" + plural(min));
   });*/

  // Encoding selector + encoding options
  var OGG_QUALITY = [-0.1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],
          OGG_KBPS = [45, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 500],
          MP3_BIT_RATE = [64, 80, 96, 112, 128, 160, 192, 224, 256, 320],
          ENCODING_OPTION = {
            wav: {
              label: '',
              hidden: true,
              max: 1,
              text: function(val) {
                return '';
              }
            },
            ogg: {
              label: 'Quality',
              hidden: false,
              max: OGG_QUALITY.length - 1,
              text: function(val) {
                return OGG_QUALITY[val].toFixed(1) +
                        " (~" + OGG_KBPS[val] + "kbps)";
              }
            },
          },
          optionValue = {
            wav: null,
            ogg: 6,
            mp3: 5
          };

  $encoding.click(function(event) {
    var encoding = $(event.target).attr('encoding'),
            option = ENCODING_OPTION[encoding];
    audioRecorder.setEncoding(encoding);
    $('#encoding-option-label').html(option.label);
    $('#encoding-option-text').html(option.text(optionValue[encoding]));
    $encodingOption.toggleClass('hidden', option.hidden).attr('max', option.max);
    $encodingOption[0].valueAsNumber = optionValue[encoding];
  });

//  $encodingOption.on('input', function() {
//    var encoding = audioRecorder.encoding,
//            option = ENCODING_OPTION[encoding];
//    optionValue[encoding] = $encodingOption[0].value;
//    $('#encoding-option-text').html(option.text(optionValue[encoding]));
//  });
//
//// encoding process selector
//  var encodingProcess = 'background';
//
//  $encodingProcess.click(function(event) {
//    encodingProcess = $(event.target).attr('mode');
//    var hidden = encodingProcess === 'background';
//    $('#report-interval-label').toggleClass('hidden', hidden);
//    //$reportInterval.toggleClass('hidden', hidden);
//    $('#report-interval-text').toggleClass('hidden', hidden);
//  });

  /*$reportInterval.on('input', function() {
   var sec = $reportInterval[0].valueAsNumber;
   $('#report-interval-text').html("" + sec + " second" + (plural(sec)));
   });*/

  // Processor buffer size
  var BUFFER_SIZE = [256, 512, 1024, 2048, 4096, 8192, 16384];

  var defaultBufSz = (function() {
    var processor = audioContext.createScriptProcessor(undefined, 2, 2);
    return processor.bufferSize;
  })();

  var iDefBufSz = BUFFER_SIZE.indexOf(defaultBufSz);

  //$bufferSize[0].valueAsNumber = iDefBufSz;   // initialize with browser default

  function updateBufferSizeText() {
    //var iBufSz = $bufferSize[0].valueAsNumber, text = "" + BUFFER_SIZE[iBufSz];
    var iBufSz = iDefBufSz;
    var text = "" + BUFFER_SIZE[iBufSz];
    if (iBufSz === iDefBufSz)
      text += ' (browser default)';
    $('#buffer-size-text').html(text);
  }

  updateBufferSizeText();         // initialize text

  /*$bufferSize.on('input', function() {
   updateBufferSizeText();
   });*/

  var audioBlob;

  // Save/Delete recording
  function saveRecording(blob, encoding) {
    var time = new Date();
    var url = URL.createObjectURL(blob);

    audioBlob = blob;

    //var html = "
"+
    //        "<audio controls src='" + url + "'></audio> " +//" ("+encoding.toUpperCase()+")"+time
    //        " Save " +
    //        "<button class='btn btn-danger' style='margin-top:-15px' recording='" + url + "'>Delete</button>"+"
";
    //
    //if ($recordingList.empty()) {
    //  $recordingList.append($(html));
    //} else {
    //  $recordingList.removeAttribute(html);
    //}

    $('#recordingUrl').prop('recording', url);
    $('#formFileCreateAudioRecorder').prop('recording', url);
    $('#audioRecordingUrl').attr('src', url);
    $('#deleteAudioRecording').prop('recording', url);

    //fileContent = TSCORE.Config.getNewTextFileContent();
    // Default new file in text file
    fileType = 'wav' || 'ogg';
    $('#newFileNameTagsAudioRecorder').select2('data', null);
    $('#newFileNameTagsAudioRecorder').select2({
      multiple: true,
      tags: TSCORE.Config.getAllTags(),
      tokenSeparators: [
        ',',
        ' '
      ],
      minimumInputLength: 1,
      selectOnBlur: true
    });

    $('#newFileNameAudioRecorder').val('');
    //$('#tagWithCurrentDate').prop('checked', false);
    $('#txtFileTypeButtonAudioRecorder').button('toggle');
    $('#formFileCreateAudioRecorder').validator();
    $('#formFileCreateAudioRecorder').submit(function(e) {
      e.preventDefault();
    });
    $('#formFileCreateAudioRecorder').on('invalid.bs.validator', function() {
      $('#audioRecordingConfirmButton').prop('disabled', true);
    });
    $('#formFileCreateAudioRecorder').on('valid.bs.validator', function() {
      $('#audioRecordingConfirmButton').prop('disabled', false);
    });
    $('#audioRecordingDialog').on('shown.bs.modal', function() {
      $('#newFileNameAudioRecorder').select2().focus();
    });
    console.debug(blob);
  }

  $recordingList.on('click', 'button', function(event) {
    var url = $(event.target).attr('recording');
    $("p[recording='" + url + "']").remove();
    URL.revokeObjectURL(url);
  });

  // Time indicator
  function minSecStr(n) {
    return (n < 10 ? "0" : "") + n;
  }

  function updateDateTime() {
    var sec = audioRecorder.recordingTime() | 0;
    $timeDisplay.html(minSecStr(sec / 60 | 0) + ":" + minSecStr(sec % 60));
    $dateTime.html((new Date).toString());
  }

  window.setInterval(updateDateTime, 200);

  // Encoding progress report modal
  var progressComplete = false;

  function setProgress(progress) {
    var percent = (progress * 100).toFixed(1) + "%";
    $modalProgress.find('.progress-bar').attr('style', "width: " + percent + ";");
    $modalProgress.find('.text-center').html(percent);
    progressComplete = progress === 1;
  }

  $modalProgress.on("hide.bs.modal", function() {
    if (!progressComplete)
      audioRecorder.cancelEncoding();
  });

  // record | stop | cancel buttons
  function disableControlsOnRecord(disabled) {
    if (microphone == null)
      $microphone.attr('disabled', disabled);
    //$timeLimit.attr('disabled', disabled);
    $encoding.attr('disabled', disabled);
    $encodingOption.attr('disabled', disabled);
    //$encodingProcess.attr('disabled', disabled);
    //$reportInterval.attr('disabled', disabled);
    //$bufferSize.attr('disabled', disabled);
  }

  function startRecording() {
    $recording.removeClass('hidden');
    $record.html('STOP');
    $cancel.removeClass('hidden');
    disableControlsOnRecord(true);
    audioRecorder.setOptions({
      //timeLimit: $timeLimit[0].valueAsNumber * 60,
      //encodeAfterRecord: encodingProcess === 'separate',
      //progressInterval: $reportInterval[0].valueAsNumber * 1000,
      ogg: {quality: OGG_QUALITY[optionValue.ogg]},
    });
    audioRecorder.startRecording();
    setProgress(0);
  }

  function stopRecording(finish) {
    $recording.addClass('hidden');
    $record.html('RECORD');
    $cancel.addClass('hidden');
    disableControlsOnRecord(false);
    if (finish) {
      audioRecorder.finishRecording();
      if (audioRecorder.options.encodeAfterRecord) {
        $modalProgress.find('.modal-title').html("Encoding " + audioRecorder.encoding.toUpperCase());
        $modalProgress.modal('show');
      }
    } else
      audioRecorder.cancelRecording();
  }

  $record.click(function() {
    if (audioRecorder.isRecording())
      stopRecording(true);
    else
      startRecording();
  });

  $cancel.click(function() {
    stopRecording(false);
  });

  // Event handlers
  audioRecorder.onTimeout = function(recorder) {
    stopRecording(true);
  };

  audioRecorder.onEncodingProgress = function(recorder, progress) {
    setProgress(progress);
  };

  audioRecorder.onComplete = function(recorder, blob) {
    if (recorder.options.encodeAfterRecord)
      $modalProgress.modal('hide');
    saveRecording(blob, recorder.encoding);
  };

  audioRecorder.onError = function(recorder, message) {
    $modalError.find('.alert').html(message);
    $modalError.modal('show');
  };

  // Public API definition
  exports.initUI = initUI;
});
<commit_msg>updating the bootswatch library<commit_after>/* Copyright (c) 2015-2016 The TagSpaces Authors. All rights reserved.
 * Use of this source code is governed by a AGPL3 license that
 * can be found in the LICENSE file. */

/* global define, Handlebars, isNode */
define(function(require, exports, module) {
  'use strict';
  console.log('Loading audiorecorder.ui.js ...');
  var TSCORE = require('tscore');
  var fileContent;
  var fileType;

  var initUI = function() {

    $('#audioRecordingConfirmButton').click(function() {
      saveAudioVideoFile();
    });

  };

  function saveAudioVideoFile() {
    var fileTags = '';
    var rawTags = $('#newFileNameTagsAudioRecorder').val().split(',');
    rawTags.forEach(function(value, index) {
      if (index === 0) {
        fileTags = value;
      } else {
        fileTags = fileTags + TSCORE.Config.getTagDelimiter() + value;
      }
    });
    if (fileTags.length > 0) {
      fileTags = TSCORE.TagUtils.beginTagContainer + fileTags + TSCORE.TagUtils.endTagContainer;
    }

    console.log(fileContent);

    var filePath = TSCORE.currentPath + TSCORE.dirSeparator + $('#newFileNameAudioRecorder').val() + fileTags + '.' + fileType;
    TSCORE.IO.saveBinaryFilePromise(filePath, fileContent).then(function() {
      TSCORE.showSuccessDialog("File saved successfully.");

    }, function(error) {
      TSCORE.hideLoadingAnimation();
      TSCORE.showAlertDialog("Saving " + filePath + " failed.");
      console.error("Save to file " + filePath + " failed " + error);
    });
  }

  // Navigator.getUserMedia shim
  navigator.getUserMedia =
          navigator.getUserMedia ||
          navigator.webkitGetUserMedia ||
          navigator.mozGetUserMedia ||
          navigator.msGetUserMedia;

  // URL shim
  window.URL = window.URL || window.webkitURL;

  // audio context + .createScriptProcessor shim
  var audioContext = new AudioContext;
  if (audioContext.createScriptProcessor == null) {
    audioContext.createScriptProcessor = audioContext.createJavaScriptNode;
  }

  // Elements (jQuery objects)
  var $testToneLevel = $('#testToneLevel'),
          $microphone = $('#microphone'),
          $microphoneLevel = $('#microphoneLevel'),
  //$timeLimit = $('#time-limit'),
          $encoding = $('input[name="encoding"]'),
          $encodingOption = $('#encoding-option'),
  //$encodingProcess = $('input[name="encoding-process"]'),
  //$reportInterval = $('#report-interval'),
  //$bufferSize = $('#buffer-size'),
          $recording = $('#recording'),
          $timeDisplay = $('#time-display'),
          $record = $('#record'),
          $cancel = $('#cancel'),
          $dateTime = $('#date-time'),
          $recordingList = $('#recordingList'),
          $modalLoading = $('#modal-loading'),
          $modalProgress = $('#modal-progress'),
          $modalError = $('#modal-error');

  // Initialize input element states (required for reloading page on Firefox)
  $testToneLevel.attr('disabled', false);
  $testToneLevel[0].valueAsNumber = 0;
  $microphone.attr('disabled', false);
  $microphone[0].checked = false;
  $microphoneLevel.attr('disabled', false);
  $microphoneLevel[0].valueAsNumber = 0;
//  $timeLimit.attr('disabled', false);
//  $timeLimit[0].valueAsNumber = 3;
  $encoding.attr('disabled', false);
  $encoding[0].checked = true;
  //$encodingProcess.attr('disabled', false);
  //$encodingProcess[0].checked = true;
  //$reportInterval.attr('disabled', false);
  //$reportInterval[0].valueAsNumber = 1;
  //$bufferSize.attr('disabled', false);

  var testTone = (function() {
    var osc = audioContext.createOscillator(),
            lfo = audioContext.createOscillator(),
            ampMod = audioContext.createGain(),
            output = audioContext.createGain();
    lfo.type = 'square';
    lfo.frequency.value = 2;
    osc.connect(ampMod);
    lfo.connect(ampMod.gain);
    output.gain.value = 0.5;
    ampMod.connect(output);
    osc.start();
    lfo.start();
    return output;
  })();

  var testToneLevel = audioContext.createGain(),
          microphone = undefined,     // obtained by user click
          microphoneLevel = audioContext.createGain(),
          mixer = audioContext.createGain();
  testTone.connect(testToneLevel);
  testToneLevel.gain.value = 0;
  testToneLevel.connect(mixer);
  microphoneLevel.gain.value = 0;
  microphoneLevel.connect(mixer);
  mixer.connect(audioContext.destination);

  // Audio recorder object
  var audioRecorder = new WebAudioRecorder(mixer, {
    workerDir: 'libs/audio-record/',
    onEncoderLoading: function(recorder, encoding) {
      $modalLoading.find('.modal-title').html("Loading " + encoding.toUpperCase() + " encoder ...");
      $modalLoading.modal('show');
    },
    onEncoderLoaded: function() {
      $modalLoading.modal('hide');
    }
  });

  // Mixer levels
  $testToneLevel.on('input', function() {
    var level = $testToneLevel[0].valueAsNumber / 100;
    testToneLevel.gain.value = level * level;
  });

  $microphoneLevel.on('input', function() {
    var level = $microphoneLevel[0].valueAsNumber / 100;
    microphoneLevel.gain.value = level * level;
  });

  // Obtaining microphone input
  $microphone.click(function() {
    if (microphone == null)
      navigator.getUserMedia({audio: true},
              function(stream) {
                microphone = audioContext.createMediaStreamSource(stream);
                microphone.connect(microphoneLevel);
                $microphone.attr('disabled', true);
                $microphoneLevel.removeClass('hidden');
              },
              function(error) {
                $microphone[0].checked = false;
                audioRecorder.onError(audioRecorder, "Could not get audio input.");
              });
  });

  // Recording time limit
  function plural(n) {
    return n > 1 ? "s" : "";
  }

  /*$timeLimit.on('input', function() {
   var min = $timeLimit[0].valueAsNumber;
   $('#time-limit-text').html("" + min + " minute" + plural(min));
   });*/

  // Encoding selector + encoding options
  var OGG_QUALITY = [-0.1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],
          OGG_KBPS = [45, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 500],
          MP3_BIT_RATE = [64, 80, 96, 112, 128, 160, 192, 224, 256, 320],
          ENCODING_OPTION = {
            wav: {
              label: '',
              hidden: true,
              max: 1,
              text: function(val) {
                return '';
              }
            },
            ogg: {
              label: 'Quality',
              hidden: false,
              max: OGG_QUALITY.length - 1,
              text: function(val) {
                return OGG_QUALITY[val].toFixed(1) +
                        " (~" + OGG_KBPS[val] + "kbps)";
              }
            },
          },
          optionValue = {
            wav: null,
            ogg: 6,
            mp3: 5
          };

  $encoding.click(function(event) {
    var encoding = $(event.target).attr('encoding'),
            option = ENCODING_OPTION[encoding];
    audioRecorder.setEncoding(encoding);
    $('#encoding-option-label').html(option.label);
    $('#encoding-option-text').html(option.text(optionValue[encoding]));
    $encodingOption.toggleClass('hidden', option.hidden).attr('max', option.max);
    $encodingOption[0].valueAsNumber = optionValue[encoding];
  });

//  $encodingOption.on('input', function() {
//    var encoding = audioRecorder.encoding,
//            option = ENCODING_OPTION[encoding];
//    optionValue[encoding] = $encodingOption[0].value;
//    $('#encoding-option-text').html(option.text(optionValue[encoding]));
//  });
//
//// encoding process selector
//  var encodingProcess = 'background';
//
//  $encodingProcess.click(function(event) {
//    encodingProcess = $(event.target).attr('mode');
//    var hidden = encodingProcess === 'background';
//    $('#report-interval-label').toggleClass('hidden', hidden);
//    //$reportInterval.toggleClass('hidden', hidden);
//    $('#report-interval-text').toggleClass('hidden', hidden);
//  });

  /*$reportInterval.on('input', function() {
   var sec = $reportInterval[0].valueAsNumber;
   $('#report-interval-text').html("" + sec + " second" + (plural(sec)));
   });*/

  // Processor buffer size
  var BUFFER_SIZE = [256, 512, 1024, 2048, 4096, 8192, 16384];

  var defaultBufSz = (function() {
    var processor = audioContext.createScriptProcessor(undefined, 2, 2);
    return processor.bufferSize;
  })();

  var iDefBufSz = BUFFER_SIZE.indexOf(defaultBufSz);

  //$bufferSize[0].valueAsNumber = iDefBufSz;   // initialize with browser default

  function updateBufferSizeText() {
    //var iBufSz = $bufferSize[0].valueAsNumber, text = "" + BUFFER_SIZE[iBufSz];
    var iBufSz = iDefBufSz;
    var text = "" + BUFFER_SIZE[iBufSz];
    if (iBufSz === iDefBufSz)
      text += ' (browser default)';
    $('#buffer-size-text').html(text);
  }

  updateBufferSizeText();         // initialize text

  /*$bufferSize.on('input', function() {
   updateBufferSizeText();
   });*/

  var audioBlob;

  // Save/Delete recording
  function saveRecording(blob, encoding) {
    var time = new Date();
    var url = URL.createObjectURL(blob);

    audioBlob = blob;

    //var html = "
"+
    //        "<audio controls src='" + url + "'></audio> " +//" ("+encoding.toUpperCase()+")"+time
    //        " Save " +
    //        "<button class='btn btn-danger' style='margin-top:-15px' recording='" + url + "'>Delete</button>"+"
";
    //
    //if ($recordingList.empty()) {
    //  $recordingList.append($(html));
    //} else {
    //  $recordingList.removeAttribute(html);
    //}

    $('#recordingUrl').prop('recording', url);
    $('#formFileCreateAudioRecorder').prop('recording', url);
    $('#audioRecordingUrl').attr('src', url);
    $('#deleteAudioRecording').prop('recording', url);

    fileContent = blob;
    // Default new file in text file
    fileType = 'wav' || 'ogg';
    $('#newFileNameTagsAudioRecorder').select2('data', null);
    $('#newFileNameTagsAudioRecorder').select2({
      multiple: true,
      tags: TSCORE.Config.getAllTags(),
      tokenSeparators: [
        ',',
        ' '
      ],
      minimumInputLength: 1,
      selectOnBlur: true
    });

    $('#newFileNameAudioRecorder').val('');
    //$('#tagWithCurrentDate').prop('checked', false);
    $('#txtFileTypeButtonAudioRecorder').button('toggle');
    $('#formFileCreateAudioRecorder').validator();
    $('#formFileCreateAudioRecorder').submit(function(e) {
      e.preventDefault();
    });
    $('#formFileCreateAudioRecorder').on('invalid.bs.validator', function() {
      $('#audioRecordingConfirmButton').prop('disabled', true);
    });
    $('#formFileCreateAudioRecorder').on('valid.bs.validator', function() {
      $('#audioRecordingConfirmButton').prop('disabled', false);
    });
    $('#audioRecordingDialog').on('shown.bs.modal', function() {
      $('#newFileNameAudioRecorder').select2().focus();
    });
  }

  $recordingList.on('click', 'button', function(event) {
    var url = $(event.target).attr('recording');
    $("p[recording='" + url + "']").remove();
    URL.revokeObjectURL(url);
  });

  // Time indicator
  function minSecStr(n) {
    return (n < 10 ? "0" : "") + n;
  }

  function updateDateTime() {
    var sec = audioRecorder.recordingTime() | 0;
    $timeDisplay.html(minSecStr(sec / 60 | 0) + ":" + minSecStr(sec % 60));
    $dateTime.html((new Date).toString());
  }

  window.setInterval(updateDateTime, 200);

  // Encoding progress report modal
  var progressComplete = false;

  function setProgress(progress) {
    var percent = (progress * 100).toFixed(1) + "%";
    $modalProgress.find('.progress-bar').attr('style', "width: " + percent + ";");
    $modalProgress.find('.text-center').html(percent);
    progressComplete = progress === 1;
  }

  $modalProgress.on("hide.bs.modal", function() {
    if (!progressComplete)
      audioRecorder.cancelEncoding();
  });

  // record | stop | cancel buttons
  function disableControlsOnRecord(disabled) {
    if (microphone == null)
      $microphone.attr('disabled', disabled);
    //$timeLimit.attr('disabled', disabled);
    $encoding.attr('disabled', disabled);
    $encodingOption.attr('disabled', disabled);
    //$encodingProcess.attr('disabled', disabled);
    //$reportInterval.attr('disabled', disabled);
    //$bufferSize.attr('disabled', disabled);
  }

  function startRecording() {
    $recording.removeClass('hidden');
    $record.html('STOP');
    $cancel.removeClass('hidden');
    disableControlsOnRecord(true);
    audioRecorder.setOptions({
      //timeLimit: $timeLimit[0].valueAsNumber * 60,
      //encodeAfterRecord: encodingProcess === 'separate',
      //progressInterval: $reportInterval[0].valueAsNumber * 1000,
      ogg: {quality: OGG_QUALITY[optionValue.ogg]},
    });
    audioRecorder.startRecording();
    setProgress(0);
  }

  function stopRecording(finish) {
    $recording.addClass('hidden');
    $record.html('RECORD');
    $cancel.addClass('hidden');
    disableControlsOnRecord(false);
    if (finish) {
      audioRecorder.finishRecording();
      if (audioRecorder.options.encodeAfterRecord) {
        $modalProgress.find('.modal-title').html("Encoding " + audioRecorder.encoding.toUpperCase());
        $modalProgress.modal('show');
      }
    } else
      audioRecorder.cancelRecording();
  }

  $record.click(function() {
    if (audioRecorder.isRecording())
      stopRecording(true);
    else
      startRecording();
  });

  $cancel.click(function() {
    stopRecording(false);
  });

  // Event handlers
  audioRecorder.onTimeout = function(recorder) {
    stopRecording(true);
  };

  audioRecorder.onEncodingProgress = function(recorder, progress) {
    setProgress(progress);
  };

  audioRecorder.onComplete = function(recorder, blob) {
    if (recorder.options.encodeAfterRecord)
      $modalProgress.modal('hide');
    saveRecording(blob, recorder.encoding);
  };

  audioRecorder.onError = function(recorder, message) {
    $modalError.find('.alert').html(message);
    $modalError.modal('show');
  };

  // Public API definition
  exports.initUI = initUI;
});
<|endoftext|>


<commit_before>// Checks to see if we've launched before (we touch started.txt). If not, write the file and open a browser
import {socketRoot} from '../../react-native/react/constants/platform.native.desktop'
import path from 'path'

const helpURL = 'https://keybase.io/getting-started'
const filePath = path.join(socketRoot, 'started.txt')
import fs from 'fs'
import {shell} from 'electron'

export default () => {
  fs.stat(filePath, (err, stats) => {
    if (err) {
      try {
        fs.writeFileSync(filePath, 'This file gets created on first run of the app')
      }
      catch (e) {
        console.error(`Couldn't mark splash screen shown: ${e}`)
        // if we cant' write this file, let's not show the splash, maybe something weird is going on
        return
      }
      shell.openExternal(helpURL)
    }
  })
}
<commit_msg>Use imported helpURL in splash<commit_after>// Checks to see if we've launched before (we touch started.txt). If not, write the file and open a browser
import {socketRoot} from '../../react-native/react/constants/platform.native.desktop'
import {helpURL} from '../../react-native/react/constants/urls'
import path from 'path'

const filePath = path.join(socketRoot, 'started.txt')
import fs from 'fs'
import {shell} from 'electron'

export default () => {
  fs.stat(filePath, (err, stats) => {
    if (err) {
      try {
        fs.writeFileSync(filePath, 'This file gets created on first run of the app')
      }
      catch (e) {
        console.error(`Couldn't mark splash screen shown: ${e}`)
        // if we cant' write this file, let's not show the splash, maybe something weird is going on
        return
      }
      shell.openExternal(helpURL)
    }
  })
}
<|endoftext|>


<commit_before>/*
search2DataSource

The search data source performs a fresh search with every new query.
Whereas the workspace data source fetches the data once, and then performs
a search against these cached results
*/
define([
    'bluebird',
    'handlebars',
    'common/searchAPI2',
    './common',
], function(
    Promise,
    Handlebars,
    SearchAPI2,
    common,
) {
    'use strict';

    class RefDataSearch {
        constructor({ url, token, timeout }) {
            this.url = url;
            this.token = token;
            this.searchAPI2 = new SearchAPI2({ url: this.url, token: this.token });
            this.timeout = timeout;
        }

        referenceGenomeTotal({ source }) {
            const params = {
                query: {
                    bool: {
                        must: [
                            {
                                term: {
                                    tags: 'refdata',
                                },
                            },
                            {
                                term: {
                                    source,
                                },
                            },
                        ],
                    },
                },
                only_public: true,
                indexes: ['genome'],
                size: 0,
                from: 0,
                track_total_hits: true,
            };
            return this.searchAPI2.search_objects({ params, timeout: this.timeout })
                .then((result) => {
                    return result.count;
                });
        }

        referenceGenomeDataSearch({ source, query, offset, limit }) {
            const params = {
                query: {
                    bool: {
                        must: [
                            {
                                term: {
                                    tags: 'refdata',
                                },
                            },
                            {
                                term: {
                                    source,
                                },
                            },
                        ],
                    },
                },
                sort: [
                    { 'scientific_name.raw': { order: 'asc' } },
                    { 'genome_id': { order: 'asc' } },
                ],
                only_public: true,
                indexes: ['genome'],
                size: limit,
                from: offset,
                track_total_hits: true,
            };
            if (query !== null) {
                params.query.bool.must.push({
                    'match': {
                        'scientific_name': {
                            'query': query,
                            'operator': 'AND',
                        },
                    },
                });
            }
            return this.searchAPI2.search_objects({ params, timeout: this.timeout });
        }

        referenceGenomeSearch({ source, query, page, pageSize }) {
            const offset = page * pageSize;
            const limit = pageSize;
            return Promise.all([
                this.referenceGenomeTotal({ source }),
                this.referenceGenomeDataSearch({ source, query, offset, limit }),
            ])
                .then(([totalAvailable, result]) => {
                    return {
                        totalAvailable,
                        result,
                    };
                });
        }
    }

    function parseGenomeSearchResultItem(item) {
        return {
            genome_id: item.doc.genome_id,
            genome_source: item.doc.source,
            genome_source_id: item.doc.source_id,
            scientific_name: item.doc.scientific_name,
            num_contigs: item.doc.num_contigs,
            num_cds: item.doc.cds_count,
            num_features: item.doc.feature_count,
            ws_ref: [item.doc.access_group, item.doc.obj_id, item.doc.version].join('/'),
            workspace_name: null,
            taxonomy: item.doc.taxonomy,
            object_name: item.doc.obj_name,
        };
    }

    return Object.create({}, {
        init: {
            value: function(arg) {
                common.requireArg(arg, 'config');
                common.requireArg(arg, 'token');
                common.requireArg(arg, 'urls.searchapi2');
                common.requireArg(arg, 'pageSize');
                const { config, token, urls: { searchapi2 }, pageSize } = arg;

                this.pageSize = pageSize;

                this.currentPage = null;
                this.page = null;
                this.config = config;
                this.queryExpression = null;
                this.availableData = null;
                this.fetchedDataCount = null;
                this.filteredData = null;
                this.searchApi = new RefDataSearch({
                    url: searchapi2,
                    token,
                    timeout: config.timeout,
                });
                this.searchState = {
                    lastSearchAt: null,
                    inProgress: false,
                    lastQuery: null,
                    currentQueryState: null,
                };
                this.titleTemplate = Handlebars.compile(this.config.templates.title);
                this.metadataTemplates = common.compileTemplates(this.config.templates.metadata);
                return this;
            },
        },
        search: {
            value: function(query) {
                return Promise.try(() => {
                    if (this.searchState.currentQueryState) {
                        return null;
                    }

                    // Prepare page number
                    let page;
                    if (query.page) {
                        page = query.page;
                    } else {
                        page = 1;
                    }
                    this.page = page;

                    // Prepare search input
                    const queryInput = query.input;
                    let newQuery;
                    if (!queryInput) {
                        newQuery = null;
                    } else if (queryInput === '*') {
                        newQuery = null;
                    } else {
                        // strip off "*" suffix from any terms in this search; it does not
                        // act as a wildcard for search2, and would be interpreted as a
                        // literal part of the search string.
                        // The "*" will have been added by the generic search ui code handling
                        // itself, not the user.
                        newQuery = queryInput.split(/[ ]+/)
                            .map((term) => {
                                if (term.charAt(term.length - 1) === '*') {
                                    return term.slice(0, -1);
                                } else {
                                    return term;
                                }
                            }).join(' ');
                    }
                    this.queryExpression = newQuery;

                    // Create state for this specific search
                    const now = new Date().getTime();

                    const queryState = {
                        query,
                        page,
                        started: now,
                        promise: null,
                        canceled: false,
                    };

                    // And update the uber-search-state.
                    this.searchState.currentQueryState = queryState;
                    this.searchState.lastSearchAt = now;
                    this.searchState.lastQuery = newQuery;

                    queryState.promise = this.searchApi.referenceGenomeSearch({
                        source: this.config.source,
                        pageSize: this.pageSize,
                        query: this.queryExpression,
                        page: this.page - 1,
                    })
                        .then((result) => {
                            this.availableDataCount = result.totalAvailable;
                            this.filteredDataCount = result.result.count;
                            this.availableData = result.result.hits.map((item, index) => {
                                // This call gives us a normalized genome result object.
                                // In porting this over, we are preserving the field names.
                                const genomeRecord = parseGenomeSearchResultItem(item);

                                const name = this.titleTemplate(genomeRecord);
                                const metadata = common.applyMetadataTemplates(this.metadataTemplates, genomeRecord);
                                return {
                                    rowNumber: index + (this.page - 1) * this.pageSize + 1,
                                    info: null,
                                    id: genomeRecord.genome_id,
                                    objectId: null,
                                    name,
                                    objectName: genomeRecord.object_name,
                                    metadata,
                                    ws: this.config.workspaceName,
                                    type: this.config.type,
                                    attached: false,
                                    workspaceReference: { ref: genomeRecord.ws_ref },
                                };
                            });
                            // assume that all items before the page have been fetched
                            this.fetchedDataCount = (this.page - 1) * this.pageSize + this.availableData.length;
                            return this.availableData;
                        })
                        .catch((error) => {
                            if (error instanceof DOMException && error.name === 'AbortError') {
                                const errorMsg = `Request canceled - perhaps timed out after ${this.config.timeout}ms`;
                                throw new Error(errorMsg);
                            }
                            throw(error);
                        });

                    return queryState.promise;
                })
                    .finally(() => {
                        this.searchState.currentQueryState = null;
                    });
            },
        },
        setQuery: {
            value: function(query) {
                this.queryExpression = query.replace(/[*]/g, ' ').trim().toLowerCase();
            },
        },
        applyQuery: {
            value: () => {
                return this.searchApi.referenceGenomeSearch({
                    source: this.config.source,
                    pageSize: this.itemsPerPage,
                    query: this.queryExpression,
                    page: this.page,
                })
                    .then((result) => {
                        this.availableDataCount = result.totalAvailable;
                        this.filteredDataCount = result.result.count;
                        this.availableData = result.result.objects.map(function(item) {
                            // This call gives us a normalized genome result object.
                            // In porting this over, we are preserving the field names.
                            const genomeRecord = parseGenomeSearchResultItem(item);

                            const name = this.titleTemplate(genomeRecord);
                            const metadata = common.applyMetadataTemplates(this.metadataTemplates, genomeRecord);
                            return {
                                info: null,
                                id: genomeRecord.genome_id,
                                objectId: null,
                                name,
                                objectName: genomeRecord.object_name,
                                metadata,
                                ws: this.config.workspaceName,
                                type: this.config.type,
                                attached: false,
                            };
                        });
                        return this.availableData;
                    });
            },
        },
        load: {
            value: function() {
                return common.listObjectsWithSets(this.narrativeService, this.config.workspaceName, this.config.type)
                    .then((data) => {
                        this.availableData = data;
                        this.availableDataCount = this.availableData.length;
                    });
            },
        },
    });
});<commit_msg>Search now filters by scientific_name, genome_id, or source id.<commit_after>/*
search2DataSource

The search data source performs a fresh search with every new query.
Whereas the workspace data source fetches the data once, and then performs
a search against these cached results
*/
define([
    'bluebird',
    'handlebars',
    'common/searchAPI2',
    './common',
], function(
    Promise,
    Handlebars,
    SearchAPI2,
    common,
) {
    'use strict';

    class RefDataSearch {
        constructor({ url, token, timeout }) {
            this.url = url;
            this.token = token;
            this.searchAPI2 = new SearchAPI2({ url: this.url, token: this.token });
            this.timeout = timeout;
        }

        referenceGenomeTotal({ source }) {
            const params = {
                query: {
                    bool: {
                        must: [
                            {
                                term: {
                                    tags: 'refdata',
                                },
                            },
                            {
                                term: {
                                    source,
                                },
                            },
                        ],
                    },
                },
                only_public: true,
                indexes: ['genome'],
                size: 0,
                from: 0,
                track_total_hits: true,
            };
            return this.searchAPI2.search_objects({ params, timeout: this.timeout })
                .then((result) => {
                    return result.count;
                });
        }

        referenceGenomeDataSearch({ source, query, offset, limit }) {
            const params = {
                query: {
                    bool: {
                        must: [
                            {
                                term: {
                                    tags: 'refdata',
                                },
                            },
                            {
                                term: {
                                    source,
                                },
                            },
                        ],
                    },
                },
                sort: [
                    { 'scientific_name.raw': { order: 'asc' } },
                    { 'genome_id': { order: 'asc' } },
                ],
                only_public: true,
                indexes: ['genome'],
                size: limit,
                from: offset,
                track_total_hits: true,
            };
            if (query !== null) {
                params.query.bool.filter = {
                    'bool': {
                        'must': {
                            'bool': {
                                'should': [
                                    {
                                        'match': {
                                            'scientific_name': {
                                                'query': query,
                                                'operator': 'AND',
                                            },
                                        },
                                    },
                                    {
                                        'match': {
                                            'source_id': query,
                                        },
                                    },
                                    {
                                        'match': {
                                            'genome_id': query,
                                        },
                                    },
                                ],
                            },
                        },
                    },
                };
            }
            return this.searchAPI2.search_objects({ params, timeout: this.timeout });
        }

        referenceGenomeSearch({ source, query, page, pageSize }) {
            const offset = page * pageSize;
            const limit = pageSize;
            return Promise.all([
                this.referenceGenomeTotal({ source }),
                this.referenceGenomeDataSearch({ source, query, offset, limit }),
            ])
                .then(([totalAvailable, result]) => {
                    return {
                        totalAvailable,
                        result,
                    };
                });
        }
    }

    function parseGenomeSearchResultItem(item) {
        return {
            genome_id: item.doc.genome_id,
            genome_source: item.doc.source,
            genome_source_id: item.doc.source_id,
            scientific_name: item.doc.scientific_name,
            num_contigs: item.doc.num_contigs,
            num_cds: item.doc.cds_count,
            num_features: item.doc.feature_count,
            ws_ref: [item.doc.access_group, item.doc.obj_id, item.doc.version].join('/'),
            workspace_name: null,
            taxonomy: item.doc.taxonomy,
            object_name: item.doc.obj_name,
        };
    }

    return Object.create({}, {
        init: {
            value: function(arg) {
                common.requireArg(arg, 'config');
                common.requireArg(arg, 'token');
                common.requireArg(arg, 'urls.searchapi2');
                common.requireArg(arg, 'pageSize');
                const { config, token, urls: { searchapi2 }, pageSize } = arg;

                this.pageSize = pageSize;

                this.currentPage = null;
                this.page = null;
                this.config = config;
                this.queryExpression = null;
                this.availableData = null;
                this.fetchedDataCount = null;
                this.filteredData = null;
                this.searchApi = new RefDataSearch({
                    url: searchapi2,
                    token,
                    timeout: config.timeout,
                });
                this.searchState = {
                    lastSearchAt: null,
                    inProgress: false,
                    lastQuery: null,
                    currentQueryState: null,
                };
                this.titleTemplate = Handlebars.compile(this.config.templates.title);
                this.metadataTemplates = common.compileTemplates(this.config.templates.metadata);
                return this;
            },
        },
        search: {
            value: function(query) {
                return Promise.try(() => {
                    if (this.searchState.currentQueryState) {
                        return null;
                    }

                    // Prepare page number
                    let page;
                    if (query.page) {
                        page = query.page;
                    } else {
                        page = 1;
                    }
                    this.page = page;

                    // Prepare search input
                    const queryInput = query.input;
                    let newQuery;
                    if (!queryInput) {
                        newQuery = null;
                    } else if (queryInput === '*') {
                        newQuery = null;
                    } else {
                        // strip off "*" suffix from any terms in this search; it does not
                        // act as a wildcard for search2, and would be interpreted as a
                        // literal part of the search string.
                        // The "*" will have been added by the generic search ui code handling
                        // itself, not the user.
                        newQuery = queryInput.split(/[ ]+/)
                            .map((term) => {
                                if (term.charAt(term.length - 1) === '*') {
                                    return term.slice(0, -1);
                                } else {
                                    return term;
                                }
                            }).join(' ');
                    }
                    this.queryExpression = newQuery;

                    // Create state for this specific search
                    const now = new Date().getTime();

                    const queryState = {
                        query,
                        page,
                        started: now,
                        promise: null,
                        canceled: false,
                    };

                    // And update the uber-search-state.
                    this.searchState.currentQueryState = queryState;
                    this.searchState.lastSearchAt = now;
                    this.searchState.lastQuery = newQuery;

                    queryState.promise = this.searchApi.referenceGenomeSearch({
                        source: this.config.source,
                        pageSize: this.pageSize,
                        query: this.queryExpression,
                        page: this.page - 1,
                    })
                        .then((result) => {
                            this.availableDataCount = result.totalAvailable;
                            this.filteredDataCount = result.result.count;
                            this.availableData = result.result.hits.map((item, index) => {
                                // This call gives us a normalized genome result object.
                                // In porting this over, we are preserving the field names.
                                const genomeRecord = parseGenomeSearchResultItem(item);

                                const name = this.titleTemplate(genomeRecord);
                                const metadata = common.applyMetadataTemplates(this.metadataTemplates, genomeRecord);
                                return {
                                    rowNumber: index + (this.page - 1) * this.pageSize + 1,
                                    info: null,
                                    id: genomeRecord.genome_id,
                                    objectId: null,
                                    name,
                                    objectName: genomeRecord.object_name,
                                    metadata,
                                    ws: this.config.workspaceName,
                                    type: this.config.type,
                                    attached: false,
                                    workspaceReference: { ref: genomeRecord.ws_ref },
                                };
                            });
                            // assume that all items before the page have been fetched
                            this.fetchedDataCount = (this.page - 1) * this.pageSize + this.availableData.length;
                            return this.availableData;
                        })
                        .catch((error) => {
                            if (error instanceof DOMException && error.name === 'AbortError') {
                                const errorMsg = `Request canceled - perhaps timed out after ${this.config.timeout}ms`;
                                throw new Error(errorMsg);
                            }
                            throw(error);
                        });

                    return queryState.promise;
                })
                    .finally(() => {
                        this.searchState.currentQueryState = null;
                    });
            },
        },
        setQuery: {
            value: function(query) {
                this.queryExpression = query.replace(/[*]/g, ' ').trim().toLowerCase();
            },
        },
        applyQuery: {
            value: () => {
                return this.searchApi.referenceGenomeSearch({
                    source: this.config.source,
                    pageSize: this.itemsPerPage,
                    query: this.queryExpression,
                    page: this.page,
                })
                    .then((result) => {
                        this.availableDataCount = result.totalAvailable;
                        this.filteredDataCount = result.result.count;
                        this.availableData = result.result.objects.map(function(item) {
                            // This call gives us a normalized genome result object.
                            // In porting this over, we are preserving the field names.
                            const genomeRecord = parseGenomeSearchResultItem(item);

                            const name = this.titleTemplate(genomeRecord);
                            const metadata = common.applyMetadataTemplates(this.metadataTemplates, genomeRecord);
                            return {
                                info: null,
                                id: genomeRecord.genome_id,
                                objectId: null,
                                name,
                                objectName: genomeRecord.object_name,
                                metadata,
                                ws: this.config.workspaceName,
                                type: this.config.type,
                                attached: false,
                            };
                        });
                        return this.availableData;
                    });
            },
        },
        load: {
            value: function() {
                return common.listObjectsWithSets(this.narrativeService, this.config.workspaceName, this.config.type)
                    .then((data) => {
                        this.availableData = data;
                        this.availableDataCount = this.availableData.length;
                    });
            },
        },
    });
});<|endoftext|>


<commit_before>var lib = require('../lib');
var log = lib.log;
var client = lib.client;

var table = require('text-table');

var fs = require('fs');
var http = require('http');
var util = require('util');
var qs = require('querystring');

var usage = exports.usage = function (bin, cmd) {
  console.log('Usage: ' + bin + ' ' + cmd + ' [OPTIONS] <string>');
};

exports.completion = function (tabtab, data) {
  if (/^--\w?/.test(data.last)) {
    return tabtab.log([
      'size',
      'filename',
      'uploaded',
      'mime',
      '_id'
    ], data, '--');
  }
};

exports.description = "Search content on gizmod";

exports.run = function (args) {

  var parsedArgs = {};

  Object.keys(args).forEach(function (key) {
    if (key !== '_' && key !== 'debug') {
      parsedArgs[key] = args[key];
    }
  });

  var parsedArgs = qs.stringify(parsedArgs);

  log.bug(parsedArgs);

  var options = {
    hostname: 'localhost',
    port: 3000,
    path: '/search?' + parsedArgs,
    method: 'GET'
  };

  client.getJSON('/search?' + parsedArgs, function (err, body) {
    if (err) {
      log.err(err);
    } else {
      console.log(util.inspect(body, { showHidden: true, depth: null, colors: true }));
    }
  });

  log.bug(options);

/*
  var req = http.request(options, function (res) {
    log.bug(res.statusCode);
    var body = "";
    res.on('data', function (data) {
      body += data;
    });
    res.on('end', function () {
      body = JSON.parse(body);
      var out = body.map(function (item) {
        return [

        ];
      });
      console.log(util.inspect(body, { showHidden: true, depth: null, colors: true }));
    });
  });

  req.on('error', function (err) {
    log.err(err);
  });

  req.end();
  */

};
<commit_msg>Cleaned up search cli code.<commit_after>var lib = require('../lib');
var log = lib.log;
var client = lib.client;

var table = require('text-table');

var util = require('util');
var qs = require('querystring');

var usage = exports.usage = function (bin, cmd) {
  console.log('Usage: ' + bin + ' ' + cmd + ' [OPTIONS] <string>');
};

exports.completion = function (tabtab, data) {
  if (/^--\w?/.test(data.last)) {
    return tabtab.log([
      'size',
      'filename',
      'uploaded',
      'mime',
      '_id'
    ], data, '--');
  }
};

exports.description = "Search content on gizmod";

exports.run = function (args) {

  var parsedArgs = {};

  Object.keys(args).forEach(function (key) {
    if (key !== '_' && key !== 'debug') {
      parsedArgs[key] = args[key];
    }
  });

  var parsedArgs = qs.stringify(parsedArgs);

  log.bug(parsedArgs);

  client.getJSON('/search?' + parsedArgs, function (err, body) {
    if (err) {
      log.err(err);
    } else {
      console.log(util.inspect(body, { showHidden: true, depth: null, colors: true }));
    }
  });

};
<|endoftext|>


<commit_before>describe('nav tests', function () {
  'use strict';
  var nav, content;

  beforeEach(function (done) {
    this.timeout(10000);

    require(['cs!modules/media/nav/nav', 'cs!models/content'], function (MediaNavView, ContentModel) {
      content = new ContentModel();
      nav = new MediaNavView({
        'model': content
      });
      done();
    });
  });
  describe('templateHelpers tests', function () {
    it('should set the rel=next/prev tags', function () {
      nav.templateHelpers();
      document.querySelector('link[rel=\'next\']').getAttribute('href').should.equal('/contents/');
      document.querySelector('link[rel=\'prev\']').getAttribute('href').should.equal('/contents/');
      document.querySelectorAll('link[rel=\'next\']').length.should.equal(1);
      document.querySelectorAll('link[rel=\'prev\']').length.should.equal(1);
    });
  });
});
<commit_msg>testing requires in nav test<commit_after>describe('nav tests', function () {
  'use strict';
  var page;

  beforeEach(function (done) {
    require(['cs!models/contents/page'], function (Page) {
      page = new Page();
      done();
    });
  });
  describe('templateHelpers tests', function () {
    it('should set the rel=next/prev tags', function () {
      page.get('content').should.not.equal('');
    });
  });
});
<|endoftext|>


<commit_before>//*@public
/**
	_enyo.InputBinding_ is a binding designed to have its source or target be an
	_input_ with an optional _placeholder_ value. This keeps the input from
	showing _undefined_ when there is no content, as the _placeholder_ value will
	then be used for display.
*/
enyo.kind({
	name: "enyo.InputBinding",
	kind: enyo.Binding,
	oneWay: false,
	//*@protected
	transform: function (value, direction, binding) {
		if (value) { return value; }
		var s = binding.source || {},
			t = binding.target || {},
			// we attempt to find the placeholder at either end, prioritizing
			// to checking the source
			ph = s.placeholder || t.placeholder || "";
		return ph;
	}
});
<commit_msg>fix issue where there was no way to keep the placeholder text from propagating the wrong direction<commit_after>//*@public
/**
	_enyo.InputBinding_ is a binding designed to have its source or target be an
	_input_ with an optional _placeholder_ value. This keeps the input from
	showing _undefined_ when there is no content, as the _placeholder_ value will
	then be used for display.
*/
enyo.kind({
	name: "enyo.InputBinding",
	kind: enyo.Binding,
	/**
		The direction priority for the placeholder text so it is not propagated when
		an empty string should be.
	*/
	placeholderDirection: "source",
	oneWay: false,
	//*@protected
	transform: function (value, direction, binding) {
		if (value) { return value; }
		var pd = binding.placeholderDirection,
			ph = binding[pd].placeholder || "";
		return ph;
	}
});
<|endoftext|>