UNPKG

ng-csv

Version:

Simple directive that turns arrays and objects into downloadable CSV files

167 lines (135 loc) 4.74 kB
/** * Created by asafdav on 15/05/14. */ angular.module('ngCsv.services'). service('CSV', ['$q', function ($q) { var EOL = '\r\n'; var BOM = "\ufeff"; var specialChars = { '\\t': '\t', '\\b': '\b', '\\v': '\v', '\\f': '\f', '\\r': '\r' }; /** * Stringify one field * @param data * @param options * @returns {*} */ this.stringifyField = function (data, options) { if (options.decimalSep === 'locale' && this.isFloat(data)) { return data.toLocaleString(); } if (options.decimalSep !== '.' && this.isFloat(data)) { return data.toString().replace('.', options.decimalSep); } if (typeof data === 'string') { data = data.replace(/"/g, '""'); // Escape double qoutes if (options.quoteStrings || data.indexOf(',') > -1 || data.indexOf('\n') > -1 || data.indexOf('\r') > -1) { data = options.txtDelim + data + options.txtDelim; } return data; } if (typeof data === 'boolean') { return data ? 'TRUE' : 'FALSE'; } return data; }; /** * Helper function to check if input is float * @param input * @returns {boolean} */ this.isFloat = function (input) { return +input === input && (!isFinite(input) || Boolean(input % 1)); }; /** * Creates a csv from a data array * @param data * @param options * * header - Provide the first row (optional) * * fieldSep - Field separator, default: ',', * * addByteOrderMarker - Add Byte order mark, default(false) * @param callback */ this.stringify = function (data, options) { var def = $q.defer(); var that = this; var csv = ""; var csvContent = ""; var dataPromise = $q.when(data).then(function (responseData) { //responseData = angular.copy(responseData);//moved to row creation // Check if there's a provided header array if (angular.isDefined(options.header) && options.header) { var encodingArray, headerString; encodingArray = []; angular.forEach(options.header, function (title, key) { this.push(that.stringifyField(title, options)); }, encodingArray); headerString = encodingArray.join(options.fieldSep ? options.fieldSep : ","); csvContent += headerString + EOL; } var arrData = []; if (angular.isArray(responseData)) { arrData = responseData; } else if (angular.isFunction(responseData)) { arrData = responseData(); } // Check if using keys as labels if (angular.isDefined(options.label) && options.label && typeof options.label === 'boolean') { var labelArray, labelString; labelArray = []; angular.forEach(arrData[0], function(value, label) { this.push(that.stringifyField(label, options)); }, labelArray); labelString = labelArray.join(options.fieldSep ? options.fieldSep : ","); csvContent += labelString + EOL; } angular.forEach(arrData, function (oldRow, index) { var row = angular.copy(arrData[index]); var dataString, infoArray; infoArray = []; var iterator = !!options.columnOrder ? options.columnOrder : row; angular.forEach(iterator, function (field, key) { var val = !!options.columnOrder ? row[field] : field; this.push(that.stringifyField(val, options)); }, infoArray); dataString = infoArray.join(options.fieldSep ? options.fieldSep : ","); csvContent += index < arrData.length ? dataString + EOL : dataString; }); // Add BOM if needed if (options.addByteOrderMarker) { csv += BOM; } // Append the content and resolve. csv += csvContent; def.resolve(csv); }); if (typeof dataPromise['catch'] === 'function') { dataPromise['catch'](function (err) { def.reject(err); }); } return def.promise; }; /** * Helper function to check if input is really a special character * @param input * @returns {boolean} */ this.isSpecialChar = function(input){ return specialChars[input] !== undefined; }; /** * Helper function to get what the special character was supposed to be * since Angular escapes the first backslash * @param input * @returns {special character string} */ this.getSpecialChar = function (input) { return specialChars[input]; }; }]);