<commit_before>import { Model as ObjectionModel } from 'objection'

import './Inflect'
import './ModelNotFoundError'
import './RelationSynchronizer'
import './RelationValidator'

const as = require('as-type')

export class Model extends ObjectionModel {
	static descriptiveName = null
	static eager = null
	static eagerFilters = null
	static useTimestamps = true
	static createdAt = 'created_at'
	static updatedAt = 'updated_at'
	static dates = [ ]

	static $$app = null

	static app(app) {
		if(!app.isNil) {
			this.$$app = app
		} else {
			return this.$$app
		}
	}

	$app() {
		return this.constructor.app()
	}

	static findById(id) {
		return this.query().findById(id)
	}

	static findByIdOrFail(id) {
		return this.findById(id).orFail()
	}

	static findByRouteParameter(value) {
		return this.findById(value)
	}

	static routeBind(name, description) {
		description = description || `${name} Value`

		this.app().routes.bind(name, (value, resolve, reject) => {
			this.findByRouteParameter(value).then(row => {
				if(row.isNil) {
					reject(new ModelNotFoundError(this))
					return
				}

				resolve(row)
			})
		}, { swagger: { name, description } })
	}

	static buildRelations() {
		return { }
	}

	static getRelations() {
		if(this.relationMappings.isNil) {
			this.relationMappings = this.buildRelations()
		}

		return super.getRelations()
	}

	static hasOne(modelClass, foreignKey = null, localKey = null) {
		return this._hasOneOrMany(this.HasOneRelation, modelClass, foreignKey, localKey)
	}

	static hasMany(modelClass, foreignKey = null, localKey = null) {
		return this._hasOneOrMany(this.HasManyRelation, modelClass, foreignKey, localKey)
	}

	static _hasOneOrMany(relation, modelClass, foreignKey = null, localKey = null) {
		foreignKey = foreignKey || Inflect.foreignKey(this.name)

		if(localKey.isNil) {
			localKey = this.getFullIdColumn()
		} else {
			localKey = `${this.tableName}.${localKey}`
		}

		return {
			relation: relation,
			modelClass: modelClass,
			join: {
				from: `${modelClass.tableName}.${foreignKey}`,
				to: localKey
			}
		}
	}

	static belongsTo(modelClass, foreignKey = null, otherKey = null) {
		foreignKey = foreignKey || Inflect.foreignKey(modelClass.name)

		if(otherKey.isNil) {
			otherKey = modelClass.getFullIdColumn()
		} else {
			otherKey = `${modelClass.tableName}.${otherKey}`
		}

		return {
			relation: this.BelongsToOneRelation,
			modelClass: modelClass,
			join: {
				from: `${this.tableName}.${foreignKey}`,
				to: otherKey
			}
		}
	}

	static belongsToMany(modelClass, tableName = null, foreignKey = null, otherKey = null) {
		tableName = tableName || [ this.tableName, modelClass.tableName ].sort().join('_')
		foreignKey = foreignKey || Inflect.foreignKey(modelClass.name)
		otherKey = otherKey || Inflect.foreignKey(this.name)

		return {
			relation: this.ManyToManyRelation,
			modelClass: modelClass,
			join: {
				from: this.getFullIdColumn(),
				through: {
					from: `${tableName}.${otherKey}`,
					to: `${tableName}.${foreignKey}`
				},
				to: modelClass.getFullIdColumn()
			}
		}
	}

	$sync(relation, ids) {
		return (new RelationSynchronizer(this, relation)).sync(ids)
	}

	$relate(relation, ids) {
		return (new RelationSynchronizer(this, relation)).relate(ids)
	}

	$unrelate(relation, ids) {
		return (new RelationSynchronizer(this, relation)).unrelate(ids)
	}

	$parseDatabaseJson(json) {
		json = super.$parseDatabaseJson(json)

		for(const date of this.constructor.getDates()) {
			if(json[date].isNil) {
				continue
			}

			json[date] = this.constructor.asDate(json[date])
		}

		const schema = this.constructor.jsonSchema

		if(schema.isNil || schema.properties.isNil) {
			return json
		}

		for(const field of Object.keys(schema.properties)) {
			if(json[field].isNil) {
				continue
			}

			if(Number.isNaN(json[field])) {
				json[field] = null
				continue
			}

			const property = schema.properties[field]

			// Boolean values can be converted to JSON as "0"/"1", convert back to boolean
			if(property.type === 'boolean') {
				json[field] = as.boolean(json[field])
			}

			// Number values can be converted to JSON as strings, convert back to numbers
			if(property.type === 'number' || property.type === 'float' || property.type === 'double') {
				json[field] = as.float(json[field])
			} else if(property.type === 'integer') {
				json[field] = as.integer(json[field])
			}
		}

		return json
	}

	$formatDatabaseJson(json) {
		json = super.$formatDatabaseJson(json)

		for(const date of this.constructor.getDates()) {
			if(json[date].isNil) {
				continue
			}

			json[date] = this.constructor.asDatabaseDate(json[date])
		}

		return json
	}

	$beforeValidate(jsonSchema, json, opt) {
		const properties = jsonSchema.properties || { }

		for(const field of Object.keys(properties)) {
			const value = json[field]

			if(value.isNil) {
				continue
			}

			const property = properties[field]
			let fieldType = property.type
			let allowsNull = false

			if(!property.anyOf.isNil) {
				fieldType = property.anyOf.map(type => type.type)
			}

			if(Array.isArray(fieldType) && fieldType.length > 1) {
				allowsNull = fieldType.indexOf('null') >= 0
				fieldType = fieldType.filter(type => type !== 'null')[0]
			}

			if(allowsNull && typeof value === 'string' && value.length === 0) {
				json[field] = null
				continue
			}

			if(fieldType === 'boolean') {
				json[field] = as.boolean(json[field])
			} else if(fieldType === 'integer') {
				json[field] = as.integer(json[field])
			} else if(fieldType === 'number' || fieldType === 'float' || fieldType === 'double') {
				json[field] = as.float(json[field])
			}
		}

		return super.$beforeValidate(jsonSchema, json, opt)
	}

	$beforeSave(inserting) {
		return new Promise(resolve => {
			if(this.constructor.useTimestamps) {
				const now = new Date
				this[this.constructor.updatedAt] = now

				if(inserting) {
					this[this.constructor.createdAt] = now
				}
			}

			resolve()
		}).then(() => RelationValidator(this))
	}

	$beforeInsert() {
		return this.$beforeSave(true)
	}

	$beforeUpdate() {
		return this.$beforeSave(false)
	}

	static getDates() {
		if(this.useTimestamps) {
			return [ ...this.dates, this.createdAt, this.updatedAt ]
		}

		return this.dates
	}

	static asDate(value) {
		return new Date(value)
	}

	static asDatabaseDate(value) {
		if(value instanceof Date) {
			return value
		}

		return new Date(value)
	}

	static describe() {
		if(!this.descriptiveName.isNil) {
			return this.descriptiveName
		}

		const name = Inflect.singularize(this.tableName)
		return name.charAt(0).toUpperCase() + name.substring(1)
	}

}
<commit_msg>add option to prevent model identifier from being changed through patch/update operation. Preserves safety feature removed from objection 0.7.0. includes fastrack for 'id' column<commit_after>import { Model as ObjectionModel } from 'objection'

import './Inflect'
import './ModelNotFoundError'
import './RelationSynchronizer'
import './RelationValidator'

const as = require('as-type')

export class Model extends ObjectionModel {
	static descriptiveName = null
	static eager = null
	static eagerFilters = null
	static useTimestamps = true
	static createdAt = 'created_at'
	static updatedAt = 'updated_at'
	static dates = [ ]
	static useIdSafeUpdates = false

	static $$app = null

	static app(app) {
		if(!app.isNil) {
			this.$$app = app
		} else {
			return this.$$app
		}
	}

	$app() {
		return this.constructor.app()
	}

	static findById(id) {
		return this.query().findById(id)
	}

	static findByIdOrFail(id) {
		return this.findById(id).orFail()
	}

	static findByRouteParameter(value) {
		return this.findById(value)
	}

	static routeBind(name, description) {
		description = description || `${name} Value`

		this.app().routes.bind(name, (value, resolve, reject) => {
			this.findByRouteParameter(value).then(row => {
				if(row.isNil) {
					reject(new ModelNotFoundError(this))
					return
				}

				resolve(row)
			})
		}, { swagger: { name, description } })
	}

	static buildRelations() {
		return { }
	}

	static getRelations() {
		if(this.relationMappings.isNil) {
			this.relationMappings = this.buildRelations()
		}

		return super.getRelations()
	}

	static hasOne(modelClass, foreignKey = null, localKey = null) {
		return this._hasOneOrMany(this.HasOneRelation, modelClass, foreignKey, localKey)
	}

	static hasMany(modelClass, foreignKey = null, localKey = null) {
		return this._hasOneOrMany(this.HasManyRelation, modelClass, foreignKey, localKey)
	}

	static _hasOneOrMany(relation, modelClass, foreignKey = null, localKey = null) {
		foreignKey = foreignKey || Inflect.foreignKey(this.name)

		if(localKey.isNil) {
			localKey = this.getFullIdColumn()
		} else {
			localKey = `${this.tableName}.${localKey}`
		}

		return {
			relation: relation,
			modelClass: modelClass,
			join: {
				from: `${modelClass.tableName}.${foreignKey}`,
				to: localKey
			}
		}
	}

	static belongsTo(modelClass, foreignKey = null, otherKey = null) {
		foreignKey = foreignKey || Inflect.foreignKey(modelClass.name)

		if(otherKey.isNil) {
			otherKey = modelClass.getFullIdColumn()
		} else {
			otherKey = `${modelClass.tableName}.${otherKey}`
		}

		return {
			relation: this.BelongsToOneRelation,
			modelClass: modelClass,
			join: {
				from: `${this.tableName}.${foreignKey}`,
				to: otherKey
			}
		}
	}

	static belongsToMany(modelClass, tableName = null, foreignKey = null, otherKey = null) {
		tableName = tableName || [ this.tableName, modelClass.tableName ].sort().join('_')
		foreignKey = foreignKey || Inflect.foreignKey(modelClass.name)
		otherKey = otherKey || Inflect.foreignKey(this.name)

		return {
			relation: this.ManyToManyRelation,
			modelClass: modelClass,
			join: {
				from: this.getFullIdColumn(),
				through: {
					from: `${tableName}.${otherKey}`,
					to: `${tableName}.${foreignKey}`
				},
				to: modelClass.getFullIdColumn()
			}
		}
	}

	$sync(relation, ids) {
		return (new RelationSynchronizer(this, relation)).sync(ids)
	}

	$relate(relation, ids) {
		return (new RelationSynchronizer(this, relation)).relate(ids)
	}

	$unrelate(relation, ids) {
		return (new RelationSynchronizer(this, relation)).unrelate(ids)
	}

	$parseDatabaseJson(json) {
		json = super.$parseDatabaseJson(json)

		for(const date of this.constructor.getDates()) {
			if(json[date].isNil) {
				continue
			}

			json[date] = this.constructor.asDate(json[date])
		}

		const schema = this.constructor.jsonSchema

		if(schema.isNil || schema.properties.isNil) {
			return json
		}

		for(const field of Object.keys(schema.properties)) {
			if(json[field].isNil) {
				continue
			}

			if(Number.isNaN(json[field])) {
				json[field] = null
				continue
			}

			const property = schema.properties[field]

			// Boolean values can be converted to JSON as "0"/"1", convert back to boolean
			if(property.type === 'boolean') {
				json[field] = as.boolean(json[field])
			}

			// Number values can be converted to JSON as strings, convert back to numbers
			if(property.type === 'number' || property.type === 'float' || property.type === 'double') {
				json[field] = as.float(json[field])
			} else if(property.type === 'integer') {
				json[field] = as.integer(json[field])
			}
		}

		return json
	}

	$formatDatabaseJson(json) {
		json = super.$formatDatabaseJson(json)

		for(const date of this.constructor.getDates()) {
			if(json[date].isNil) {
				continue
			}

			json[date] = this.constructor.asDatabaseDate(json[date])
		}

		return json
	}

	$beforeValidate(jsonSchema, json, opt) {
		const properties = jsonSchema.properties || { }

		for(const field of Object.keys(properties)) {
			const value = json[field]

			if(value.isNil) {
				continue
			}

			const property = properties[field]
			let fieldType = property.type
			let allowsNull = false

			if(!property.anyOf.isNil) {
				fieldType = property.anyOf.map(type => type.type)
			}

			if(Array.isArray(fieldType) && fieldType.length > 1) {
				allowsNull = fieldType.indexOf('null') >= 0
				fieldType = fieldType.filter(type => type !== 'null')[0]
			}

			if(allowsNull && typeof value === 'string' && value.length === 0) {
				json[field] = null
				continue
			}

			if(fieldType === 'boolean') {
				json[field] = as.boolean(json[field])
			} else if(fieldType === 'integer') {
				json[field] = as.integer(json[field])
			} else if(fieldType === 'number' || fieldType === 'float' || fieldType === 'double') {
				json[field] = as.float(json[field])
			}
		}

		return super.$beforeValidate(jsonSchema, json, opt)
	}

	$beforeSave(inserting) {
		return new Promise(resolve => {
			if(this.constructor.useTimestamps) {
				const now = new Date
				this[this.constructor.updatedAt] = now

				if(inserting) {
					this[this.constructor.createdAt] = now
				}
			}

			resolve()
		}).then(() => RelationValidator(this))
	}

	$beforeInsert() {
		return this.$beforeSave(true)
	}

	$beforeUpdate() {
		if(this.constructor.useIdSafeUpdates) {
			const cols = this.constructor.getIdColumnArray()

			if(cols.length === 1) {
				delete this[cols[0]]
			} else {
				for(let i = 0, l = cols.length; i < l; i++) {
					delete this[cols[i]]
				}
			}
		}

		return this.$beforeSave(false)
	}

	static getDates() {
		if(this.useTimestamps) {
			return [ ...this.dates, this.createdAt, this.updatedAt ]
		}

		return this.dates
	}

	static asDate(value) {
		return new Date(value)
	}

	static asDatabaseDate(value) {
		if(value instanceof Date) {
			return value
		}

		return new Date(value)
	}

	static describe() {
		if(!this.descriptiveName.isNil) {
			return this.descriptiveName
		}

		const name = Inflect.singularize(this.tableName)
		return name.charAt(0).toUpperCase() + name.substring(1)
	}

}
<|endoftext|>


<commit_before>
define( [ "slick/core/Dataview" ], function() {

	var html =
			"
" +
			"
" +
				"<button class='pager-prev' disabled='disabled'></button>" +
				"<button class='pager-next' disabled='disabled'></button>" +
			"
" +

			"
" +
				"<input type='text' class='pager-current' maxlength='5'>" +
				"<button disabled='disabled' class='pager-total'></button>" +
			"
" +

			"

" +

			"
" +
				"" +
					"<select></select>" +
				"" +
			"
" +
			"
"

	, defaults = {

		container: undefined,

		pagingInfo: {
			pageSize: 50,
			pageNum: 0,

			sizes: [ 50, 100 ]
		}
	};

	return function( $G, dataView, options ) {

		var settings = $.extend( true, {}, defaults, options || {} )

		, container = $( html )

		, current = container.find( "input.pager-current" )
		, size = container.find( "select:first" )
		, total = container.find( "button.pager-total" )

		, sort = {

			local: function( e, args ) {

				var field = args.sortCol.field;

				dataView.sort( function( a, b ) {
					var x = a[ field ], y = b[ field ];

					return (x === y ? 0 : (x > y ? 1 : -1));
				}, args.sortAsc );
			},

			ajax: function( e, args ) {

				pager( {
					pageSize: +size.val(),
					pageNum: current.val()
				}, args.sortCol.field, args.sortAsc );
			}
		}

		/** Update the paging info to UI */
		, uiRefresh = function( pagingInfo ) {

			var

			  prev = container.find( ".pager-prev" ),
			  next = container.find( ".pager-next" ),

			  value = pagingInfo.pageNum + 1,
			  max = pagingInfo.totalPages || 1;

			/** Clear the last state, prevent has been disabled after the size change */
			prev.removeAttr( "disabled" ), next.removeAttr( "disabled" );

			(value < max && value > 1) && ( prev.removeAttr( "disabled" ), next.removeAttr( "disabled" ) );

			value === 1 && prev.attr( "disabled", "disabled" );
			value === max && next.attr( "disabled", "disabled" );

			$G.resetActiveCell();
			$G.setSortColumns( [] );

			current.val( value );
			size.val( pagingInfo.pageSize );
			total.html( max ).attr( "data-total", max );
		}

		/** A function that implement for paging */
		, pager;

		for ( var sizes = settings.pagingInfo.sizes, length = sizes.length, i = 0; i < length; ) {

			/** Right now DOM is not in the render tree, so there is no reflow */
			size.append( "<option value=" + sizes[ i ] + ">" + sizes[ i++ ] + "</option>" );
		}

		$G.onSort.subscribe( function( e, args ) {

			$G.resetActiveCell();
		} );

		/** All operations in local */
		if ( !settings.ajaxOptions ) {

			dataView.setItems( settings.data );

			/** Skip the first notify */
			dataView.setRefreshHints( { isFilterUnchanged: true } );
			dataView.setPagingOptions( settings.pagingInfo );

			dataView.onRowCountChanged.subscribe( function( e, args ) {

				$G.updateRowCount();
				$G.render();
			} );

			dataView.onRowsChanged.subscribe( function( e, args ) {

				$G.invalidateRows( args.rows );
				$G.render();
			} );

			dataView.onPagingInfoChanged.subscribe( function( e, args ) {
				uiRefresh( dataView.getPagingInfo() );
			} );

			$G.onSort.subscribe( sort[ "local" ] );

			/** The implementation of local paging */
			pager = dataView.setPagingOptions;

			pager( dataView.getPagingInfo() );
		} else {

			/** All operations in server-side */

			var
			  request,
			  ajaxOptions = settings.ajaxOptions,
			  loading = $( "

" );

			if ( !ajaxOptions.serviceName ) {

				throw "Service name cann't be null";
			}

			$( $G.getContainerNode() ).append( loading );

			pager = function( pagingInfo, field, asc ) {

				var VO = { wpf_dup_token: +new Date() + Math.random() };

				VO[ ajaxOptions.moduleName || (ajaxOptions.moduleName = "gridElement_kiss") ] = JSON.stringify( $.extend( {}, {

					pageVO: {
						curPage: pagingInfo.pageNum,
						incrementalPaging: false,
						pageSize: pagingInfo.pageSize,
						remoteSortField: field || "",
						remoteSortOrder: asc === void 0 ? "" : (asc ? "asc" : "desc"),
						totalRows: -1
					}
				}, ajaxOptions.VO ) );

				/** Keep one ajax instance */
				request && request.abort();

				request = $.ajax( {

					beforeSend: function() { loading.fadeIn(); },

					data: {
						name: ajaxOptions.serviceName,
						params: JSON.stringify( $.extend( {}, VO, ajaxOptions.params || {} ) )
					}
				} )

				.done( function( data ) {

					try {

						data = eval( "(" + data + ")" );
						data = data[ "result" ][ ajaxOptions.moduleName ];
						data = JSON.parse( data );

						dataView.setItems( data.result );

						/** Render all rows */
						$G.invalidate();

						with ( data.pageVO ) {
							uiRefresh( { pageNum: curPage, pageSize: pageSize, totalPages: totalPages } );
						}
					} catch ( ex ) {

						throw "Call the service '" + ajaxOptions.serviceName + "' failed:\n" + data;
					}
				} )

				.always( function() {
					loading.fadeOut( 100 );
				} );
			};

			$( $G.getContainerNode() ).append( loading );

			$G.onSort.subscribe( sort[ "ajax" ] );

			pager( settings.pagingInfo );
		}

		container

		.delegate( ".pager-prev", "click", function( e ) {

			var value = +current.val();

			e.stopImmediatePropagation();
			e.preventDefault();

			value > 1 && pager( { pageNum: value - 2 } );
		} )

		.delegate( ".pager-next", "click", function( e ) {

			var value = +current.val()

			, max = +total.attr( "data-total" );

			e.stopImmediatePropagation();
			e.preventDefault();

			value <= max && pager( { pageNum: value } );
		} )

		.delegate( "select", "change", function( e ) {

			pager( { pageSize: +$( this ).val() } );
			e.stopImmediatePropagation();
		} )

		.delegate( "input.pager-current", "keyup", function( e ) {

			var value = +current.val() || 1
			, max = +total.attr( "data-total" ) || 1;

			switch ( e.keyCode ) {

				case 38:
					++value <= max
						? current.val( value )
						: --value;
					break;

				case 40:
					--value >= 1
						? current.val( value )
						: ++value;
					break;

				case 13:

					if ( value <= max && value >= 1 ) {

						current.blur();
						pager( { pageNum: value, pageSize: +size.val() } );
					} else {
						current.select();
					}
					break;
			}

			e.stopImmediatePropagation();
		} );

		$( $G.getContainerNode() ).after( container );
	};
} );

<commit_msg>Update Pager.js<commit_after>
define( [ "slick/core/Dataview" ], function() {

	var html =
			"
" +
			"
" +
				"<button class='pager-prev' disabled='disabled'></button>" +
				"<button class='pager-next' disabled='disabled'></button>" +
			"
" +

			"
" +
				"<input type='text' class='pager-current' maxlength='5' value='1'>" +
				"<button disabled='disabled' class='pager-total'>1</button>" +
			"
" +

			"

" +

			"
" +
				"" +
					"<select></select>" +
				"" +
			"
" +
			"
"

	, defaults = {

		container: undefined,

		pagingInfo: {
			pageSize: 50,
			pageNum: 0,

			sizes: [ 50, 100 ]
		}
	};

	return function( $G, dataView, options ) {

		var settings = $.extend( true, {}, defaults, options || {} )

		, container = $( html )

		, current = container.find( "input.pager-current" )
		, size = container.find( "select:first" )
		, total = container.find( "button.pager-total" )

		, sort = {

			local: function( e, args ) {

				var field = args.sortCol.field;

				dataView.sort( function( a, b ) {
					var x = a[ field ], y = b[ field ];

					return (x === y ? 0 : (x > y ? 1 : -1));
				}, args.sortAsc );
			},

			ajax: function( e, args ) {

				pager( {
					pageSize: +size.val(),
					pageNum: +current.val()
				}, 0, args.sortCol.field, args.sortAsc );
			}
		}

		/** Update the paging info to UI */
		, uiRefresh = function( pagingInfo ) {

			var

			  prev = container.find( ".pager-prev" ),
			  next = container.find( ".pager-next" ),

			  value = pagingInfo.pageNum + 1,
			  max = pagingInfo.totalPages || 1;

			/** Clear the last state, prevent has been disabled after the size change */
			prev.removeAttr( "disabled" ), next.removeAttr( "disabled" );

			(value < max && value > 1) && ( prev.removeAttr( "disabled" ), next.removeAttr( "disabled" ) );

			value === 1 && prev.attr( "disabled", "disabled" );
			value === max && next.attr( "disabled", "disabled" );

			$G.resetActiveCell();

			current.val( value );
			size.val( pagingInfo.pageSize );
			total.html( max ).attr( "data-total", max );
		}

		/** A function that implement for paging */
		, pager;

		for ( var sizes = settings.pagingInfo.sizes, length = sizes.length, i = 0; i < length; ) {

			/** Right now DOM is not in the render tree, so there is no reflow */
			size.append( "<option value=" + sizes[ i ] + ">" + sizes[ i++ ] + "</option>" );
		}

		/** All operations in local */
		if ( !settings.ajaxOptions ) {

			dataView.setItems( settings.data );

			/** Skip the first notify */
			dataView.setRefreshHints( { isFilterUnchanged: true } );
			dataView.setPagingOptions( settings.pagingInfo );

			dataView.onRowCountChanged.subscribe( function( e, args ) {

				$G.updateRowCount();
				$G.render();
			} );

			dataView.onRowsChanged.subscribe( function( e, args ) {

				$G.invalidateRows( args.rows );
				$G.render();
			} );

			dataView.onPagingInfoChanged.subscribe( function( e, args ) {
				uiRefresh( dataView.getPagingInfo() );
			} );

			$G.onSort.subscribe( sort[ "local" ] );

			/** The implementation of local paging */
			pager = dataView.setPagingOptions;

			pager( dataView.getPagingInfo(), 1 );
		} else {

			/** All operations in server-side */

			var
			  request,
			  ajaxOptions = settings.ajaxOptions,
			  loading = $( "

" );

			if ( !ajaxOptions.serviceName ) {

				throw "Service name cann't be null";
			}

			$( $G.getContainerNode() ).append( loading );

			/** In SCM the 'pageNum' start from 1, so you should specify an offset to patch it */
			pager = function( pagingInfo, offset, field, asc ) {

				var VO = { wpf_dup_token: +new Date() + Math.random() };

				VO[ ajaxOptions.moduleName || (ajaxOptions.moduleName = "gridElement_kiss") ] = JSON.stringify( $.extend( {}, {

					pageVO: {
						curPage: +pagingInfo.pageNum + (offset || 0),
						incrementalPaging: false,
						pageSize: +pagingInfo.pageSize,
						remoteSortField: field || "",
						remoteSortOrder: asc === void 0 ? "" : (asc ? "asc" : "desc"),
						totalRows: -1
					}
				}, ajaxOptions.VO ) );

				/** Keep one ajax instance */
				request && request.abort();

				request = $.ajax( {

					beforeSend: function() {
						/** Show the loading */
						loading.fadeIn();
					},

					data: {
						name: ajaxOptions.serviceName,
						params: JSON.stringify( $.extend( {}, VO, ajaxOptions.params || {} ) )
					}
				} )

				.done( function( data ) {

					try {

						data = eval( "(" + data + ")" );
						data = data[ "result" ][ ajaxOptions.moduleName ];
						data = JSON.parse( data );

						dataView.setItems( data.result );

						/** Render all rows */
						$G.invalidate();

						with ( data.pageVO ) {
							uiRefresh( { pageNum: curPage - 1, pageSize: pageSize, totalPages: totalPages } );
						}
					} catch ( ex ) {

						throw "Call the service '" + ajaxOptions.serviceName + "' failed:\n" + data;
					}
				} )

				.always( function() {
					loading.fadeOut( 100 );
				} );
			};

			$( $G.getContainerNode() ).append( loading );

			$G.onSort.subscribe( sort[ "ajax" ] );

			pager( settings.pagingInfo, 1 );
		}

		container

		.delegate( ".pager-prev", "click", function( e ) {

			var value = +current.val();

			e.stopImmediatePropagation();
			e.preventDefault();

			$G.setSortColumns( [] );

			value > 1 && pager( { pageNum: value - 2, pageSize: +size.val() } );
		} )

		.delegate( ".pager-next", "click", function( e ) {

			var value = +current.val()

			, max = +total.attr( "data-total" );

			e.stopImmediatePropagation();
			e.preventDefault();

			$G.setSortColumns( [] );

			value <= max && pager( { pageNum: value, pageSize: +size.val() }, 1 );
		} )

		.delegate( "select", "change", function( e ) {

			pager( { pageSize: +$( this ).val(), pageNum: 0 }, 1 );

			e.stopImmediatePropagation();

			$G.setSortColumns( [] );
		} )

		.delegate( "input.pager-current", "keyup", function( e ) {

			var value = +current.val() || 1
			, max = +total.attr( "data-total" ) || 1;

			switch ( e.keyCode ) {

				case 38:
					++value <= max
						? current.val( value )
						: --value;
					break;

				case 40:
					--value >= 1
						? current.val( value )
						: ++value;
					break;

				case 13:

					if ( value <= max && value >= 1 ) {

						current.blur();
						pager( { pageNum: value, pageSize: +size.val() }, -1 );
					} else {
						current.select();
					}
					break;
			}

			e.stopImmediatePropagation();

			$G.setSortColumns( [] );
		} )

		.delegate( "div.pager-refresh", "click", function( e ) {

			pager( {
				pageSize: +size.val(),
				pageNum: +current.val()
			} );

			$G.setSortColumns( [] );

			e.stopPropagation();
		} );

		$( $G.getContainerNode() ).after( container );
	};
} );

<|endoftext|>


<commit_before>// This is called on every message. It can reject a message, or transform it, or let it through.

export default class MessageProxy {
	lastMessage = {}
	spamInterval = 1000

	sniff(message, eventName) {
		// Types that represent "actual" data and not events
		const message_types = ["text","audio","document","photo","sticker","video","voice","contact","location"];
		// Let events through
		if (message_types.indexOf(eventName) == -1) return Promise.resolve(message);

		const now = (new Date()).getTime();
		const author = message.chat.username;
		var rejected = false;
		const lastMessage = this.lastMessage[author];
		// The difference is in milliseconds.
		if (lastMessage && ((now - lastMessage) < this.spamInterval))
			rejected = true;

		this.lastMessage[author] = now;
		if (rejected)
			return Promise.reject();
		else
			return Promise.resolve(message);
	}
}<commit_msg>Fixed a branch mess<commit_after>// This is called on every message. It can reject a message, or transform it, or let it through.

export default class MessageProxy {
	lastMessage = {}
	spamInterval = 1000

	sniff(message, eventName) {
		// Types that represent "actual" data and not events
		const message_types = ["text","audio","document","photo","sticker","video","voice","contact","location"];
		// Let events through
		if (message_types.indexOf(eventName) == -1) return Promise.resolve(message);

		const now = (new Date()).getTime();
		const author = message.from.id;
		var rejected = false;
		const lastMessage = this.lastMessage[author];
		// The difference is in milliseconds.
		if (lastMessage && ((now - lastMessage) < this.spamInterval))
			rejected = true;

		this.lastMessage[author] = now;
		if (rejected)
			return Promise.reject();
		else
			return Promise.resolve(message);
	}
}<|endoftext|>


<commit_before>const path = require('path');
const {statSync, readdirSync} = require('fs');

const {execSync} = require('./exec');

/**
 * Get single packages full path
 * @param  {string} pkg specific package name or full path
 * @param  {string} packagesDir path where packages are stored
 * @returns {array} array of full path strings
 */
function getPackage(pkg, packagesDir = 'packages/node_modules/@ciscospark') {
  // check if this is a valid path
  try {
    if (statSync(pkg).isDirectory()) {
      const fullpath = path.resolve(pkg);
      statSync(path.resolve(fullpath, 'package.json'));
      return fullpath;
    }
  }
  catch (err) {
    if (err.code === 'ENOENT') {
      return getPackage(path.resolve(packagesDir, pkg));
    }
  }
  return false;
}

/**
 * Starts a specific package with Webpack Dev Server
 * @param  {string} pkgName
 * @param  {string} pkgPath
 * @returns {undefined}
 */
function runInPackage({
  constructCommand,
  commandName,
  pkgName,
  pkgPath
}) {
  const outputPkgPath = getPackage(pkgName || pkgPath);
  if (outputPkgPath) {
    try {
      console.info(`${commandName} ${pkgName} ...`);
      const command = constructCommand(outputPkgPath);
      execSync(command)
        .catch((error) => {
          console.error(error.stdout);
          throw new Error(`Error when running ${commandName} on ${pkgName}`, error);
        });
    }
    catch (err) {
      throw new Error(`Error ${commandName} ${pkgName} package`, err);
    }
  }
}

/**
 * Get a list of all package paths
 * @param  {string} packagesDir path where packages are stored
 * @returns {array} array of full path strings
 */
function getAllPackagePaths(packagesDir = 'packages/node_modules/@ciscospark') {
  return readdirSync(packagesDir).reduce((acc, packagePath) => {
    const pkg = getPackage(packagePath, packagesDir);
    if (pkg) {
      acc.push(pkg);
    }
    return acc;
  }, []);
}

function getAllPackages(omitPrivate) {
  let pkgPaths = getAllPackagePaths();
  if (omitPrivate) {
    pkgPaths = pkgPaths.filter((pkgPath) => !require(path.resolve(pkgPath, 'package.json')).private);
  }
  return pkgPaths.map((pkgPath) => require(path.resolve(pkgPath, 'package.json')).name);
}

function getWidgetPackages() {
  const pkgPaths = getAllPackagePaths();
  return pkgPaths
    .filter((pkgPath) => {
      const pkgName = require(path.resolve(pkgPath, 'package.json')).name;
      return pkgName.startsWith('@ciscospark/widget') && !pkgName.startsWith('@ciscospark/widget-base');
    });
}

/**
 * Starts a specific package with Webpack Dev Server
 * @param  {string} pkgName Name of package without @ciscospark (e.g. react-component-button)
 * @param  {string} pkgPath Full path of package
 * @returns {Promise}
 */
function startPackage(pkgName, pkgPath) {
  return runInPackage({
    constructCommand: (targetPath) => `webpack-dev-server --config scripts/webpack/webpack.dev.babel.js --hot --inline --history-api-fallback --context ${path.resolve(targetPath, 'src')}`,
    commandName: 'Start Package',
    pkgName,
    pkgPath
  });
}

module.exports = {
  getWidgetPackages,
  getPackage,
  getAllPackages,
  getAllPackagePaths,
  runInPackage,
  startPackage
};
<commit_msg>chore(tooling): Remove old widget-base check<commit_after>const path = require('path');
const {statSync, readdirSync} = require('fs');

const {execSync} = require('./exec');

/**
 * Get single packages full path
 * @param  {string} pkg specific package name or full path
 * @param  {string} packagesDir path where packages are stored
 * @returns {array} array of full path strings
 */
function getPackage(pkg, packagesDir = 'packages/node_modules/@ciscospark') {
  // check if this is a valid path
  try {
    if (statSync(pkg).isDirectory()) {
      const fullpath = path.resolve(pkg);
      statSync(path.resolve(fullpath, 'package.json'));
      return fullpath;
    }
  }
  catch (err) {
    if (err.code === 'ENOENT') {
      return getPackage(path.resolve(packagesDir, pkg));
    }
  }
  return false;
}

/**
 * Starts a specific package with Webpack Dev Server
 * @param  {string} pkgName
 * @param  {string} pkgPath
 * @returns {undefined}
 */
function runInPackage({
  constructCommand,
  commandName,
  pkgName,
  pkgPath
}) {
  const outputPkgPath = getPackage(pkgName || pkgPath);
  if (outputPkgPath) {
    try {
      console.info(`${commandName} ${pkgName} ...`);
      const command = constructCommand(outputPkgPath);
      execSync(command)
        .catch((error) => {
          console.error(error.stdout);
          throw new Error(`Error when running ${commandName} on ${pkgName}`, error);
        });
    }
    catch (err) {
      throw new Error(`Error ${commandName} ${pkgName} package`, err);
    }
  }
}

/**
 * Get a list of all package paths
 * @param  {string} packagesDir path where packages are stored
 * @returns {array} array of full path strings
 */
function getAllPackagePaths(packagesDir = 'packages/node_modules/@ciscospark') {
  return readdirSync(packagesDir).reduce((acc, packagePath) => {
    const pkg = getPackage(packagePath, packagesDir);
    if (pkg) {
      acc.push(pkg);
    }
    return acc;
  }, []);
}

function getAllPackages(omitPrivate) {
  let pkgPaths = getAllPackagePaths();
  if (omitPrivate) {
    pkgPaths = pkgPaths.filter((pkgPath) => !require(path.resolve(pkgPath, 'package.json')).private);
  }
  return pkgPaths.map((pkgPath) => require(path.resolve(pkgPath, 'package.json')).name);
}

function getWidgetPackages() {
  const pkgPaths = getAllPackagePaths();
  return pkgPaths
    .filter((pkgPath) => {
      const pkgName = require(path.resolve(pkgPath, 'package.json')).name;
      return pkgName.startsWith('@ciscospark/widget');
    });
}

/**
 * Starts a specific package with Webpack Dev Server
 * @param  {string} pkgName Name of package without @ciscospark (e.g. react-component-button)
 * @param  {string} pkgPath Full path of package
 * @returns {Promise}
 */
function startPackage(pkgName, pkgPath) {
  return runInPackage({
    constructCommand: (targetPath) => `webpack-dev-server --config scripts/webpack/webpack.dev.babel.js --hot --inline --history-api-fallback --context ${path.resolve(targetPath, 'src')}`,
    commandName: 'Start Package',
    pkgName,
    pkgPath
  });
}

module.exports = {
  getWidgetPackages,
  getPackage,
  getAllPackages,
  getAllPackagePaths,
  runInPackage,
  startPackage
};
<|endoftext|>


<commit_before>/**
 * @author: Dennis Hernández
 * @webSite: http://djhvscf.github.io/Blog
 * @version: v1.0.0
 */

!function ($) {

    'use strict';

    var sprintf = function (str) {
        var args = arguments,
            flag = true,
            i = 1;

        str = str.replace(/%s/g, function () {
            var arg = args[i++];

            if (typeof arg === 'undefined') {
                flag = false;
                return '';
            }
            return arg;
        });
        return flag ? str : '';
    };

    var getFieldIndex = function (columns, field) {
        var index = -1;

        $.each(columns, function (i, column) {
            if (column.field === field) {
                index = i;
                return false;
            }
            return true;
        });
        return index;
    };

    var calculateObjectValue = function (self, name, args, defaultValue) {
        if (typeof name === 'string') {
            // support obj.func1.func2
            var names = name.split('.');

            if (names.length > 1) {
                name = window;
                $.each(names, function (i, f) {
                    name = name[f];
                });
            } else {
                name = window[name];
            }
        }
        if (typeof name === 'object') {
            return name;
        }
        if (typeof name === 'function') {
            return name.apply(self, args);
        }
        return defaultValue;
    };

    $.extend($.fn.bootstrapTable.defaults, {
        filterControl: false,
        onColumnSearch: function (field, text) {
            return false;
        }
    });

    $.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
        filterControl: undefined
    });

    $.extend($.fn.bootstrapTable.Constructor.EVENTS, {
        'column-search.bs.table': 'onColumnSearch'
    });

    var BootstrapTable = $.fn.bootstrapTable.Constructor,
        _initHeader = BootstrapTable.prototype.initHeader,
        _initBody = BootstrapTable.prototype.initBody,
        _initSearch = BootstrapTable.prototype.initSearch;

    BootstrapTable.prototype.initHeader = function () {
        _initHeader.apply(this, Array.prototype.slice.apply(arguments));

        if (!this.options.filterControl) {
            return;
        }

        var addedFilterControl = false,
            that = this,
            isVisible,
            html,
            timeoutId = 0;

        $.each(this.options.columns, function (i, column) {
            isVisible = 'hidden';
            html = [];

            if (!column.filterControl) {
                html.push('

');
            } else {
                html.push('
');

                if (column.filterControl && column.searchable) {
                    addedFilterControl = true;
                    isVisible = 'visible'
                }
                switch (column.filterControl.toLowerCase()) {
                    case 'input' :
                        html.push(sprintf('<input type="text" class="form-control" style="width: 100%; visibility: %s">', isVisible));
                        break;
                    case 'select':
                        html.push(sprintf('<select class="%s form-control" style="width: 100%; visibility: %s"></select>',
                            column.field, isVisible))
                        break;
                }
            }

            that.$header.find(sprintf('.th-inner:contains("%s")', column.title)).next().append(html.join(''));
        });

        if (addedFilterControl) {
            this.$header.off('keyup', 'input').on('keyup', 'input', function (event) {
                clearTimeout(timeoutId);
                timeoutId = setTimeout(function () {
                    that.onColumnSearch(event);
                }, that.options.searchTimeOut);
            });

            this.$header.off('change', 'select').on('change', 'select', function (event) {
                clearTimeout(timeoutId);
                timeoutId = setTimeout(function () {
                    that.onColumnSearch(event);
                }, that.options.searchTimeOut);
            });
        } else {
            this.$header.find('.filterControl').hide();
        }
    };

    BootstrapTable.prototype.initBody = function () {
        _initBody.apply(this, Array.prototype.slice.apply(arguments));

        var that = this,
            data = this.getData();

        for (var i = this.pageFrom - 1; i < this.pageTo; i++) {
            var key,
                item = data[i];

            $.each(this.header.fields, function (j, field) {
                var value = item[field],
                    column = that.options.columns[getFieldIndex(that.options.columns, field)];

                value = calculateObjectValue(that.header,
                    that.header.formatters[j], [value, item, i], value);

                if ((!column.checkbox) || (!column.radio)) {
                    if (column.filterControl !== undefined && column.filterControl.toLowerCase() === 'select'
                        && column.searchable) {

                        var selectControl = $('.' + column.field),
                            iOpt = 0,
                            exitsOpt = false,
                            options;
                        if (selectControl !== undefined) {
                            options = selectControl.get(0).options;

                            if (options.length === 0) {

                                //Added the default option
                                selectControl.append($("<option></option>")
                                    .attr("value", '')
                                    .text(''));

                                selectControl.append($("<option></option>")
                                    .attr("value", value)
                                    .text(value));
                            } else {
                                for (; iOpt < options.length; iOpt++) {
                                    if (options[iOpt].value === value) {
                                        exitsOpt = true;
                                        break;
                                    }
                                }

                                if (!exitsOpt) {
                                    selectControl.append($("<option></option>")
                                        .attr("value", value)
                                        .text(value));
                                }
                            }
                        }
                    }
                }
            });
        }
    };

    BootstrapTable.prototype.initSearch = function () {
        _initSearch.apply(this, Array.prototype.slice.apply(arguments));

        var that = this;
        var fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial;

        //Check partial column filter
        this.data = fp ? $.grep(this.data, function (item, i) {
            for (var key in fp) {
                var fval = fp[key].toLowerCase();
                var value = item[key];
                value = calculateObjectValue(that.header,
                    that.header.formatters[$.inArray(key, that.header.fields)],
                    [value, item, i], value);

                if (!($.inArray(key, that.header.fields) !== -1 &&
                    (typeof value === 'string' || typeof value === 'number') &&
                    (value + '').toLowerCase().indexOf(fval) !== -1)) {
                    return false;
                }
            }
            return true;
        }) : this.data;
    };

    BootstrapTable.prototype.onColumnSearch = function (event) {
        var text = $.trim($(event.currentTarget).val());
        var $field = $(event.currentTarget).parent().parent().parent().data('field')

        if ($.isEmptyObject(this.filterColumnsPartial)) {
            this.filterColumnsPartial = {};
        }
        if (text) {
            this.filterColumnsPartial[$field] = text;
        } else {
            delete this.filterColumnsPartial[$field];
        }

        this.options.pageNumber = 1;
        this.onSearch(event);
        this.updatePagination();
        this.trigger('column-search', $field, text);
    };
}(jQuery);<commit_msg>Imporve the filter-control extension<commit_after>/**
 * @author: Dennis Hernández
 * @webSite: http://djhvscf.github.io/Blog
 * @version: v1.0.0
 */

!function ($) {

    'use strict';

    var sprintf = function (str) {
        var args = arguments,
            flag = true,
            i = 1;

        str = str.replace(/%s/g, function () {
            var arg = args[i++];

            if (typeof arg === 'undefined') {
                flag = false;
                return '';
            }
            return arg;
        });
        return flag ? str : '';
    };

    var getFieldIndex = function (columns, field) {
        var index = -1;

        $.each(columns, function (i, column) {
            if (column.field === field) {
                index = i;
                return false;
            }
            return true;
        });
        return index;
    };

    var calculateObjectValue = function (self, name, args, defaultValue) {
        if (typeof name === 'string') {
            // support obj.func1.func2
            var names = name.split('.');

            if (names.length > 1) {
                name = window;
                $.each(names, function (i, f) {
                    name = name[f];
                });
            } else {
                name = window[name];
            }
        }
        if (typeof name === 'object') {
            return name;
        }
        if (typeof name === 'function') {
            return name.apply(self, args);
        }
        return defaultValue;
    };

    $.extend($.fn.bootstrapTable.defaults, {
        filterControl: false,
        onColumnSearch: function (field, text) {
            return false;
        }
    });

    $.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
        filterControl: undefined
    });

    $.extend($.fn.bootstrapTable.Constructor.EVENTS, {
        'column-search.bs.table': 'onColumnSearch'
    });

    var BootstrapTable = $.fn.bootstrapTable.Constructor,
        _initHeader = BootstrapTable.prototype.initHeader,
        _initBody = BootstrapTable.prototype.initBody,
        _initSearch = BootstrapTable.prototype.initSearch;

    BootstrapTable.prototype.initHeader = function () {
        _initHeader.apply(this, Array.prototype.slice.apply(arguments));

        if (!this.options.filterControl) {
            return;
        }

        var addedFilterControl = false,
            that = this,
            isVisible,
            html,
            timeoutId = 0;

        $.each(this.options.columns, function (i, column) {
            isVisible = 'hidden';
            html = [];

            if (!column.filterControl) {
                html.push('

');
            } else {
                html.push('
');

                if (column.filterControl && column.searchable) {
                    addedFilterControl = true;
                    isVisible = 'visible'
                }
                switch (column.filterControl.toLowerCase()) {
                    case 'input' :
                        html.push(sprintf('<input type="text" class="form-control" style="width: 100%; visibility: %s">', isVisible));
                        break;
                    case 'select':
                        html.push(sprintf('<select class="%s form-control" style="width: 100%; visibility: %s"></select>',
                            column.field, isVisible))
                        break;
                }
            }

            that.$header.find(sprintf('.th-inner:contains("%s")', column.title)).next().append(html.join(''));
        });

        if (addedFilterControl) {
            this.$header.off('keyup', 'input').on('keyup', 'input', function (event) {
                clearTimeout(timeoutId);
                timeoutId = setTimeout(function () {
                    that.onColumnSearch(event);
                }, that.options.searchTimeOut);
            });

            this.$header.off('change', 'select').on('change', 'select', function (event) {
                clearTimeout(timeoutId);
                timeoutId = setTimeout(function () {
                    that.onColumnSearch(event);
                }, that.options.searchTimeOut);
            });
        } else {
            this.$header.find('.filterControl').hide();
        }
    };

    BootstrapTable.prototype.initBody = function () {
        _initBody.apply(this, Array.prototype.slice.apply(arguments));

        var that = this,
            data = this.getData();

        for (var i = this.pageFrom - 1; i < this.pageTo; i++) {
            var key,
                item = data[i];

            $.each(this.header.fields, function (j, field) {
                var value = item[field],
                    column = that.options.columns[getFieldIndex(that.options.columns, field)];

                value = calculateObjectValue(that.header,
                    that.header.formatters[j], [value, item, i], value);

                if ((!column.checkbox) || (!column.radio)) {
                    if (column.filterControl !== undefined && column.filterControl.toLowerCase() === 'select' && column.searchable) {
                        var selectControl = $('.' + column.field),
                            iOpt = 0,
                            existsOpt = false,
                            options;
                        if (selectControl !== undefined) {
                            options = selectControl.get(0).options;

                            if (options.length === 0) {
                                //Added the default option
                                selectControl.append($("<option></option>").attr("value", '').text(''));
                            }

                            for (; iOpt < options.length; iOpt++) {
                                if (options[iOpt].value === value) {
                                    existsOpt = true;
                                    break;
                                }
                            }

                            if (!existsOpt) {
                                selectControl.append($("<option></option>")
                                    .attr("value", value)
                                    .text(value));
                            }
                        }
                    }
                }
            });
        }
    };

    BootstrapTable.prototype.initSearch = function () {
        _initSearch.apply(this, Array.prototype.slice.apply(arguments));

        var that = this;
        var fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial;

        //Check partial column filter
        this.data = fp ? $.grep(this.data, function (item, i) {
            for (var key in fp) {
                var fval = fp[key].toLowerCase();
                var value = item[key];
                value = calculateObjectValue(that.header,
                    that.header.formatters[$.inArray(key, that.header.fields)],
                    [value, item, i], value);

                if (!($.inArray(key, that.header.fields) !== -1 &&
                    (typeof value === 'string' || typeof value === 'number') &&
                    (value + '').toLowerCase().indexOf(fval) !== -1)) {
                    return false;
                }
            }
            return true;
        }) : this.data;
    };

    BootstrapTable.prototype.onColumnSearch = function (event) {
        var text = $.trim($(event.currentTarget).val());
        var $field = $(event.currentTarget).parent().parent().parent().data('field')

        if ($.isEmptyObject(this.filterColumnsPartial)) {
            this.filterColumnsPartial = {};
        }
        if (text) {
            this.filterColumnsPartial[$field] = text;
        } else {
            delete this.filterColumnsPartial[$field];
        }

        this.options.pageNumber = 1;
        this.onSearch(event);
        this.updatePagination();
        this.trigger('column-search', $field, text);
    };
}(jQuery);<|endoftext|>


<commit_before>/*

*/

var log = {
 error: function(info) {
  console.error(info)
 }
}

function getId(info) {
 return document.getElementById(info);
}

function getClasses(info) {
 return document.getElementsByClassName(info);
}

function getFirstClass(info) {
 return document.getElementsByClassName(info)[0];
}

function getElements(info) {
 if (document.getElementsByTagName(info)) {
 return document.getElementsByTagName(info);
 } else {
  log.error('Couldn\'t find selected elements');
 }
}
<commit_msg>Update simpleScript.js<commit_after>/*

*/

var log = {
 error: function(info) {
  console.error(info)
 }
}

function newElement(info) {
 document.createElement(info)
}

function getId(info) {
 return document.getElementById(info);
}

function getClasses(info) {
 return document.getElementsByClassName(info);
}

function getFirstClass(info) {
 return document.getElementsByClassName(info)[0];
}

function getElements(info) {
 if (document.getElementsByTagName(info)) {
  return document.getElementsByTagName(info);
 } else {
  log.error('Couldn\'t find selected elements');
 }
}

function getFirstElement(info) {
 return document.getElementById(info);
}

function checkUpdate() {
 a = newElement('iframe')
 a.src = 'https://darkheart527.github.io/domain/simpleScriptUpdate.html'
 a.style.width = '100%'
 a.style.height = '100%'
 a.style = 'position:absolute;top: 0px; left: 0px;'
 log.info('Update Checked - Page Modified And Showed')
}
<|endoftext|>


<commit_before>//DEBUG boolean, should debug console prints be shown
var DEBUG = true;

//boolean values as objects so that they are mutable form inside the button listener
var showingPrimarySchools = {value: false};
var showingSecondarySchools = {value: false};

function redraw() {
  clean(); //remove everything

  if(DEBUG) {
	console.log("Showing Primary Schools: " + showingPrimarySchools.value);
	console.log("Showing Secondary Schools: " + showingSecondarySchools.value);
  }

  if(showingPrimarySchools.value) { //if supposed to be drawing; draw.
    draw("primary");
  }

  if(showingSecondarySchools.value) {
    draw("secondary");
  }
}

//draw all schools of the given type
//types "secondary", "primary"
function draw(type) {
  for(var key in schools){
    if(schools[key].type == type){
      schools[key].show();
      for(var i = 0; i < schools[key].conns.length; i++)
        schools[key].conns[i].show();
    }
  }
}

// hide everything
function clean() {
  for(var key in schools){
    schools[key].hide();
    for(var i =0; i < schools[key].conns.length; i++){
      schools[key].conns[i].hide();
    }
  }
}

var zones = []

function testZones() {
	zones.push({
		"ui" : null,
		"latLong" : new google.maps.LatLng(56.632064, -3.729858),
		"rank" : {
			"income" : 100,
			"crime" : 6505,
			"education" : 1,
			"employment" : 1000,
			"health" : 2000,
			"overall" : 3000,
			"housing" : 4000
		}
	});
	drawZones("Education");
}

//Accepts the arguments Overall, Crime, Education, Income, Employment, Health and Housing
function drawZones(type) {
	for (var key in dataZones) {
    dataZones[key].draw(type);
	}
}

var map; //holds the map

var mapStyles = [ { "featureType": "poi", "stylers": [ { "weight": 1.9 }, { "visibility": "off" } ] },{ "featureType": "poi.school", "stylers": [ { "visibility": "on" } ] },{ "featureType": "landscape.man_made", "stylers": [ { "visibility": "on" } ] },{ "featureType": "landscape.natural", "stylers": [ { "visibility": "off" } ] } ] ;

//called on load
function initialize() {
  var centerLatlng = new google.maps.LatLng(56.632064, -3.729858); //The centre of Scotland
  var mapOptions = {
    zoom: 7,
    center: centerLatlng ,
	disableDefaultUI: true,
    panControl: false,
    zoomControl: true,
    scaleControl: false,
    mapTypeControlOptions: {
        mapTypeIds: [google.maps.MapTypeId.ROADMAP, 'map_style']
      }
  }

  var mapDiv = document.getElementById('map-canvas');
  map = new google.maps.Map(mapDiv, mapOptions); //create the map

  map.setOptions({styles : mapStyles});

  var defaultBounds = new google.maps.LatLngBounds(
      new google.maps.LatLng(61.037012, -9.294434),
      new google.maps.LatLng(55.788929, 0.780029));

  var defStyle = [{}];
  var markers = [];

  var styledMap = new google.maps.StyledMapType(defStyle, {name: "Default"});
  map.mapTypes.set('map_style', styledMap);
  map.setMapTypeId('map_style');

  searchBar(); //do all actions related to the search bar

  button(" Primary ", showingPrimarySchools);
  button(" Secondary ", showingSecondarySchools);

  infoBox();
  var deprivationTypes = {
    'crime': 'crime',
    'education': 'education',
    'employment': 'employment',
    'geographicAccess': 'geographic access',
    'health': 'health',
    'housing': 'housing',
    'income': 'incode',
    'overall': 'overall'
  };
  for(var key in deprivationTypes){
    deprivationButtons.push(new DeprivationButton(key, deprivationTypes[key]));
  }

  for(var key in schools){
    schools[key].draw();
    for(var i = 0; i < schools[key].conns.length; i++){
      schools[key].conns[i].draw();
    }
  }
  for(var key in dataZones) {
    numZones++;
  }

  redraw(); //draw all schools
  drawZones("education");
  setDeprivationType("education");
}

function searchBar() {
  var markers = [];
  var input = (document.getElementById('pac-input'));
  map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

  var searchBox = new google.maps.places.SearchBox(input);

  // Listen for the event fired when the user selects an item from the
  // pick list. Retrieve the matching places for that item.
  google.maps.event.addListener(searchBox, 'places_changed', function() {
    var places = searchBox.getPlaces();

    for (var i = 0, marker; marker = markers[i]; i++) {
      marker.setMap(null);
    }

    //For each place, get the icon, place name, and location.
    markers = [];
    var bounds = new google.maps.LatLngBounds();

    for (var i = 0, place; place = places[i]; i++) {
	alert();
      var image = {
        url: place.icon,
        size: new google.maps.Size(71, 71),
        origin: new google.maps.Point(0, 0),
        anchor: new google.maps.Point(17, 34),
        scaledSize: new google.maps.Size(25, 25)
      };

      // Create a marker for each place.
      var marker = new google.maps.Marker({
        map: map,
        icon: image,
        title: place.name,
        position: place.geometry.location
      });

      markers.push(marker);
	  bounds.extend(place.geometry.location);
    }

    map.fitBounds(bounds);
  });

  //Bias the SearchBox results towards places that are within the bounds of the current map's viewport.
  google.maps.event.addListener(map, 'bounds_changed', function() {
    var bounds = new google.maps.LatLngBounds(new google.maps.LatLng(61.037012, -9.294434),
											  new google.maps.LatLng(55.788929, 0.780029));
    searchBox.setBounds(bounds);
  });
}

var showing = false;
var helpText = "this
is
help
text";

function infoBox() {
  var textBox = document.getElementById('textBox');
  var cross = document.getElementById('boxCross');

  if(showing) {
	  textBox.innerHTML = helpText;
	  textBox.appendChild(cross);
	  textBox.style.width = '200px';
	} else {
	  textBox.innerHTML = "Click for info";
	  textBox.style.width = '138px';
	}

  google.maps.event.addDomListener(textBox, 'click', function() {
	showing = !showing;
    if(showing) {
	  textBox.innerHTML = helpText;
	  textBox.appendChild(cross);
	  textBox.style.width = '200px';
	} else {
	  textBox.innerHTML = "Click for info";
	  textBox.style.width = '138px';
	}
  });
  map.controls[google.maps.ControlPosition.RIGHT_TOP].push(textBox);
}

var deprivationButtons = []
// It gets drawn, then hidden.
var dataZonesVisible = true;

function toggleDataZones(){
  for(var key in dataZones){
    if(dataZonesVisible)
      dataZones[key].hide();
    else
      dataZones[key].show();
  }
  dataZonesVisible = !dataZonesVisible;
}

function DeprivationButton(type, name){
  var controlDiv = document.createElement('div');

  this.selected = false;
  this.type = type;
  this.name = name;
  //setting the visual variables -->
  controlDiv.style.padding = '5px';

  var controlUI = document.createElement('div');
  controlUI.style.width = '160px';
  controlUI.style.borderStyle = 'solid';
  controlUI.style.borderWidth = '1px';
  controlUI.style.cursor = 'pointer';
  controlUI.style.textAlign = 'center';
  controlDiv.appendChild(controlUI);

  this.ui = controlUI;
  var controlText = document.createElement('div');
  controlText.style.fontFamily = 'Arial,sans-serif';
  controlText.style.fontSize = '12px';
  controlText.style.paddingLeft = '4px';
  controlText.style.paddingRight = '4px';
  controlText.innerHTML = "Show " + name + " deprivation";
  controlUI.appendChild(controlText);
  this.textui = controlText;

  var this_ = this;
  google.maps.event.addDomListener(controlUI, 'click', function() {
    if(this_.selected){
      toggleDataZones();
      if(dataZonesVisible){
        this_.textui.innerHTML = "Hide " + this_.name + " deprivation";
        this_.ui.style.backgroundColor = '#99ff66';
      }
      else{
        this_.textui.innerHTML = "Show " + this_.name + " deprivation";
        this_.ui.style.backgroundColor = '#dddddd';
      }
    }
    else{
      this_.selected = !this_.selected;
      setDeprivationType(this_.type);
    }
  });
  map.controls[google.maps.ControlPosition.RIGHT_TOP].push(controlDiv);
}

function setDeprivationType(type){
  for(var i = 0; i < deprivationButtons.length; i++){
    if(deprivationButtons[i].type == type){
      deprivationButtons[i].textui.innerHTML = "Hide " +
        deprivationButtons[i].name + " deprivation";
      deprivationButtons[i].selected = true;
      deprivationButtons[i].ui.style.backgroundColor = '#99ff66';
    }
    else{
      deprivationButtons[i].textui.innerHTML = "Show " +
        deprivationButtons[i].name + " deprivation";
      deprivationButtons[i].selected = false;
      deprivationButtons[i].ui.style.backgroundColor = '#dddddd';
    }
  }
  drawZones(type);
  if(!dataZonesVisible)
    toggleDataZones();
}

function button(type, bool) {
  var homeControlDiv = document.createElement('div');
  var bc = new buttonControl(homeControlDiv, type, bool);
  map.controls[google.maps.ControlPosition.RIGHT_TOP].push(homeControlDiv);
}

function buttonControl(controlDiv, type, bool) {
  //button names and colours
  var startDrawing = "Show" + type + "Schools";
  var stopDrawing = "Hide" + type + "Schools";
  var info = "Toggle" + type + "Schools";
  var showColor = "#99FF66";
  var hideColor = "#dddddd";

  //setting the visual variables -->
  controlDiv.style.padding = '5px';

  var controlUI = document.getElementById('button').cloneNode(false);
  controlUI.style.backgroundColor = bool.value ? hideColor : showColor;
  controlUI.title = info;
  controlDiv.appendChild(controlUI);

  var controlText = document.getElementById('buttonText').cloneNode(false);
  controlText.innerHTML = bool.value ? stopDrawing : startDrawing;
  controlUI.appendChild(controlText);

  google.maps.event.addDomListener(controlUI, 'click', function() {
	bool.value = !bool.value; //toggle the drawing state

    if(bool.value) { //if drawing
	  controlText.innerHTML = stopDrawing; //set button text to "stop drawing"
      controlUI.style.backgroundColor = hideColor;
	} else {
	  controlText.innerHTML = startDrawing; // set button text to "draw"
	  controlUI.style.backgroundColor = showColor;
	}

	redraw(); //redraw all the schools
  });
}

var numZones = 0

//Draws a zone with a colour that scales from Green to Red depending on the rank supplied

var openInfoWindow = null;
<commit_msg>fixed button styling<commit_after>//DEBUG boolean, should debug console prints be shown
var DEBUG = true;

//boolean values as objects so that they are mutable form inside the button listener
var showingPrimarySchools = {value: false};
var showingSecondarySchools = {value: false};

function redraw() {
  clean(); //remove everything

  if(DEBUG) {
	console.log("Showing Primary Schools: " + showingPrimarySchools.value);
	console.log("Showing Secondary Schools: " + showingSecondarySchools.value);
  }

  if(showingPrimarySchools.value) { //if supposed to be drawing; draw.
    draw("primary");
  }

  if(showingSecondarySchools.value) {
    draw("secondary");
  }
}

//draw all schools of the given type
//types "secondary", "primary"
function draw(type) {
  for(var key in schools){
    if(schools[key].type == type){
      schools[key].show();
      for(var i = 0; i < schools[key].conns.length; i++)
        schools[key].conns[i].show();
    }
  }
}

// hide everything
function clean() {
  for(var key in schools){
    schools[key].hide();
    for(var i =0; i < schools[key].conns.length; i++){
      schools[key].conns[i].hide();
    }
  }
}

var zones = []

function testZones() {
	zones.push({
		"ui" : null,
		"latLong" : new google.maps.LatLng(56.632064, -3.729858),
		"rank" : {
			"income" : 100,
			"crime" : 6505,
			"education" : 1,
			"employment" : 1000,
			"health" : 2000,
			"overall" : 3000,
			"housing" : 4000
		}
	});
	drawZones("Education");
}

//Accepts the arguments Overall, Crime, Education, Income, Employment, Health and Housing
function drawZones(type) {
	for (var key in dataZones) {
    dataZones[key].draw(type);
	}
}

var map; //holds the map

var mapStyles = [ { "featureType": "poi", "stylers": [ { "weight": 1.9 }, { "visibility": "off" } ] },{ "featureType": "poi.school", "stylers": [ { "visibility": "on" } ] },{ "featureType": "landscape.man_made", "stylers": [ { "visibility": "on" } ] },{ "featureType": "landscape.natural", "stylers": [ { "visibility": "off" } ] } ] ;

//called on load
function initialize() {
  var centerLatlng = new google.maps.LatLng(56.632064, -3.729858); //The centre of Scotland
  var mapOptions = {
    zoom: 7,
    center: centerLatlng ,
	disableDefaultUI: true,
    panControl: false,
    zoomControl: true,
    scaleControl: false,
    mapTypeControlOptions: {
        mapTypeIds: [google.maps.MapTypeId.ROADMAP, 'map_style']
      }
  }

  var mapDiv = document.getElementById('map-canvas');
  map = new google.maps.Map(mapDiv, mapOptions); //create the map

  map.setOptions({styles : mapStyles});

  var defaultBounds = new google.maps.LatLngBounds(
      new google.maps.LatLng(61.037012, -9.294434),
      new google.maps.LatLng(55.788929, 0.780029));

  var defStyle = [{}];
  var markers = [];

  var styledMap = new google.maps.StyledMapType(defStyle, {name: "Default"});
  map.mapTypes.set('map_style', styledMap);
  map.setMapTypeId('map_style');

  searchBar(); //do all actions related to the search bar

  button(" Primary ", showingPrimarySchools);
  button(" Secondary ", showingSecondarySchools);

  var deprivationTypes = {
    'crime': 'crime',
    'education': 'education',
    'employment': 'employment',
    'geographicAccess': 'geographic access',
    'health': 'health',
    'housing': 'housing',
    'income': 'incode',
    'overall': 'overall'
  };

  for(var key in deprivationTypes){
    deprivationButtons.push(new DeprivationButton(key, deprivationTypes[key]));
  }

  infoBox();

  for(var key in schools){
    schools[key].draw();
    for(var i = 0; i < schools[key].conns.length; i++){
      schools[key].conns[i].draw();
    }
  }
  for(var key in dataZones) {
    numZones++;
  }

  redraw(); //draw all schools
  drawZones("education");
  setDeprivationType("education");
}

function searchBar() {
  var markers = [];
  var input = (document.getElementById('pac-input'));
  map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

  var searchBox = new google.maps.places.SearchBox(input);

  // Listen for the event fired when the user selects an item from the
  // pick list. Retrieve the matching places for that item.
  google.maps.event.addListener(searchBox, 'places_changed', function() {
    var places = searchBox.getPlaces();

    for (var i = 0, marker; marker = markers[i]; i++) {
      marker.setMap(null);
    }

    //For each place, get the icon, place name, and location.
    markers = [];
    var bounds = new google.maps.LatLngBounds();

    for (var i = 0, place; place = places[i]; i++) {
	alert();
      var image = {
        url: place.icon,
        size: new google.maps.Size(71, 71),
        origin: new google.maps.Point(0, 0),
        anchor: new google.maps.Point(17, 34),
        scaledSize: new google.maps.Size(25, 25)
      };

      // Create a marker for each place.
      var marker = new google.maps.Marker({
        map: map,
        icon: image,
        title: place.name,
        position: place.geometry.location
      });

      markers.push(marker);
	  bounds.extend(place.geometry.location);
    }

    map.fitBounds(bounds);
  });

  //Bias the SearchBox results towards places that are within the bounds of the current map's viewport.
  google.maps.event.addListener(map, 'bounds_changed', function() {
    var bounds = new google.maps.LatLngBounds(new google.maps.LatLng(61.037012, -9.294434),
											  new google.maps.LatLng(55.788929, 0.780029));
    searchBox.setBounds(bounds);
  });
}

var showing = false;
var helpText = "this
is
help
text";

function infoBox() {
  var textBox = document.getElementById('textBox');
  var cross = document.getElementById('boxCross');

  if(showing) {
	  textBox.innerHTML = helpText;
	  textBox.appendChild(cross);
	  textBox.style.width = '200px';
	} else {
	  textBox.innerHTML = "Click for info";
	  textBox.style.width = '138px';
	}

  google.maps.event.addDomListener(textBox, 'click', function() {
	showing = !showing;
    if(showing) {
	  textBox.innerHTML = helpText;
	  textBox.appendChild(cross);
	  textBox.style.width = '200px';
	} else {
	  textBox.innerHTML = "Click for info";
	  textBox.style.width = '138px';
	}
  });
  map.controls[google.maps.ControlPosition.RIGHT_TOP].push(textBox);
}

var deprivationButtons = []
// It gets drawn, then hidden.
var dataZonesVisible = true;

function toggleDataZones(){
  for(var key in dataZones){
    if(dataZonesVisible)
      dataZones[key].hide();
    else
      dataZones[key].show();
  }
  dataZonesVisible = !dataZonesVisible;
}

function DeprivationButton(type, name){
  var controlDiv = document.createElement('div');

  this.selected = false;
  this.type = type;
  this.name = name;
  //setting the visual variables -->
  controlDiv.style.padding = '5px';

  var controlUI = document.getElementById('button').cloneNode(false);
  controlDiv.appendChild(controlUI);
  this.ui = controlUI;

  var controlText = document.getElementById('buttonText').cloneNode(false);
  controlText.innerHTML = "Show " + name + " deprivation";
  controlUI.appendChild(controlText);
  this.textui = controlText;

  var this_ = this;
  google.maps.event.addDomListener(controlUI, 'click', function() {
    if(this_.selected){
      toggleDataZones();
      if(dataZonesVisible){
        this_.textui.innerHTML = "Hide " + this_.name + " deprivation";
        this_.ui.style.backgroundColor = '#99ff66';
      }
      else{
        this_.textui.innerHTML = "Show " + this_.name + " deprivation";
        this_.ui.style.backgroundColor = '#dddddd';
      }
    }
    else{
      this_.selected = !this_.selected;
      setDeprivationType(this_.type);
    }
  });
  map.controls[google.maps.ControlPosition.RIGHT_TOP].push(controlDiv);
}

function setDeprivationType(type){
  for(var i = 0; i < deprivationButtons.length; i++){
    if(deprivationButtons[i].type == type){
      deprivationButtons[i].textui.innerHTML = "Hide " +
        deprivationButtons[i].name + " deprivation";
      deprivationButtons[i].selected = true;
      deprivationButtons[i].ui.style.backgroundColor = '#99ff66';
    }
    else{
      deprivationButtons[i].textui.innerHTML = "Show " +
        deprivationButtons[i].name + " deprivation";
      deprivationButtons[i].selected = false;
      deprivationButtons[i].ui.style.backgroundColor = '#dddddd';
    }
  }
  drawZones(type);
  if(!dataZonesVisible)
    toggleDataZones();
}

function button(type, bool) {
  var homeControlDiv = document.createElement('div');
  var bc = new buttonControl(homeControlDiv, type, bool);
  map.controls[google.maps.ControlPosition.RIGHT_TOP].push(homeControlDiv);
}

function buttonControl(controlDiv, type, bool) {
  //button names and colours
  var startDrawing = "Show" + type + "Schools";
  var stopDrawing = "Hide" + type + "Schools";
  var info = "Toggle" + type + "Schools";
  var showColor = "#99FF66";
  var hideColor = "#dddddd";

  //setting the visual variables -->
  controlDiv.style.padding = '5px';

  var controlUI = document.getElementById('button').cloneNode(false);
  controlUI.style.backgroundColor = bool.value ? hideColor : showColor;
  controlUI.title = info;
  controlDiv.appendChild(controlUI);

  var controlText = document.getElementById('buttonText').cloneNode(false);
  controlText.innerHTML = bool.value ? stopDrawing : startDrawing;
  controlUI.appendChild(controlText);

  google.maps.event.addDomListener(controlUI, 'click', function() {
	bool.value = !bool.value; //toggle the drawing state

    if(bool.value) { //if drawing
	  controlText.innerHTML = stopDrawing; //set button text to "stop drawing"
      controlUI.style.backgroundColor = hideColor;
	} else {
	  controlText.innerHTML = startDrawing; // set button text to "draw"
	  controlUI.style.backgroundColor = showColor;
	}

	redraw(); //redraw all the schools
  });
}

var numZones = 0

//Draws a zone with a colour that scales from Green to Red depending on the rank supplied

var openInfoWindow = null;
<|endoftext|>


<commit_before>
/*!
 * Skeleton.js - History
 * Copyright(c) 2012 Rubén Norte <rubennorte@gmail.com>
 * MIT Licensed
 */

define([
  'backbone',
  'config',
  './util/url'
], function(Backbone, config, URL){

  'use strict';

  // Create the history object if it's not created, as Backbone does
  Backbone.history || (Backbone.history = new Backbone.History);

  _.extend(Backbone.history, {

    /**
     * Start method redefined to add some default values
     */
    start: function(options){
      // Set default options
      options || (options = {});
      if (typeof(options.root) == 'undefined')
        options.root = URL.parseUri(config.url.root).path;
      if (typeof(options.pushState) == 'undefined')
        options.pushState = true;

      Backbone.History.prototype.start.call(this, options);
    },

    /**
     * Generates a URL replacing the route params with the values of those
     * params in the specified object
     */
    generateRoute: function(route, params){
      return route.replace(/:(\w+)/g, function(match, paramName){
        return params[paramName];
      });
    },

    /**
     * Returns the current route
     */
    getCurrentRoute: function(){
      var current = Backbone.history.fragment,
          root = Backbone.history.options.root;
      // Fixes error in backbone
      if (root && current.indexOf(root) == 0){
        current = current.substr(root.length);
      }
      return current;
    },

    /**
     * Triggers again the handler for the current route
     */
    refresh: function(){
      this.loadUrl(this.getCurrentRoute());
    }

  });

  return Backbone.history;

});<commit_msg>Fixed missing dependency in skeleton history.<commit_after>
/*!
 * Skeleton.js - History
 * Copyright(c) 2012 Rubén Norte <rubennorte@gmail.com>
 * MIT Licensed
 */

define([
  'backbone',
  'config',
  './util/url',
  'underscore'
], function(Backbone, config, URL, _){

  'use strict';

  // Create the history object if it's not created, as Backbone does
  Backbone.history || (Backbone.history = new Backbone.History);

  _.extend(Backbone.history, {

    /**
     * Start method redefined to add some default values
     */
    start: function(options){
      // Set default options
      options || (options = {});
      if (typeof(options.root) == 'undefined')
        options.root = URL.parseUri(config.url.root).path;
      if (typeof(options.pushState) == 'undefined')
        options.pushState = true;

      Backbone.History.prototype.start.call(this, options);
    },

    /**
     * Generates a URL replacing the route params with the values of those
     * params in the specified object
     */
    generateRoute: function(route, params){
      return route.replace(/:(\w+)/g, function(match, paramName){
        return params[paramName];
      });
    },

    /**
     * Returns the current route
     */
    getCurrentRoute: function(){
      var current = Backbone.history.fragment,
          root = Backbone.history.options.root;
      // Fixes error in backbone
      if (root && current.indexOf(root) == 0){
        current = current.substr(root.length);
      }
      return current;
    },

    /**
     * Triggers again the handler for the current route
     */
    refresh: function(){
      this.loadUrl(this.getCurrentRoute());
    }

  });

  return Backbone.history;

});<|endoftext|>


<commit_before>/*!
    Copyright (C) 2016 Google Inc.
    Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
*/

(function (can, GGRC, moment) {
  'use strict';

  GGRC.Components('datepicker', {
    tag: 'datepicker',
    template: can.view(
      GGRC.mustache_path +
      '/components/datepicker/datepicker.mustache'
    ),
    scope: {
      date: null,
      format: '@',
      helptext: '@',
      isShown: false,
      pattern: 'MM/DD/YYYY',
      setMinDate: null,
      setMaxDate: null,
      _date: null,
      required: '@',
      define: {
        label: {
          type: 'string'
        },
        persistent: {
          type: 'boolean',
          'default': false
        }
      },
      onSelect: function (val, ev) {
        this.attr('_date', val);
        this.attr('isShown', false);
      },
      onFocus: function (el, ev) {
        this.attr('showTop', false);
        this.attr('isShown', true);

        if (!GGRC.Utils.inViewport(this.picker)) {
          this.attr('showTop', true);
        }
      }
    },
    events: {
      inserted: function () {
        var element = this.element.find('.datepicker__calendar');
        var date = this.getDate(this.scope.date);

        element.datepicker({
          altField: this.element.find('.datepicker__input'),
          onSelect: this.scope.onSelect.bind(this.scope)
        });

        this.scope.attr('picker', element);

        this.scope.picker.datepicker('setDate', date);
        if (this.scope.setMinDate) {
          this.updateDate('minDate', this.scope.setMinDate);
        }
        if (this.scope.setMaxDate) {
          this.updateDate('maxDate', this.scope.setMaxDate);
        }
        this.scope._date = date;
      },
      getDate: function (date) {
        if (date instanceof Date) {
          date = moment(date).format(this.scope.pattern);
        } else if (!this.isValidDate(date)) {
          date = null;
        }
        return date;
      },
      isValidDate: function (date) {
        return moment(date, this.scope.pattern, true).isValid();
      },
      updateDate: function (type, date) {
        var types = {
          minDate: function () {
            date.add(1, 'day');
          },
          maxDate: function () {
            date.subtract(1, 'day');
          }
        };
        if (!date) {
          return;
        }
        date = moment(date);

        if (types[type]) {
          types[type]();
        }
        date = date.toDate();
        this.scope.picker.datepicker('option', type, date);
        return date;
      },
      '{scope} setMinDate': function (scope, ev, date) {
        var updated = this.updateDate('minDate', date);
        if (this.scope.attr('date') < updated) {
          this.scope.attr('_date', moment(updated).format(this.scope.pattern));
        }
      },
      '{scope} setMaxDate': function (scope, ev, date) {
        this.updateDate('maxDate', date);
      },
      '{scope} _date': function (scope, ev, val) {
        scope.attr('date', val);
      },
      '{window} mousedown': function (el, ev) {
        var isInside;

        if (this.scope.attr('persistent')) {
          return;
        }
        isInside = GGRC.Utils.events.isInnerClick(this.element, ev.target);

        if (this.scope.isShown && !isInside) {
          this.scope.attr('isShown', false);
        }
      }
    },
    helpers: {
      isHidden: function (opts) {
        if (this.attr('isShown') || this.attr('persistent')) {
          return opts.inverse();
        }
        return opts.fn();
      }
    }
  });
})(window.can, window.GGRC, window.moment);
<commit_msg>Fix min/max date after change value in datepicker<commit_after>/*!
    Copyright (C) 2016 Google Inc.
    Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
*/

(function (can, GGRC, moment) {
  'use strict';

  GGRC.Components('datepicker', {
    tag: 'datepicker',
    template: can.view(
      GGRC.mustache_path +
      '/components/datepicker/datepicker.mustache'
    ),
    scope: {
      date: null,
      format: '@',
      helptext: '@',
      isShown: false,
      pattern: 'MM/DD/YYYY',
      setMinDate: null,
      setMaxDate: null,
      _date: null,
      required: '@',
      define: {
        label: {
          type: 'string'
        },
        persistent: {
          type: 'boolean',
          'default': false
        }
      },
      onSelect: function (val, ev) {
        this.attr('_date', val);
        this.attr('isShown', false);
      },
      onFocus: function (el, ev) {
        this.attr('showTop', false);
        this.attr('isShown', true);

        if (!GGRC.Utils.inViewport(this.picker)) {
          this.attr('showTop', true);
        }
      }
    },
    events: {
      inserted: function () {
        var element = this.element.find('.datepicker__calendar');
        var date = this.getDate(this.scope.date);

        element.datepicker({
          altField: this.element.find('.datepicker__input'),
          onSelect: this.scope.onSelect.bind(this.scope)
        });

        this.scope.attr('picker', element);

        this.scope.picker.datepicker('setDate', date);
        if (this.scope.setMinDate) {
          this.updateDate('minDate', this.scope.setMinDate);
        }
        if (this.scope.setMaxDate) {
          this.updateDate('maxDate', this.scope.setMaxDate);
        }
        this.scope._date = date;
      },
      getDate: function (date) {
        if (date instanceof Date) {
          date = moment(date).format(this.scope.pattern);
        } else if (!this.isValidDate(date)) {
          date = null;
        }
        return date;
      },
      isValidDate: function (date) {
        return moment(date, this.scope.pattern, true).isValid();
      },
      updateDate: function (type, date) {
        var types = {
          minDate: function () {
            date.add(1, 'day');
          },
          maxDate: function () {
            date.subtract(1, 'day');
          }
        };
        if (!date) {
          this.scope.picker.datepicker('option', type, null);
          return;
        }
        date = moment(date);

        if (types[type]) {
          types[type]();
        }
        date = date.toDate();
        this.scope.picker.datepicker('option', type, date);
        return date;
      },
      '{scope} setMinDate': function (scope, ev, date) {
        var updated = this.updateDate('minDate', date);
        if (this.scope.attr('date') < updated) {
          this.scope.attr('_date', moment(updated).format(this.scope.pattern));
        }
      },
      '{scope} setMaxDate': function (scope, ev, date) {
        this.updateDate('maxDate', date);
      },
      '{scope} _date': function (scope, ev, val) {
        scope.attr('date', val);
        scope.picker.datepicker('setDate', val);
      },
      '{window} mousedown': function (el, ev) {
        var isInside;

        if (this.scope.attr('persistent')) {
          return;
        }
        isInside = GGRC.Utils.events.isInnerClick(this.element, ev.target);

        if (this.scope.isShown && !isInside) {
          this.scope.attr('isShown', false);
        }
      }
    },
    helpers: {
      isHidden: function (opts) {
        if (this.attr('isShown') || this.attr('persistent')) {
          return opts.inverse();
        }
        return opts.fn();
      }
    }
  });
})(window.can, window.GGRC, window.moment);
<|endoftext|>


<commit_before>/*
Copyright 2015, 2016 OpenMarket Ltd

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.
*/

import MatrixClientPeg from './MatrixClientPeg';
import Promise from 'bluebird';

/**
 * Given a room object, return the alias we should use for it,
 * if any. This could be the canonical alias if one exists, otherwise
 * an alias selected arbitrarily but deterministically from the list
 * of aliases. Otherwise return null;
 */
export function getDisplayAliasForRoom(room) {
    return room.getCanonicalAlias() || room.getAliases()[0];
}

/**
 * If the room contains only two members including the logged-in user,
 * return the other one. Otherwise, return null.
 */
export function getOnlyOtherMember(room, myUserId) {
    if (room.currentState.getJoinedMemberCount() === 2) {
        return room.getJoinedMembers().filter(function(m) {
            return m.userId !== myUserId;
        })[0];
    }

    return null;
}

function _isConfCallRoom(room, myUserId, conferenceHandler) {
    if (!conferenceHandler) return false;

    const myMembership = room.getMyMembership();
    if (myMembership != "join") {
        return false;
    }

    const otherMember = getOnlyOtherMember(room, myUserId);
    if (!otherMember) {
        return false;
    }

    if (conferenceHandler.isConferenceUser(otherMember.userId)) {
        return true;
    }

    return false;
}

// Cache whether a room is a conference call. Assumes that rooms will always
// either will or will not be a conference call room.
const isConfCallRoomCache = {
    // $roomId: bool
};

export function isConfCallRoom(room, myUserId, conferenceHandler) {
    if (isConfCallRoomCache[room.roomId] !== undefined) {
        return isConfCallRoomCache[room.roomId];
    }

    const result = _isConfCallRoom(room, myUserId, conferenceHandler);

    isConfCallRoomCache[room.roomId] = result;

    return result;
}

export function looksLikeDirectMessageRoom(room, myUserId) {
    const myMembership = room.getMyMembership();
    const me = room.getMember(myUserId);

    if (myMembership == "join" || myMembership === "ban" || (me && me.isKicked())) {
        // Used to split rooms via tags
        const tagNames = Object.keys(room.tags);
        // Used for 1:1 direct chats
        // Show 1:1 chats in seperate "Direct Messages" section as long as they haven't
        // been moved to a different tag section
        const totalMemberCount = room.currentState.getJoinedMemberCount() +
            room.currentState.getInvitedMemberCount();
        if (totalMemberCount === 2 && !tagNames.length) {
            return true;
        }
    }
    return false;
}

export function guessAndSetDMRoom(room, isDirect) {
    let newTarget;
    if (isDirect) {
        const guessedUserId = guessDMRoomTargetId(
            room, MatrixClientPeg.get().getUserId(),
        );
        newTarget = guessedUserId;
    } else {
        newTarget = null;
    }

    return setDMRoom(room.roomId, newTarget);
}

/**
 * Marks or unmarks the given room as being as a DM room.
 * @param {string} roomId The ID of the room to modify
 * @param {string} userId The user ID of the desired DM
                   room target user or null to un-mark
                   this room as a DM room
 * @returns {object} A promise
 */
export function setDMRoom(roomId, userId) {
    if (MatrixClientPeg.get().isGuest()) {
        return Promise.resolve();
    }

    const mDirectEvent = MatrixClientPeg.get().getAccountData('m.direct');
    let dmRoomMap = {};

    if (mDirectEvent !== undefined) dmRoomMap = mDirectEvent.getContent();

    // remove it from the lists of any others users
    // (it can only be a DM room for one person)
    for (const thisUserId of Object.keys(dmRoomMap)) {
        const roomList = dmRoomMap[thisUserId];

        if (thisUserId != userId) {
            const indexOfRoom = roomList.indexOf(roomId);
            if (indexOfRoom > -1) {
                roomList.splice(indexOfRoom, 1);
            }
        }
    }

    // now add it, if it's not already there
    if (userId) {
        const roomList = dmRoomMap[userId] || [];
        if (roomList.indexOf(roomId) == -1) {
            roomList.push(roomId);
        }
        dmRoomMap[userId] = roomList;
    }

    return MatrixClientPeg.get().setAccountData('m.direct', dmRoomMap);
}

/**
 * Given a room, estimate which of its members is likely to
 * be the target if the room were a DM room and return that user.
 */
function guessDMRoomTargetId(room, myUserId) {
    let oldestTs;
    let oldestUser;

    // Pick the joined user who's been here longest (and isn't us),
    for (const user of room.getJoinedMembers()) {
        if (user.userId == myUserId) continue;

        if (oldestTs === undefined || (user.events.member && user.events.member.getTs() < oldestTs)) {
            oldestUser = user;
            oldestTs = user.events.member.getTs();
        }
    }
    if (oldestUser) return oldestUser;

    // if there are no joined members other than us, use the oldest member
    for (const user of room.currentState.getMembers()) {
        if (user.userId == myUserId) continue;

        if (oldestTs === undefined || (user.events.member && user.events.member.getTs() < oldestTs)) {
            oldestUser = user;
            oldestTs = user.events.member.getTs();
        }
    }

    if (oldestUser === undefined) return myUserId;
    return oldestUser;
}
<commit_msg>Fix settings direct chat<commit_after>/*
Copyright 2015, 2016 OpenMarket Ltd

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.
*/

import MatrixClientPeg from './MatrixClientPeg';
import Promise from 'bluebird';

/**
 * Given a room object, return the alias we should use for it,
 * if any. This could be the canonical alias if one exists, otherwise
 * an alias selected arbitrarily but deterministically from the list
 * of aliases. Otherwise return null;
 */
export function getDisplayAliasForRoom(room) {
    return room.getCanonicalAlias() || room.getAliases()[0];
}

/**
 * If the room contains only two members including the logged-in user,
 * return the other one. Otherwise, return null.
 */
export function getOnlyOtherMember(room, myUserId) {
    if (room.currentState.getJoinedMemberCount() === 2) {
        return room.getJoinedMembers().filter(function(m) {
            return m.userId !== myUserId;
        })[0];
    }

    return null;
}

function _isConfCallRoom(room, myUserId, conferenceHandler) {
    if (!conferenceHandler) return false;

    const myMembership = room.getMyMembership();
    if (myMembership != "join") {
        return false;
    }

    const otherMember = getOnlyOtherMember(room, myUserId);
    if (!otherMember) {
        return false;
    }

    if (conferenceHandler.isConferenceUser(otherMember.userId)) {
        return true;
    }

    return false;
}

// Cache whether a room is a conference call. Assumes that rooms will always
// either will or will not be a conference call room.
const isConfCallRoomCache = {
    // $roomId: bool
};

export function isConfCallRoom(room, myUserId, conferenceHandler) {
    if (isConfCallRoomCache[room.roomId] !== undefined) {
        return isConfCallRoomCache[room.roomId];
    }

    const result = _isConfCallRoom(room, myUserId, conferenceHandler);

    isConfCallRoomCache[room.roomId] = result;

    return result;
}

export function looksLikeDirectMessageRoom(room, myUserId) {
    const myMembership = room.getMyMembership();
    const me = room.getMember(myUserId);

    if (myMembership == "join" || myMembership === "ban" || (me && me.isKicked())) {
        // Used to split rooms via tags
        const tagNames = Object.keys(room.tags);
        // Used for 1:1 direct chats
        // Show 1:1 chats in seperate "Direct Messages" section as long as they haven't
        // been moved to a different tag section
        const totalMemberCount = room.currentState.getJoinedMemberCount() +
            room.currentState.getInvitedMemberCount();
        if (totalMemberCount === 2 && !tagNames.length) {
            return true;
        }
    }
    return false;
}

export function guessAndSetDMRoom(room, isDirect) {
    let newTarget;
    if (isDirect) {
        const guessedUserId = guessDMRoomTargetId(
            room, MatrixClientPeg.get().getUserId(),
        );
        newTarget = guessedUserId;
    } else {
        newTarget = null;
    }

    return setDMRoom(room.roomId, newTarget);
}

/**
 * Marks or unmarks the given room as being as a DM room.
 * @param {string} roomId The ID of the room to modify
 * @param {string} userId The user ID of the desired DM
                   room target user or null to un-mark
                   this room as a DM room
 * @returns {object} A promise
 */
export function setDMRoom(roomId, userId) {
    if (MatrixClientPeg.get().isGuest()) {
        return Promise.resolve();
    }

    const mDirectEvent = MatrixClientPeg.get().getAccountData('m.direct');
    let dmRoomMap = {};

    if (mDirectEvent !== undefined) dmRoomMap = mDirectEvent.getContent();

    // remove it from the lists of any others users
    // (it can only be a DM room for one person)
    for (const thisUserId of Object.keys(dmRoomMap)) {
        const roomList = dmRoomMap[thisUserId];

        if (thisUserId != userId) {
            const indexOfRoom = roomList.indexOf(roomId);
            if (indexOfRoom > -1) {
                roomList.splice(indexOfRoom, 1);
            }
        }
    }

    // now add it, if it's not already there
    if (userId) {
        const roomList = dmRoomMap[userId] || [];
        if (roomList.indexOf(roomId) == -1) {
            roomList.push(roomId);
        }
        dmRoomMap[userId] = roomList;
    }

    return MatrixClientPeg.get().setAccountData('m.direct', dmRoomMap);
}

/**
 * Given a room, estimate which of its members is likely to
 * be the target if the room were a DM room and return that user.
 *
 * @param {Object} room Target room
 * @param {string} myUserId User ID of the current user
 * @returns {string} User ID of the user that the room is probably a DM with
 */
function guessDMRoomTargetId(room, myUserId) {
    let oldestTs;
    let oldestUser;

    // Pick the joined user who's been here longest (and isn't us),
    for (const user of room.getJoinedMembers()) {
        if (user.userId == myUserId) continue;

        if (oldestTs === undefined || (user.events.member && user.events.member.getTs() < oldestTs)) {
            oldestUser = user;
            oldestTs = user.events.member.getTs();
        }
    }
    if (oldestUser) return oldestUser.userId;

    // if there are no joined members other than us, use the oldest member
    for (const user of room.currentState.getMembers()) {
        if (user.userId == myUserId) continue;

        if (oldestTs === undefined || (user.events.member && user.events.member.getTs() < oldestTs)) {
            oldestUser = user;
            oldestTs = user.events.member.getTs();
        }
    }

    if (oldestUser === undefined) return myUserId;
    return oldestUser.userId;
}
<|endoftext|>