commit 069f4af6683879ed8e5e84a9daeac8256df17893 Author: Faris Ansari Date: Tue Sep 19 23:28:19 2017 +0530 First commit diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..7b1c321 --- /dev/null +++ b/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["es2015"], + "plugins": ["babel-plugin-add-module-exports"] +} \ No newline at end of file diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..48fe40a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = LF +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..e053304 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,184 @@ +{ + "ecmaFeatures": { + "globalReturn": true, + "jsx": true, + "modules": true + }, + + "env": { + "browser": true, + "es6": true, + "node": true + }, + + "globals": { + "document": false, + "escape": false, + "navigator": false, + "unescape": false, + "window": false, + "describe": true, + "before": true, + "it": true, + "expect": true, + "sinon": true + }, + + "parser": "babel-eslint", + + "plugins": [ + + ], + + "rules": { + "block-scoped-var": 2, + "brace-style": [2, "1tbs", { "allowSingleLine": true }], + "camelcase": [2, { "properties": "always" }], + "comma-dangle": [2, "never"], + "comma-spacing": [2, { "before": false, "after": true }], + "comma-style": [2, "last"], + "complexity": 0, + "consistent-return": 2, + "consistent-this": 0, + "curly": [2, "multi-line"], + "default-case": 0, + "dot-location": [2, "property"], + "dot-notation": 0, + "eol-last": 2, + "eqeqeq": [2, "allow-null"], + "func-names": 0, + "func-style": 0, + "generator-star-spacing": [2, "both"], + "guard-for-in": 0, + "handle-callback-err": [2, "^(err|error|anySpecificError)$" ], + "indent": [2, 2, { "SwitchCase": 1 }], + "key-spacing": [2, { "beforeColon": false, "afterColon": true }], + "keyword-spacing": [2, {"before": true, "after": true}], + "linebreak-style": 0, + "max-depth": 0, + "max-len": [2, 120, 4], + "max-nested-callbacks": 0, + "max-params": 0, + "max-statements": 0, + "new-cap": [2, { "newIsCap": true, "capIsNew": false }], + "newline-after-var": [2, "always"], + "new-parens": 2, + "no-alert": 0, + "no-array-constructor": 2, + "no-bitwise": 0, + "no-caller": 2, + "no-catch-shadow": 0, + "no-cond-assign": 2, + "no-console": 0, + "no-constant-condition": 0, + "no-continue": 0, + "no-control-regex": 2, + "no-debugger": 2, + "no-delete-var": 2, + "no-div-regex": 0, + "no-dupe-args": 2, + "no-dupe-keys": 2, + "no-duplicate-case": 2, + "no-else-return": 2, + "no-empty": 0, + "no-empty-character-class": 2, + "no-eq-null": 0, + "no-eval": 2, + "no-ex-assign": 2, + "no-extend-native": 2, + "no-extra-bind": 2, + "no-extra-boolean-cast": 2, + "no-extra-parens": 0, + "no-extra-semi": 0, + "no-extra-strict": 0, + "no-fallthrough": 2, + "no-floating-decimal": 2, + "no-func-assign": 2, + "no-implied-eval": 2, + "no-inline-comments": 0, + "no-inner-declarations": [2, "functions"], + "no-invalid-regexp": 2, + "no-irregular-whitespace": 2, + "no-iterator": 2, + "no-label-var": 2, + "no-labels": 2, + "no-lone-blocks": 0, + "no-lonely-if": 0, + "no-loop-func": 0, + "no-mixed-requires": 0, + "no-mixed-spaces-and-tabs": [2, false], + "no-multi-spaces": 2, + "no-multi-str": 2, + "no-multiple-empty-lines": [2, { "max": 1 }], + "no-native-reassign": 2, + "no-negated-in-lhs": 2, + "no-nested-ternary": 0, + "no-new": 2, + "no-new-func": 2, + "no-new-object": 2, + "no-new-require": 2, + "no-new-wrappers": 2, + "no-obj-calls": 2, + "no-octal": 2, + "no-octal-escape": 2, + "no-path-concat": 0, + "no-plusplus": 0, + "no-process-env": 0, + "no-process-exit": 0, + "no-proto": 2, + "no-redeclare": 2, + "no-regex-spaces": 2, + "no-reserved-keys": 0, + "no-restricted-modules": 0, + "no-return-assign": 2, + "no-script-url": 0, + "no-self-compare": 2, + "no-sequences": 2, + "no-shadow": 0, + "no-shadow-restricted-names": 2, + "no-spaced-func": 2, + "no-sparse-arrays": 2, + "no-sync": 0, + "no-ternary": 0, + "no-throw-literal": 2, + "no-trailing-spaces": 2, + "no-undef": 2, + "no-undef-init": 2, + "no-undefined": 0, + "no-underscore-dangle": 0, + "no-unneeded-ternary": 2, + "no-unreachable": 2, + "no-unused-expressions": 0, + "no-unused-vars": [2, { "vars": "all", "args": "none" }], + "no-use-before-define": 2, + "no-var": 0, + "no-void": 0, + "no-warning-comments": 0, + "no-with": 2, + "one-var": 0, + "operator-assignment": 0, + "operator-linebreak": [2, "after"], + "padded-blocks": 0, + "quote-props": 0, + "quotes": [2, "single", "avoid-escape"], + "radix": 2, + "semi": [2, "always"], + "semi-spacing": 0, + "sort-vars": 0, + "space-before-blocks": [2, "always"], + "space-before-function-paren": [2, {"anonymous": "always", "named": "never"}], + "space-in-brackets": 0, + "space-in-parens": [2, "never"], + "space-infix-ops": 2, + "space-unary-ops": [2, { "words": true, "nonwords": false }], + "spaced-comment": [2, "always"], + "strict": 0, + "use-isnan": 2, + "valid-jsdoc": 0, + "valid-typeof": 2, + "vars-on-top": 2, + "wrap-iife": [2, "any"], + "wrap-regex": 0, + "yoda": [2, "never"] + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bc2b59d --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git +node_modules + +# Remove some common IDE working directories +.idea +.vscode diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..d064077 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v6.10 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..95862e0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2017 Faris Ansari + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..1c04b7f --- /dev/null +++ b/README.md @@ -0,0 +1,83 @@ +# Webpack library starter + +Webpack based boilerplate for producing libraries (Input: ES6, Output: universal library) + +## Features + +* Webpack 3 based. +* ES6 as a source. +* Exports in a [umd](https://github.com/umdjs/umd) format so your library works everywhere. +* ES6 test setup with [Mocha](http://mochajs.org/) and [Chai](http://chaijs.com/). +* Linting with [ESLint](http://eslint.org/). + +## Process + +``` +ES6 source files + | + | + webpack + | + +--- babel, eslint + | + ready to use + library + in umd format +``` + +*Have in mind that you have to build your library before publishing. The files under the `lib` folder are the ones that should be distributed.* + +## Getting started + +1. Setting up the name of your library + * Open `webpack.config.js` file and change the value of `libraryName` variable. + * Open `package.json` file and change the value of `main` property so it matches the name of your library. +2. Build your library + * Run `npm install` to get the project's dependencies + * Run `npm run build` to produce minified version of your library. +3. Development mode + * Having all the dependencies installed run `npm run dev`. This command will generate an non-minified version of your library and will run a watcher so you get the compilation on file change. +4. Running the tests + * Run `npm run test` + +## Scripts + +* `npm run build` - produces production version of your library under the `lib` folder +* `npm run dev` - produces development version of your library and runs a watcher +* `npm run test` - well ... it runs the tests :) +* `npm run test:watch` - same as above but in a watch mode + +## Readings + +* [Start your own JavaScript library using webpack and ES6](http://krasimirtsonev.com/blog/article/javascript-library-starter-using-webpack-es6) + +## Misc + +### An example of using dependencies that shouldn’t be resolved by webpack, but should become dependencies of the resulting bundle + +In the following example we are excluding React and Lodash: + +```js +{ + devtool: 'source-map', + output: { + path: '...', + libraryTarget: 'umd', + library: '...' + }, + entry: '...', + ... + externals: { + react: 'react' + // Use more complicated mapping for lodash. + // We need to access it differently depending + // on the environment. + lodash: { + commonjs: 'lodash', + commonjs2: 'lodash', + amd: '_', + root: '_' + } + } +} +``` diff --git a/lib/ReGrid.js b/lib/ReGrid.js new file mode 100644 index 0000000..f095ed4 --- /dev/null +++ b/lib/ReGrid.js @@ -0,0 +1,494 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define("ReGrid", [], factory); + else if(typeof exports === 'object') + exports["ReGrid"] = factory(); + else + root["ReGrid"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ReGrid = undefined; + +var _regrid = __webpack_require__(1); + +var _regrid2 = _interopRequireDefault(_regrid); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.ReGrid = _regrid2.default; + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _utils = __webpack_require__(2); + +var _jQuery = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"jQuery\""); e.code = 'MODULE_NOT_FOUND'; throw e; }())); + +var _jQuery2 = _interopRequireDefault(_jQuery); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var ReGrid = function () { + function ReGrid(_ref) { + var wrapper = _ref.wrapper, + events = _ref.events; + + _classCallCheck(this, ReGrid); + + this.wrapper = wrapper; + this.events = events || {}; + this.makeDom(); + this.bindEvents(); + } + + _createClass(ReGrid, [{ + key: 'makeDom', + value: function makeDom() { + this.wrapper.html('\n
\n \n
\n
\n \n
\n
\n \n
\n
\n
\n
\n '); + + this.header = this.wrapper.find('.data-table-header'); + this.bodyScrollable = this.wrapper.find('.body-scrollable'); + this.body = this.wrapper.find('.data-table-body'); + this.footer = this.wrapper.find('.data-table-footer'); + } + }, { + key: 'render', + value: function render(_ref2) { + var columns = _ref2.columns, + rows = _ref2.rows; + + if (this.wrapper.find('.data-table').length === 0) { + this.makeDom(); + this.bindEvents(); + } + + this.columns = this.prepareColumns(columns); + this.rows = this.prepareRows(rows); + + this.header.html((0, _utils.getHeader)(this.columns)); + this.body.html((0, _utils.getBody)(this.rows)); + + this.setDimensions(); + } + }, { + key: 'updateCell', + value: function updateCell(rowIndex, colIndex, value) { + var row = this.getRow(rowIndex); + var cell = row.find(function (cell) { + return cell.col_index === colIndex; + }); + + cell.data = value; + this.refreshCell(cell); + } + }, { + key: 'refreshRows', + value: function refreshRows(rows) { + if (rows) { + this.rows = this.prepareRows(rows); + } + this.body.html((0, _utils.getBody)(this.rows)); + this.setDimensions(); + } + }, { + key: 'refreshCell', + value: function refreshCell(cell) { + var selector = '.data-table-col[data-row-index="' + cell.row_index + '"][data-col-index="' + cell.col_index + '"]'; + var $cell = this.body.find(selector); + var $newCell = (0, _jQuery2.default)((0, _utils.getCell)(cell)); + + $cell.replaceWith($newCell); + } + }, { + key: 'prepareColumns', + value: function prepareColumns(columns) { + return columns.map(function (col, i) { + col.colIndex = i; + col.isHeader = 1; + col.format = function (val) { + return '' + val + ''; + }; + return col; + }); + } + }, { + key: 'prepareRows', + value: function prepareRows(rows) { + return rows.map(function (cells, i) { + return cells.map(function (cell, j) { + cell.colIndex = j; + cell.rowIndex = i; + return cell; + }); + }); + } + }, { + key: 'bindEvents', + value: function bindEvents() { + var me = this; + + this.bodyScrollable.on('click', '.data-table-col', function () { + var $col = (0, _jQuery2.default)(this); + + me.bodyScrollable.find('.data-table-col').removeClass('selected'); + $col.addClass('selected'); + }); + + this.bindCellDoubleClick(); + this.bindResizeColumn(); + this.bindSortColumn(); + } + }, { + key: 'setDimensions', + value: function setDimensions() { + var me = this; + + // set the width for each cell + this.header.find('.data-table-col').each(function () { + var col = (0, _jQuery2.default)(this); + var height = col.find('.content').height(); + var width = col.find('.content').width(); + var colIndex = col.attr('data-col-index'); + var selector = '.data-table-col[data-col-index="' + colIndex + '"] .content'; + var $cell = me.bodyScrollable.find(selector); + + $cell.width(width); + $cell.height(height); + }); + + // setting width as 0 will ensure that the + // header doesn't take the available space + this.header.css({ + width: 0, + margin: 0 + }); + + this.bodyScrollable.css({ + width: this.header.css('width'), + marginTop: this.header.height() + 1 + }); + + this.bodyScrollable.find('.table').css('margin', 0); + } + }, { + key: 'bindCellDoubleClick', + value: function bindCellDoubleClick() { + var events = this.events; + + + var $editPopup = this.wrapper.find('.edit-popup'); + + $editPopup.hide(); + + this.bodyScrollable.on('dblclick', '.data-table-col', function () { + var $cell = (0, _jQuery2.default)(this); + var rowIndex = $cell.attr('data-row-index'); + var colIndex = $cell.attr('data-col-index'); + + $editPopup.empty(); + + var _$cell$position = $cell.position(), + top = _$cell$position.top, + left = _$cell$position.left; + + $editPopup.css({ + top: top - 12, + left: left - 12 + }); + + // showing the popup is the responsibility of event handler + events.on_cell_doubleclick($cell.get(0), $editPopup, rowIndex, colIndex); + }); + + (0, _jQuery2.default)(document.body).on('click', function (e) { + if ((0, _jQuery2.default)(e.target).is('.edit-popup, .edit-popup *')) return; + $editPopup.hide(); + }); + } + }, { + key: 'bindResizeColumn', + value: function bindResizeColumn() { + var me = this; + var isDragging = false; + var $currCell = void 0, + startWidth = void 0, + startX = void 0; + + this.header.on('mousedown', '.data-table-col', function (e) { + $currCell = (0, _jQuery2.default)(this); + var col = me.getColumn($currCell.attr('data-col-index')); + + if (col && col.resizable === false) { + return; + } + + isDragging = true; + startWidth = $currCell.find('.content').width(); + startX = e.pageX; + }); + + (0, _jQuery2.default)('body').on('mouseup', function (e) { + if (!$currCell) return; + isDragging = false; + var colIndex = $currCell.attr('data-col-index'); + + if ($currCell) { + var width = $currCell.find('.content').css('width'); + + me.setColumnWidth(colIndex, width); + me.bodyScrollable.css('width', me.header.css('width')); + $currCell = null; + } + }); + + this.header.on('mousemove', '.data-table-col', function (e) { + if (!isDragging) return; + var fwidth = startWidth + (e.pageX - startX); + + $currCell.find('.content').width(fwidth); + }); + } + }, { + key: 'bindSortColumn', + value: function bindSortColumn() { + var me = this; + + this.header.on('click', '.data-table-col .content span', function () { + var $cell = (0, _jQuery2.default)(this).closest('.data-table-col'); + var sortBy = $cell.attr('data-sort-by'); + var colIndex = $cell.attr('data-col-index'); + + if (sortBy === 'none') { + $cell.attr('data-sort-by', 'asc'); + $cell.find('.content').append(''); + } else if (sortBy === 'asc') { + $cell.attr('data-sort-by', 'desc'); + $cell.find('.content .octicon').removeClass('octicon-chevron-up').addClass('octicon-chevron-down'); + } else if (sortBy === 'desc') { + $cell.attr('data-sort-by', 'none'); + $cell.find('.content .octicon').remove(); + } + + var sortByAction = $cell.attr('data-sort-by'); + + if (me.events.on_sort) { + me.events.on_sort.apply(null, [colIndex, sortByAction]); + } else { + me.sortRows(colIndex, sortByAction); + me.refreshRows(); + } + }); + } + }, { + key: 'sortRows', + value: function sortRows(colIndex) { + var sortBy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'none'; + + this.rows.sort(function (a, b) { + var _aIndex = a[0].row_index; + var _bIndex = b[0].row_index; + var _a = a[colIndex].data; + var _b = b[colIndex].data; + + if (sortBy === 'none') { + return _aIndex - _bIndex; + } else if (sortBy === 'asc') { + if (_a < _b) return -1; + if (_a > _b) return 1; + if (_a === _b) return 0; + } else if (sortBy === 'desc') { + if (_a < _b) return 1; + if (_a > _b) return -1; + if (_a === _b) return 0; + } + return 0; + }); + } + }, { + key: 'setColumnWidth', + value: function setColumnWidth(colIndex, width) { + var header = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + var selector = '.data-table-col[data-col-index="' + colIndex + '"] .content'; + var $el = void 0; + + if (header) { + $el = this.header.find(selector); + } else { + $el = this.bodyScrollable.find(selector); + } + $el.css('width', width); + } + }, { + key: 'getColumn', + value: function getColumn(colIndex) { + return this.columns.find(function (col) { + return col.col_index === colIndex; + }); + } + }, { + key: 'getRow', + value: function getRow(rowIndex) { + return this.rows.find(function (row) { + return row[0].row_index === rowIndex; + }); + } + }]); + + return ReGrid; +}(); + +exports.default = ReGrid; +module.exports = exports['default']; + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _jQuery = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"jQuery\""); e.code = 'MODULE_NOT_FOUND'; throw e; }())); + +var _jQuery2 = _interopRequireDefault(_jQuery); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getCell(cell) { + var customAttr = [!isNaN(cell.colIndex) ? 'data-col-index="' + cell.colIndex + '"' : '', !isNaN(cell.rowIndex) ? 'data-row-index="' + cell.rowIndex + '"' : '', cell.isHeader ? 'data-sort-by="none"' : ''].join(' '); + + return '\n \n
\n ' + (cell.format ? cell.format(cell.data) : cell.data) + '\n
\n \n '; +} + +function getRow(row) { + var header = row.isHeader ? 'data-header' : ''; + var cells = row.cells; + var dataRowIndex = !isNaN(cells[0].rowIndex) ? 'data-row-index="' + cells[0].rowIndex + '"' : ''; + + return '\n \n ' + cells.map(getCell).join('') + '\n \n '; +} + +function getHeader(columns) { + var $header = (0, _jQuery2.default)('\n ' + getRow({ cells: columns, isHeader: 1 }) + '\n \n '); + + columns.map(function (col) { + if (!col.width) return; + var $cellContent = $header.find('.data-table-col[data-col-index="' + col.colIndex + '"] .content'); + + $cellContent.width(col.width); + // $cell_content.css('max-width', col.width + 'px'); + }); + + return $header; +} + +function getBody(rows) { + return '\n ' + rows.map(function (row) { + return getRow({ cells: row }); + }).join('') + '\n \n '; +} + +exports.default = { + getHeader: getHeader, + getBody: getBody, + getRow: getRow, + getCell: getCell +}; +module.exports = exports['default']; + +/***/ }) +/******/ ]); +}); +//# sourceMappingURL=ReGrid.js.map \ No newline at end of file diff --git a/lib/ReGrid.js.map b/lib/ReGrid.js.map new file mode 100644 index 0000000..bef0959 --- /dev/null +++ b/lib/ReGrid.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap 7ac26c4bf51513474366","webpack:///./src/index.js","webpack:///./src/regrid.js","webpack:///./src/utils.js"],"names":["ReGrid","wrapper","events","makeDom","bindEvents","html","header","find","bodyScrollable","body","footer","columns","rows","length","prepareColumns","prepareRows","setDimensions","rowIndex","colIndex","value","row","getRow","cell","col_index","data","refreshCell","selector","row_index","$cell","$newCell","replaceWith","map","col","i","isHeader","format","val","cells","j","me","on","$col","removeClass","addClass","bindCellDoubleClick","bindResizeColumn","bindSortColumn","each","height","width","attr","css","margin","marginTop","$editPopup","hide","empty","position","top","left","on_cell_doubleclick","get","document","e","target","is","isDragging","$currCell","startWidth","startX","getColumn","resizable","pageX","setColumnWidth","fwidth","closest","sortBy","append","remove","sortByAction","on_sort","apply","sortRows","refreshRows","sort","a","b","_aIndex","_bIndex","_a","_b","$el","getCell","customAttr","isNaN","join","dataRowIndex","getHeader","$header","$cellContent","getBody"],"mappings":"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","file":"ReGrid.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"ReGrid\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ReGrid\"] = factory();\n\telse\n\t\troot[\"ReGrid\"] = factory();\n})(this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 7ac26c4bf51513474366","import ReGrid from './regrid.js';\nexport { ReGrid };\n\n\n\n// WEBPACK FOOTER //\n// ./src/index.js","import { getHeader, getBody, getCell } from './utils.js';\nimport $ from 'jQuery';\n\nexport default class ReGrid {\n constructor({ wrapper, events }) {\n this.wrapper = wrapper;\n this.events = events || {};\n this.makeDom();\n this.bindEvents();\n }\n\n makeDom() {\n this.wrapper.html(`\n
\n \n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n `);\n\n this.header = this.wrapper.find('.data-table-header');\n this.bodyScrollable = this.wrapper.find('.body-scrollable');\n this.body = this.wrapper.find('.data-table-body');\n this.footer = this.wrapper.find('.data-table-footer');\n }\n\n render({ columns, rows }) {\n if (this.wrapper.find('.data-table').length === 0) {\n this.makeDom();\n this.bindEvents();\n }\n\n this.columns = this.prepareColumns(columns);\n this.rows = this.prepareRows(rows);\n\n this.header.html(getHeader(this.columns));\n this.body.html(getBody(this.rows));\n\n this.setDimensions();\n }\n\n updateCell(rowIndex, colIndex, value) {\n const row = this.getRow(rowIndex);\n const cell = row.find(cell => cell.col_index === colIndex);\n\n cell.data = value;\n this.refreshCell(cell);\n }\n\n refreshRows(rows) {\n if (rows) {\n this.rows = this.prepareRows(rows);\n }\n this.body.html(getBody(this.rows));\n this.setDimensions();\n }\n\n refreshCell(cell) {\n const selector = `.data-table-col[data-row-index=\"${cell.row_index}\"][data-col-index=\"${cell.col_index}\"]`;\n const $cell = this.body.find(selector);\n const $newCell = $(getCell(cell));\n\n $cell.replaceWith($newCell);\n }\n\n prepareColumns(columns) {\n return columns.map((col, i) => {\n col.colIndex = i;\n col.isHeader = 1;\n col.format = val => `${val}`;\n return col;\n });\n }\n\n prepareRows(rows) {\n return rows.map((cells, i) => {\n return cells.map((cell, j) => {\n cell.colIndex = j;\n cell.rowIndex = i;\n return cell;\n });\n });\n }\n\n bindEvents() {\n const me = this;\n\n this.bodyScrollable.on('click', '.data-table-col', function () {\n const $col = $(this);\n\n me.bodyScrollable.find('.data-table-col').removeClass('selected');\n $col.addClass('selected');\n });\n\n this.bindCellDoubleClick();\n this.bindResizeColumn();\n this.bindSortColumn();\n }\n\n setDimensions() {\n const me = this;\n\n // set the width for each cell\n this.header.find('.data-table-col').each(function () {\n const col = $(this);\n const height = col.find('.content').height();\n const width = col.find('.content').width();\n const colIndex = col.attr('data-col-index');\n const selector = `.data-table-col[data-col-index=\"${colIndex}\"] .content`;\n const $cell = me.bodyScrollable.find(selector);\n\n $cell.width(width);\n $cell.height(height);\n });\n\n // setting width as 0 will ensure that the\n // header doesn't take the available space\n this.header.css({\n width: 0,\n margin: 0\n });\n\n this.bodyScrollable.css({\n width: this.header.css('width'),\n marginTop: this.header.height() + 1\n });\n\n this.bodyScrollable.find('.table').css('margin', 0);\n }\n\n bindCellDoubleClick() {\n const { events } = this;\n\n const $editPopup = this.wrapper.find('.edit-popup');\n\n $editPopup.hide();\n\n this.bodyScrollable.on('dblclick', '.data-table-col', function () {\n const $cell = $(this);\n const rowIndex = $cell.attr('data-row-index');\n const colIndex = $cell.attr('data-col-index');\n\n $editPopup.empty();\n const { top, left } = $cell.position();\n\n $editPopup.css({\n top: top - 12,\n left: left - 12\n });\n\n // showing the popup is the responsibility of event handler\n events.on_cell_doubleclick(\n $cell.get(0),\n $editPopup,\n rowIndex,\n colIndex\n );\n });\n\n $(document.body).on('click', e => {\n if ($(e.target).is('.edit-popup, .edit-popup *')) return;\n $editPopup.hide();\n });\n }\n\n bindResizeColumn() {\n const me = this;\n let isDragging = false;\n let $currCell, startWidth, startX;\n\n this.header.on('mousedown', '.data-table-col', function (e) {\n $currCell = $(this);\n const col = me.getColumn($currCell.attr('data-col-index'));\n\n if (col && col.resizable === false) {\n return;\n }\n\n isDragging = true;\n startWidth = $currCell.find('.content').width();\n startX = e.pageX;\n });\n\n $('body').on('mouseup', function (e) {\n if (!$currCell) return;\n isDragging = false;\n const colIndex = $currCell.attr('data-col-index');\n\n if ($currCell) {\n const width = $currCell.find('.content').css('width');\n\n me.setColumnWidth(colIndex, width);\n me.bodyScrollable.css('width', me.header.css('width'));\n $currCell = null;\n }\n });\n\n this.header.on('mousemove', '.data-table-col', function (e) {\n if (!isDragging) return;\n const fwidth = startWidth + (e.pageX - startX);\n\n $currCell.find('.content').width(fwidth);\n });\n }\n\n bindSortColumn() {\n const me = this;\n\n this.header.on('click', '.data-table-col .content span', function () {\n const $cell = $(this).closest('.data-table-col');\n const sortBy = $cell.attr('data-sort-by');\n const colIndex = $cell.attr('data-col-index');\n\n if (sortBy === 'none') {\n $cell.attr('data-sort-by', 'asc');\n $cell\n .find('.content')\n .append('');\n } else if (sortBy === 'asc') {\n $cell.attr('data-sort-by', 'desc');\n $cell\n .find('.content .octicon')\n .removeClass('octicon-chevron-up')\n .addClass('octicon-chevron-down');\n } else if (sortBy === 'desc') {\n $cell.attr('data-sort-by', 'none');\n $cell.find('.content .octicon').remove();\n }\n\n const sortByAction = $cell.attr('data-sort-by');\n\n if (me.events.on_sort) {\n me.events.on_sort.apply(null, [colIndex, sortByAction]);\n } else {\n me.sortRows(colIndex, sortByAction);\n me.refreshRows();\n }\n });\n }\n\n sortRows(colIndex, sortBy = 'none') {\n this.rows.sort((a, b) => {\n const _aIndex = a[0].row_index;\n const _bIndex = b[0].row_index;\n const _a = a[colIndex].data;\n const _b = b[colIndex].data;\n\n if (sortBy === 'none') {\n return _aIndex - _bIndex;\n } else if (sortBy === 'asc') {\n if (_a < _b) return -1;\n if (_a > _b) return 1;\n if (_a === _b) return 0;\n } else if (sortBy === 'desc') {\n if (_a < _b) return 1;\n if (_a > _b) return -1;\n if (_a === _b) return 0;\n }\n return 0;\n });\n }\n\n setColumnWidth(colIndex, width, header = false) {\n const selector = `.data-table-col[data-col-index=\"${colIndex}\"] .content`;\n let $el;\n\n if (header) {\n $el = this.header.find(selector);\n } else {\n $el = this.bodyScrollable.find(selector);\n }\n $el.css('width', width);\n }\n\n getColumn(colIndex) {\n return this.columns.find(col => col.col_index === colIndex);\n }\n\n getRow(rowIndex) {\n return this.rows.find(row => row[0].row_index === rowIndex);\n }\n}\n\n\n\n\n// WEBPACK FOOTER //\n// ./src/regrid.js","import $ from 'jQuery';\n\nfunction getCell(cell) {\n const customAttr = [\n !isNaN(cell.colIndex) ? `data-col-index=\"${cell.colIndex}\"` : '',\n !isNaN(cell.rowIndex) ? `data-row-index=\"${cell.rowIndex}\"` : '',\n cell.isHeader ? 'data-sort-by=\"none\"' : ''\n ].join(' ');\n\n return `\n \n
\n ${cell.format ? cell.format(cell.data) : cell.data}\n
\n \n `;\n}\n\nfunction getRow(row) {\n const header = row.isHeader ? 'data-header' : '';\n const cells = row.cells;\n const dataRowIndex = !isNaN(cells[0].rowIndex) ?\n `data-row-index=\"${cells[0].rowIndex}\"` : '';\n\n return `\n \n ${cells.map(getCell).join('')}\n \n `;\n}\n\nfunction getHeader(columns) {\n const $header = $(`\n ${getRow({ cells: columns, isHeader: 1 })}\n \n `);\n\n columns.map(col => {\n if (!col.width) return;\n const $cellContent = $header.find(\n `.data-table-col[data-col-index=\"${col.colIndex}\"] .content`\n );\n\n $cellContent.width(col.width);\n // $cell_content.css('max-width', col.width + 'px');\n });\n\n return $header;\n}\n\nfunction getBody(rows) {\n return `\n ${rows.map(row => getRow({ cells: row })).join('')}\n \n `;\n}\n\nexport default {\n getHeader,\n getBody,\n getRow,\n getCell\n};\n\n\n\n// WEBPACK FOOTER //\n// ./src/utils.js"],"sourceRoot":""} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..289b831 --- /dev/null +++ b/package.json @@ -0,0 +1,45 @@ +{ + "name": "regrid", + "version": "0.0.1", + "description": "A modern grid for the web", + "main": "lib/regrid.js", + "scripts": { + "build": "webpack --env build", + "dev": "webpack --progress --colors --watch --env dev", + "test": "mocha --compilers js:babel-core/register --colors ./test/*.spec.js", + "test:watch": "mocha --compilers js:babel-core/register --colors -w ./test/*.spec.js" + }, + "devDependencies": { + "babel-cli": "6.24.1", + "babel-core": "6.24.1", + "babel-eslint": "7.2.3", + "babel-loader": "7.0.0", + "babel-plugin-add-module-exports": "0.2.1", + "babel-preset-es2015": "6.24.1", + "chai": "3.5.0", + "eslint": "3.19.0", + "eslint-loader": "1.7.1", + "mocha": "3.3.0", + "webpack": "3.1.0", + "yargs": "7.1.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/netchampfaris/regrid.git" + }, + "keywords": [ + "webpack", + "es6", + "starter", + "library", + "universal", + "umd", + "commonjs" + ], + "author": "Faris Ansari", + "license": "MIT", + "bugs": { + "url": "https://github.com/netchampfaris/regrid/issues" + }, + "homepage": "https://github.com/netchampfaris/regrid" +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..73dadb2 --- /dev/null +++ b/src/index.js @@ -0,0 +1,2 @@ +import ReGrid from './regrid.js'; +export { ReGrid }; diff --git a/src/regrid.js b/src/regrid.js new file mode 100644 index 0000000..e37c750 --- /dev/null +++ b/src/regrid.js @@ -0,0 +1,291 @@ +import { getHeader, getBody, getCell } from './utils.js'; +import $ from 'jQuery'; + +export default class ReGrid { + constructor({ wrapper, events }) { + this.wrapper = wrapper; + this.events = events || {}; + this.makeDom(); + this.bindEvents(); + } + + makeDom() { + this.wrapper.html(` +
+ +
+
+ +
+
+ +
+
+
+
+ `); + + this.header = this.wrapper.find('.data-table-header'); + this.bodyScrollable = this.wrapper.find('.body-scrollable'); + this.body = this.wrapper.find('.data-table-body'); + this.footer = this.wrapper.find('.data-table-footer'); + } + + render({ columns, rows }) { + if (this.wrapper.find('.data-table').length === 0) { + this.makeDom(); + this.bindEvents(); + } + + this.columns = this.prepareColumns(columns); + this.rows = this.prepareRows(rows); + + this.header.html(getHeader(this.columns)); + this.body.html(getBody(this.rows)); + + this.setDimensions(); + } + + updateCell(rowIndex, colIndex, value) { + const row = this.getRow(rowIndex); + const cell = row.find(cell => cell.col_index === colIndex); + + cell.data = value; + this.refreshCell(cell); + } + + refreshRows(rows) { + if (rows) { + this.rows = this.prepareRows(rows); + } + this.body.html(getBody(this.rows)); + this.setDimensions(); + } + + refreshCell(cell) { + const selector = `.data-table-col[data-row-index="${cell.row_index}"][data-col-index="${cell.col_index}"]`; + const $cell = this.body.find(selector); + const $newCell = $(getCell(cell)); + + $cell.replaceWith($newCell); + } + + prepareColumns(columns) { + return columns.map((col, i) => { + col.colIndex = i; + col.isHeader = 1; + col.format = val => `${val}`; + return col; + }); + } + + prepareRows(rows) { + return rows.map((cells, i) => { + return cells.map((cell, j) => { + cell.colIndex = j; + cell.rowIndex = i; + return cell; + }); + }); + } + + bindEvents() { + const me = this; + + this.bodyScrollable.on('click', '.data-table-col', function () { + const $col = $(this); + + me.bodyScrollable.find('.data-table-col').removeClass('selected'); + $col.addClass('selected'); + }); + + this.bindCellDoubleClick(); + this.bindResizeColumn(); + this.bindSortColumn(); + } + + setDimensions() { + const me = this; + + // set the width for each cell + this.header.find('.data-table-col').each(function () { + const col = $(this); + const height = col.find('.content').height(); + const width = col.find('.content').width(); + const colIndex = col.attr('data-col-index'); + const selector = `.data-table-col[data-col-index="${colIndex}"] .content`; + const $cell = me.bodyScrollable.find(selector); + + $cell.width(width); + $cell.height(height); + }); + + // setting width as 0 will ensure that the + // header doesn't take the available space + this.header.css({ + width: 0, + margin: 0 + }); + + this.bodyScrollable.css({ + width: this.header.css('width'), + marginTop: this.header.height() + 1 + }); + + this.bodyScrollable.find('.table').css('margin', 0); + } + + bindCellDoubleClick() { + const { events } = this; + + const $editPopup = this.wrapper.find('.edit-popup'); + + $editPopup.hide(); + + this.bodyScrollable.on('dblclick', '.data-table-col', function () { + const $cell = $(this); + const rowIndex = $cell.attr('data-row-index'); + const colIndex = $cell.attr('data-col-index'); + + $editPopup.empty(); + const { top, left } = $cell.position(); + + $editPopup.css({ + top: top - 12, + left: left - 12 + }); + + // showing the popup is the responsibility of event handler + events.on_cell_doubleclick( + $cell.get(0), + $editPopup, + rowIndex, + colIndex + ); + }); + + $(document.body).on('click', e => { + if ($(e.target).is('.edit-popup, .edit-popup *')) return; + $editPopup.hide(); + }); + } + + bindResizeColumn() { + const me = this; + let isDragging = false; + let $currCell, startWidth, startX; + + this.header.on('mousedown', '.data-table-col', function (e) { + $currCell = $(this); + const col = me.getColumn($currCell.attr('data-col-index')); + + if (col && col.resizable === false) { + return; + } + + isDragging = true; + startWidth = $currCell.find('.content').width(); + startX = e.pageX; + }); + + $('body').on('mouseup', function (e) { + if (!$currCell) return; + isDragging = false; + const colIndex = $currCell.attr('data-col-index'); + + if ($currCell) { + const width = $currCell.find('.content').css('width'); + + me.setColumnWidth(colIndex, width); + me.bodyScrollable.css('width', me.header.css('width')); + $currCell = null; + } + }); + + this.header.on('mousemove', '.data-table-col', function (e) { + if (!isDragging) return; + const fwidth = startWidth + (e.pageX - startX); + + $currCell.find('.content').width(fwidth); + }); + } + + bindSortColumn() { + const me = this; + + this.header.on('click', '.data-table-col .content span', function () { + const $cell = $(this).closest('.data-table-col'); + const sortBy = $cell.attr('data-sort-by'); + const colIndex = $cell.attr('data-col-index'); + + if (sortBy === 'none') { + $cell.attr('data-sort-by', 'asc'); + $cell + .find('.content') + .append(''); + } else if (sortBy === 'asc') { + $cell.attr('data-sort-by', 'desc'); + $cell + .find('.content .octicon') + .removeClass('octicon-chevron-up') + .addClass('octicon-chevron-down'); + } else if (sortBy === 'desc') { + $cell.attr('data-sort-by', 'none'); + $cell.find('.content .octicon').remove(); + } + + const sortByAction = $cell.attr('data-sort-by'); + + if (me.events.on_sort) { + me.events.on_sort.apply(null, [colIndex, sortByAction]); + } else { + me.sortRows(colIndex, sortByAction); + me.refreshRows(); + } + }); + } + + sortRows(colIndex, sortBy = 'none') { + this.rows.sort((a, b) => { + const _aIndex = a[0].row_index; + const _bIndex = b[0].row_index; + const _a = a[colIndex].data; + const _b = b[colIndex].data; + + if (sortBy === 'none') { + return _aIndex - _bIndex; + } else if (sortBy === 'asc') { + if (_a < _b) return -1; + if (_a > _b) return 1; + if (_a === _b) return 0; + } else if (sortBy === 'desc') { + if (_a < _b) return 1; + if (_a > _b) return -1; + if (_a === _b) return 0; + } + return 0; + }); + } + + setColumnWidth(colIndex, width, header = false) { + const selector = `.data-table-col[data-col-index="${colIndex}"] .content`; + let $el; + + if (header) { + $el = this.header.find(selector); + } else { + $el = this.bodyScrollable.find(selector); + } + $el.css('width', width); + } + + getColumn(colIndex) { + return this.columns.find(col => col.col_index === colIndex); + } + + getRow(rowIndex) { + return this.rows.find(row => row[0].row_index === rowIndex); + } +} + diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000..560f285 --- /dev/null +++ b/src/utils.js @@ -0,0 +1,63 @@ +import $ from 'jQuery'; + +function getCell(cell) { + const customAttr = [ + !isNaN(cell.colIndex) ? `data-col-index="${cell.colIndex}"` : '', + !isNaN(cell.rowIndex) ? `data-row-index="${cell.rowIndex}"` : '', + cell.isHeader ? 'data-sort-by="none"' : '' + ].join(' '); + + return ` + +
+ ${cell.format ? cell.format(cell.data) : cell.data} +
+ + `; +} + +function getRow(row) { + const header = row.isHeader ? 'data-header' : ''; + const cells = row.cells; + const dataRowIndex = !isNaN(cells[0].rowIndex) ? + `data-row-index="${cells[0].rowIndex}"` : ''; + + return ` + + ${cells.map(getCell).join('')} + + `; +} + +function getHeader(columns) { + const $header = $(` + ${getRow({ cells: columns, isHeader: 1 })} + + `); + + columns.map(col => { + if (!col.width) return; + const $cellContent = $header.find( + `.data-table-col[data-col-index="${col.colIndex}"] .content` + ); + + $cellContent.width(col.width); + // $cell_content.css('max-width', col.width + 'px'); + }); + + return $header; +} + +function getBody(rows) { + return ` + ${rows.map(row => getRow({ cells: row })).join('')} + + `; +} + +export default { + getHeader, + getBody, + getRow, + getCell +}; diff --git a/test/regrid.spec.js b/test/regrid.spec.js new file mode 100644 index 0000000..6917c8c --- /dev/null +++ b/test/regrid.spec.js @@ -0,0 +1,32 @@ +/* global describe, it, before */ + +import chai from 'chai'; +import {Cat, Dog} from '../lib/regrid.js'; + +chai.expect(); + +const expect = chai.expect; + +let lib; + +describe('Given an instance of my Cat library', () => { + before(() => { + lib = new Cat(); + }); + describe('when I need the name', () => { + it('should return the name', () => { + expect(lib.name).to.be.equal('Cat'); + }); + }); +}); + +describe('Given an instance of my Dog library', () => { + before(() => { + lib = new Dog(); + }); + describe('when I need the name', () => { + it('should return the name', () => { + expect(lib.name).to.be.equal('Dog'); + }); + }); +}); diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..c8868b7 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,50 @@ +/* global __dirname, require, module*/ + +const webpack = require('webpack'); +const UglifyJsPlugin = webpack.optimize.UglifyJsPlugin; +const path = require('path'); +const env = require('yargs').argv.env; // use --env with webpack 2 + +let libraryName = 'ReGrid'; + +let plugins = [], outputFile; + +if (env === 'build') { + plugins.push(new UglifyJsPlugin({ minimize: true })); + outputFile = libraryName + '.min.js'; +} else { + outputFile = libraryName + '.js'; +} + +const config = { + entry: __dirname + '/src/index.js', + devtool: 'source-map', + output: { + path: __dirname + '/lib', + filename: outputFile, + library: libraryName, + libraryTarget: 'umd', + umdNamedDefine: true + }, + module: { + rules: [ + { + test: /(\.jsx|\.js)$/, + loader: 'babel-loader', + exclude: /(node_modules|bower_components)/ + }, + { + test: /(\.jsx|\.js)$/, + loader: 'eslint-loader', + exclude: /node_modules/ + } + ] + }, + resolve: { + modules: [path.resolve('./node_modules'), path.resolve('./src')], + extensions: ['.json', '.js'] + }, + plugins: plugins +}; + +module.exports = config;