Skip to content

Commit

Permalink
js modules with lots of
Browse files Browse the repository at this point in the history
  • Loading branch information
uzbeki committed Apr 15, 2024
1 parent 6a204cc commit 3137bb8
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 77 deletions.
60 changes: 48 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ This is a fork of the original [jquery-gantt](https://github.com/taitems/jQuery.

## About

jQuery Gantt Chart is a simple and fast plugin that implements gantt functionality as
a jQuery component.
jQuery Gantt Chart is a modern and fast plugin that implements gantt functionality as
a jQuery component with JS Module support.

Plugin was tested and should work on:
All major browsers that support ES6 or above.
Expand All @@ -60,7 +60,14 @@ All major browsers that support ES6 or above.
```

## Usage
Simply include the plugin in your html file and call it on a div element.
Simply include the plugin and its stylesheet in your html file and call it on a div element.

```html
<link rel="stylesheet" href="./src/jquery.gantt.css">
<script type="module" src="./src/index.js"></script>
```

<!-- Simply include the plugin in your html file and call it on a div element.
### Download the plugin and include it in your html file
Expand All @@ -73,18 +80,20 @@ Simply include the plugin in your html file and call it on a div element.
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@uzbeki/jquery-gantt-chart/dist/jquery.gantt.min.css">
<script defer src="https://cdn.jsdelivr.net/npm/@uzbeki/jquery-gantt-chart/dist/jquery.gantt.min.js"></script>
```
``` -->

### Create a div element and call the plugin on it
```js
$("#gantt").gantt({
source: data, // json data
scale: "days",
onItemClick: console.log,
onAddClick: console.log,
onRender: () => console.log("chart rendered"),
onGetPage: (page) => yourPageHandler(page),
});
<script type="module">
$("#gantt").gantt({
source: data, // json data
scale: "days",
onItemClick: console.log,
onAddClick: console.log,
onRender: () => console.log("chart rendered"),
onGetPage: (page) => yourPageHandler(page),
});
</script>
```

## Customizable Options
Expand All @@ -102,6 +111,9 @@ $("#gantt").gantt({
- `itemsPerPage` - items per page, defaults to `10`
- `dow` - days of week, defaults to `["S", "M", "T", "W", "T", "F", "S"]`
- `months` - months, defaults to `["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]`
- `barOptions` - bar options, defaults to [DefaultBarOptions](#defaultbaroptions)
- `resizability` - bar resizability, defaults to [DefaultBarOptions.resizability](#defaultbaroptions)
- `movability` - bar movability, defaults to [DefaultBarOptions.movability](#defaultbaroptions)
- `onItemClick` - callback on item click, called with item object
- `onAddClick` - callback on add button click, called with date and row data
- `onRender` - callback on chart render
Expand Down Expand Up @@ -129,6 +141,30 @@ type SourceData = {
};
```

### DefaultBarOptions
```ts
const DefaultBarOptions = {
resizability: {
minWidth: DEFAULT_CELL_SIZE, // 24
maxWidth: Infinity, // maximum width
onResize: newWidth => {}, // callback on resize
stepSize: DEFAULT_CELL_SIZE, // 24
handleVisibility: "hover", // "hover" | "click" | "always"
leftHandle: false, // show left handle to resize
rightHandle: true, // show right handle to resize
},
movability: {
stepSize: DEFAULT_CELL_SIZE, // 24
horizontal: true, // allow horizontal movement
vertical: false, // allow vertical movement
minX: 0, // minimum x position
minY: 0, // minimum y position
maxX: Number.POSITIVE_INFINITY, // maximum x position
maxY: Number.POSITIVE_INFINITY, // maximum y position
};
};
```

## License
MIT

23 changes: 17 additions & 6 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<!-- <link rel="stylesheet" href="./dist/jquery.gantt.min.css"> -->
<!-- <script src="./dist/jquery.gantt.min.js"></script> -->
<link rel="stylesheet" href="./src/jquery.gantt.css">
<script type="module" src="./src//index.js"></script>
<script type="module" src="./src/index.js"></script>
<title>jQuery Gantt Chart Demo</title>
<style>
#gantt {
Expand Down Expand Up @@ -55,11 +55,12 @@ <h2>Features</h2>
</li>
<li>📅 Mark holidays or today</li>
<li>🔍 Zoom in/out</li>
<li>🆕 Drag Sortable Header Support (from <code>v0.3.0</code>)</li>
<li>🆕 ES Module support (from <code>v0.3.0</code>)</li>
<li>🆕 Remember Zoom Level and Header Order (from <code>v0.3.5</code>)</li>
<li>🔜 Resizable Bars (coming soon from <code>v0.4.0</code>)</li>
<li>🔜 Movable Bars (coming soon from <code>v0.5.0</code>)</li>
<li>🆕 Drag Sortable Header Support</li>
<li>🆕 ES Module support</li>
<li>🆕 Remember Zoom Level and Header Order</li>
<li>🆕 Resizable Bars from both left and righ ends with <code>barOptions.resizability</code> options</li>
<li>🆕 Movable Bars (vertial and horizontal support) with <code>barOptions.movability</code> options</li>
<li>Easy to sort bars to align them one after the another</li>
</ul>
<p>For more, please refer to <a href="https://github.com/uzbeki/jquery-gantt-chart#readme">README file</a>.
</p>
Expand Down Expand Up @@ -416,6 +417,16 @@ <h2>Features</h2>
navigate: "scroll", // buttons, scroll
scale: "days",
cellSize: 26,
barOptions: {
resizability: {
leftHandle: false,
rightHandle: true,
},
movability: {
horizontal: true,
vertical: false,
},
},
onItemClick: console.log,
onAddClick: console.log,
onRender: () => console.log("chart rendered"),
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"name": "@uzbeki/jquery-gantt-chart",
"description": "Simple Gantt Chart implemented with modernJS and jQuery. Previously known as jQuery.Gantt.",
"homepage": "https://github.com/uzbeki/jquery-gantt-chart#readme",
"version": "0.3.0",
"version": "1.0.0",
"type": "module",
"main": "./dist/jquery.gantt.js",
"module": "./dist/jquery.gantt.js",
"main": "./src/index.js",
"module": "./src/index.js",
"engines": {
"node": ">= 10.0.0"
},
Expand Down
32 changes: 10 additions & 22 deletions src/helpers/Movable.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,15 @@
/**
* @typedef {Object} MovableOptions
* @property {number} [stepSize=1] - The step size for resizing the element.
* @property {boolean} [horizontal=true] - Whether the element can be moved horizontally (left and right).
* @property {boolean} [vertical=true] - Whether the element can be moved vertically (up and down).
* @property {number} [minX=0] - The minimum value for the left position.
* @property {number} [minY=0] - The minimum value for the top position.
* @property {number} [maxX=Number.POSITIVE_INFINITY] - The maximum value for the left position.
* @property {number} [maxY=Number.POSITIVE_INFINITY] - The maximum value for the top position.
*/
const initialOptions = {
stepSize: 1,
horizontal: true,
vertical: false,
minX: 0,
minY: 0,
maxX: Number.POSITIVE_INFINITY,
maxY: Number.POSITIVE_INFINITY,
};
import { initialMovableOptions } from "./initials.js";

class Movable {
constructor(element, options = initialOptions) {
/**
* Creates an instance of Movable.
* @constructor
* @param {HTMLElement} element - The element to make movable.
* @param {typeof initialMovableOptions} [options=initialMovableOptions] - The options for the movable object.
*/
constructor(element, options = initialMovableOptions) {
this.element = element;
this.options = { ...initialOptions, ...options };

this.options = { ...initialMovableOptions, ...options };
// move with mouse
this.element.addEventListener("mousedown", this.handleMouseDown.bind(this));
document.addEventListener("mousemove", this.handleMouseMove.bind(this));
Expand Down Expand Up @@ -68,6 +55,7 @@ class Movable {

handleMouseUp() {
this.isDragging = false;
console.log(this.options.stepSize);

const moveEvent = new CustomEvent("move", {
detail: {
Expand Down
27 changes: 4 additions & 23 deletions src/helpers/Resizer.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,18 @@
/**
* @typedef {Object} ResizerOptions
* @property {number} [minWidth=10] - The minimum width of the element in pixels.
* @property {number} [maxWidth=Infinity] - The maximum width of the element in pixels.
* @property {Function} [onResize=(newWidth) => {}] - The callback function to be called when the element is resized.
* @property {number} [stepSize=1] - The step size for resizing the element.
* @property {string} [handleVisibility="hover"] - The visibility of the resize handles. Possible values: "hover" | "click" | "always".
* @property {boolean} [leftHandle=false] - Whether to show the left handle.
* @property {boolean} [rightHandle=true] - Whether to show the right handle.
*/
const initialOptions = {
minWidth: 10,
maxWidth: Infinity,
onResize: newWidth => {},
stepSize: 1,
handleVisibility: "hover", // "hover" | "click" | "always"
leftHandle: false,
rightHandle: true
};

import { initialResizerOptions } from "./initials.js";
class Resizer {
/**
* Creates a new instance of the Resizer class.
* @param {HTMLElement} element - The element to be resized.
* @param {ResizerOptions} [options=initialOptions] - The options for the Resizer.
* @param {typeof initialResizerOptions} [options=initialResizerOptions] - The options for the Resizer.
*/
constructor(element, options = initialOptions) {
constructor(element, options = initialResizerOptions) {
this.element = element;
this.leftHandle = null;
this.rightHandle = null;
this.startX = 0;
this.startWidth = 0;

this.options = { ...initialOptions, ...options }; // TODO: validate options, ex: minWidth < maxWidth, types
this.options = { ...initialResizerOptions, ...options }; // TODO: validate options, ex: minWidth < maxWidth, types
// Bind the methods in the constructor
this.startResize = this.startResize.bind(this);
this.resize = this.resize.bind(this);
Expand Down
52 changes: 51 additions & 1 deletion src/helpers/initials.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,48 @@
const DEFAULT_CELL_SIZE = 24;
/**
* @typedef {Object} MovableOptions
* @property {number} [stepSize=1] - The step size for resizing the element.
* @property {boolean} [horizontal=true] - Whether the element can be moved horizontally (left and right).
* @property {boolean} [vertical=true] - Whether the element can be moved vertically (up and down).
* @property {number} [minX=0] - The minimum value for the left position.
* @property {number} [minY=0] - The minimum value for the top position.
* @property {number} [maxX=Number.POSITIVE_INFINITY] - The maximum value for the left position.
* @property {number} [maxY=Number.POSITIVE_INFINITY] - The maximum value for the top position.
*/

/** @type {MovableOptions} */
export const initialMovableOptions = {
stepSize: DEFAULT_CELL_SIZE,
horizontal: true,
vertical: false,
minX: 0,
minY: 0,
maxX: Number.POSITIVE_INFINITY,
maxY: Number.POSITIVE_INFINITY,
};

/**
* @typedef {Object} ResizerOptions
* @property {number} [minWidth=10] - The minimum width of the element in pixels.
* @property {number} [maxWidth=Infinity] - The maximum width of the element in pixels.
* @property {Function} [onResize=(newWidth) => {}] - The callback function to be called when the element is resized.
* @property {number} [stepSize=1] - The step size for resizing the element.
* @property {string} [handleVisibility="hover"] - The visibility of the resize handles. Possible values: "hover" | "click" | "always".
* @property {boolean} [leftHandle=false] - Whether to show the left handle.
* @property {boolean} [rightHandle=true] - Whether to show the right handle.
*/

/** @type {ResizerOptions} */
export const initialResizerOptions = {
minWidth: DEFAULT_CELL_SIZE,
maxWidth: Infinity,
onResize: newWidth => {},
stepSize: DEFAULT_CELL_SIZE,
handleVisibility: "hover", // "hover" | "click" | "always"
leftHandle: false,
rightHandle: true,
};

/**
* @typedef {Object} Source
* @property {SourceData[]} data - Array of data objects
Expand Down Expand Up @@ -41,6 +86,7 @@
* @property {Array<string>} dow - Array of day of week labels
* @property {Array<string>} months - Array of month labels
* @property {Array<string>} holidays - Array of holiday dates
* @property {{resizability: ResizerOptions, movability: MovableOptions}} barOptions - Options for bar resizing and moving
* @property {function(data: Object): void} onItemClick - Callback function for item click event
* @property {function(dt: Date, rowId: number): void} onAddClick - Callback function for add click event
* @property {function(): void} onRender - Callback function for render event
Expand All @@ -56,7 +102,7 @@ export const initialSettings = {
maxScale: "months",
// minScale: "every hour",
minScale: "hour",
cellSize: 24,
cellSize: DEFAULT_CELL_SIZE,
scrollToToday: true,
rememberZoomLevel: true,
zoomLevelKey: "jquery-gantt-chart-zoom-level",
Expand All @@ -78,6 +124,10 @@ export const initialSettings = {
"December",
],
holidays: [],
barOptions: {
resizability: initialResizerOptions,
movability: initialMovableOptions,
},
onItemClick: data => {},
onAddClick: (dt, rowId) => {},
onRender: () => {},
Expand Down
22 changes: 22 additions & 0 deletions src/helpers/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,25 @@ export const canChangeScale = (nextScale, minScale, maxScale, zoomIn) => {
return SCALES.indexOf(nextScale) <= SCALES.indexOf(maxScale);
// return ["months", "weeks", "days"].includes(nextScale);
};


/**
* Counts the number of work days between two dates.
* Ignores Saturdays and Sundays and provided holidays.
* @param {Date} startDate - The start date.
* @param {Date} endDate - The end date.
* @param {Array<Date>} holidays - An array of holiday dates.
* @returns {number} The number of work days between the two dates.
*/
export const countWorkDays = (startDate, endDate, holidays=[]) => {
if (startDate > endDate) throw new Error("Start date must be before end date.");
let count = 0;
let currentDate = new Date(startDate);
while (currentDate <= endDate) {
if (currentDate.getDay() !== 0 && currentDate.getDay() !== 6 && !holidays.includes(currentDate)) {
count++;
}
currentDate.setDate(currentDate.getDate() + 1);
}
return count;
}
Loading

0 comments on commit 3137bb8

Please sign in to comment.