1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394 |
- 'use strict';
- exports.__esModule = true;
- var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
- exports.default = Core;
- var _numbro = require('numbro');
- var _numbro2 = _interopRequireDefault(_numbro);
- var _element = require('./helpers/dom/element');
- var _setting = require('./helpers/setting');
- var _function = require('./helpers/function');
- var _mixed = require('./helpers/mixed');
- var _browser = require('./helpers/browser');
- var _dataMap = require('./dataMap');
- var _dataMap2 = _interopRequireDefault(_dataMap);
- var _editorManager = require('./editorManager');
- var _editorManager2 = _interopRequireDefault(_editorManager);
- var _eventManager = require('./eventManager');
- var _eventManager2 = _interopRequireDefault(_eventManager);
- var _object = require('./helpers/object');
- var _array = require('./helpers/array');
- var _plugins = require('./plugins');
- var _renderers = require('./renderers');
- var _validators = require('./validators');
- var _string = require('./helpers/string');
- var _number = require('./helpers/number');
- var _tableView = require('./tableView');
- var _tableView2 = _interopRequireDefault(_tableView);
- var _dataSource = require('./dataSource');
- var _dataSource2 = _interopRequireDefault(_dataSource);
- var _data = require('./helpers/data');
- var _recordTranslator = require('./utils/recordTranslator');
- var _src = require('./3rdparty/walkontable/src');
- var _pluginHooks = require('./pluginHooks');
- var _pluginHooks2 = _interopRequireDefault(_pluginHooks);
- var _defaultSettings = require('./defaultSettings');
- var _defaultSettings2 = _interopRequireDefault(_defaultSettings);
- var _cellTypes = require('./cellTypes');
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
- var activeGuid = null;
- /**
- * Handsontable constructor
- *
- * @core
- * @dependencies numbro
- * @constructor Core
- * @description
- *
- * After Handsontable is constructed, you can modify the grid behavior using the available public methods.
- *
- * ---
- * ## How to call methods
- *
- * These are 2 equal ways to call a Handsontable method:
- *
- * ```js
- * // all following examples assume that you constructed Handsontable like this
- * var ht = new Handsontable(document.getElementById('example1'), options);
- *
- * // now, to use setDataAtCell method, you can either:
- * ht.setDataAtCell(0, 0, 'new value');
- * ```
- *
- * Alternatively, you can call the method using jQuery wrapper (__obsolete__, requires initialization using our jQuery guide
- * ```js
- * $('#example1').handsontable('setDataAtCell', 0, 0, 'new value');
- * ```
- * ---
- */
- function Core(rootElement, userSettings) {
- var priv,
- datamap,
- dataSource,
- grid,
- selection,
- editorManager,
- instance = this,
- GridSettings = function GridSettings() {},
- eventManager = new _eventManager2.default(instance);
- (0, _object.extend)(GridSettings.prototype, _defaultSettings2.default.prototype); // create grid settings as a copy of default settings
- (0, _object.extend)(GridSettings.prototype, userSettings); // overwrite defaults with user settings
- (0, _object.extend)(GridSettings.prototype, expandType(userSettings));
- this.rootElement = rootElement;
- this.isHotTableEnv = (0, _element.isChildOfWebComponentTable)(this.rootElement);
- _eventManager2.default.isHotTableEnv = this.isHotTableEnv;
- this.container = document.createElement('DIV');
- this.renderCall = false;
- rootElement.insertBefore(this.container, rootElement.firstChild);
- this.guid = 'ht_' + (0, _string.randomString)(); // this is the namespace for global events
- var recordTranslator = (0, _recordTranslator.getTranslator)(instance);
- dataSource = new _dataSource2.default(instance);
- if (!this.rootElement.id || this.rootElement.id.substring(0, 3) === 'ht_') {
- this.rootElement.id = this.guid; // if root element does not have an id, assign a random id
- }
- priv = {
- cellSettings: [],
- columnSettings: [],
- columnsSettingConflicts: ['data', 'width'],
- settings: new GridSettings(), // current settings instance
- selRange: null, // exposed by public method `getSelectedRange`
- isPopulated: null,
- scrollable: null,
- firstRun: true
- };
- grid = {
- /**
- * Inserts or removes rows and columns
- *
- * @memberof Core#
- * @function alter
- * @private
- * @param {String} action Possible values: "insert_row", "insert_col", "remove_row", "remove_col"
- * @param {Number} index
- * @param {Number} amount
- * @param {String} [source] Optional. Source of hook runner.
- * @param {Boolean} [keepEmptyRows] Optional. Flag for preventing deletion of empty rows.
- */
- alter: function alter(action, index, amount, source, keepEmptyRows) {
- var delta;
- amount = amount || 1;
- function spliceWith(data, index, count, toInject) {
- var valueFactory = function valueFactory() {
- var result = void 0;
- if (toInject === 'array') {
- result = [];
- } else if (toInject === 'object') {
- result = {};
- }
- return result;
- };
- var spliceArgs = (0, _array.arrayMap)(new Array(count), function () {
- return valueFactory();
- });
- spliceArgs.unshift(index, 0);
- data.splice.apply(data, _toConsumableArray(spliceArgs));
- }
- /* eslint-disable no-case-declarations */
- switch (action) {
- case 'insert_row':
- var numberOfSourceRows = instance.countSourceRows();
- if (instance.getSettings().maxRows === numberOfSourceRows) {
- return;
- }
- index = (0, _mixed.isDefined)(index) ? index : numberOfSourceRows;
- delta = datamap.createRow(index, amount, source);
- spliceWith(priv.cellSettings, index, amount, 'array');
- if (delta) {
- if (selection.isSelected() && priv.selRange.from.row >= index) {
- priv.selRange.from.row += delta;
- selection.transformEnd(delta, 0); // will call render() internally
- } else {
- selection.refreshBorders(); // it will call render and prepare methods
- }
- }
- break;
- case 'insert_col':
- delta = datamap.createCol(index, amount, source);
- for (var row = 0, len = instance.countSourceRows(); row < len; row++) {
- if (priv.cellSettings[row]) {
- spliceWith(priv.cellSettings[row], index, amount);
- }
- }
- if (delta) {
- if (Array.isArray(instance.getSettings().colHeaders)) {
- var spliceArray = [index, 0];
- spliceArray.length += delta; // inserts empty (undefined) elements at the end of an array
- Array.prototype.splice.apply(instance.getSettings().colHeaders, spliceArray); // inserts empty (undefined) elements into the colHeader array
- }
- if (selection.isSelected() && priv.selRange.from.col >= index) {
- priv.selRange.from.col += delta;
- selection.transformEnd(0, delta); // will call render() internally
- } else {
- selection.refreshBorders(); // it will call render and prepare methods
- }
- }
- break;
- case 'remove_row':
- datamap.removeRow(index, amount, source);
- priv.cellSettings.splice(index, amount);
- var totalRows = instance.countRows();
- var fixedRowsTop = instance.getSettings().fixedRowsTop;
- if (fixedRowsTop >= index + 1) {
- instance.getSettings().fixedRowsTop -= Math.min(amount, fixedRowsTop - index);
- }
- var fixedRowsBottom = instance.getSettings().fixedRowsBottom;
- if (fixedRowsBottom && index >= totalRows - fixedRowsBottom) {
- instance.getSettings().fixedRowsBottom -= Math.min(amount, fixedRowsBottom);
- }
- grid.adjustRowsAndCols();
- selection.refreshBorders(); // it will call render and prepare methods
- break;
- case 'remove_col':
- var logicalColumnIndex = recordTranslator.toPhysicalColumn(index);
- datamap.removeCol(index, amount, source);
- for (var _row = 0, _len = instance.countSourceRows(); _row < _len; _row++) {
- if (priv.cellSettings[_row]) {
- // if row hasn't been rendered it wouldn't have cellSettings
- priv.cellSettings[_row].splice(logicalColumnIndex, amount);
- }
- }
- var fixedColumnsLeft = instance.getSettings().fixedColumnsLeft;
- if (fixedColumnsLeft >= index + 1) {
- instance.getSettings().fixedColumnsLeft -= Math.min(amount, fixedColumnsLeft - index);
- }
- if (Array.isArray(instance.getSettings().colHeaders)) {
- if (typeof logicalColumnIndex == 'undefined') {
- logicalColumnIndex = -1;
- }
- instance.getSettings().colHeaders.splice(logicalColumnIndex, amount);
- }
- grid.adjustRowsAndCols();
- selection.refreshBorders(); // it will call render and prepare methods
- break;
- default:
- throw new Error('There is no such action "' + action + '"');
- }
- if (!keepEmptyRows) {
- grid.adjustRowsAndCols(); // makes sure that we did not add rows that will be removed in next refresh
- }
- },
- /**
- * Makes sure there are empty rows at the bottom of the table
- */
- adjustRowsAndCols: function adjustRowsAndCols() {
- if (priv.settings.minRows) {
- // should I add empty rows to data source to meet minRows?
- var rows = instance.countRows();
- if (rows < priv.settings.minRows) {
- for (var r = 0, minRows = priv.settings.minRows; r < minRows - rows; r++) {
- datamap.createRow(instance.countRows(), 1, 'auto');
- }
- }
- }
- if (priv.settings.minSpareRows) {
- var emptyRows = instance.countEmptyRows(true);
- // should I add empty rows to meet minSpareRows?
- if (emptyRows < priv.settings.minSpareRows) {
- for (; emptyRows < priv.settings.minSpareRows && instance.countSourceRows() < priv.settings.maxRows; emptyRows++) {
- datamap.createRow(instance.countRows(), 1, 'auto');
- }
- }
- }
- {
- var emptyCols = void 0;
- // count currently empty cols
- if (priv.settings.minCols || priv.settings.minSpareCols) {
- emptyCols = instance.countEmptyCols(true);
- }
- // should I add empty cols to meet minCols?
- if (priv.settings.minCols && !priv.settings.columns && instance.countCols() < priv.settings.minCols) {
- for (; instance.countCols() < priv.settings.minCols; emptyCols++) {
- datamap.createCol(instance.countCols(), 1, 'auto');
- }
- }
- // should I add empty cols to meet minSpareCols?
- if (priv.settings.minSpareCols && !priv.settings.columns && instance.dataType === 'array' && emptyCols < priv.settings.minSpareCols) {
- for (; emptyCols < priv.settings.minSpareCols && instance.countCols() < priv.settings.maxCols; emptyCols++) {
- datamap.createCol(instance.countCols(), 1, 'auto');
- }
- }
- }
- var rowCount = instance.countRows();
- var colCount = instance.countCols();
- if (rowCount === 0 || colCount === 0) {
- selection.deselect();
- }
- if (selection.isSelected()) {
- var selectionChanged = false;
- var fromRow = priv.selRange.from.row;
- var fromCol = priv.selRange.from.col;
- var toRow = priv.selRange.to.row;
- var toCol = priv.selRange.to.col;
- // if selection is outside, move selection to last row
- if (fromRow > rowCount - 1) {
- fromRow = rowCount - 1;
- selectionChanged = true;
- if (toRow > fromRow) {
- toRow = fromRow;
- }
- } else if (toRow > rowCount - 1) {
- toRow = rowCount - 1;
- selectionChanged = true;
- if (fromRow > toRow) {
- fromRow = toRow;
- }
- }
- // if selection is outside, move selection to last row
- if (fromCol > colCount - 1) {
- fromCol = colCount - 1;
- selectionChanged = true;
- if (toCol > fromCol) {
- toCol = fromCol;
- }
- } else if (toCol > colCount - 1) {
- toCol = colCount - 1;
- selectionChanged = true;
- if (fromCol > toCol) {
- fromCol = toCol;
- }
- }
- if (selectionChanged) {
- instance.selectCell(fromRow, fromCol, toRow, toCol);
- }
- }
- if (instance.view) {
- instance.view.wt.wtOverlays.adjustElementsSize();
- }
- },
- /**
- * Populate the data from the provided 2d array from the given cell coordinates.
- *
- * @private
- * @param {Object} start Start selection position.
- * @param {Array} input 2d data array.
- * @param {Object} [end] End selection position (only for drag-down mode).
- * @param {String} [source="populateFromArray"] Source information string.
- * @param {String} [method="overwrite"] Populate method. Possible options: `shift_down`, `shift_right`, `overwrite`.
- * @param {String} direction (left|right|up|down) String specifying the direction.
- * @param {Array} deltas The deltas array.
- * @returns {Object|undefined} ending td in pasted area (only if any cell was changed).
- */
- populateFromArray: function populateFromArray(start, input, end, source, method, direction, deltas) {
- var r,
- rlen,
- c,
- clen,
- setData = [],
- current = {};
- rlen = input.length;
- if (rlen === 0) {
- return false;
- }
- var repeatCol,
- repeatRow,
- cmax,
- rmax,
- baseEnd = {
- row: end === null ? null : end.row,
- col: end === null ? null : end.col
- };
- /* eslint-disable no-case-declarations */
- // insert data with specified pasteMode method
- switch (method) {
- case 'shift_down':
- repeatCol = end ? end.col - start.col + 1 : 0;
- repeatRow = end ? end.row - start.row + 1 : 0;
- input = (0, _data.translateRowsToColumns)(input);
- for (c = 0, clen = input.length, cmax = Math.max(clen, repeatCol); c < cmax; c++) {
- if (c < clen) {
- var _instance;
- for (r = 0, rlen = input[c].length; r < repeatRow - rlen; r++) {
- input[c].push(input[c][r % rlen]);
- }
- input[c].unshift(start.col + c, start.row, 0);
- (_instance = instance).spliceCol.apply(_instance, _toConsumableArray(input[c]));
- } else {
- var _instance2;
- input[c % clen][0] = start.col + c;
- (_instance2 = instance).spliceCol.apply(_instance2, _toConsumableArray(input[c % clen]));
- }
- }
- break;
- case 'shift_right':
- repeatCol = end ? end.col - start.col + 1 : 0;
- repeatRow = end ? end.row - start.row + 1 : 0;
- for (r = 0, rlen = input.length, rmax = Math.max(rlen, repeatRow); r < rmax; r++) {
- if (r < rlen) {
- var _instance3;
- for (c = 0, clen = input[r].length; c < repeatCol - clen; c++) {
- input[r].push(input[r][c % clen]);
- }
- input[r].unshift(start.row + r, start.col, 0);
- (_instance3 = instance).spliceRow.apply(_instance3, _toConsumableArray(input[r]));
- } else {
- var _instance4;
- input[r % rlen][0] = start.row + r;
- (_instance4 = instance).spliceRow.apply(_instance4, _toConsumableArray(input[r % rlen]));
- }
- }
- break;
- case 'overwrite':
- default:
- // overwrite and other not specified options
- current.row = start.row;
- current.col = start.col;
- var selected = { // selected range
- row: end && start ? end.row - start.row + 1 : 1,
- col: end && start ? end.col - start.col + 1 : 1
- };
- var skippedRow = 0;
- var skippedColumn = 0;
- var pushData = true;
- var cellMeta = void 0;
- var getInputValue = function getInputValue(row) {
- var col = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
- var rowValue = input[row % input.length];
- if (col !== null) {
- return rowValue[col % rowValue.length];
- }
- return rowValue;
- };
- var rowInputLength = input.length;
- var rowSelectionLength = end ? end.row - start.row + 1 : 0;
- if (end) {
- rlen = rowSelectionLength;
- } else {
- rlen = Math.max(rowInputLength, rowSelectionLength);
- }
- for (r = 0; r < rlen; r++) {
- if (end && current.row > end.row && rowSelectionLength > rowInputLength || !priv.settings.allowInsertRow && current.row > instance.countRows() - 1 || current.row >= priv.settings.maxRows) {
- break;
- }
- var logicalRow = r - skippedRow;
- var colInputLength = getInputValue(logicalRow).length;
- var colSelectionLength = end ? end.col - start.col + 1 : 0;
- if (end) {
- clen = colSelectionLength;
- } else {
- clen = Math.max(colInputLength, colSelectionLength);
- }
- current.col = start.col;
- cellMeta = instance.getCellMeta(current.row, current.col);
- if ((source === 'CopyPaste.paste' || source === 'Autofill.autofill') && cellMeta.skipRowOnPaste) {
- skippedRow++;
- current.row++;
- rlen++;
- /* eslint-disable no-continue */
- continue;
- }
- skippedColumn = 0;
- for (c = 0; c < clen; c++) {
- if (end && current.col > end.col && colSelectionLength > colInputLength || !priv.settings.allowInsertColumn && current.col > instance.countCols() - 1 || current.col >= priv.settings.maxCols) {
- break;
- }
- cellMeta = instance.getCellMeta(current.row, current.col);
- if ((source === 'CopyPaste.paste' || source === 'Autofill.fill') && cellMeta.skipColumnOnPaste) {
- skippedColumn++;
- current.col++;
- clen++;
- continue;
- }
- if (cellMeta.readOnly) {
- current.col++;
- /* eslint-disable no-continue */
- continue;
- }
- var logicalColumn = c - skippedColumn;
- var value = getInputValue(logicalRow, logicalColumn);
- var orgValue = instance.getDataAtCell(current.row, current.col);
- var index = {
- row: logicalRow,
- col: logicalColumn
- };
- if (source === 'Autofill.fill') {
- var result = instance.runHooks('beforeAutofillInsidePopulate', index, direction, input, deltas, {}, selected);
- if (result) {
- value = (0, _mixed.isUndefined)(result.value) ? value : result.value;
- }
- }
- if (value !== null && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object') {
- if (orgValue === null || (typeof orgValue === 'undefined' ? 'undefined' : _typeof(orgValue)) !== 'object') {
- pushData = false;
- } else {
- var orgValueSchema = (0, _object.duckSchema)(orgValue[0] || orgValue);
- var valueSchema = (0, _object.duckSchema)(value[0] || value);
- /* eslint-disable max-depth */
- if ((0, _object.isObjectEquals)(orgValueSchema, valueSchema)) {
- value = (0, _object.deepClone)(value);
- } else {
- pushData = false;
- }
- }
- } else if (orgValue !== null && (typeof orgValue === 'undefined' ? 'undefined' : _typeof(orgValue)) === 'object') {
- pushData = false;
- }
- if (pushData) {
- setData.push([current.row, current.col, value]);
- }
- pushData = true;
- current.col++;
- }
- current.row++;
- }
- instance.setDataAtCell(setData, null, null, source || 'populateFromArray');
- break;
- }
- }
- };
- /* eslint-disable no-multi-assign */
- this.selection = selection = { // this public assignment is only temporary
- inProgress: false,
- selectedHeader: {
- cols: false,
- rows: false
- },
- /**
- * @param {Boolean} [rows=false]
- * @param {Boolean} [cols=false]
- * @param {Boolean} [corner=false]
- */
- setSelectedHeaders: function setSelectedHeaders() {
- var rows = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
- var cols = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
- var corner = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
- instance.selection.selectedHeader.rows = rows;
- instance.selection.selectedHeader.cols = cols;
- instance.selection.selectedHeader.corner = corner;
- },
- /**
- * Sets inProgress to `true`. This enables onSelectionEnd and onSelectionEndByProp to function as desired.
- */
- begin: function begin() {
- instance.selection.inProgress = true;
- },
- /**
- * Sets inProgress to `false`. Triggers onSelectionEnd and onSelectionEndByProp.
- */
- finish: function finish() {
- var sel = instance.getSelected();
- instance.runHooks('afterSelectionEnd', sel[0], sel[1], sel[2], sel[3]);
- instance.runHooks('afterSelectionEndByProp', sel[0], instance.colToProp(sel[1]), sel[2], instance.colToProp(sel[3]));
- instance.selection.inProgress = false;
- },
- /**
- * @returns {Boolean}
- */
- isInProgress: function isInProgress() {
- return instance.selection.inProgress;
- },
- /**
- * Starts selection range on given td object.
- *
- * @param {CellCoords} coords
- * @param keepEditorOpened
- */
- setRangeStart: function setRangeStart(coords, keepEditorOpened) {
- instance.runHooks('beforeSetRangeStart', coords);
- priv.selRange = new _src.CellRange(coords, coords, coords);
- selection.setRangeEnd(coords, null, keepEditorOpened);
- },
- /**
- * Starts selection range on given td object.
- *
- * @param {CellCoords} coords
- * @param keepEditorOpened
- */
- setRangeStartOnly: function setRangeStartOnly(coords) {
- instance.runHooks('beforeSetRangeStartOnly', coords);
- priv.selRange = new _src.CellRange(coords, coords, coords);
- },
- /**
- * Ends selection range on given td object.
- *
- * @param {CellCoords} coords
- * @param {Boolean} [scrollToCell=true] If `true`, viewport will be scrolled to range end
- * @param {Boolean} [keepEditorOpened] If `true`, cell editor will be still opened after changing selection range
- */
- setRangeEnd: function setRangeEnd(coords, scrollToCell, keepEditorOpened) {
- if (priv.selRange === null) {
- return;
- }
- var disableVisualSelection,
- isHeaderSelected = false,
- areCoordsPositive = true;
- var firstVisibleRow = instance.view.wt.wtTable.getFirstVisibleRow();
- var firstVisibleColumn = instance.view.wt.wtTable.getFirstVisibleColumn();
- var newRangeCoords = {
- row: null,
- col: null
- };
- // trigger handlers
- instance.runHooks('beforeSetRangeEnd', coords);
- instance.selection.begin();
- newRangeCoords.row = coords.row < 0 ? firstVisibleRow : coords.row;
- newRangeCoords.col = coords.col < 0 ? firstVisibleColumn : coords.col;
- priv.selRange.to = new _src.CellCoords(newRangeCoords.row, newRangeCoords.col);
- if (!priv.settings.multiSelect) {
- priv.selRange.from = coords;
- }
- // set up current selection
- instance.view.wt.selections.current.clear();
- disableVisualSelection = instance.getCellMeta(priv.selRange.highlight.row, priv.selRange.highlight.col).disableVisualSelection;
- if (typeof disableVisualSelection === 'string') {
- disableVisualSelection = [disableVisualSelection];
- }
- if (disableVisualSelection === false || Array.isArray(disableVisualSelection) && disableVisualSelection.indexOf('current') === -1) {
- instance.view.wt.selections.current.add(priv.selRange.highlight);
- }
- // set up area selection
- instance.view.wt.selections.area.clear();
- if ((disableVisualSelection === false || Array.isArray(disableVisualSelection) && disableVisualSelection.indexOf('area') === -1) && selection.isMultiple()) {
- instance.view.wt.selections.area.add(priv.selRange.from);
- instance.view.wt.selections.area.add(priv.selRange.to);
- }
- // set up highlight
- if (priv.settings.currentHeaderClassName || priv.settings.currentRowClassName || priv.settings.currentColClassName) {
- instance.view.wt.selections.highlight.clear();
- instance.view.wt.selections.highlight.add(priv.selRange.from);
- instance.view.wt.selections.highlight.add(priv.selRange.to);
- }
- var preventScrolling = (0, _object.createObjectPropListener)('value');
- // trigger handlers
- instance.runHooks('afterSelection', priv.selRange.from.row, priv.selRange.from.col, priv.selRange.to.row, priv.selRange.to.col, preventScrolling);
- instance.runHooks('afterSelectionByProp', priv.selRange.from.row, datamap.colToProp(priv.selRange.from.col), priv.selRange.to.row, datamap.colToProp(priv.selRange.to.col), preventScrolling);
- if (priv.selRange.from.row === 0 && priv.selRange.to.row === instance.countRows() - 1 && instance.countRows() > 1 || priv.selRange.from.col === 0 && priv.selRange.to.col === instance.countCols() - 1 && instance.countCols() > 1) {
- isHeaderSelected = true;
- }
- if (coords.row < 0 || coords.col < 0) {
- areCoordsPositive = false;
- }
- if (preventScrolling.isTouched()) {
- scrollToCell = !preventScrolling.value;
- }
- if (scrollToCell !== false && !isHeaderSelected && areCoordsPositive) {
- if (priv.selRange.from && !selection.isMultiple()) {
- instance.view.scrollViewport(priv.selRange.from);
- } else {
- instance.view.scrollViewport(coords);
- }
- }
- if (selection.selectedHeader.rows && selection.selectedHeader.cols) {
- (0, _element.addClass)(instance.rootElement, ['ht__selection--rows', 'ht__selection--columns']);
- } else if (selection.selectedHeader.rows) {
- (0, _element.removeClass)(instance.rootElement, 'ht__selection--columns');
- (0, _element.addClass)(instance.rootElement, 'ht__selection--rows');
- } else if (selection.selectedHeader.cols) {
- (0, _element.removeClass)(instance.rootElement, 'ht__selection--rows');
- (0, _element.addClass)(instance.rootElement, 'ht__selection--columns');
- } else {
- (0, _element.removeClass)(instance.rootElement, ['ht__selection--rows', 'ht__selection--columns']);
- }
- selection.refreshBorders(null, keepEditorOpened);
- },
- /**
- * Destroys editor, redraws borders around cells, prepares editor.
- *
- * @param {Boolean} [revertOriginal]
- * @param {Boolean} [keepEditor]
- */
- refreshBorders: function refreshBorders(revertOriginal, keepEditor) {
- if (!keepEditor) {
- editorManager.destroyEditor(revertOriginal);
- }
- instance.view.render();
- if (selection.isSelected() && !keepEditor) {
- editorManager.prepareEditor();
- }
- },
- /**
- * Returns information if we have a multiselection.
- *
- * @returns {Boolean}
- */
- isMultiple: function isMultiple() {
- var isMultiple = !(priv.selRange.to.col === priv.selRange.from.col && priv.selRange.to.row === priv.selRange.from.row),
- modifier = instance.runHooks('afterIsMultipleSelection', isMultiple);
- if (isMultiple) {
- return modifier;
- }
- },
- /**
- * Selects cell relative to current cell (if possible).
- */
- transformStart: function transformStart(rowDelta, colDelta, force, keepEditorOpened) {
- var delta = new _src.CellCoords(rowDelta, colDelta),
- rowTransformDir = 0,
- colTransformDir = 0,
- totalRows,
- totalCols,
- coords,
- fixedRowsBottom;
- instance.runHooks('modifyTransformStart', delta);
- totalRows = instance.countRows();
- totalCols = instance.countCols();
- fixedRowsBottom = instance.getSettings().fixedRowsBottom;
- if (priv.selRange.highlight.row + rowDelta > totalRows - 1) {
- if (force && priv.settings.minSpareRows > 0 && !(fixedRowsBottom && priv.selRange.highlight.row >= totalRows - fixedRowsBottom - 1)) {
- instance.alter('insert_row', totalRows);
- totalRows = instance.countRows();
- } else if (priv.settings.autoWrapCol) {
- delta.row = 1 - totalRows;
- delta.col = priv.selRange.highlight.col + delta.col == totalCols - 1 ? 1 - totalCols : 1;
- }
- } else if (priv.settings.autoWrapCol && priv.selRange.highlight.row + delta.row < 0 && priv.selRange.highlight.col + delta.col >= 0) {
- delta.row = totalRows - 1;
- delta.col = priv.selRange.highlight.col + delta.col == 0 ? totalCols - 1 : -1;
- }
- if (priv.selRange.highlight.col + delta.col > totalCols - 1) {
- if (force && priv.settings.minSpareCols > 0) {
- instance.alter('insert_col', totalCols);
- totalCols = instance.countCols();
- } else if (priv.settings.autoWrapRow) {
- delta.row = priv.selRange.highlight.row + delta.row == totalRows - 1 ? 1 - totalRows : 1;
- delta.col = 1 - totalCols;
- }
- } else if (priv.settings.autoWrapRow && priv.selRange.highlight.col + delta.col < 0 && priv.selRange.highlight.row + delta.row >= 0) {
- delta.row = priv.selRange.highlight.row + delta.row == 0 ? totalRows - 1 : -1;
- delta.col = totalCols - 1;
- }
- coords = new _src.CellCoords(priv.selRange.highlight.row + delta.row, priv.selRange.highlight.col + delta.col);
- if (coords.row < 0) {
- rowTransformDir = -1;
- coords.row = 0;
- } else if (coords.row > 0 && coords.row >= totalRows) {
- rowTransformDir = 1;
- coords.row = totalRows - 1;
- }
- if (coords.col < 0) {
- colTransformDir = -1;
- coords.col = 0;
- } else if (coords.col > 0 && coords.col >= totalCols) {
- colTransformDir = 1;
- coords.col = totalCols - 1;
- }
- instance.runHooks('afterModifyTransformStart', coords, rowTransformDir, colTransformDir);
- selection.setRangeStart(coords, keepEditorOpened);
- },
- /**
- * Sets selection end cell relative to current selection end cell (if possible).
- */
- transformEnd: function transformEnd(rowDelta, colDelta) {
- var delta = new _src.CellCoords(rowDelta, colDelta),
- rowTransformDir = 0,
- colTransformDir = 0,
- totalRows,
- totalCols,
- coords;
- instance.runHooks('modifyTransformEnd', delta);
- totalRows = instance.countRows();
- totalCols = instance.countCols();
- coords = new _src.CellCoords(priv.selRange.to.row + delta.row, priv.selRange.to.col + delta.col);
- if (coords.row < 0) {
- rowTransformDir = -1;
- coords.row = 0;
- } else if (coords.row > 0 && coords.row >= totalRows) {
- rowTransformDir = 1;
- coords.row = totalRows - 1;
- }
- if (coords.col < 0) {
- colTransformDir = -1;
- coords.col = 0;
- } else if (coords.col > 0 && coords.col >= totalCols) {
- colTransformDir = 1;
- coords.col = totalCols - 1;
- }
- instance.runHooks('afterModifyTransformEnd', coords, rowTransformDir, colTransformDir);
- selection.setRangeEnd(coords, true);
- },
- /**
- * Returns `true` if currently there is a selection on screen, `false` otherwise.
- *
- * @returns {Boolean}
- */
- isSelected: function isSelected() {
- return priv.selRange !== null;
- },
- /**
- * Returns `true` if coords is within current selection coords.
- *
- * @param {CellCoords} coords
- * @returns {Boolean}
- */
- inInSelection: function inInSelection(coords) {
- if (!selection.isSelected()) {
- return false;
- }
- return priv.selRange.includes(coords);
- },
- /**
- * Deselects all selected cells
- */
- deselect: function deselect() {
- if (!selection.isSelected()) {
- return;
- }
- instance.selection.inProgress = false; // needed by HT inception
- priv.selRange = null;
- instance.view.wt.selections.current.clear();
- instance.view.wt.selections.area.clear();
- if (priv.settings.currentHeaderClassName || priv.settings.currentRowClassName || priv.settings.currentColClassName) {
- instance.view.wt.selections.highlight.clear();
- }
- editorManager.destroyEditor();
- selection.refreshBorders();
- (0, _element.removeClass)(instance.rootElement, ['ht__selection--rows', 'ht__selection--columns']);
- instance.runHooks('afterDeselect');
- },
- /**
- * Select all cells
- */
- selectAll: function selectAll() {
- if (!priv.settings.multiSelect) {
- return;
- }
- selection.setSelectedHeaders(true, true, true);
- selection.setRangeStart(new _src.CellCoords(0, 0));
- selection.setRangeEnd(new _src.CellCoords(instance.countRows() - 1, instance.countCols() - 1), false);
- },
- /**
- * Deletes data from selected cells
- */
- empty: function empty() {
- if (!selection.isSelected()) {
- return;
- }
- var topLeft = priv.selRange.getTopLeftCorner();
- var bottomRight = priv.selRange.getBottomRightCorner();
- var r,
- c,
- changes = [];
- for (r = topLeft.row; r <= bottomRight.row; r++) {
- for (c = topLeft.col; c <= bottomRight.col; c++) {
- if (!instance.getCellMeta(r, c).readOnly) {
- changes.push([r, c, '']);
- }
- }
- }
- instance.setDataAtCell(changes);
- }
- };
- this.init = function () {
- dataSource.setData(priv.settings.data);
- instance.runHooks('beforeInit');
- if ((0, _browser.isMobileBrowser)()) {
- (0, _element.addClass)(instance.rootElement, 'mobile');
- }
- this.updateSettings(priv.settings, true);
- this.view = new _tableView2.default(this);
- editorManager = new _editorManager2.default(instance, priv, selection, datamap);
- this.forceFullRender = true; // used when data was changed
- instance.runHooks('init');
- this.view.render();
- if (_typeof(priv.firstRun) === 'object') {
- instance.runHooks('afterChange', priv.firstRun[0], priv.firstRun[1]);
- priv.firstRun = false;
- }
- instance.runHooks('afterInit');
- };
- function ValidatorsQueue() {
- // moved this one level up so it can be used in any function here. Probably this should be moved to a separate file
- var resolved = false;
- return {
- validatorsInQueue: 0,
- valid: true,
- addValidatorToQueue: function addValidatorToQueue() {
- this.validatorsInQueue++;
- resolved = false;
- },
- removeValidatorFormQueue: function removeValidatorFormQueue() {
- this.validatorsInQueue = this.validatorsInQueue - 1 < 0 ? 0 : this.validatorsInQueue - 1;
- this.checkIfQueueIsEmpty();
- },
- onQueueEmpty: function onQueueEmpty(valid) {},
- checkIfQueueIsEmpty: function checkIfQueueIsEmpty() {
- if (this.validatorsInQueue == 0 && resolved == false) {
- resolved = true;
- this.onQueueEmpty(this.valid);
- }
- }
- };
- }
- function validateChanges(changes, source, callback) {
- var waitingForValidator = new ValidatorsQueue();
- waitingForValidator.onQueueEmpty = resolve;
- for (var i = changes.length - 1; i >= 0; i--) {
- if (changes[i] === null) {
- changes.splice(i, 1);
- } else {
- var row = changes[i][0];
- var col = datamap.propToCol(changes[i][1]);
- var cellProperties = instance.getCellMeta(row, col);
- if (cellProperties.type === 'numeric' && typeof changes[i][3] === 'string') {
- if (changes[i][3].length > 0 && (/^-?[\d\s]*(\.|,)?\d*$/.test(changes[i][3]) || cellProperties.format)) {
- var len = changes[i][3].length;
- if ((0, _mixed.isUndefined)(cellProperties.language)) {
- _numbro2.default.culture('en-US');
- } else if (changes[i][3].indexOf('.') === len - 3 && changes[i][3].indexOf(',') === -1) {
- // this input in format XXXX.XX is likely to come from paste. Let's parse it using international rules
- _numbro2.default.culture('en-US');
- } else {
- _numbro2.default.culture(cellProperties.language);
- }
- var _numbro$cultureData = _numbro2.default.cultureData(_numbro2.default.culture()),
- delimiters = _numbro$cultureData.delimiters;
- // try to parse to float - https://github.com/foretagsplatsen/numbro/pull/183
- if (_numbro2.default.validate(changes[i][3]) && !isNaN(changes[i][3])) {
- changes[i][3] = parseFloat(changes[i][3]);
- } else {
- changes[i][3] = (0, _numbro2.default)().unformat(changes[i][3]) || changes[i][3];
- }
- }
- }
- /* eslint-disable no-loop-func */
- if (instance.getCellValidator(cellProperties)) {
- waitingForValidator.addValidatorToQueue();
- instance.validateCell(changes[i][3], cellProperties, function (i, cellProperties) {
- return function (result) {
- if (typeof result !== 'boolean') {
- throw new Error('Validation error: result is not boolean');
- }
- if (result === false && cellProperties.allowInvalid === false) {
- changes.splice(i, 1); // cancel the change
- cellProperties.valid = true; // we cancelled the change, so cell value is still valid
- var cell = instance.getCell(cellProperties.row, cellProperties.col);
- (0, _element.removeClass)(cell, instance.getSettings().invalidCellClassName);
- --i;
- }
- waitingForValidator.removeValidatorFormQueue();
- };
- }(i, cellProperties), source);
- }
- }
- }
- waitingForValidator.checkIfQueueIsEmpty();
- function resolve() {
- var beforeChangeResult;
- if (changes.length) {
- beforeChangeResult = instance.runHooks('beforeChange', changes, source);
- if ((0, _function.isFunction)(beforeChangeResult)) {
- console.warn('Your beforeChange callback returns a function. It\'s not supported since Handsontable 0.12.1 (and the returned function will not be executed).');
- } else if (beforeChangeResult === false) {
- changes.splice(0, changes.length); // invalidate all changes (remove everything from array)
- }
- }
- callback(); // called when async validators are resolved and beforeChange was not async
- }
- }
- /**
- * Internal function to apply changes. Called after validateChanges
- *
- * @private
- * @param {Array} changes Array in form of [row, prop, oldValue, newValue]
- * @param {String} source String that identifies how this change will be described in changes array (useful in onChange callback)
- * @fires Hooks#beforeChangeRender
- * @fires Hooks#afterChange
- */
- function applyChanges(changes, source) {
- var i = changes.length - 1;
- if (i < 0) {
- return;
- }
- for (; i >= 0; i--) {
- var skipThisChange = false;
- if (changes[i] === null) {
- changes.splice(i, 1);
- /* eslint-disable no-continue */
- continue;
- }
- if (changes[i][2] == null && changes[i][3] == null) {
- /* eslint-disable no-continue */
- continue;
- }
- if (priv.settings.allowInsertRow) {
- while (changes[i][0] > instance.countRows() - 1) {
- var numberOfCreatedRows = datamap.createRow(void 0, void 0, source);
- if (numberOfCreatedRows === 0) {
- skipThisChange = true;
- break;
- }
- }
- }
- if (skipThisChange) {
- /* eslint-disable no-continue */
- continue;
- }
- if (instance.dataType === 'array' && (!priv.settings.columns || priv.settings.columns.length === 0) && priv.settings.allowInsertColumn) {
- while (datamap.propToCol(changes[i][1]) > instance.countCols() - 1) {
- datamap.createCol(void 0, void 0, source);
- }
- }
- datamap.set(changes[i][0], changes[i][1], changes[i][3]);
- }
- instance.forceFullRender = true; // used when data was changed
- grid.adjustRowsAndCols();
- instance.runHooks('beforeChangeRender', changes, source);
- selection.refreshBorders(null, true);
- instance.view.wt.wtOverlays.adjustElementsSize();
- instance.runHooks('afterChange', changes, source || 'edit');
- var activeEditor = instance.getActiveEditor();
- if (activeEditor && (0, _mixed.isDefined)(activeEditor.refreshValue)) {
- activeEditor.refreshValue();
- }
- }
- this.validateCell = function (value, cellProperties, callback, source) {
- var validator = instance.getCellValidator(cellProperties);
- function done(valid) {
- var col = cellProperties.visualCol,
- row = cellProperties.visualRow,
- td = instance.getCell(row, col, true);
- if (td && td.nodeName != 'TH') {
- instance.view.wt.wtSettings.settings.cellRenderer(row, col, td);
- }
- callback(valid);
- }
- if ((0, _mixed.isRegExp)(validator)) {
- validator = function (validator) {
- return function (value, callback) {
- callback(validator.test(value));
- };
- }(validator);
- }
- if ((0, _function.isFunction)(validator)) {
- value = instance.runHooks('beforeValidate', value, cellProperties.visualRow, cellProperties.prop, source);
- // To provide consistent behaviour, validation should be always asynchronous
- instance._registerTimeout(setTimeout(function () {
- validator.call(cellProperties, value, function (valid) {
- valid = instance.runHooks('afterValidate', valid, value, cellProperties.visualRow, cellProperties.prop, source);
- cellProperties.valid = valid;
- done(valid);
- instance.runHooks('postAfterValidate', valid, value, cellProperties.visualRow, cellProperties.prop, source);
- });
- }, 0));
- } else {
- // resolve callback even if validator function was not found
- instance._registerTimeout(setTimeout(function () {
- cellProperties.valid = true;
- done(cellProperties.valid);
- }, 0));
- }
- };
- function setDataInputToArray(row, propOrCol, value) {
- if ((typeof row === 'undefined' ? 'undefined' : _typeof(row)) === 'object') {
- // is it an array of changes
- return row;
- }
- return [[row, propOrCol, value]];
- }
- /**
- * @description
- * Set new value to a cell. To change many cells at once, pass an array of `changes` in format `[[row, col, value], ...]` as
- * the only parameter. `col` is the index of a __visible__ column (note that if columns were reordered,
- * the current visible order will be used). `source` is a flag for before/afterChange events. If you pass only array of
- * changes then `source` could be set as second parameter.
- *
- * @memberof Core#
- * @function setDataAtCell
- * @param {Number|Array} row Row index or array of changes in format `[[row, col, value], ...]`.
- * @param {Number} col Column index.
- * @param {String} value New value.
- * @param {String} [source] String that identifies how this change will be described in the changes array (useful in onAfterChange or onBeforeChange callback).
- */
- this.setDataAtCell = function (row, col, value, source) {
- var input = setDataInputToArray(row, col, value),
- i,
- ilen,
- changes = [],
- prop;
- for (i = 0, ilen = input.length; i < ilen; i++) {
- if (_typeof(input[i]) !== 'object') {
- throw new Error('Method `setDataAtCell` accepts row number or changes array of arrays as its first parameter');
- }
- if (typeof input[i][1] !== 'number') {
- throw new Error('Method `setDataAtCell` accepts row and column number as its parameters. If you want to use object property name, use method `setDataAtRowProp`');
- }
- prop = datamap.colToProp(input[i][1]);
- changes.push([input[i][0], prop, dataSource.getAtCell(recordTranslator.toPhysicalRow(input[i][0]), input[i][1]), input[i][2]]);
- }
- if (!source && (typeof row === 'undefined' ? 'undefined' : _typeof(row)) === 'object') {
- source = col;
- }
- instance.runHooks('afterSetDataAtCell', changes, source);
- validateChanges(changes, source, function () {
- applyChanges(changes, source);
- });
- };
- /**
- * @description
- * Set new value to a cell. To change many cells at once, pass an array of `changes` in format `[[row, prop, value], ...]` as
- * the only parameter. `prop` is the name of the object property (e.g. `first.name`). `source` is a flag for before/afterChange events.
- * If you pass only array of changes then `source` could be set as second parameter.
- *
- * @memberof Core#
- * @function setDataAtRowProp
- * @param {Number|Array} row Row index or array of changes in format `[[row, prop, value], ...]`.
- * @param {String} prop Property name or the source string.
- * @param {String} value Value to be set.
- * @param {String} [source] String that identifies how this change will be described in changes array (useful in onChange callback).
- */
- this.setDataAtRowProp = function (row, prop, value, source) {
- var input = setDataInputToArray(row, prop, value),
- i,
- ilen,
- changes = [];
- for (i = 0, ilen = input.length; i < ilen; i++) {
- changes.push([input[i][0], input[i][1], dataSource.getAtCell(recordTranslator.toPhysicalRow(input[i][0]), input[i][1]), input[i][2]]);
- }
- if (!source && (typeof row === 'undefined' ? 'undefined' : _typeof(row)) === 'object') {
- source = prop;
- }
- instance.runHooks('afterSetDataAtRowProp', changes, source);
- validateChanges(changes, source, function () {
- applyChanges(changes, source);
- });
- };
- /**
- * Listen to the keyboard input on document body.
- *
- * @memberof Core#
- * @function listen
- * @since 0.11
- */
- this.listen = function () {
- activeGuid = instance.guid;
- };
- /**
- * Stop listening to keyboard input on the document body.
- *
- * @memberof Core#
- * @function unlisten
- * @since 0.11
- */
- this.unlisten = function () {
- activeGuid = null;
- };
- /**
- * Returns `true` if the current Handsontable instance is listening to keyboard input on document body.
- *
- * @memberof Core#
- * @function isListening
- * @since 0.11
- * @returns {Boolean} `true` if the instance is listening, `false` otherwise.
- */
- this.isListening = function () {
- return activeGuid === instance.guid;
- };
- /**
- * Destroys the current editor, renders and selects the current cell.
- *
- * @memberof Core#
- * @function destroyEditor
- * @param {Boolean} [revertOriginal] If != `true`, edited data is saved. Otherwise the previous value is restored.
- */
- this.destroyEditor = function (revertOriginal) {
- selection.refreshBorders(revertOriginal);
- };
- /**
- * Populate cells at position with 2D input array (e.g. `[[1, 2], [3, 4]]`).
- * Use `endRow`, `endCol` when you want to cut input when a certain row is reached.
- * Optional `source` parameter (default value "populateFromArray") is used to identify this call in the resulting events (beforeChange, afterChange).
- * Optional `populateMethod` parameter (default value "overwrite", possible values "shift_down" and "shift_right")
- * has the same effect as pasteMode option {@link Options#pasteMode}
- *
- * @memberof Core#
- * @function populateFromArray
- * @since 0.9.0
- * @param {Number} row Start row
- * @param {Number} col Start column
- * @param {Array} input 2d array
- * @param {Number} [endRow] End row (use when you want to cut input when certain row is reached)
- * @param {Number} [endCol] End column (use when you want to cut input when certain column is reached)
- * @param {String} [source="populateFromArray"] Source string.
- * @param {String} [method="overwrite"] Populate method. Possible options: `shift_down`, `shift_right`, `overwrite`.
- * @param {String} direction Populate direction. (left|right|up|down)
- * @param {Array} deltas Deltas array.
- * @returns {Object|undefined} The ending TD element in pasted area (only if any cells were changed).
- */
- this.populateFromArray = function (row, col, input, endRow, endCol, source, method, direction, deltas) {
- var c;
- if (!((typeof input === 'undefined' ? 'undefined' : _typeof(input)) === 'object' && _typeof(input[0]) === 'object')) {
- throw new Error('populateFromArray parameter `input` must be an array of arrays'); // API changed in 0.9-beta2, let's check if you use it correctly
- }
- c = typeof endRow === 'number' ? new _src.CellCoords(endRow, endCol) : null;
- return grid.populateFromArray(new _src.CellCoords(row, col), input, c, source, method, direction, deltas);
- };
- /**
- * Adds/removes data from the column. This function is modelled after Array.splice.
- * Parameter `col` is the index of the column in which do you want to do splice.
- * Parameter `index` is the row index at which to start changing the array.
- * If negative, will begin that many elements from the end. Parameter `amount`, is the number of the old array elements to remove.
- * If the amount is 0, no elements are removed. Fourth and further parameters are the `elements` to add to the array.
- * If you don't specify any elements, spliceCol simply removes elements from the array.
- * {@link DataMap#spliceCol}
- *
- * @memberof Core#
- * @function spliceCol
- * @since 0.9-beta2
- * @param {Number} col Index of the column in which do you want to do splice.
- * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end.
- * @param {Number} amount An integer indicating the number of old array elements to remove. If amount is 0, no elements are removed.
- * @param {*} [elements] The elements to add to the array. If you don't specify any elements, spliceCol simply removes elements from the array.
- */
- this.spliceCol = function (col, index, amount /* , elements... */) {
- var _datamap;
- return (_datamap = datamap).spliceCol.apply(_datamap, arguments);
- };
- /**
- * Adds/removes data from the row. This function works is modelled after Array.splice.
- * Parameter `row` is the index of row in which do you want to do splice.
- * Parameter `index` is the column index at which to start changing the array.
- * If negative, will begin that many elements from the end. Parameter `amount`, is the number of old array elements to remove.
- * If the amount is 0, no elements are removed. Fourth and further parameters are the `elements` to add to the array.
- * If you don't specify any elements, spliceCol simply removes elements from the array.
- * {@link DataMap#spliceRow}
- *
- * @memberof Core#
- * @function spliceRow
- * @since 0.11
- * @param {Number} row Index of column in which do you want to do splice.
- * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end.
- * @param {Number} amount An integer indicating the number of old array elements to remove. If amount is 0, no elements are removed.
- * @param {*} [elements] The elements to add to the array. If you don't specify any elements, spliceCol simply removes elements from the array.
- */
- this.spliceRow = function (row, index, amount /* , elements... */) {
- var _datamap2;
- return (_datamap2 = datamap).spliceRow.apply(_datamap2, arguments);
- };
- /**
- * Returns indexes of the currently selected cells as an array `[startRow, startCol, endRow, endCol]`.
- *
- * Start row and start col are the coordinates of the active cell (where the selection was started).
- *
- * @memberof Core#
- * @function getSelected
- * @returns {Array} Array of the selection's indexes.
- */
- this.getSelected = function () {
- // https://github.com/handsontable/handsontable/issues/44 //cjl
- if (selection.isSelected()) {
- return [priv.selRange.from.row, priv.selRange.from.col, priv.selRange.to.row, priv.selRange.to.col];
- }
- };
- /**
- * Returns the current selection as a CellRange object.
- *
- * @memberof Core#
- * @function getSelectedRange
- * @since 0.11
- * @returns {CellRange} Selected range object or undefined` if there is no selection.
- */
- this.getSelectedRange = function () {
- // https://github.com/handsontable/handsontable/issues/44 //cjl
- if (selection.isSelected()) {
- return priv.selRange;
- }
- };
- /**
- * Rerender the table.
- *
- * @memberof Core#
- * @function render
- */
- this.render = function () {
- if (instance.view) {
- instance.renderCall = true;
- instance.forceFullRender = true; // used when data was changed
- selection.refreshBorders(null, true);
- }
- };
- /**
- * Reset all cells in the grid to contain data from the data array.
- *
- * @memberof Core#
- * @function loadData
- * @param {Array} data Array of arrays or array of objects containing data.
- * @fires Hooks#afterLoadData
- * @fires Hooks#afterChange
- */
- this.loadData = function (data) {
- if (Array.isArray(priv.settings.dataSchema)) {
- instance.dataType = 'array';
- } else if ((0, _function.isFunction)(priv.settings.dataSchema)) {
- instance.dataType = 'function';
- } else {
- instance.dataType = 'object';
- }
- if (datamap) {
- datamap.destroy();
- }
- datamap = new _dataMap2.default(instance, priv, GridSettings);
- if ((typeof data === 'undefined' ? 'undefined' : _typeof(data)) === 'object' && data !== null) {
- if (!(data.push && data.splice)) {
- // check if data is array. Must use duck-type check so Backbone Collections also pass it
- // when data is not an array, attempt to make a single-row array of it
- data = [data];
- }
- } else if (data === null) {
- data = [];
- var row;
- var r = 0;
- var rlen = 0;
- var dataSchema = datamap.getSchema();
- for (r = 0, rlen = priv.settings.startRows; r < rlen; r++) {
- if ((instance.dataType === 'object' || instance.dataType === 'function') && priv.settings.dataSchema) {
- row = (0, _object.deepClone)(dataSchema);
- data.push(row);
- } else if (instance.dataType === 'array') {
- row = (0, _object.deepClone)(dataSchema[0]);
- data.push(row);
- } else {
- row = [];
- for (var c = 0, clen = priv.settings.startCols; c < clen; c++) {
- row.push(null);
- }
- data.push(row);
- }
- }
- } else {
- throw new Error('loadData only accepts array of objects or array of arrays (' + (typeof data === 'undefined' ? 'undefined' : _typeof(data)) + ' given)');
- }
- priv.isPopulated = false;
- GridSettings.prototype.data = data;
- if (Array.isArray(data[0])) {
- instance.dataType = 'array';
- }
- datamap.dataSource = data;
- dataSource.data = data;
- dataSource.dataType = instance.dataType;
- dataSource.colToProp = datamap.colToProp.bind(datamap);
- dataSource.propToCol = datamap.propToCol.bind(datamap);
- clearCellSettingCache();
- grid.adjustRowsAndCols();
- instance.runHooks('afterLoadData', priv.firstRun);
- if (priv.firstRun) {
- priv.firstRun = [null, 'loadData'];
- } else {
- instance.runHooks('afterChange', null, 'loadData');
- instance.render();
- }
- priv.isPopulated = true;
- function clearCellSettingCache() {
- priv.cellSettings.length = 0;
- }
- };
- /**
- * Returns the current data object (the same one that was passed by `data` configuration option or `loadData` method,
- * unless the `modifyRow` hook was used to trim some of the rows. If that's the case - use the {@link Core#getSourceData} method.).
- * Optionally you can provide cell range by defining `row`, `col`, `row2`, `col2` to get only a fragment of grid data.
- *
- * Note: getData functionality changed with the release of version 0.20. If you're looking for the previous functionality,
- * you should use the {@link Core#getSourceData} method.
- *
- * @memberof Core#
- * @function getData
- * @param {Number} [r] From row.
- * @param {Number} [c] From column.
- * @param {Number} [r2] To row.
- * @param {Number} [c2] To column.
- * @returns {Array} Array with the data.
- */
- this.getData = function (r, c, r2, c2) {
- if ((0, _mixed.isUndefined)(r)) {
- return datamap.getAll();
- }
- return datamap.getRange(new _src.CellCoords(r, c), new _src.CellCoords(r2, c2), datamap.DESTINATION_RENDERER);
- };
- /**
- * Returns a string value of the selected range. Each column is separated by tab, each row is separated by a new line character.
- * {@link DataMap#getCopyableText}
- *
- * @memberof Core#
- * @function getCopyableText
- * @since 0.11
- * @param {Number} startRow From row.
- * @param {Number} startCol From column.
- * @param {Number} endRow To row.
- * @param {Number} endCol To column.
- * @returns {String}
- */
- this.getCopyableText = function (startRow, startCol, endRow, endCol) {
- return datamap.getCopyableText(new _src.CellCoords(startRow, startCol), new _src.CellCoords(endRow, endCol));
- };
- /**
- * Returns the data's copyable value at specified row and column index ({@link DataMap#getCopyable}).
- *
- * @memberof Core#
- * @function getCopyableData
- * @since 0.19.0
- * @param {Number} row Row index.
- * @param {Number} column Column index.
- * @returns {String}
- */
- this.getCopyableData = function (row, column) {
- return datamap.getCopyable(row, datamap.colToProp(column));
- };
- /**
- * Returns schema provided by constructor settings. If it doesn't exist then it returns the schema based on the data
- * structure in the first row.
- *
- * @memberof Core#
- * @function getSchema
- * @since 0.13.2
- * @returns {Object} Schema object.
- */
- this.getSchema = function () {
- return datamap.getSchema();
- };
- /**
- * Use it if you need to change configuration after initialization. The `settings` parameter is an object containing the new
- * settings, declared the same way as in the initial settings object.
- * Note, that although the `updateSettings` method doesn't overwrite the previously declared settings, it might reset
- * the settings made post-initialization. (for example - ignore changes made using the columnResize feature).
- *
- * @memberof Core#
- * @function updateSettings
- * @param {Object} settings New settings object.
- * @param {Boolean} init
- * @example
- * ```js
- * hot.updateSettings({
- * contextMenu: true,
- * colHeaders: true,
- * fixedRowsTop: 2
- * });
- * ```
- * @fires Hooks#afterCellMetaReset
- * @fires Hooks#afterUpdateSettings
- */
- this.updateSettings = function (settings, init) {
- var columnsAsFunc = false;
- var i = void 0;
- var j = void 0;
- var clen = void 0;
- if ((0, _mixed.isDefined)(settings.rows)) {
- throw new Error('"rows" setting is no longer supported. do you mean startRows, minRows or maxRows?');
- }
- if ((0, _mixed.isDefined)(settings.cols)) {
- throw new Error('"cols" setting is no longer supported. do you mean startCols, minCols or maxCols?');
- }
- for (i in settings) {
- if (i === 'data') {
- /* eslint-disable no-continue */
- continue; // loadData will be triggered later
- } else if (_pluginHooks2.default.getSingleton().getRegistered().indexOf(i) > -1) {
- if ((0, _function.isFunction)(settings[i]) || Array.isArray(settings[i])) {
- settings[i].initialHook = true;
- instance.addHook(i, settings[i]);
- }
- } else if (!init && (0, _object.hasOwnProperty)(settings, i)) {
- // Update settings
- GridSettings.prototype[i] = settings[i];
- }
- }
- // Load data or create data map
- if (settings.data === void 0 && priv.settings.data === void 0) {
- instance.loadData(null); // data source created just now
- } else if (settings.data !== void 0) {
- instance.loadData(settings.data); // data source given as option
- } else if (settings.columns !== void 0) {
- datamap.createMap();
- }
- clen = instance.countCols();
- var columnSetting = settings.columns || GridSettings.prototype.columns;
- // Init columns constructors configuration
- if (columnSetting && (0, _function.isFunction)(columnSetting)) {
- clen = instance.countSourceCols();
- columnsAsFunc = true;
- }
- // Clear cellSettings cache
- if (settings.cell !== void 0 || settings.cells !== void 0 || settings.columns !== void 0) {
- priv.cellSettings.length = 0;
- }
- if (clen > 0) {
- var proto = void 0;
- var column = void 0;
- for (i = 0, j = 0; i < clen; i++) {
- if (columnsAsFunc && !columnSetting(i)) {
- /* eslint-disable no-continue */
- continue;
- }
- priv.columnSettings[j] = (0, _setting.columnFactory)(GridSettings, priv.columnsSettingConflicts);
- // shortcut for prototype
- proto = priv.columnSettings[j].prototype;
- // Use settings provided by user
- if (columnSetting) {
- if (columnsAsFunc) {
- column = columnSetting(i);
- } else {
- column = columnSetting[j];
- }
- if (column) {
- (0, _object.extend)(proto, column);
- (0, _object.extend)(proto, expandType(column));
- }
- }
- j++;
- }
- }
- if ((0, _mixed.isDefined)(settings.cell)) {
- for (var key in settings.cell) {
- if ((0, _object.hasOwnProperty)(settings.cell, key)) {
- var cell = settings.cell[key];
- instance.setCellMetaObject(cell.row, cell.col, cell);
- }
- }
- }
- instance.runHooks('afterCellMetaReset');
- if ((0, _mixed.isDefined)(settings.className)) {
- if (GridSettings.prototype.className) {
- (0, _element.removeClass)(instance.rootElement, GridSettings.prototype.className);
- }
- if (settings.className) {
- (0, _element.addClass)(instance.rootElement, settings.className);
- }
- }
- var currentHeight = instance.rootElement.style.height;
- if (currentHeight !== '') {
- currentHeight = parseInt(instance.rootElement.style.height, 10);
- }
- var height = settings.height;
- if ((0, _function.isFunction)(height)) {
- height = height();
- }
- if (init) {
- var initialStyle = instance.rootElement.getAttribute('style');
- if (initialStyle) {
- instance.rootElement.setAttribute('data-initialstyle', instance.rootElement.getAttribute('style'));
- }
- }
- if (height === null) {
- var _initialStyle = instance.rootElement.getAttribute('data-initialstyle');
- if (_initialStyle && (_initialStyle.indexOf('height') > -1 || _initialStyle.indexOf('overflow') > -1)) {
- instance.rootElement.setAttribute('style', _initialStyle);
- } else {
- instance.rootElement.style.height = '';
- instance.rootElement.style.overflow = '';
- }
- } else if (height !== void 0) {
- instance.rootElement.style.height = height + 'px';
- instance.rootElement.style.overflow = 'hidden';
- }
- if (typeof settings.width != 'undefined') {
- var width = settings.width;
- if ((0, _function.isFunction)(width)) {
- width = width();
- }
- instance.rootElement.style.width = width + 'px';
- }
- if (!init) {
- datamap.clearLengthCache(); // force clear cache length on updateSettings() #3416
- if (instance.view) {
- instance.view.wt.wtViewport.resetHasOversizedColumnHeadersMarked();
- }
- instance.runHooks('afterUpdateSettings');
- }
- grid.adjustRowsAndCols();
- if (instance.view && !priv.firstRun) {
- instance.forceFullRender = true; // used when data was changed
- selection.refreshBorders(null, true);
- }
- if (!init && instance.view && (currentHeight === '' || height === '' || height === void 0) && currentHeight !== height) {
- instance.view.wt.wtOverlays.updateMainScrollableElements();
- }
- };
- /**
- * Get value from the selected cell.
- *
- * @memberof Core#
- * @function getValue
- * @since 0.11
- * @returns {*} Value of selected cell.
- */
- this.getValue = function () {
- var sel = instance.getSelected();
- if (GridSettings.prototype.getValue) {
- if ((0, _function.isFunction)(GridSettings.prototype.getValue)) {
- return GridSettings.prototype.getValue.call(instance);
- } else if (sel) {
- return instance.getData()[sel[0]][GridSettings.prototype.getValue];
- }
- } else if (sel) {
- return instance.getDataAtCell(sel[0], sel[1]);
- }
- };
- function expandType(obj) {
- if (!(0, _object.hasOwnProperty)(obj, 'type')) {
- // ignore obj.prototype.type
- return;
- }
- var type,
- expandedType = {};
- if (_typeof(obj.type) === 'object') {
- type = obj.type;
- } else if (typeof obj.type === 'string') {
- type = (0, _cellTypes.getCellType)(obj.type);
- }
- for (var i in type) {
- if ((0, _object.hasOwnProperty)(type, i) && !(0, _object.hasOwnProperty)(obj, i)) {
- expandedType[i] = type[i];
- }
- }
- return expandedType;
- }
- /**
- * Returns the object settings.
- *
- * @memberof Core#
- * @function getSettings
- * @returns {Object} Object containing the current grid settings.
- */
- this.getSettings = function () {
- return priv.settings;
- };
- /**
- * Clears the data from the grid. (The table settings remain intact.)
- *
- * @memberof Core#
- * @function clear
- * @since 0.11
- */
- this.clear = function () {
- selection.selectAll();
- selection.empty();
- };
- /**
- * @memberof Core#
- * @function alter
- * @param {String} action See grid.alter for possible values: `"insert_row"`, `"insert_col"`, `"remove_row"`, `"remove_col"`
- * @param {Number} index Index of the row/column before which the new row/column will be inserted/removed.
- * @param {Number} [amount = 1] Amound of rows/columns to be inserted/removed.
- * @param {String} [source] Source indicator.
- * @param {Boolean} [keepEmptyRows] Flag for preventing deletion of empty rows.
- * @description
- *
- * Allows altering the table structure by either inserting/removing rows or inserting/removing columns:
- *
- * Insert new row(s) above the row with a given `index`. If index is `null` or `undefined`, the new row will be
- * added after the last row.
- * ```js
- * var hot = new Handsontable(document.getElementById('example'));
- * hot.alter('insert_row', 10);
- * ```
- *
- * Insert new column(s) before the column with a given `index`. If index is `null` or `undefined`, the new column
- * will be added after the last column.
- * ```js
- * var hot = new Handsontable(document.getElementById('example'));
- * hot.alter('insert_col', 10);
- * ```
- *
- * Remove the row(s) at the given `index`.
- * ```js
- * var hot = new Handsontable(document.getElementById('example'));
- * hot.alter('remove_row', 10);
- * ```
- *
- * Remove the column(s) at the given `index`.
- * ```js
- * var hot = new Handsontable(document.getElementById('example'));
- * hot.alter('remove_col', 10);
- * ```
- */
- this.alter = function (action, index, amount, source, keepEmptyRows) {
- grid.alter(action, index, amount, source, keepEmptyRows);
- };
- /**
- * Returns a TD element for the given `row` and `col` arguments, if it is rendered on screen.
- * Returns `null` if the TD is not rendered on screen (probably because that part of the table is not visible).
- *
- * @memberof Core#
- * @function getCell
- * @param {Number} row Row index.
- * @param {Number} col Column index.
- * @param {Boolean} topmost If set to true, it returns the TD element from the topmost overlay. For example,
- * if the wanted cell is in the range of fixed rows, it will return a TD element from the `top` overlay.
- * @returns {Element} The cell's TD element.
- */
- this.getCell = function (row, col, topmost) {
- return instance.view.getCellAtCoords(new _src.CellCoords(row, col), topmost);
- };
- /**
- * Returns the coordinates of the cell, provided as a HTML Element.
- *
- * @memberof Core#
- * @function getCoords
- * @param {Element} elem The HTML Element representing the cell.
- * @returns {CellCoords} Coordinates object.
- */
- this.getCoords = function (elem) {
- return this.view.wt.wtTable.getCoords.call(this.view.wt.wtTable, elem);
- };
- /**
- * Returns the property name that corresponds with the given column index. {@link DataMap#colToProp}
- * If the data source is an array of arrays, it returns the columns index.
- *
- * @memberof Core#
- * @function colToProp
- * @param {Number} col Column index
- * @returns {String|Number} Column property or column index.
- */
- this.colToProp = function (col) {
- return datamap.colToProp(col);
- };
- /**
- * Returns column index that corresponds with the given property. {@link DataMap#propToCol}
- *
- * @memberof Core#
- * @function propToCol
- * @param {String|Number} prop Property name or column index.
- * @returns {Number} Column index.
- */
- this.propToCol = function (prop) {
- return datamap.propToCol(prop);
- };
- /**
- * Translate physical row index into visual.
- *
- * @since 0.29.0
- * @memberof Core#
- * @function toVisualRow
- * @param {Number} row Physical row index.
- * @returns {Number} Returns visual row index.
- */
- this.toVisualRow = function (row) {
- return recordTranslator.toVisualRow(row);
- };
- /**
- * Translate physical column index into visual.
- *
- * @since 0.29.0
- * @memberof Core#
- * @function toVisualColumn
- * @param {Number} column Physical column index.
- * @returns {Number} Returns visual column index.
- */
- this.toVisualColumn = function (column) {
- return recordTranslator.toVisualColumn(column);
- };
- /**
- * Translate visual row index into physical.
- * If displayed rows order is different than the order of rows stored in memory (i.e. sorting is applied)
- * to retrieve valid physical row index you can use this method.
- *
- * @since 0.29.0
- * @memberof Core#
- * @function toPhysicalRow
- * @param {Number} row Visual row index.
- * @returns {Number} Returns physical row index.
- */
- this.toPhysicalRow = function (row) {
- return recordTranslator.toPhysicalRow(row);
- };
- /**
- * Translate visual column index into physical.
- * If displayed columns order is different than the order of columns stored in memory (i.e. manual column move is applied)
- * to retrieve valid physical column index you can use this method.
- *
- * @since 0.29.0
- * @memberof Core#
- * @function toPhysicalColumn
- * @param {Number} column Visual column index.
- * @returns {Number} Returns physical column index.
- */
- this.toPhysicalColumn = function (column) {
- return recordTranslator.toPhysicalColumn(column);
- };
- /**
- * @description
- * Returns the cell value at `row`, `col`. `row` and `col` are the __visible__ indexes (note, that if columns were reordered or sorted,
- * the currently visible order will be used).
- *
- * @memberof Core#
- * @function getDataAtCell
- * @param {Number} row Row index.
- * @param {Number} col Column index.
- * @returns {String|Boolean|null} Data at cell.
- */
- this.getDataAtCell = function (row, col) {
- return datamap.get(row, datamap.colToProp(col));
- };
- /**
- * Return value at `row`, `prop`. (Uses {@link DataMap#get})
- *
- * @memberof Core#
- * @function getDataAtRowProp
- * @param {Number} row Row index.
- * @param {String} prop Property name.
- * @returns {*} Cell value.
- */
- this.getDataAtRowProp = function (row, prop) {
- return datamap.get(row, prop);
- };
- /**
- * @description
- * Returns array of column values from the data source. `col` is the __visible__ index of the column.
- * Note, that if columns were reordered or sorted, the currently visible order will be used.
- *
- * @memberof Core#
- * @function getDataAtCol
- * @since 0.9-beta2
- * @param {Number} col Column index.
- * @returns {Array} Array of cell values.
- */
- this.getDataAtCol = function (col) {
- var out = [];
- return out.concat.apply(out, _toConsumableArray(datamap.getRange(new _src.CellCoords(0, col), new _src.CellCoords(priv.settings.data.length - 1, col), datamap.DESTINATION_RENDERER)));
- };
- /**
- * Given the object property name (e.g. `'first.name'`), returns an array of column's values from the data source.
- * You can also provide a column index as the first argument.
- *
- * @memberof Core#
- * @function getDataAtProp
- * @since 0.9-beta2
- * @param {String|Number} prop Property name / column index.
- * @returns {Array} Array of cell values.
- */
- this.getDataAtProp = function (prop) {
- var out = [],
- range;
- range = datamap.getRange(new _src.CellCoords(0, datamap.propToCol(prop)), new _src.CellCoords(priv.settings.data.length - 1, datamap.propToCol(prop)), datamap.DESTINATION_RENDERER);
- return out.concat.apply(out, _toConsumableArray(range));
- };
- /**
- * Returns the source data object (the same that was passed by `data` configuration option or `loadData` method).
- * Optionally you can provide a cell range by using the `row`, `col`, `row2`, `col2` arguments, to get only a fragment of grid data.
- *
- * @memberof Core#
- * @function getSourceData
- * @since 0.20.0
- * @param {Number} [r] From row.
- * @param {Number} [c] From column.
- * @param {Number} [r2] To row.
- * @param {Number} [c2] To column.
- * @returns {Array} Array of grid data.
- */
- this.getSourceData = function (r, c, r2, c2) {
- var data = void 0;
- if (r === void 0) {
- data = dataSource.getData();
- } else {
- data = dataSource.getByRange(new _src.CellCoords(r, c), new _src.CellCoords(r2, c2));
- }
- return data;
- };
- /**
- * Returns the source data object as an arrays of arrays format even when source data was provided in another format.
- * Optionally you can provide a cell range by using the `row`, `col`, `row2`, `col2` arguments, to get only a fragment of grid data.
- *
- * @memberof Core#
- * @function getSourceDataArray
- * @since 0.28.0
- * @param {Number} [r] From row.
- * @param {Number} [c] From column.
- * @param {Number} [r2] To row.
- * @param {Number} [c2] To column.
- * @returns {Array} An array of arrays.
- */
- this.getSourceDataArray = function (r, c, r2, c2) {
- var data = void 0;
- if (r === void 0) {
- data = dataSource.getData(true);
- } else {
- data = dataSource.getByRange(new _src.CellCoords(r, c), new _src.CellCoords(r2, c2), true);
- }
- return data;
- };
- /**
- * Returns an array of column values from the data source. `col` is the index of the row in the data source.
- *
- * @memberof Core#
- * @function getSourceDataAtCol
- * @since 0.11.0-beta3
- * @param {Number} column Column index.
- * @returns {Array} Array of the column's cell values.
- */
- this.getSourceDataAtCol = function (column) {
- return dataSource.getAtColumn(column);
- };
- /**
- * Returns a single row of the data (array or object, depending on what you have). `row` is the index of the row in the data source.
- *
- * @memberof Core#
- * @function getSourceDataAtRow
- * @since 0.11.0-beta3
- * @param {Number} row Row index.
- * @returns {Array|Object} Single row of data.
- */
- this.getSourceDataAtRow = function (row) {
- return dataSource.getAtRow(row);
- };
- /**
- * Returns a single value from the data source.
- *
- * @memberof Core#
- * @function getSourceDataAtCell
- * @param {Number} row Row index.
- * @param {Number} column Column index.
- * @returns {*} Cell data.
- * @since 0.20.0
- */
- this.getSourceDataAtCell = function (row, column) {
- return dataSource.getAtCell(row, column);
- };
- /**
- * @description
- * Returns a single row of the data. The `row` argument is the __visible__ index of the row.
- *
- * @memberof Core#
- * @function getDataAtRow
- * @param {Number} row Row index.
- * @returns {Array} Array of row's cell data.
- * @since 0.9-beta2
- */
- this.getDataAtRow = function (row) {
- var data = datamap.getRange(new _src.CellCoords(row, 0), new _src.CellCoords(row, this.countCols() - 1), datamap.DESTINATION_RENDERER);
- return data[0] || [];
- };
- /**
- * @description
- * Returns a data type defined in the Handsontable settings under the `type` key ([Options#type](http://docs.handsontable.com/Options.html#type)).
- * If there are cells with different types in the selected range, it returns `'mixed'`.
- *
- * @since 0.18.1
- * @memberof Core#
- * @function getDataType
- * @param {Number} rowFrom From row index.
- * @param {Number} columnFrom To row index.
- * @param {Number} rowTo From column index.
- * @param {Number} columnTo To column index.
- * @returns {String} Cell type (e.q: `'mixed'`, `'text'`, `'numeric'`, `'autocomplete'`).
- */
- this.getDataType = function (rowFrom, columnFrom, rowTo, columnTo) {
- var _this = this;
- var previousType = null;
- var currentType = null;
- if (rowFrom === void 0) {
- rowFrom = 0;
- rowTo = this.countRows();
- columnFrom = 0;
- columnTo = this.countCols();
- }
- if (rowTo === void 0) {
- rowTo = rowFrom;
- }
- if (columnTo === void 0) {
- columnTo = columnFrom;
- }
- var type = 'mixed';
- (0, _number.rangeEach)(Math.min(rowFrom, rowTo), Math.max(rowFrom, rowTo), function (row) {
- var isTypeEqual = true;
- (0, _number.rangeEach)(Math.min(columnFrom, columnTo), Math.max(columnFrom, columnTo), function (column) {
- var cellType = _this.getCellMeta(row, column);
- currentType = cellType.type;
- if (previousType) {
- isTypeEqual = previousType === currentType;
- } else {
- previousType = currentType;
- }
- return isTypeEqual;
- });
- type = isTypeEqual ? currentType : 'mixed';
- return isTypeEqual;
- });
- return type;
- };
- /**
- * Remove a property defined by the `key` argument from the cell meta object for the provided `row` and `col` coordinates.
- *
- * @memberof Core#
- * @function removeCellMeta
- * @param {Number} row Row index.
- * @param {Number} col Column index.
- * @param {String} key Property name.
- */
- this.removeCellMeta = function (row, col, key) {
- var cellMeta = instance.getCellMeta(row, col);
- if (cellMeta[key] != undefined) {
- delete priv.cellSettings[row][col][key];
- }
- };
- /**
- * Remove one or more rows from the cell meta object.
- *
- * @since 0.30.0
- * @param {Number} index An integer that specifies at what position to add/remove items, Use negative values to specify the position from the end of the array.
- * @param {Number} deleteAmount The number of items to be removed. If set to 0, no items will be removed.
- * @param {Array} items The new items to be added to the array.
- */
- this.spliceCellsMeta = function (index, deleteAmount) {
- var _priv$cellSettings;
- for (var _len2 = arguments.length, items = Array(_len2 > 2 ? _len2 - 2 : 0), _key = 2; _key < _len2; _key++) {
- items[_key - 2] = arguments[_key];
- }
- (_priv$cellSettings = priv.cellSettings).splice.apply(_priv$cellSettings, [index, deleteAmount].concat(items));
- };
- /**
- * Set cell meta data object defined by `prop` to the corresponding params `row` and `col`.
- *
- * @memberof Core#
- * @function setCellMetaObject
- * @since 0.11
- * @param {Number} row Row index.
- * @param {Number} col Column index.
- * @param {Object} prop Meta object.
- */
- this.setCellMetaObject = function (row, col, prop) {
- if ((typeof prop === 'undefined' ? 'undefined' : _typeof(prop)) === 'object') {
- for (var key in prop) {
- if ((0, _object.hasOwnProperty)(prop, key)) {
- var value = prop[key];
- this.setCellMeta(row, col, key, value);
- }
- }
- }
- };
- /**
- * Sets a property defined by the `key` object to the meta object of a cell corresponding to params `row` and `col`.
- *
- * @memberof Core#
- * @function setCellMeta
- * @since 0.11
- * @param {Number} row Row index.
- * @param {Number} col Column index.
- * @param {String} key Property name.
- * @param {String} val Property value.
- * @fires Hooks#afterSetCellMeta
- */
- this.setCellMeta = function (row, col, key, val) {
- var _recordTranslator$toP = recordTranslator.toPhysical(row, col);
- var _recordTranslator$toP2 = _slicedToArray(_recordTranslator$toP, 2);
- row = _recordTranslator$toP2[0];
- col = _recordTranslator$toP2[1];
- if (!priv.columnSettings[col]) {
- priv.columnSettings[col] = (0, _setting.columnFactory)(GridSettings, priv.columnsSettingConflicts);
- }
- if (!priv.cellSettings[row]) {
- priv.cellSettings[row] = [];
- }
- if (!priv.cellSettings[row][col]) {
- priv.cellSettings[row][col] = new priv.columnSettings[col]();
- }
- priv.cellSettings[row][col][key] = val;
- instance.runHooks('afterSetCellMeta', row, col, key, val);
- };
- /**
- * Get all the cells meta settings at least once generated in the table (in order of cell initialization).
- *
- * @since 0.19.0
- * @returns {Array} Returns Array of ColumnSettings object.
- */
- this.getCellsMeta = function () {
- return (0, _array.arrayFlatten)(priv.cellSettings);
- };
- /**
- * Returns the cell properties object for the given `row` and `col` coordinates.
- *
- * @memberof Core#
- * @function getCellMeta
- * @param {Number} row Row index.
- * @param {Number} col Column index.
- * @returns {Object} The cell properties object.
- * @fires Hooks#beforeGetCellMeta
- * @fires Hooks#afterGetCellMeta
- */
- this.getCellMeta = function (row, col) {
- var prop = datamap.colToProp(col),
- cellProperties;
- var visualRow = row;
- var visualCol = col;
- var _recordTranslator$toP3 = recordTranslator.toPhysical(row, col);
- var _recordTranslator$toP4 = _slicedToArray(_recordTranslator$toP3, 2);
- row = _recordTranslator$toP4[0];
- col = _recordTranslator$toP4[1];
- if (!priv.columnSettings[col]) {
- priv.columnSettings[col] = (0, _setting.columnFactory)(GridSettings, priv.columnsSettingConflicts);
- }
- if (!priv.cellSettings[row]) {
- priv.cellSettings[row] = [];
- }
- if (!priv.cellSettings[row][col]) {
- priv.cellSettings[row][col] = new priv.columnSettings[col]();
- }
- cellProperties = priv.cellSettings[row][col]; // retrieve cellProperties from cache
- cellProperties.row = row;
- cellProperties.col = col;
- cellProperties.visualRow = visualRow;
- cellProperties.visualCol = visualCol;
- cellProperties.prop = prop;
- cellProperties.instance = instance;
- instance.runHooks('beforeGetCellMeta', row, col, cellProperties);
- (0, _object.extend)(cellProperties, expandType(cellProperties)); // for `type` added in beforeGetCellMeta
- if (cellProperties.cells) {
- var settings = cellProperties.cells.call(cellProperties, row, col, prop);
- if (settings) {
- (0, _object.extend)(cellProperties, settings);
- (0, _object.extend)(cellProperties, expandType(settings)); // for `type` added in cells
- }
- }
- instance.runHooks('afterGetCellMeta', row, col, cellProperties);
- return cellProperties;
- };
- /**
- * Returns a row off the cell meta array.
- *
- * @memberof Core#
- * @function getCellMetaAtRow
- * @since 0.30.0
- * @param {Number} row Index of the row to return cell meta for.
- * @returns {Array}
- */
- this.getCellMetaAtRow = function (row) {
- return priv.cellSettings[row];
- };
- /**
- * Checks if the data format and config allows user to modify the column structure.
- * @returns {boolean}
- */
- this.isColumnModificationAllowed = function () {
- return !(instance.dataType === 'object' || instance.getSettings().columns);
- };
- var rendererLookup = (0, _data.cellMethodLookupFactory)('renderer');
- /**
- * Returns the cell renderer function by given `row` and `col` arguments.
- *
- * @memberof Core#
- * @function getCellRenderer
- * @since 0.11
- * @param {Number|Object} row Row index or cell meta object.
- * @param {Number} [col] Column index.
- * @returns {Function} The renderer function.
- */
- this.getCellRenderer = function (row, col) {
- return (0, _renderers.getRenderer)(rendererLookup.call(this, row, col));
- };
- /**
- * Returns the cell editor by the provided `row` and `col` arguments.
- *
- * @memberof Core#
- * @function getCellEditor
- * @param {Number} row Row index.
- * @param {Number} col Column index.
- * @returns {Object} The Editor object.
- */
- this.getCellEditor = (0, _data.cellMethodLookupFactory)('editor');
- var validatorLookup = (0, _data.cellMethodLookupFactory)('validator');
- /**
- * Returns the cell validator by `row` and `col`, provided a validator is defined. If not - it doesn't return anything.
- *
- * @memberof Core#
- * @function getCellValidator
- * @param {Number} row Row index.
- * @param {Number} col Column index.
- * @returns {Function|RegExp|undefined} The validator function.
- */
- this.getCellValidator = function (row, col) {
- var validator = validatorLookup.call(this, row, col);
- if (typeof validator === 'string') {
- validator = (0, _validators.getValidator)(validator);
- }
- return validator;
- };
- /**
- * Validates all cells using their validator functions and calls callback when finished.
- *
- * If one of the cells is invalid, the callback will be fired with `'valid'` arguments as `false` - otherwise it would equal `true`.
- *
- * @memberof Core#
- * @function validateCells
- * @param {Function} [callback] The callback function.
- */
- this.validateCells = function (callback) {
- var waitingForValidator = new ValidatorsQueue();
- if (callback) {
- waitingForValidator.onQueueEmpty = callback;
- }
- var i = instance.countRows() - 1;
- while (i >= 0) {
- var j = instance.countCols() - 1;
- while (j >= 0) {
- waitingForValidator.addValidatorToQueue();
- instance.validateCell(instance.getDataAtCell(i, j), instance.getCellMeta(i, j), function (result) {
- if (typeof result !== 'boolean') {
- throw new Error('Validation error: result is not boolean');
- }
- if (result === false) {
- waitingForValidator.valid = false;
- }
- waitingForValidator.removeValidatorFormQueue();
- }, 'validateCells');
- j--;
- }
- i--;
- }
- waitingForValidator.checkIfQueueIsEmpty();
- };
- /**
- * Returns an array of row headers' values (if they are enabled). If param `row` was given, it returns the header of the given row as a string.
- *
- * @memberof Core#
- * @function getRowHeader
- * @param {Number} [row] Row index.
- * @fires Hooks#modifyRowHeader
- * @returns {Array|String} Array of header values / single header value.
- */
- this.getRowHeader = function (row) {
- var rowHeader = priv.settings.rowHeaders;
- if (row !== void 0) {
- row = instance.runHooks('modifyRowHeader', row);
- }
- if (row === void 0) {
- rowHeader = [];
- (0, _number.rangeEach)(instance.countRows() - 1, function (i) {
- rowHeader.push(instance.getRowHeader(i));
- });
- } else if (Array.isArray(rowHeader) && rowHeader[row] !== void 0) {
- rowHeader = rowHeader[row];
- } else if ((0, _function.isFunction)(rowHeader)) {
- rowHeader = rowHeader(row);
- } else if (rowHeader && typeof rowHeader !== 'string' && typeof rowHeader !== 'number') {
- rowHeader = row + 1;
- }
- return rowHeader;
- };
- /**
- * Returns information about if this table is configured to display row headers.
- *
- * @memberof Core#
- * @function hasRowHeaders
- * @returns {Boolean} `true` if the instance has the row headers enabled, `false` otherwise.
- * @since 0.11
- */
- this.hasRowHeaders = function () {
- return !!priv.settings.rowHeaders;
- };
- /**
- * Returns information about if this table is configured to display column headers.
- *
- * @memberof Core#
- * @function hasColHeaders
- * @since 0.11
- * @returns {Boolean} `True` if the instance has the column headers enabled, `false` otherwise.
- */
- this.hasColHeaders = function () {
- if (priv.settings.colHeaders !== void 0 && priv.settings.colHeaders !== null) {
- // Polymer has empty value = null
- return !!priv.settings.colHeaders;
- }
- for (var i = 0, ilen = instance.countCols(); i < ilen; i++) {
- if (instance.getColHeader(i)) {
- return true;
- }
- }
- return false;
- };
- /**
- * Returns an array of column headers (in string format, if they are enabled). If param `col` is given, it returns the header at the given column as a string.
- *
- * @memberof Core#
- * @function getColHeader
- * @param {Number} [col] Column index.
- * @fires Hooks#modifyColHeader
- * @returns {Array|String} The column header(s).
- */
- this.getColHeader = function (col) {
- var columnsAsFunc = priv.settings.columns && (0, _function.isFunction)(priv.settings.columns);
- var result = priv.settings.colHeaders;
- col = instance.runHooks('modifyColHeader', col);
- if (col === void 0) {
- var out = [];
- var ilen = columnsAsFunc ? instance.countSourceCols() : instance.countCols();
- for (var i = 0; i < ilen; i++) {
- out.push(instance.getColHeader(i));
- }
- result = out;
- } else {
- var translateVisualIndexToColumns = function translateVisualIndexToColumns(col) {
- var arr = [];
- var columnsLen = instance.countSourceCols();
- var index = 0;
- for (; index < columnsLen; index++) {
- if ((0, _function.isFunction)(instance.getSettings().columns) && instance.getSettings().columns(index)) {
- arr.push(index);
- }
- }
- return arr[col];
- };
- var baseCol = col;
- col = instance.runHooks('modifyCol', col);
- var prop = translateVisualIndexToColumns(col);
- if (priv.settings.columns && (0, _function.isFunction)(priv.settings.columns) && priv.settings.columns(prop) && priv.settings.columns(prop).title) {
- result = priv.settings.columns(prop).title;
- } else if (priv.settings.columns && priv.settings.columns[col] && priv.settings.columns[col].title) {
- result = priv.settings.columns[col].title;
- } else if (Array.isArray(priv.settings.colHeaders) && priv.settings.colHeaders[col] !== void 0) {
- result = priv.settings.colHeaders[col];
- } else if ((0, _function.isFunction)(priv.settings.colHeaders)) {
- result = priv.settings.colHeaders(col);
- } else if (priv.settings.colHeaders && typeof priv.settings.colHeaders !== 'string' && typeof priv.settings.colHeaders !== 'number') {
- result = (0, _data.spreadsheetColumnLabel)(baseCol); // see #1458
- }
- }
- return result;
- };
- /**
- * Return column width from settings (no guessing). Private use intended.
- *
- * @private
- * @memberof Core#
- * @function _getColWidthFromSettings
- * @param {Number} col
- * @returns {Number}
- */
- this._getColWidthFromSettings = function (col) {
- var cellProperties = instance.getCellMeta(0, col);
- var width = cellProperties.width;
- if (width === void 0 || width === priv.settings.width) {
- width = cellProperties.colWidths;
- }
- if (width !== void 0 && width !== null) {
- switch (typeof width === 'undefined' ? 'undefined' : _typeof(width)) {
- case 'object':
- // array
- width = width[col];
- break;
- case 'function':
- width = width(col);
- break;
- default:
- break;
- }
- if (typeof width === 'string') {
- width = parseInt(width, 10);
- }
- }
- return width;
- };
- /**
- * Returns the width of the requested column.
- *
- * @memberof Core#
- * @function getColWidth
- * @since 0.11
- * @param {Number} col Column index.
- * @returns {Number} Column width.
- * @fires Hooks#modifyColWidth
- */
- this.getColWidth = function (col) {
- var width = instance._getColWidthFromSettings(col);
- width = instance.runHooks('modifyColWidth', width, col);
- if (width === void 0) {
- width = _src.ViewportColumnsCalculator.DEFAULT_WIDTH;
- }
- return width;
- };
- /**
- * Return row height from settings (no guessing). Private use intended.
- *
- * @private
- * @memberof Core#
- * @function _getRowHeightFromSettings
- * @param {Number} row
- * @returns {Number}
- */
- this._getRowHeightFromSettings = function (row) {
- // let cellProperties = instance.getCellMeta(row, 0);
- // let height = cellProperties.height;
- //
- // if (height === void 0 || height === priv.settings.height) {
- // height = cellProperties.rowHeights;
- // }
- var height = priv.settings.rowHeights;
- if (height !== void 0 && height !== null) {
- switch (typeof height === 'undefined' ? 'undefined' : _typeof(height)) {
- case 'object':
- // array
- height = height[row];
- break;
- case 'function':
- height = height(row);
- break;
- default:
- break;
- }
- if (typeof height === 'string') {
- height = parseInt(height, 10);
- }
- }
- return height;
- };
- /**
- * Returns the row height.
- *
- * @memberof Core#
- * @function getRowHeight
- * @since 0.11
- * @param {Number} row Row index.
- * @returns {Number} The given row's height.
- * @fires Hooks#modifyRowHeight
- */
- this.getRowHeight = function (row) {
- var height = instance._getRowHeightFromSettings(row);
- height = instance.runHooks('modifyRowHeight', height, row);
- return height;
- };
- /**
- * Returns the total number of rows in the data source.
- *
- * @memberof Core#
- * @function countSourceRows
- * @since 0.20.0
- * @returns {Number} Total number in rows in data source.
- */
- this.countSourceRows = function () {
- var sourceLength = instance.runHooks('modifySourceLength');
- return sourceLength || (instance.getSourceData() ? instance.getSourceData().length : 0);
- };
- /**
- * Returns the total number of columns in the data source.
- *
- * @memberof Core#
- * @function countSourceCols
- * @since 0.26.1
- * @returns {Number} Total number in columns in data source.
- */
- this.countSourceCols = function () {
- var len = 0;
- var obj = instance.getSourceData() && instance.getSourceData()[0] ? instance.getSourceData()[0] : [];
- if ((0, _object.isObject)(obj)) {
- len = (0, _object.deepObjectSize)(obj);
- } else {
- len = obj.length || 0;
- }
- return len;
- };
- /**
- * Returns the total number of rows in the grid.
- *
- * @memberof Core#
- * @function countRows
- * @returns {Number} Total number in rows the grid.
- */
- this.countRows = function () {
- return datamap.getLength();
- };
- /**
- * Returns the total number of columns in the grid.
- *
- * @memberof Core#
- * @function countCols
- * @returns {Number} Total number of columns.
- */
- this.countCols = function () {
- var maxCols = this.getSettings().maxCols;
- var dataHasLength = false;
- var dataLen = 0;
- if (instance.dataType === 'array') {
- dataHasLength = priv.settings.data && priv.settings.data[0] && priv.settings.data[0].length;
- }
- if (dataHasLength) {
- dataLen = priv.settings.data[0].length;
- }
- if (priv.settings.columns) {
- var columnsIsFunction = (0, _function.isFunction)(priv.settings.columns);
- if (columnsIsFunction) {
- if (instance.dataType === 'array') {
- var columnLen = 0;
- for (var i = 0; i < dataLen; i++) {
- if (priv.settings.columns(i)) {
- columnLen++;
- }
- }
- dataLen = columnLen;
- } else if (instance.dataType === 'object' || instance.dataType === 'function') {
- dataLen = datamap.colToPropCache.length;
- }
- } else {
- dataLen = priv.settings.columns.length;
- }
- } else if (instance.dataType === 'object' || instance.dataType === 'function') {
- dataLen = datamap.colToPropCache.length;
- }
- return Math.min(maxCols, dataLen);
- };
- /**
- * Returns an index of the first rendered row.
- *
- * @memberof Core#
- * @function rowOffset
- * @returns {Number} Index of first rendered row.
- */
- this.rowOffset = function () {
- return instance.view.wt.wtTable.getFirstRenderedRow();
- };
- /**
- * Returns the index of the first rendered column.
- *
- * @memberof Core#
- * @function colOffset
- * @returns {Number} Index of the first visible column.
- */
- this.colOffset = function () {
- return instance.view.wt.wtTable.getFirstRenderedColumn();
- };
- /**
- * Returns the number of rendered rows (including rows partially or fully rendered outside viewport).
- *
- * @memberof Core#
- * @function countRenderedRows
- * @returns {Number} Returns -1 if table is not visible.
- */
- this.countRenderedRows = function () {
- return instance.view.wt.drawn ? instance.view.wt.wtTable.getRenderedRowsCount() : -1;
- };
- /**
- * Returns the number of visible rows (rendered rows that fully fit inside viewport).
- *
- * @memberof Core#
- * @function countVisibleRows
- * @returns {Number} Number of visible rows or -1.
- */
- this.countVisibleRows = function () {
- return instance.view.wt.drawn ? instance.view.wt.wtTable.getVisibleRowsCount() : -1;
- };
- /**
- * Returns the number of rendered columns (including columns partially or fully rendered outside viewport).
- *
- * @memberof Core#
- * @function countRenderedCols
- * @returns {Number} Returns -1 if table is not visible.
- */
- this.countRenderedCols = function () {
- return instance.view.wt.drawn ? instance.view.wt.wtTable.getRenderedColumnsCount() : -1;
- };
- /**
- * Returns the number of visible columns. Returns -1 if table is not visible
- *
- * @memberof Core#
- * @function countVisibleCols
- * @return {Number} Number of visible columns or -1.
- */
- this.countVisibleCols = function () {
- return instance.view.wt.drawn ? instance.view.wt.wtTable.getVisibleColumnsCount() : -1;
- };
- /**
- * Returns the number of empty rows. If the optional ending parameter is `true`, returns the
- * number of empty rows at the bottom of the table.
- *
- * @memberof Core#
- * @function countEmptyRows
- * @param {Boolean} [ending] If `true`, will only count empty rows at the end of the data source.
- * @returns {Number} Count empty rows
- * @fires Hooks#modifyRow
- */
- this.countEmptyRows = function (ending) {
- var i = instance.countRows() - 1,
- empty = 0,
- row;
- while (i >= 0) {
- row = instance.runHooks('modifyRow', i);
- if (instance.isEmptyRow(row)) {
- empty++;
- } else if (ending) {
- break;
- }
- i--;
- }
- return empty;
- };
- /**
- * Returns the number of empty columns. If the optional ending parameter is `true`, returns the number of empty
- * columns at right hand edge of the table.
- *
- * @memberof Core#
- * @function countEmptyCols
- * @param {Boolean} [ending] If `true`, will only count empty columns at the end of the data source row.
- * @returns {Number} Count empty cols
- */
- this.countEmptyCols = function (ending) {
- if (instance.countRows() < 1) {
- return 0;
- }
- var i = instance.countCols() - 1,
- empty = 0;
- while (i >= 0) {
- if (instance.isEmptyCol(i)) {
- empty++;
- } else if (ending) {
- break;
- }
- i--;
- }
- return empty;
- };
- /**
- * Check if all cells in the row declared by the `row` argument are empty.
- *
- * @memberof Core#
- * @function isEmptyRow
- * @param {Number} row Row index.
- * @returns {Boolean} `true` if the row at the given `row` is empty, `false` otherwise.
- */
- this.isEmptyRow = function (row) {
- return priv.settings.isEmptyRow.call(instance, row);
- };
- /**
- * Check if all cells in the the column declared by the `col` argument are empty.
- *
- * @memberof Core#
- * @function isEmptyCol
- * @param {Number} col Column index.
- * @returns {Boolean} `true` if the column at the given `col` is empty, `false` otherwise.
- */
- this.isEmptyCol = function (col) {
- return priv.settings.isEmptyCol.call(instance, col);
- };
- /**
- * Select cell specified by `row` and `col` values or a range of cells finishing at `endRow`, `endCol`.
- * By default, viewport will be scrolled to selection.
- * After the `selectCell` method had finished, the instance will be listening to keyboard input on the document.
- *
- * @memberof Core#
- * @function selectCell
- * @param {Number} row Row index.
- * @param {Number} col Column index.
- * @param {Number} [endRow] End row index (if selecting a range).
- * @param {Number} [endCol] End column index (if selecting a range).
- * @param {Boolean} [scrollToCell=true] If `true`, the viewport will be scrolled to the selection.
- * @param {Boolean} [changeListener=true] If `false`, Handsontable will not change keyboard events listener to himself.
- * @returns {Boolean} `true` if selection was successful, `false` otherwise.
- */
- this.selectCell = function (row, col, endRow, endCol, scrollToCell, changeListener) {
- var coords;
- changeListener = (0, _mixed.isUndefined)(changeListener) || changeListener === true;
- if (typeof row !== 'number' || row < 0 || row >= instance.countRows()) {
- return false;
- }
- if (typeof col !== 'number' || col < 0 || col >= instance.countCols()) {
- return false;
- }
- if ((0, _mixed.isDefined)(endRow)) {
- if (typeof endRow !== 'number' || endRow < 0 || endRow >= instance.countRows()) {
- return false;
- }
- if (typeof endCol !== 'number' || endCol < 0 || endCol >= instance.countCols()) {
- return false;
- }
- }
- coords = new _src.CellCoords(row, col);
- priv.selRange = new _src.CellRange(coords, coords, coords);
- if (changeListener) {
- instance.listen();
- }
- if ((0, _mixed.isUndefined)(endRow)) {
- selection.setRangeEnd(priv.selRange.from, scrollToCell);
- } else {
- selection.setRangeEnd(new _src.CellCoords(endRow, endCol), scrollToCell);
- }
- instance.selection.finish();
- return true;
- };
- /**
- * Select the cell specified by the `row` and `prop` arguments, or a range finishing at `endRow`, `endProp`.
- * By default, viewport will be scrolled to selection.
- *
- * @memberof Core#
- * @function selectCellByProp
- * @param {Number} row Row index.
- * @param {String} prop Property name.
- * @param {Number} [endRow] End row index (if selecting a range).
- * @param {String} [endProp] End property name (if selecting a range).
- * @param {Boolean} [scrollToCell=true] If `true`, viewport will be scrolled to the selection.
- * @returns {Boolean} `true` if selection was successful, `false` otherwise.
- */
- this.selectCellByProp = function (row, prop, endRow, endProp, scrollToCell) {
- var _instance5;
- arguments[1] = datamap.propToCol(arguments[1]);
- if ((0, _mixed.isDefined)(arguments[3])) {
- arguments[3] = datamap.propToCol(arguments[3]);
- }
- return (_instance5 = instance).selectCell.apply(_instance5, arguments);
- };
- /**
- * Deselects the current cell selection on grid.
- *
- * @memberof Core#
- * @function deselectCell
- */
- this.deselectCell = function () {
- selection.deselect();
- };
- /**
- * Scroll viewport to coords specified by the `row` and `column` arguments.
- *
- * @since 0.24.3
- * @memberof Core#
- * @function scrollViewportTo
- * @param {Number} [row] Row index.
- * @param {Number} [column] Column index.
- * @param {Boolean} [snapToBottom = false] If `true`, viewport is scrolled to show the cell on the bottom of the table.
- * @param {Boolean} [snapToRight = false] If `true`, viewport is scrolled to show the cell on the right side of the table.
- * @returns {Boolean} `true` if scroll was successful, `false` otherwise.
- */
- this.scrollViewportTo = function (row, column) {
- var snapToBottom = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
- var snapToRight = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
- if (row !== void 0 && (row < 0 || row >= instance.countRows())) {
- return false;
- }
- if (column !== void 0 && (column < 0 || column >= instance.countCols())) {
- return false;
- }
- var result = false;
- if (row !== void 0 && column !== void 0) {
- instance.view.wt.wtOverlays.topOverlay.scrollTo(row, snapToBottom);
- instance.view.wt.wtOverlays.leftOverlay.scrollTo(column, snapToRight);
- result = true;
- }
- if (typeof row === 'number' && typeof column !== 'number') {
- instance.view.wt.wtOverlays.topOverlay.scrollTo(row, snapToBottom);
- result = true;
- }
- if (typeof column === 'number' && typeof row !== 'number') {
- instance.view.wt.wtOverlays.leftOverlay.scrollTo(column, snapToRight);
- result = true;
- }
- return result;
- };
- /**
- * Removes grid from the DOM.
- *
- * @memberof Core#
- * @function destroy
- * @fires Hooks#afterDestroy
- */
- this.destroy = function () {
- instance._clearTimeouts();
- if (instance.view) {
- // in case HT is destroyed before initialization has finished
- instance.view.destroy();
- }
- if (dataSource) {
- dataSource.destroy();
- }
- dataSource = null;
- (0, _element.empty)(instance.rootElement);
- eventManager.destroy();
- instance.runHooks('afterDestroy');
- _pluginHooks2.default.getSingleton().destroy(instance);
- for (var i in instance) {
- if ((0, _object.hasOwnProperty)(instance, i)) {
- // replace instance methods with post mortem
- if ((0, _function.isFunction)(instance[i])) {
- instance[i] = postMortem;
- } else if (i !== 'guid') {
- // replace instance properties with null (restores memory)
- // it should not be necessary but this prevents a memory leak side effects that show itself in Jasmine tests
- instance[i] = null;
- }
- }
- }
- // replace private properties with null (restores memory)
- // it should not be necessary but this prevents a memory leak side effects that show itself in Jasmine tests
- if (datamap) {
- datamap.destroy();
- }
- datamap = null;
- priv = null;
- grid = null;
- selection = null;
- editorManager = null;
- instance = null;
- GridSettings = null;
- };
- /**
- * Replacement for all methods after Handsotnable was destroyed.
- *
- * @private
- */
- function postMortem() {
- throw new Error('This method cannot be called because this Handsontable instance has been destroyed');
- }
- /**
- * Returns the active editor object.
- *
- * @memberof Core#
- * @function getActiveEditor
- * @returns {Object} The active editor object.
- */
- this.getActiveEditor = function () {
- return editorManager.getActiveEditor();
- };
- /**
- * Returns plugin instance using the plugin name provided.
- *
- * @memberof Core#
- * @function getPlugin
- * @param {String} pluginName The plugin name.
- * @returns {*} The plugin instance.
- * @since 0.15.0
- */
- this.getPlugin = function (pluginName) {
- return (0, _plugins.getPlugin)(this, pluginName);
- };
- /**
- * Returns the Handsontable instance.
- *
- * @memberof Core#
- * @function getInstance
- * @returns {Handsontable} The Handsontable instance.
- */
- this.getInstance = function () {
- return instance;
- };
- /**
- * Adds listener to the specified hook name (only for this Handsontable instance).
- *
- * @memberof Core#
- * @function addHook
- * @see Hooks#add
- * @param {String} key Hook name.
- * @param {Function|Array} callback Function or array of Functions.
- *
- * @example
- * ```js
- * hot.addHook('beforeInit', myCallback);
- * ```
- */
- this.addHook = function (key, callback) {
- _pluginHooks2.default.getSingleton().add(key, callback, instance);
- };
- /**
- * Check if for a specified hook name there are added listeners (only for this Handsontable instance).
- *
- * @memberof Core#
- * @function hasHook
- * @see Hooks#has
- * @param {String} key Hook name
- * @return {Boolean}
- *
- * @example
- * ```js
- * var hasBeforeInitListeners = hot.hasHook('beforeInit');
- * ```
- */
- this.hasHook = function (key) {
- return _pluginHooks2.default.getSingleton().has(key, instance);
- };
- /**
- * Adds listener to specified hook name (only for this Handsontable instance).
- * After the listener is triggered, it will be automatically removed.
- *
- * @memberof Core#
- * @function addHookOnce
- * @see Hooks#once
- * @param {String} key Hook name.
- * @param {Function|Array} callback Function or array of Functions.
- *
- * @example
- * ```js
- * hot.addHookOnce('beforeInit', myCallback);
- * ```
- */
- this.addHookOnce = function (key, callback) {
- _pluginHooks2.default.getSingleton().once(key, callback, instance);
- };
- /**
- * Removes the hook listener previously registered with {@link Core#addHook}.
- *
- * @memberof Core#
- * @function removeHook
- * @see Hooks#remove
- * @param {String} key Hook name.
- * @param {Function} callback Function which have been registered via {@link Core#addHook}.
- *
- * @example
- * ```js
- * hot.removeHook('beforeInit', myCallback);
- * ```
- */
- this.removeHook = function (key, callback) {
- _pluginHooks2.default.getSingleton().remove(key, callback, instance);
- };
- /**
- * Run the callbacks for the hook provided in the `key` argument using the parameters given in the other arguments.
- *
- * @memberof Core#
- * @function runHooks
- * @see Hooks#run
- * @param {String} key Hook name.
- * @param {*} [p1] Argument passed to the callback.
- * @param {*} [p2] Argument passed to the callback.
- * @param {*} [p3] Argument passed to the callback.
- * @param {*} [p4] Argument passed to the callback.
- * @param {*} [p5] Argument passed to the callback.
- * @param {*} [p6] Argument passed to the callback.
- * @returns {*}
- *
- * @example
- * ```js
- * hot.runHooks('beforeInit');
- * ```
- */
- this.runHooks = function (key, p1, p2, p3, p4, p5, p6) {
- return _pluginHooks2.default.getSingleton().run(instance, key, p1, p2, p3, p4, p5, p6);
- };
- this.timeouts = [];
- /**
- * Sets timeout. Purpose of this method is to clear all known timeouts when `destroy` method is called.
- *
- * @param {*} handle
- * @private
- */
- this._registerTimeout = function (handle) {
- this.timeouts.push(handle);
- };
- /**
- * Clears all known timeouts.
- *
- * @private
- */
- this._clearTimeouts = function () {
- for (var i = 0, ilen = this.timeouts.length; i < ilen; i++) {
- clearTimeout(this.timeouts[i]);
- }
- };
- /**
- * Handsontable version
- *
- * @type {String}
- */
- // this.version = Handsontable.version;
- _pluginHooks2.default.getSingleton().run(instance, 'construct');
- };
|