-
Notifications
You must be signed in to change notification settings - Fork 304
Mouse and touch drag can be used to scroll the chart. #83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
690844c
9f51941
767d4a0
c64dc7f
2085862
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,7 +46,9 @@ | |
| onItemClick: function (data) { return; }, | ||
| onAddClick: function (data) { return; }, | ||
| onRender: function() { return; }, | ||
| scrollToToday: true | ||
| scrollToToday: true, | ||
| scrollOnWheel: true, | ||
| scrollOnDrag: false | ||
| }; | ||
|
|
||
| // custom selector `:findday` used to match on specified day in ms. | ||
|
|
@@ -223,6 +225,7 @@ | |
| element.dateStart = tools.getMinDate(element); | ||
| element.dateEnd = tools.getMaxDate(element); | ||
|
|
||
| element.dataPanelIgnoreNextClick = false; | ||
|
|
||
| /* core.render(element); */ | ||
| core.waitToggle(element, true, function () { core.render(element); }); | ||
|
|
@@ -338,19 +341,33 @@ | |
| dataPanel: function (element, width) { | ||
| var dataPanel = $('<div class="dataPanel" style="width: ' + width + 'px;"/>'); | ||
|
|
||
| // Handle mousewheel events for scrolling the data panel | ||
| var mousewheelevt = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel"; | ||
| if (document.attachEvent) { | ||
| element.attachEvent("on" + mousewheelevt, function (e) { core.wheelScroll(element, e); }); | ||
| } else if (document.addEventListener) { | ||
| element.addEventListener(mousewheelevt, function (e) { core.wheelScroll(element, e); }, false); | ||
| if (settings.scrollOnWheel == true) { | ||
| // Handle mousewheel events for scrolling the data panel | ||
| $(element).on('wheel', function (e) { core.wheelScroll(element, e); }); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are still quite a few older (but still globally-popular) browsers that don't support the 'wheel' event, which is why the check was in there, even if it wasn't quite correct. I suggest something like this (adapted from MDN): var wheel = core.wheel = 'onwheel' in element ? 'wheel' : document.onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll';
$(element).on(wheel, function (e) { core.wheelScroll(element, e); }); |
||
| } | ||
|
|
||
| if (settings.scrollOnDrag == true) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for |
||
| dataPanel.on('touchstart', function (e) { core.dragDataPanelStart(element, e.originalEvent.changedTouches[0].screenX, e); }); | ||
| dataPanel.on('touchmove', function (e) { core.dragDataPanelMove(element, e.originalEvent.changedTouches[0].screenX, e); }); | ||
| dataPanel.on('touchend', function (e) { core.dragDataPanelStop(element); }); | ||
|
|
||
| dataPanel.mousedown(function (e) { core.dragDataPanelStart(element, e.screenX, e); }); | ||
| dataPanel.mousemove(function (e) { core.dragDataPanelMove(element, e.screenX, e); }); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. mousemove listeners are expensive. The event fires all the dang time. Maybe only bind the handler after (or inside) a |
||
| dataPanel.mouseout(function (e) { core.dragDataPanelStop(element); }); | ||
| dataPanel.mouseup(function (e) { core.dragDataPanelStop(element); }); | ||
| } | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe a matter of code style, but I would rewrite these to look slightly cleaner, e.g.: dataPanel.on('mousedown touchstart', function (e) {
var screenX = e.type.indexOf('mouse') === 0 ? e.screenX : e.originalEvent.changedTouches[0].screenX;
core.dragDataPanelStart(element, screenX, e);
});
dataPanel.on('mouseup mouseout touchend', function (e) { core.dragDataPanelStop(element); }); |
||
| // Handle click events and dispatch to registered `onAddClick` | ||
| // function | ||
| dataPanel.click(function (e) { | ||
|
|
||
| e.stopPropagation(); | ||
|
|
||
| if (element.dataPanelIgnoreNextClick == true) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for the |
||
| element.dataPanelIgnoreNextClick = false; | ||
| return dataPanel; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You might also want an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or, actually, just change the line to |
||
| } | ||
|
|
||
| var corrX, corrY; | ||
| var leftpanel = $(element).find(".fn-gantt .leftPanel"); | ||
| var datapanel = $(element).find(".fn-gantt .dataPanel"); | ||
|
|
@@ -672,7 +689,7 @@ | |
| default: | ||
| range = tools.parseDateRange(element.dateStart, element.dateEnd); | ||
|
|
||
| var dateBefore = ktkGetNextDate(range[0], -1); | ||
| var dateBefore = ktkGetNextDate(range[0], -1); | ||
| var year = dateBefore.getFullYear(); | ||
| var month = dateBefore.getMonth(); | ||
| var day = dateBefore; | ||
|
|
@@ -931,7 +948,7 @@ | |
| // **Progress Bar** | ||
| // Return an element representing a progress of position within | ||
| // the entire chart | ||
| createProgressBar: function (days, cls, desc, label, dataObj) { | ||
| createProgressBar: function (days, cls, desc, label, dataObj, element) { | ||
| var cellWidth = tools.getCellSize(); | ||
| var barMarg = tools.getProgressBarMargin() || 0; | ||
| var bar = $('<div class="bar"><div class="fn-label">' + label + '</div></div>') | ||
|
|
@@ -960,7 +977,12 @@ | |
| } | ||
| bar.click(function (e) { | ||
| e.stopPropagation(); | ||
| settings.onItemClick($(this).data("dataObj")); | ||
|
|
||
| if (element.dataPanelIgnoreNextClick == true) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, no need for |
||
| element.dataPanelIgnoreNextClick = false; | ||
| } else { | ||
| settings.onItemClick($(this).data("dataObj")); | ||
| } | ||
| }); | ||
| return bar; | ||
| }, | ||
|
|
@@ -1026,7 +1048,8 @@ | |
| day.customClass ? day.customClass : "", | ||
| day.desc ? day.desc : "", | ||
| day.label ? day.label : "", | ||
| day.dataObj ? day.dataObj : null | ||
| day.dataObj ? day.dataObj : null, | ||
| element | ||
| ); | ||
|
|
||
| // find row | ||
|
|
@@ -1069,7 +1092,8 @@ | |
| day.customClass ? day.customClass : "", | ||
| day.desc ? day.desc : "", | ||
| day.label ? day.label : "", | ||
| day.dataObj ? day.dataObj : null | ||
| day.dataObj ? day.dataObj : null, | ||
| element | ||
| ); | ||
|
|
||
| // find row | ||
|
|
@@ -1109,7 +1133,8 @@ | |
| day.customClass ? day.customClass : "", | ||
| day.desc ? day.desc : "", | ||
| day.label ? day.label : "", | ||
| day.dataObj ? day.dataObj : null | ||
| day.dataObj ? day.dataObj : null, | ||
| element | ||
| ); | ||
|
|
||
| // find row | ||
|
|
@@ -1135,7 +1160,8 @@ | |
| day.customClass ? day.customClass : "", | ||
| day.desc ? day.desc : "", | ||
| day.label ? day.label : "", | ||
| day.dataObj ? day.dataObj : null | ||
| day.dataObj ? day.dataObj : null, | ||
| element | ||
| ); | ||
|
|
||
| // find row | ||
|
|
@@ -1303,7 +1329,7 @@ | |
|
|
||
| // Move chart via mousewheel | ||
| wheelScroll: function (element, e) { | ||
| var delta = e.detail ? e.detail * (-50) : e.wheelDelta / 120 * 50; | ||
| var delta = e.originalEvent.deltaY * 50; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To go with the cross-browser mouse wheel event solution I suggested above, we should adjust this as well. Something like this (again, stolen from Mozilla): var delta = - 50 * (core.wheel === 'mousewheel' ? - 1/40 * e.originalEvent.wheelDelta : e.detail); |
||
|
|
||
| core.scrollPanel(element, delta); | ||
|
|
||
|
|
@@ -1431,6 +1457,25 @@ | |
| } | ||
| element.loader = null; | ||
| } | ||
| }, | ||
|
|
||
| dragDataPanelStart: function (element, screenX, e) { | ||
| element.scrollNavigation.dragStartX = screenX; | ||
| }, | ||
|
|
||
| dragDataPanelMove: function (element, screenX, e) { | ||
| if (element.scrollNavigation.dragStartX != undefined) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should use |
||
| core.scrollPanel(element, screenX - element.scrollNavigation.dragStartX) | ||
| element.scrollNavigation.dragStartX = screenX | ||
|
|
||
| // Stop the click event from being generated on mouse up when the drag ends. | ||
| element.dataPanelIgnoreNextClick = true; | ||
| e.preventDefault(); | ||
| } | ||
| }, | ||
|
|
||
| dragDataPanelStop: function (element) { | ||
| element.scrollNavigation.dragStartX = undefined; | ||
| } | ||
| }; | ||
|
|
||
|
|
@@ -1541,27 +1586,27 @@ | |
| var ret = []; | ||
| var i = 0; | ||
| for(;;) { | ||
| var dayStartTime = new Date(current); | ||
| dayStartTime.setHours(Math.floor((current.getHours()) / scaleStep) * scaleStep); | ||
| var dayStartTime = new Date(current); | ||
| dayStartTime.setHours(Math.floor((current.getHours()) / scaleStep) * scaleStep); | ||
|
|
||
| if (ret[i] && dayStartTime.getDay() !== ret[i].getDay()) { | ||
| // If mark-cursor jumped to next day, make sure it starts at 0 hours | ||
| dayStartTime.setHours(0); | ||
| // If mark-cursor jumped to next day, make sure it starts at 0 hours | ||
| dayStartTime.setHours(0); | ||
| } | ||
| ret[i] = dayStartTime; | ||
| ret[i] = dayStartTime; | ||
|
|
||
| // Note that we use ">" because we want to include the end-time point. | ||
| if(current.getTime() > to.getTime()) break; | ||
| // Note that we use ">" because we want to include the end-time point. | ||
| if(current.getTime() > to.getTime()) break; | ||
|
|
||
| /* BUG-2: current is moved backwards producing a dead-lock! (crashes chrome/IE/firefox) | ||
| * SEE: https://github.com/taitems/jQuery.Gantt/issues/62 | ||
| /* BUG-2: current is moved backwards producing a dead-lock! (crashes chrome/IE/firefox) | ||
| * SEE: https://github.com/taitems/jQuery.Gantt/issues/62 | ||
| if (current.getDay() !== ret[i].getDay()) { | ||
| current.setHours(0); | ||
| } | ||
| */ | ||
| */ | ||
|
|
||
| // GR Fix Begin | ||
| current = ktkGetNextDate(dayStartTime, scaleStep); | ||
| current = ktkGetNextDate(dayStartTime, scaleStep); | ||
| // GR Fix End | ||
|
|
||
| i++; | ||
|
|
@@ -1728,7 +1773,8 @@ | |
| panelMargin: 0, | ||
| repositionDelay: 0, | ||
| panelMaxPos: 0, | ||
| canScroll: true | ||
| canScroll: true, | ||
| dragStartX: undefined | ||
| }; | ||
|
|
||
| this.gantt = null; | ||
|
|
@@ -1742,15 +1788,15 @@ | |
| })(jQuery); | ||
|
|
||
| function ktkGetNextDate(currentDate, scaleStep) { | ||
| for(var minIncrements = 1;; minIncrements++) { | ||
| var nextDate = new Date(currentDate); | ||
| nextDate.setHours(currentDate.getHours() + scaleStep * minIncrements); | ||
| for(var minIncrements = 1;; minIncrements++) { | ||
| var nextDate = new Date(currentDate); | ||
| nextDate.setHours(currentDate.getHours() + scaleStep * minIncrements); | ||
|
|
||
| if(nextDate.getTime() != currentDate.getTime()) { | ||
| return nextDate; | ||
| } | ||
| if(nextDate.getTime() != currentDate.getTime()) { | ||
| return nextDate; | ||
| } | ||
|
|
||
| // If code reaches here, it's because current didn't really increment (invalid local time) because of daylight-saving adjustments | ||
| // => retry adding 2, 3, 4 hours, and so on (until nextDate > current) | ||
| } | ||
| // If code reaches here, it's because current didn't really increment (invalid local time) because of daylight-saving adjustments | ||
| // => retry adding 2, 3, 4 hours, and so on (until nextDate > current) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,7 +42,11 @@ <h1> | |
| </h1> | ||
|
|
||
| <p> | ||
| <strong>Expected behaviour:</strong> Gantt bar should run from "now" until 2 hours from now. It fails when all the bars are docked left at the hour view. | ||
| <strong>Expected behaviour:</strong> | ||
| <ul> | ||
| <li>Two Gantt bars are present. The first runs from "now" until 2 hours from now. The second runs from "now" until 10 hours from now. It fails when all the bars are docked left at the hour view.</li> | ||
| <li>Mouse wheel scrolls the chart.</li> | ||
| </ul> | ||
| </p> | ||
|
|
||
| <p> | ||
|
|
@@ -72,6 +76,7 @@ <h1> | |
|
|
||
| var today_friendly = "/Date(" + today.valueOf() + ")/"; | ||
| var next_friendly = "/Date(" + andTwoHours.valueOf() + ")/"; | ||
| var far_next_friendly = "/Date(" + today.add("hours", 10).valueOf() + ")/"; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer |
||
|
|
||
| $(".gantt").gantt({ | ||
| source: [{ | ||
|
|
@@ -83,7 +88,17 @@ <h1> | |
| label: "Test", | ||
| customClass: "ganttRed" | ||
| }] | ||
| }], | ||
| }, | ||
| { | ||
| name: "Large bar", | ||
| desc: " ", | ||
| values: [{ | ||
| from: today_friendly, | ||
| to: far_next_friendly, | ||
| label: "Large bar", | ||
| customClass: "ganttRed" | ||
| }] | ||
| } ], | ||
| scale: "hours", | ||
| minScale: "hours", | ||
| navigate: "scroll" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| <!doctype html> | ||
| <html lang="en-au"> | ||
| <head> | ||
| <title>jQuery.Gantt - Test Suite 02</title> | ||
| <meta charset="utf-8"> | ||
| <meta http-equiv="X-UA-Compatible" content="IE=Edge;chrome=1" > | ||
| <link rel="stylesheet" href="../css/style.css" /> | ||
| <link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet"> | ||
| <link rel="stylesheet" href="http://taitems.github.com/UX-Lab/core/css/prettify.css" /> | ||
| <style type="text/css"> | ||
| body { | ||
| font-family: Helvetica, Arial, sans-serif; | ||
| font-size: 13px; | ||
| padding: 0 0 50px 0; | ||
| } | ||
| .contain { | ||
| width: 800px; | ||
| margin: 0 auto; | ||
| } | ||
| h1 { | ||
| margin: 40px 0 20px 0; | ||
| } | ||
| h2 { | ||
| font-size: 1.5em; | ||
| padding-bottom: 3px; | ||
| border-bottom: 1px solid #DDD; | ||
| margin-top: 50px; | ||
| margin-bottom: 25px; | ||
| } | ||
| table th:first-child { | ||
| width: 150px; | ||
| } | ||
| </style> | ||
| </head> | ||
| <body> | ||
|
|
||
| <div class="contain"> | ||
|
|
||
| <h1> | ||
| jQuery.Gantt | ||
| <small>— Test Suite 02</small> | ||
| </h1> | ||
|
|
||
| <p> | ||
| <strong>Expected behaviour:</strong> | ||
| <ul> | ||
| <li>Chart can be scrolled by dragging empty space in data panel.</li> | ||
| <li>Touch screen clients can scroll with drag touches.</li> | ||
| <li>Releasing the mouse over a Gantt item after a drag completes doesn't trigger the onItemClick event.</li> | ||
| <li>Releasing the mouse over an empty spot on the data panel after a drag completes doesn't trigger the onAddClick event.</li> | ||
| <li>Using the scroll wheel while mouse is over the data panel doesn't scroll the data panel.</li> | ||
| </ul> | ||
| </p> | ||
|
|
||
| <p> | ||
| <strong>Manual validation:</strong> | ||
| <ul> | ||
| <li>Passing</li> | ||
| </ul> | ||
| </p> | ||
|
|
||
| <div class="gantt"></div> | ||
|
|
||
|
|
||
| </body> | ||
| <script src="../js/jquery.min.js"></script> | ||
| <script src="../js/jquery.fn.gantt.js"></script> | ||
| <script src="moment.min.js"></script> | ||
| <script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script> | ||
| <script src="http://taitems.github.com/UX-Lab/core/js/prettify.js"></script> | ||
| <script> | ||
|
|
||
| $(function() { | ||
|
|
||
| "use strict"; | ||
|
|
||
| var today = moment(); | ||
| var future = moment().add("hours",200); | ||
|
|
||
| var today_friendly = "/Date(" + today.valueOf() + ")/"; | ||
| var next_friendly = "/Date(" + future.valueOf() + ")/"; | ||
| var click_date_friendly = "/Date(" + today.add("hours", -10).valueOf() + ")/"; | ||
|
|
||
| $(".gantt").gantt({ | ||
| source: [ | ||
| { | ||
| name: "Testing", | ||
| desc: " ", | ||
| values: [{ | ||
| from: today_friendly, | ||
| to: next_friendly, | ||
| label: "Test", | ||
| customClass: "ganttRed" | ||
| }] | ||
| }, | ||
| { | ||
| name: "Test click release", | ||
| desc: " ", | ||
| values: [{ | ||
| from: click_date_friendly, | ||
| to: next_friendly, | ||
| label: "Test2", | ||
| customClass: "ganttRed" | ||
| }] | ||
| } | ||
| ], | ||
| scale: "hours", | ||
| minScale: "hours", | ||
| navigate: "scroll", | ||
| scrollOnDrag: true, | ||
| scrollOnWheel: false, | ||
| onItemClick: function() { alert('Gantt item clicked.'); }, | ||
| onAddClick: function() { alert('Data panel clicked.'); } | ||
| }); | ||
| }); | ||
|
|
||
| </script> | ||
| </html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for
== true.