From d78a823d4ee9a49227d4147ef24e8ab1ac08ec67 Mon Sep 17 00:00:00 2001 From: jos Date: Fri, 20 Jun 2014 17:18:51 +0200 Subject: [PATCH] Removed the 'rangeoverflow' item type --- HISTORY.md | 8 ++- docs/timeline.html | 8 +-- examples/timeline/18_range_overflow.html | 55 ++++++++++++++++++ examples/timeline/index.html | 1 + src/timeline/component/ItemSet.js | 10 +++- src/timeline/component/css/item.css | 16 +++--- src/timeline/component/item/ItemRange.js | 40 +++++++++---- .../component/item/ItemRangeOverflow.js | 57 ------------------- test/timeline.html | 16 +++++- 9 files changed, 126 insertions(+), 85 deletions(-) create mode 100644 examples/timeline/18_range_overflow.html delete mode 100644 src/timeline/component/item/ItemRangeOverflow.js diff --git a/HISTORY.md b/HISTORY.md index d3674871..029ef2a1 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,12 +2,18 @@ http://visjs.org -## 2014-06-19, version 2.0.1 +## not yet released, version 2.1.0 ### Timeline - Fixed auto detected item type being preferred over the global item `type`. - Throws an error when constructing without new keyword. +- Removed the 'rangeoverflow' item type. Instead, one can use a regular range + and change css styling of the item contents to: + + .vis.timeline .item.range .content { + overflow: visible; + } ### Graph diff --git a/docs/timeline.html b/docs/timeline.html index 6907887d..07da66f4 100644 --- a/docs/timeline.html +++ b/docs/timeline.html @@ -202,8 +202,8 @@ var items = [ type String 'box' - The type of the item. Can be 'box' (default), 'point', 'range', or 'rangeoverflow'. - Types 'box' and 'point' need a start date, and types 'range' and 'rangeoverflow' need both a start and end date. Types 'range' and rangeoverflow are equal, except that overflowing text in 'range' is hidden, while visible in 'rangeoverflow'. + The type of the item. Can be 'box' (default), 'point', or 'range'. + Types 'box' and 'point' need a start date, and type 'range' needs both a start and end date. @@ -604,8 +604,8 @@ var options = { type String - 'box' - Specifies the default type for the timeline items. Choose from 'box', 'point', 'range', and 'rangeoverflow'. Note that individual items can override this default type. + none + Specifies the default type for the timeline items. Choose from 'box', 'point', and 'range'. Note that individual items can override this default type. If undefined, the Timeline will auto detect the type from the items data: if a start and end date is available, a 'range' will be created, and else, a 'box' is created. diff --git a/examples/timeline/18_range_overflow.html b/examples/timeline/18_range_overflow.html new file mode 100644 index 00000000..1220db71 --- /dev/null +++ b/examples/timeline/18_range_overflow.html @@ -0,0 +1,55 @@ + + + + Timeline | Range overflow + + + + + + + + +

+ In case of ranges being spread over a wide range of time, it can be interesting to have the text contents of the ranges overflow the box. This can be achieved by changing the overflow property of the contents to visible with css: +

+
+.vis.timeline .item.range .content {
+  overflow: visible;
+}
+
+ +
+ + + + \ No newline at end of file diff --git a/examples/timeline/index.html b/examples/timeline/index.html index 88ba04b7..79b67820 100644 --- a/examples/timeline/index.html +++ b/examples/timeline/index.html @@ -29,6 +29,7 @@

15_item_class_names.html

16_navigation_menu.html

17_data_serialization.html

+

18_range_overflow.html

requirejs_example.html

diff --git a/src/timeline/component/ItemSet.js b/src/timeline/component/ItemSet.js index 92c45076..2eee85ea 100644 --- a/src/timeline/component/ItemSet.js +++ b/src/timeline/component/ItemSet.js @@ -13,7 +13,7 @@ function ItemSet(body, options) { this.body = body; this.defaultOptions = { - type: null, // 'box', 'point', 'range', 'rangeoverflow' + type: null, // 'box', 'point', 'range' orientation: 'bottom', // 'top' or 'bottom' align: 'center', // alignment of box items stack: true, @@ -114,7 +114,6 @@ ItemSet.prototype = new Component(); ItemSet.types = { box: ItemBox, range: ItemRange, - rangeoverflow: ItemRangeOverflow, point: ItemPoint }; @@ -696,6 +695,11 @@ ItemSet.prototype._onUpdate = function(ids) { item.id = id; // TODO: not so nice setting id afterwards me._addItem(item); } + else if (type == 'rangeoverflow') { + // TODO: deprecated since version 2.1.0 (or 3.0.0?). cleanup some day + throw new TypeError('Item type "rangeoverflow" is deprecated. Use css styling instead: ' + + '.vis.timeline .item.range .content {overflow: visible;}'); + } else { throw new TypeError('Unknown item type "' + type + '"'); } @@ -1205,7 +1209,7 @@ ItemSet.prototype._onAddItem = function (event) { }; // when default type is a range, add a default end date to the new item - if (this.options.type === 'range' || this.options.type == 'rangeoverflow') { + if (this.options.type === 'range') { var end = this.body.util.toTime(x + this.props.width / 5); newItem.end = snap ? snap(end) : end; } diff --git a/src/timeline/component/css/item.css b/src/timeline/component/css/item.css index 1291a49f..ea763ab2 100644 --- a/src/timeline/component/css/item.css +++ b/src/timeline/component/css/item.css @@ -41,15 +41,13 @@ border-radius: 4px; } -.vis.timeline .item.range, -.vis.timeline .item.rangeoverflow{ +.vis.timeline .item.range { border-style: solid; border-radius: 2px; box-sizing: border-box; } -.vis.timeline .item.range .content, -.vis.timeline .item.rangeoverflow .content { +.vis.timeline .item.range .content { position: relative; display: inline-block; } @@ -59,6 +57,10 @@ max-width: 100%; } +.vis.timeline .item.range.overflow .content { + overflow: visible; +} + .vis.timeline .item.line { padding: 0; position: absolute; @@ -82,8 +84,7 @@ cursor: pointer; } -.vis.timeline .item.range .drag-left, -.vis.timeline .item.rangeoverflow .drag-left { +.vis.timeline .item.range .drag-left { position: absolute; width: 24px; height: 100%; @@ -94,8 +95,7 @@ z-index: 10000; } -.vis.timeline .item.range .drag-right, -.vis.timeline .item.rangeoverflow .drag-right { +.vis.timeline .item.range .drag-right { position: absolute; width: 24px; height: 100%; diff --git a/src/timeline/component/item/ItemRange.js b/src/timeline/component/item/ItemRange.js index 00a2b241..98572557 100644 --- a/src/timeline/component/item/ItemRange.js +++ b/src/timeline/component/item/ItemRange.js @@ -14,6 +14,7 @@ function ItemRange (data, conversion, options) { width: 0 } }; + this.overflow = false; // if contents can overflow (css styling), this flag is set to true // validate data if (data) { @@ -107,6 +108,9 @@ ItemRange.prototype.redraw = function() { // recalculate size if (this.dirty) { + // determine from css whether this box has overflow + this.overflow = window.getComputedStyle(dom.content).overflow !== 'hidden'; + this.props.content.width = this.dom.content.offsetWidth; this.height = this.dom.box.offsetHeight; @@ -151,6 +155,7 @@ ItemRange.prototype.hide = function() { * Reposition the item horizontally * @Override */ +// TODO: delete the old function ItemRange.prototype.repositionX = function() { var props = this.props, parentWidth = this.parent.width, @@ -166,22 +171,35 @@ ItemRange.prototype.repositionX = function() { if (end > 2 * parentWidth) { end = 2 * parentWidth; } + var boxWidth = Math.max(end - start, 1); - // when range exceeds left of the window, position the contents at the left of the visible area - if (start < 0) { - contentLeft = Math.min(-start, - (end - start - props.content.width - 2 * padding)); - // TODO: remove the need for options.padding. it's terrible. - } - else { - contentLeft = 0; + if (this.overflow) { + // when range exceeds left of the window, position the contents at the left of the visible area + contentLeft = Math.max(-start, 0); + + this.left = start; + this.width = boxWidth + this.props.content.width; + // Note: The calculation of width is an optimistic calculation, giving + // a width which will not change when moving the Timeline + // So no restacking needed, which is nicer for the eye; } + else { // no overflow + // when range exceeds left of the window, position the contents at the left of the visible area + if (start < 0) { + contentLeft = Math.min(-start, + (end - start - props.content.width - 2 * padding)); + // TODO: remove the need for options.padding. it's terrible. + } + else { + contentLeft = 0; + } - this.left = start; - this.width = Math.max(end - start, 1); + this.left = start; + this.width = boxWidth; + } this.dom.box.style.left = this.left + 'px'; - this.dom.box.style.width = this.width + 'px'; + this.dom.box.style.width = boxWidth + 'px'; this.dom.content.style.left = contentLeft + 'px'; }; diff --git a/src/timeline/component/item/ItemRangeOverflow.js b/src/timeline/component/item/ItemRangeOverflow.js deleted file mode 100644 index 3d5d474e..00000000 --- a/src/timeline/component/item/ItemRangeOverflow.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @constructor ItemRangeOverflow - * @extends ItemRange - * @param {Object} data Object containing parameters start, end - * content, className. - * @param {{toScreen: function, toTime: function}} conversion - * Conversion functions from time to screen and vice versa - * @param {Object} [options] Configuration options - * // TODO: describe options - */ -function ItemRangeOverflow (data, conversion, options) { - this.props = { - content: { - left: 0, - width: 0 - } - }; - - ItemRange.call(this, data, conversion, options); -} - -ItemRangeOverflow.prototype = new ItemRange (null, null, null); - -ItemRangeOverflow.prototype.baseClassName = 'item rangeoverflow'; - -/** - * Reposition the item horizontally - * @Override - */ -ItemRangeOverflow.prototype.repositionX = function() { - var parentWidth = this.parent.width, - start = this.conversion.toScreen(this.data.start), - end = this.conversion.toScreen(this.data.end), - contentLeft; - - // limit the width of the this, as browsers cannot draw very wide divs - if (start < -parentWidth) { - start = -parentWidth; - } - if (end > 2 * parentWidth) { - end = 2 * parentWidth; - } - - // when range exceeds left of the window, position the contents at the left of the visible area - contentLeft = Math.max(-start, 0); - - this.left = start; - var boxWidth = Math.max(end - start, 1); - this.width = boxWidth + this.props.content.width; - // Note: The calculation of width is an optimistic calculation, giving - // a width which will not change when moving the Timeline - // So no restacking needed, which is nicer for the eye - - this.dom.box.style.left = this.left + 'px'; - this.dom.box.style.width = boxWidth + 'px'; - this.dom.content.style.left = contentLeft + 'px'; -}; diff --git a/test/timeline.html b/test/timeline.html index 14ce8d91..b7fc9e59 100644 --- a/test/timeline.html +++ b/test/timeline.html @@ -15,6 +15,15 @@ #visualization .itemset { /*background: rgba(255, 255, 0, 0.5);*/ } + + /* + .vis.timeline .item.range .content { + overflow: hidden; + max-width: none; + } + */ + + @@ -70,7 +79,12 @@ {_id: 2, content: 'item 2', start: now.clone().add('days', -2).toDate() }, {_id: 3, content: 'item 3', start: now.clone().add('days', 2).toDate()}, { - _id: 4, content: 'item 4', + _id: 4, content: 'item 4 asdfjkadsf adksfk adskfadks aksdfk asdfkkadkskafdskdfs ', + start: now.clone().add('days', 0).toDate(), + end: now.clone().add('days', 7).toDate(), className: 'overflow' + }, + { + _id: 7, content: 'item 7 asdfjkadsf adksfk adskfadks aksdfk asdfkkadkskafdskdfs ', start: now.clone().add('days', 0).toDate(), end: now.clone().add('days', 7).toDate() },