import VueDatatableCell from '../vue-datatable-cell.vue';
import VueDatatableHeader from '../vue-datatable-header.vue';
import VueDatatablePagerButton from '../vue-datatable-pager-button.vue';
import TableType from './table-type.js';
/**
* @member {'datatable'} DEFAULT_DATATABLE - The default table type name
* @memberof DatatableFactory
* @public
* @readonly
*/
const DEFAULT_DATATABLE = 'datatable';
/**
* Registers Vuejs-Datatable components globally in VueJS.
*
* @example import DatatableFactory from 'vuejs-datatable';
Vue.use(DatatableFactory);
*/
class DatatableFactory {
/**
* Initialize the default factory
*/
constructor(){
/**
* @private
* @member {VueConstructor | undefined} - A reference to the Vue instance the plugin is installed in. It may be used to check if the factory was already installed
*/
this.vueInstance = undefined;
/**
* @private
* @member {Dictionary<TableType>} - Registry of declared table types.
*/
this.tableTypes = {};
/**
* @private
* @member {TableType} - The default table type to use if no other configuration was provided.
*/
this.defaultTableType = new TableType( DEFAULT_DATATABLE );
this.useDefaultType( true );
}
/**
* Get a table type by its identifier.
*
* @param {string} [id = DEFAULT_DATATABLE] - The identifier of the table type. If not provided, it will default to the default table type.
* @returns {TableType | undefined} The table type registered with that identifier.
*/
getTableType( id = DEFAULT_DATATABLE ){
return this.tableTypes[id];
}
/**
* Controls the definition of default table type.
*
* @param {boolean} [use] - `true` to use the default type, `false` otherwise. If not provided, this method returns a boolean indicating if the default table type is / will be used.
* @returns {this | boolean} - `this` for chaining, or the value if `use` is undefined
*/
useDefaultType( use ){
if ( typeof use !== 'boolean' && !use ){
return this.tableTypes[DEFAULT_DATATABLE] === this.defaultTableType;
}
if ( use ){
this.registerTableType( this.defaultTableType );
} else {
this.deregisterTableType( this.defaultTableType );
}
return this;
}
/**
* Creates a new table type with a specified prefix, that you can customize using a callback.
*
* @param {string | TableType} nameOrTableType - The name of the component to register, or a {@link TableType} object.
* @param {function} [callback] - An optional function to execute, that configures the newly created {@link TableType}. It takes a single parameter: the newly created {@link TableType}, and should return the transformed table type.
* @returns {this} - For chaining.
*/
registerTableType( nameOrTableType, callback ){
const tableType = nameOrTableType instanceof TableType ? nameOrTableType : new TableType( nameOrTableType );
const transformedTableType = ( callback && typeof callback === 'function' ) ? callback( tableType ) || tableType : tableType;
const name = transformedTableType.id;
this.tableTypes[name] = transformedTableType;
if ( this.vueInstance ){
this.installTableType( name );
}
return this;
}
/**
* Creates a new table type with a specified prefix, that you can customize using a callback.
*
* @param {string | TableType} nameOrTableType - The name of the component to register, or a {@link TableType} object.
* @returns {this} - For chaining.
*/
deregisterTableType( nameOrTableType ){
const name = nameOrTableType instanceof TableType ? nameOrTableType.id : nameOrTableType;
if ( this.vueInstance ){
this.uninstallTableType( name );
}
delete this.tableTypes[name];
return this;
}
/**
* Declares global components exported by vuejs-datatable, & load configs.
*
* @param {VueConstructor} Vue - The Vue instance to configure.
* @returns {void}
*/
install( Vue ){
this.vueInstance = Vue;
Vue.prototype.$datatables = {};
Vue.component( `${ DEFAULT_DATATABLE }-cell`, VueDatatableCell );
Vue.component( `${ DEFAULT_DATATABLE }-header`, VueDatatableHeader );
Vue.component( `${ DEFAULT_DATATABLE }-button`, VueDatatablePagerButton );
for ( const type of Object.values( this.tableTypes ) ){
this.installTableType( type.id );
}
}
/**
* Declares a pair of components (a Datatable & a Datatable-Pager) sharing a config.
*
* @private
* @param {string} id - The base name of the datatable type.
* @param {TableType} tableType - The configuration object that describes both datatable & the related pager.
* @returns {this} - For chaining.
*/
installTableType( id ){
const tableType = this.tableTypes[id];
const tableDef = tableType.getTableDefinition();
this.vueInstance.component( tableDef.name, tableDef );
const pagerDef = tableType.getPagerDefinition();
this.vueInstance.component( pagerDef.name, pagerDef );
return this;
}
/**
* Remove a table type definition from vue (the datatable & its associated pager).
* This should be used carefully, because Vue won't be able to instanciate new instances of this table type.
*
* @private
* @param {string} id - The base name of the datatable type to forget.
* @returns {this} - For chaining.
*/
uninstallTableType( id ){
const tableType = this.tableTypes[id];
const tableDef = tableType.getTableDefinition();
delete this.vueInstance.options.components[tableDef.name];
const pagerDef = tableType.getPagerDefinition();
delete this.vueInstance.options.components[pagerDef.name];
return this;
}
}
export default DatatableFactory;