META-INF.dirigible.ide-bpm.libs.ng-handsontable_0.13.ngHandsontable.js Maven / Gradle / Ivy
/**
* ng-handsontable 0.13.0
*
* Copyright 2012-2015 Marcin Warpechowski
* Copyright 2015 Handsoncode sp. z o.o.
* Licensed under the MIT license.
* https://github.com/handsontable/ngHandsontable
* Date: Wed Oct 26 2016 10:00:05 GMT+0200 (CEST)
*/
if (document.all && !document.addEventListener) { // IE 8 and lower
document.createElement('hot-table');
document.createElement('hot-column');
document.createElement('hot-autocomplete');
}
angular.module('ngHandsontable.services', []);
angular.module('ngHandsontable.directives', []);
angular.module('ngHandsontable', [
'ngHandsontable.services',
'ngHandsontable.directives'
]);
Handsontable.hooks.add('afterContextMenuShow', function() {
Handsontable.eventManager.isHotTableEnv = false;
});
(function() {
function autoCompleteFactory($parse) {
return {
parseAutoComplete: function(column, dataSet, propertyOnly) {
column.source = function(query, process) {
var row = this.instance.getSelected()[0];
var source = [];
var data = dataSet[row];
if (!data) {
return;
}
var options = column.optionList;
if (!options || !options.object) {
return;
}
if (angular.isArray(options.object)) {
source = options.object;
} else {
// Using $parse to evaluate the expression against the row object
// allows us to support filters like the ngRepeat directive does.
var paramObject = $parse(options.object)(data);
if (angular.isArray(paramObject)) {
if (propertyOnly) {
for (var i = 0, length = paramObject.length; i < length; i++) {
var item = paramObject[i][options.property];
if (item !== null && item !== undefined) {
source.push(item);
}
}
} else {
source = paramObject;
}
} else {
source = paramObject;
}
}
process(source);
};
}
};
}
autoCompleteFactory.$inject = ['$parse'];
angular.module('ngHandsontable.services').factory('autoCompleteFactory', autoCompleteFactory);
}());
(function() {
function hotRegisterer() {
var instances = {};
return {
getInstance: function(id) {
return instances[id];
},
registerInstance: function(id, instance) {
instances[id] = instance;
},
removeInstance: function(id) {
instances[id] = void 0;
}
};
}
hotRegisterer.$inject = [];
angular.module('ngHandsontable.services').factory('hotRegisterer', hotRegisterer);
}());
(function() {
function hyphenate(string) {
return string.replace(/[A-Z]/g, function(match) {
return ('-' + match.charAt(0).toLowerCase());
});
}
function camelCase(string) {
return string.replace(/-\D/g, function(match) {
return match.charAt(1).toUpperCase();
});
}
function ucFirst(string) {
return string.substr(0, 1).toUpperCase() + string.substr(1, string.length - 1);
}
function settingFactory(hotRegisterer) {
return {
containerClassName: 'handsontable-container',
/**
* Append handsontable container div and initialize handsontable instance inside element.
*
* @param {qLite} element
* @param {Object} htSettings
*/
initializeHandsontable: function(element, htSettings) {
var container = document.createElement('div'),
hot;
container.className = this.containerClassName;
if (htSettings.hotId) {
container.id = htSettings.hotId;
}
element[0].appendChild(container);
hot = new Handsontable(container, htSettings);
if (htSettings.hotId) {
hotRegisterer.registerInstance(htSettings.hotId, hot);
}
return hot;
},
/**
* Set new settings to handsontable instance.
*
* @param {Handsontable} instance
* @param {Object} settings
*/
updateHandsontableSettings: function(instance, settings) {
if (instance) {
instance.updateSettings(settings);
}
},
/**
* Render handsontable instance inside element.
*
* @param {Handsontable} instance
*/
renderHandsontable: function(instance) {
if (instance) {
instance.render();
}
},
/**
* Merge original handsontable settings with setting defined in scope.
*
* @param {Object} settings
* @param {Object} scope
* @returns {Object}
*/
mergeSettingsFromScope: function(settings, scope) {
var
scopeOptions = angular.extend({}, scope),
htOptions, i, length;
settings = settings || {};
angular.extend(scopeOptions, scope.settings || {});
htOptions = this.getAvailableSettings();
for (i = 0, length = htOptions.length; i < length; i++) {
if (typeof scopeOptions[htOptions[i]] !== 'undefined') {
settings[htOptions[i]] = scopeOptions[htOptions[i]];
}
}
return settings;
},
/**
* Merge original handsontable hooks with hooks defined in scope.
*
* @param {Object} settings
* @param {Object} scope
* @returns {Object}
*/
mergeHooksFromScope: function(settings, scope) {
var
scopeOptions = angular.extend({}, scope),
htHooks, i, length, attribute;
settings = settings || {};
angular.extend(scopeOptions, scope.settings || {});
htHooks = this.getAvailableHooks();
for (i = 0, length = htHooks.length; i < length; i++) {
attribute = 'on' + ucFirst(htHooks[i]);
if (typeof scopeOptions[htHooks[i]] === 'function' || typeof scopeOptions[attribute] === 'function') {
settings[htHooks[i]] = scopeOptions[htHooks[i]] || scopeOptions[attribute];
}
}
return settings;
},
/**
* Trim scope definition according to attrs object from directive.
*
* @param {Object} scopeDefinition
* @param {Object} attrs
* @returns {Object}
*/
trimScopeDefinitionAccordingToAttrs: function(scopeDefinition, attrs) {
for (var i in scopeDefinition) {
if (scopeDefinition.hasOwnProperty(i) && attrs[i] === void 0 &&
attrs[scopeDefinition[i].substr(1, scopeDefinition[i].length)] === void 0) {
delete scopeDefinition[i];
}
}
return scopeDefinition;
},
/**
* Get isolate scope definition for main handsontable directive.
*
* @return {Object}
*/
getTableScopeDefinition: function() {
var scopeDefinition = {};
this.applyAvailableSettingsScopeDef(scopeDefinition);
this.applyAvailableHooksScopeDef(scopeDefinition);
scopeDefinition.datarows = '=';
scopeDefinition.dataschema = '=';
scopeDefinition.observeDomVisibility = '=';
//scopeDefinition.settings = '=';
return scopeDefinition;
},
/**
* Get isolate scope definition for column directive.
*
* @return {Object}
*/
getColumnScopeDefinition: function() {
var scopeDefinition = {};
this.applyAvailableSettingsScopeDef(scopeDefinition);
scopeDefinition.data = '@';
return scopeDefinition;
},
/**
* Apply all available handsontable settings into object which represents scope definition.
*
* @param {Object} [scopeDefinition]
* @returns {Object}
*/
applyAvailableSettingsScopeDef: function(scopeDefinition) {
var options, i, length;
options = this.getAvailableSettings();
for (i = 0, length = options.length; i < length; i++) {
scopeDefinition[options[i]] = '=';
}
return scopeDefinition;
},
/**
* Apply all available handsontable hooks into object which represents scope definition.
*
* @param {Object} [scopeDefinition]
* @returns {Object}
*/
applyAvailableHooksScopeDef: function(scopeDefinition) {
var options, i, length;
options = this.getAvailableHooks();
for (i = 0, length = options.length; i < length; i++) {
scopeDefinition[options[i]] = '=on' + ucFirst(options[i]);
}
return scopeDefinition;
},
/**
* Get all available settings from handsontable, returns settings by default in camelCase mode.
*
* @param {Boolean} [hyphenateStyle=undefined] If `true` then returns options in hyphenate mode (eq. row-header)
* @returns {Array}
*/
getAvailableSettings: function(hyphenateStyle) {
var settings = Object.keys(Handsontable.DefaultSettings.prototype);
if (settings.indexOf('contextMenuCopyPaste') === -1) {
settings.push('contextMenuCopyPaste');
}
if (settings.indexOf('handsontable') === -1) {
settings.push('handsontable');
}
if (settings.indexOf('settings') >= 0) {
settings.splice(settings.indexOf('settings'), 1);
}
if (hyphenateStyle) {
settings = settings.map(hyphenate);
}
return settings;
},
/**
* Get all available hooks from handsontable, returns hooks by default in camelCase mode.
*
* @param {Boolean} [hyphenateStyle=undefined] If `true` then returns hooks in hyphenate mode (eq. on-after-init)
* @returns {Array}
*/
getAvailableHooks: function(hyphenateStyle) {
var settings = Handsontable.hooks.getRegistered();
if (hyphenateStyle) {
settings = settings.map(function(hook) {
return 'on-' + hyphenate(hook);
});
}
return settings;
}
};
}
settingFactory.$inject = ['hotRegisterer'];
angular.module('ngHandsontable.services').factory('settingFactory', settingFactory);
}());
(function() {
/**
* Angular Handsontable directive for autocomplete settings
*/
function hotAutocomplete() {
return {
restrict: 'EA',
scope: true,
require: '^hotColumn',
link: function(scope, element, attrs, controllerInstance) {
var options = attrs.datarows;
controllerInstance.setColumnOptionList(options);
}
};
}
hotAutocomplete.$inject = [];
angular.module('ngHandsontable.directives').directive('hotAutocomplete', hotAutocomplete);
}());
(function() {
/**
* Angular Handsontable directive for single column settings
*/
function hotColumn(settingFactory) {
return {
restrict: 'EA',
require: '^hotTable',
scope: {},
controller: ['$scope', function($scope) {
this.setColumnOptionList = function(options) {
if (!$scope.column) {
$scope.column = {};
}
var optionList = {};
var match = options.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)\s*$/);
if (match) {
optionList.property = match[1];
optionList.object = match[2];
} else {
optionList.object = options.split(',');
}
$scope.column.optionList = optionList;
};
}],
compile: function(tElement, tAttrs) {
var _this = this;
this.scope = settingFactory.trimScopeDefinitionAccordingToAttrs(settingFactory.getColumnScopeDefinition(), tAttrs);
//this.$$isolateBindings = {};
angular.forEach(Object.keys(this.scope), function(key) {
_this.$$isolateBindings[key] = {
attrName: key,
collection: false,
mode: key === 'data' ? '@' : '=',
optional: false
};
});
return function(scope, element, attrs, controllerInstance) {
var column = {};
// Turn all attributes without value as `true` by default
angular.forEach(Object.keys(attrs), function(key) {
if (key.charAt(0) !== '$' && attrs[key] === '') {
column[key] = true;
}
});
settingFactory.mergeSettingsFromScope(column, scope);
if (!scope.column) {
scope.column = {};
}
angular.extend(scope.column, column);
controllerInstance.setColumnSetting(scope.column);
scope.$on('$destroy', function() {
controllerInstance.removeColumnSetting(scope.column);
});
};
}
};
}
hotColumn.$inject = ['settingFactory'];
angular.module('ngHandsontable.directives').directive('hotColumn', hotColumn);
}());
(function() {
/**
* Main Angular Handsontable directive
*/
function hotTable(settingFactory, autoCompleteFactory, $rootScope, $parse) {
return {
restrict: 'EA',
scope: {},
// for ng-repeat
priority: -400,
controller: ['$scope', function($scope) {
this.setColumnSetting = function(column) {
if (!$scope.htSettings) {
$scope.htSettings = {};
}
if (!$scope.htSettings.columns) {
$scope.htSettings.columns = [];
}
$scope.htSettings.columns.push(column);
settingFactory.updateHandsontableSettings($scope.hotInstance, $scope.htSettings);
};
this.removeColumnSetting = function(column) {
if ($scope.htSettings.columns.indexOf(column) > -1) {
$scope.htSettings.columns.splice($scope.htSettings.columns.indexOf(column), 1);
settingFactory.updateHandsontableSettings($scope.hotInstance, $scope.htSettings);
}
};
}],
compile: function(tElement, tAttrs) {
var _this = this,
bindingsKeys;
this.scope = settingFactory.trimScopeDefinitionAccordingToAttrs(settingFactory.getTableScopeDefinition(), tAttrs);
bindingsKeys = Object.keys(this.scope);
angular.forEach(bindingsKeys, function(key) {
var mode = _this.scope[key].charAt(0);
_this.$$isolateBindings[key] = {
attrName: _this.scope[key].length > 1 ? _this.scope[key].substr(1, _this.scope[key].length) : key,
collection: key === 'datarows',
mode: mode,
optional: false
};
});
return function(scope, element, attrs) {
scope.settings = $parse(attrs.settings)(scope.$parent);
if (!scope.htSettings) {
scope.htSettings = {};
}
// Turn all attributes without value as `true` by default
angular.forEach(Object.keys(attrs), function(key) {
if (key.charAt(0) !== '$' && attrs[key] === '') {
scope.htSettings[key] = true;
}
});
settingFactory.mergeSettingsFromScope(scope.htSettings, scope);
settingFactory.mergeHooksFromScope(scope.htSettings, scope);
if (!scope.htSettings.data) {
scope.htSettings.data = scope.datarows;
}
scope.htSettings.dataSchema = scope.dataschema;
scope.htSettings.hotId = attrs.hotId;
scope.htSettings.observeDOMVisibility = scope.observeDomVisibility;
if (scope.htSettings.columns) {
for (var i = 0, length = scope.htSettings.columns.length; i < length; i++) {
var column = scope.htSettings.columns[i];
if (column.type !== 'autocomplete') {
continue;
}
if (!column.optionList) {
continue;
}
if (typeof column.optionList === 'string') {
var optionList = {};
var match = column.optionList.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)\s*$/);
if (match) {
optionList.property = match[1];
optionList.object = match[2];
} else {
optionList.object = optionList;
}
column.optionList = optionList;
}
autoCompleteFactory.parseAutoComplete(column, scope.datarows, true);
}
}
var origAfterChange = scope.htSettings.afterChange;
scope.htSettings.afterChange = function() {
if (origAfterChange) {
origAfterChange.apply(this, arguments);
}
if (!$rootScope.$$phase) {
scope.$apply();
}
};
scope.hotInstance = settingFactory.initializeHandsontable(element, scope.htSettings);
// TODO: Add watch properties descriptor + needs perf test. Watch full equality vs toJson
angular.forEach(bindingsKeys, function(key) {
scope.$watch(key, function(newValue, oldValue) {
if (newValue === void 0) {
return;
}
if (key === 'datarows') {
// If reference to data rows is not changed then only re-render table
if (scope.hotInstance.getSettings().data === newValue) {
settingFactory.renderHandsontable(scope.hotInstance);
} else {
scope.hotInstance.loadData(newValue);
scope.htSettings.data = newValue;
}
} else if (newValue !== oldValue) {
scope.htSettings[key] = newValue;
settingFactory.updateHandsontableSettings(scope.hotInstance, scope.htSettings);
}
}, ['datarows', 'columns', 'rowHeights', 'colWidths', 'rowHeaders', 'colHeaders'].indexOf(key) >= 0);
});
/**
* Check for reference equality changes for datarows
* TODO: must the remaining bindingsKeys need to be added also if their reference changes
*/
scope.$watch('datarows', function(newValue) {
if (newValue === void 0) {
return;
}
if (scope.hotInstance.getSettings().data !== newValue) {
scope.hotInstance.loadData(newValue);
}
});
/**
* Check if data length has been changed
*/
scope.$watchCollection('datarows', function(newValue, oldValue) {
if (oldValue && oldValue.length === scope.htSettings.minSpareRows && newValue.length !== scope.htSettings.minSpareRows) {
scope.htSettings.data = scope.datarows;
settingFactory.updateHandsontableSettings(scope.hotInstance, scope.htSettings);
}
});
};
}
};
}
hotTable.$inject = ['settingFactory', 'autoCompleteFactory', '$rootScope', '$parse'];
angular.module('ngHandsontable.directives').directive('hotTable', hotTable);
}());
© 2015 - 2025 Weber Informatics LLC | Privacy Policy