diff --git a/dist/vis.css b/dist/vis.css index 0f6cd685..b2d1edc3 100644 --- a/dist/vis.css +++ b/dist/vis.css @@ -340,33 +340,38 @@ } - -.vis.timeline .dataaxis .text.measure { +.vis.timeline .dataaxis .yAxis.major { + width: 100%; position: absolute; + color: #4d4d4d; + white-space: nowrap; +} + +.vis.timeline .dataaxis .yAxis.major.measure{ padding-left: 0; padding-right: 0; margin-left: 0; margin-right: 0; visibility: hidden; -} - -.vis.timeline .dataaxis .yAxis.major { - font-size:12px; - width: 100%; - position: absolute; - color: #4d4d4d; - white-space: nowrap; + width: auto; } .vis.timeline .dataaxis .yAxis.minor{ - font-size:12px; position: absolute; width: 100%; color: #979797; white-space: nowrap; } +.vis.timeline .dataaxis .yAxis.minor.measure{ + padding-left: 0; + padding-right: 0; + margin-left: 0; + margin-right: 0; + visibility: hidden; + width: auto; +} .vis.timeline .graphGroup0 { fill:#4f81bd; fill-opacity:0; diff --git a/dist/vis.js b/dist/vis.js index 75df9866..84e9802a 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 1.1.0 - * @date 2014-06-19 + * @date 2014-06-20 * * @license * Copyright (C) 2011-2014 Almende B.V, http://almende.com @@ -420,10 +420,10 @@ util.selectiveExtend = function (props, a, b) { throw new Error('Array with property names expected as first argument'); } - for (var i = 1, len = arguments.length; i < len; i++) { + for (var i = 2; i < arguments.length; i++) { var other = arguments[i]; - for (var p = 0, pp = props.length; p < pp; p++) { + for (var p = 0; p < props.length; p++) { var prop = props[p]; if (other.hasOwnProperty(prop)) { a[prop] = other[prop]; @@ -434,6 +434,46 @@ util.selectiveExtend = function (props, a, b) { return a; }; +/** + * Extend object a with selected properties of object b or a series of objects + * Only properties with defined values are copied + * @param {Array.} props + * @param {Object} a + * @param {... Object} b + * @return {Object} a + */ +util.selectiveDeepExtend = function (props, a, b) { + // TODO: add support for Arrays to deepExtend + if (Array.isArray(b)) { + throw new TypeError('Arrays are not supported by deepExtend'); + } + for (var i = 2; i < arguments.length; i++) { + var other = arguments[i]; + for (var p = 0; p < props.length; p++) { + var prop = props[p]; + if (other.hasOwnProperty(prop)) { + if (b[prop] && b[prop].constructor === Object) { + if (a[prop] === undefined) { + a[prop] = {}; + } + if (a[prop].constructor === Object) { + util.deepExtend(a[prop], b[prop]); + } + else { + a[prop] = b[prop]; + } + } else if (Array.isArray(b[prop])) { + throw new TypeError('Arrays are not supported by deepExtend'); + } else { + a[prop] = b[prop]; + } + + } + } + } + return a; +}; + /** * Deep extend an object a with the properties of object b * @param {Object} a @@ -2529,7 +2569,8 @@ DataView.prototype.unsubscribe = DataView.prototype.off; * @param {ItemSet} itemSet */ function GraphGroup (group, options, linegraph) { - this.options = util.copyObject(options,{}); + var fields = ['yAxisOrientation','barGraph','drawPoints','catmullRom'] + this.options = util.selectiveDeepExtend(fields,{},options); this.linegraph = linegraph; this.usingDefaultStyle = group.className === undefined; this.update(group); @@ -2605,7 +2646,8 @@ function Legend(body, options, linegraph) { this.linegraph = linegraph; this.defaultOptions = { orientation: 'left', // left, right - position: 'left' // left, center, right + position: 'left', // left, center, right + visible: true } this.options = util.extend({},this.defaultOptions); @@ -2769,11 +2811,12 @@ function DataAxis (body, options) { showMajorLabels: true, majorLinesOffset: 7, minorLinesOffset: 4, - labelOffsetX: 9, - labelOffsetY: -6, + labelOffsetX: 10, + labelOffsetY: 2, iconWidth: 20, width: '40px', - height: '300px' + height: '300px', + visible: true }; this.props = {}; @@ -2950,8 +2993,6 @@ DataAxis.prototype.redraw = function () { var props = this.props; var frame = this.dom.frame; - - // update classname frame.className = 'dataaxis'; @@ -3049,7 +3090,7 @@ DataAxis.prototype._redrawLabels = function () { var isMajor = step.isMajor(); if (this.options['showMinorLabels'] && isMajor == false) { - this._redrawLabel(y - 2, step.current, orientation, 'yAxis minor'); + this._redrawLabel(y - 2, step.current, orientation, 'yAxis minor', this.props.minorCharHeight); } if (isMajor && this.options['showMajorLabels']) { @@ -3057,7 +3098,7 @@ DataAxis.prototype._redrawLabels = function () { if (xFirstMajorLabel == undefined) { xFirstMajorLabel = y; } - this._redrawLabel(y - 2, step.current, orientation, 'yAxis major'); + this._redrawLabel(y - 2, step.current, orientation, 'yAxis major', this.props.majorCharHeight); } this._redrawMajorLine(y, orientation); } @@ -3069,7 +3110,7 @@ DataAxis.prototype._redrawLabels = function () { max++; } - var offset = this.drawIcons == true ? this.options.iconWidth + this.options.labelOffsetX : this.options.labelOffsetX; + var offset = this.drawIcons == true ? this.options.iconWidth + this.options.labelOffsetX + 15 : this.options.labelOffsetX + 15; if (this.maxLabelSize > (this.width - offset)) { this.width = this.maxLabelSize + offset; this.options.width = this.width + "px"; @@ -3114,7 +3155,7 @@ DataAxis.prototype.convertValue = function(value) { * @param {String} orientation "top" or "bottom" (default) * @private */ -DataAxis.prototype._redrawLabel = function (y, text, orientation, className) { +DataAxis.prototype._redrawLabel = function (y, text, orientation, className, characterHeight) { // reuse redundant label var label = this.dom.redundant.labels.shift(); @@ -3140,13 +3181,16 @@ DataAxis.prototype._redrawLabel = function (y, text, orientation, className) { label.style.textAlign = "left"; } - label.style.top = y + this.options.labelOffsetY + 'px'; + label.style.top = y - 0.5 * characterHeight + this.options.labelOffsetY + 'px'; + text += ''; var largestWidth = this.props.majorCharWidth > this.props.minorCharWidth ? this.props.majorCharWidth : this.props.minorCharWidth; if (this.maxLabelSize < text.length * largestWidth) { this.maxLabelSize = text.length * largestWidth; } + + }; /** @@ -3223,7 +3267,7 @@ DataAxis.prototype._calculateCharSize = function () { var textMinor = document.createTextNode('0'); var measureCharMinor = document.createElement('DIV'); - measureCharMinor.className = 'text minor measure'; + measureCharMinor.className = 'yAxis minor measure'; measureCharMinor.appendChild(textMinor); this.dom.frame.appendChild(measureCharMinor); @@ -3236,7 +3280,7 @@ DataAxis.prototype._calculateCharSize = function () { if (!('majorCharHeight' in this.props)) { var textMajor = document.createTextNode('0'); var measureCharMajor = document.createElement('DIV'); - measureCharMajor.className = 'text major measure'; + measureCharMajor.className = 'yAxis major measure'; measureCharMajor.appendChild(textMajor); this.dom.frame.appendChild(measureCharMajor); @@ -3286,22 +3330,20 @@ function Linegraph(body, options) { alpha: 0.5 }, dataAxis: { - showMinorLabels: true, - showMajorLabels: true, - majorLinesOffset: 27, - minorLinesOffset: 24, - labelOffsetX: 2, - labelOffsetY: 0, - width: '60px' - }, - dataAxisRight: { showMinorLabels: true, showMajorLabels: true, majorLinesOffset: 7, minorLinesOffset: 4, - labelOffsetX: 9, - labelOffsetY: -6, - width: '60px' + labelOffsetX: 10, + labelOffsetY: 2, + iconWidth: 20, + width: '40px', + visible:true + }, + legend: { + orientation: 'left', // left, right + position: 'left', // left, center, right + visible: true } }; @@ -3394,10 +3436,9 @@ Linegraph.prototype._create = function(){ frame.appendChild(this.svg); // panel with time axis - this.yAxisLeft = new DataAxis(this.body, { - orientation: 'left', - height: this.svg.style.height - }); + this.options.dataAxis.orientation = 'left'; + this.options.dataAxis.height = this.svg.style.height; + this.yAxisLeft = new DataAxis(this.body, this.options.dataAxis); this.yAxisRight = new DataAxis(this.body, { orientation: 'right', @@ -3417,8 +3458,8 @@ Linegraph.prototype._create = function(){ */ Linegraph.prototype.setOptions = function(options) { if (options) { - var fields = ['yAxisOrientation']; - util.selectiveExtend(fields, this.options, options); + var fields = ['yAxisOrientation','dataAxis','legend']; + util.selectiveDeepExtend(fields, this.options, options); if (options.catmullRom) { if (typeof options.catmullRom == 'object') { @@ -3436,6 +3477,8 @@ Linegraph.prototype.setOptions = function(options) { } } } + + console.log("OPTIONS:",this.options , options); this._mergeOptions(this.options, options,'catmullRom'); this._mergeOptions(this.options, options,'drawPoints'); this._mergeOptions(this.options, options,'shaded'); @@ -3451,7 +3494,7 @@ Linegraph.prototype.setOptions = function(options) { * @param [String] option | this is the option key in the options argument * @private */ -Linegraph.prototype._mergeOptions = function (mergeTarget, options,option) { +Linegraph.prototype._mergeOptions = function (mergeTarget, options, option) { if (options[option]) { if (typeof options[option] == 'boolean') { mergeTarget[option].enabled = options[option]; @@ -13688,7 +13731,7 @@ var physicsMixin = { _loadPhysicsConfiguration: function () { if (this.physicsConfiguration === undefined) { this.backupConstants = {}; - util.copyObject(this.constants, this.backupConstants); + util.deepExtend(this.backupConstants,this.constants); var hierarchicalLayoutDirections = ["LR", "RL", "UD", "DU"]; this.physicsConfiguration = document.createElement('div'); @@ -25326,7 +25369,7 @@ else { })(this); },{}],4:[function(require,module,exports){ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};//! moment.js -//! version : 2.6.0 +//! version : 2.7.0 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors //! license : MIT //! momentjs.com @@ -25338,7 +25381,7 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? ************************************/ var moment, - VERSION = "2.6.0", + VERSION = "2.7.0", // the global-scope this is NOT the global object in Node.js globalScope = typeof global !== 'undefined' ? global : this, oldGlobalMoment, @@ -25363,6 +25406,7 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? _f : null, _l : null, _strict : null, + _tzm : null, _isUTC : null, _offset : null, // optional. Combine with _isUTC _pf : null, @@ -25471,6 +25515,16 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? // format function strings formatFunctions = {}, + // default relative time thresholds + relativeTimeThresholds = { + s: 45, //seconds to minutes + m: 45, //minutes to hours + h: 22, //hours to days + dd: 25, //days to month (month == 1) + dm: 45, //days to months (months > 1) + dy: 345 //days to year + }, + // tokens to ordinalize and pad ordinalizeTokens = 'DDD w W M D d'.split(' '), paddedTokens = 'M D H h m s w W'.split(' '), @@ -25610,6 +25664,16 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin']; + // Pick the first defined of two or three arguments. dfl comes from + // default. + function dfl(a, b, c) { + switch (arguments.length) { + case 2: return a != null ? a : b; + case 3: return a != null ? a : b != null ? b : c; + default: throw new Error("Implement me"); + } + } + function defaultParsingFlags() { // We need to deep clone this object, and es5 standard is not very // helpful. @@ -26478,39 +26542,94 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? config._useUTC = true; config._tzm = timezoneMinutesFromString(input); break; + // WEEKDAY - human + case 'dd': + case 'ddd': + case 'dddd': + a = getLangDefinition(config._l).weekdaysParse(input); + // if we didn't get a weekday name, mark the date as invalid + if (a != null) { + config._w = config._w || {}; + config._w['d'] = a; + } else { + config._pf.invalidWeekday = input; + } + break; + // WEEK, WEEK DAY - numeric case 'w': case 'ww': case 'W': case 'WW': case 'd': - case 'dd': - case 'ddd': - case 'dddd': case 'e': case 'E': token = token.substr(0, 1); /* falls through */ - case 'gg': case 'gggg': - case 'GG': case 'GGGG': case 'GGGGG': token = token.substr(0, 2); if (input) { config._w = config._w || {}; - config._w[token] = input; + config._w[token] = toInt(input); } break; + case 'gg': + case 'GG': + config._w = config._w || {}; + config._w[token] = moment.parseTwoDigitYear(input); } } + function dayOfYearFromWeekInfo(config) { + var w, weekYear, week, weekday, dow, doy, temp, lang; + + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + dow = 1; + doy = 4; + + // TODO: We need to take the current isoWeekYear, but that depends on + // how we interpret now (local, utc, fixed offset). So create + // a now version of current config (take local/utc/offset flags, and + // create now). + weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year); + week = dfl(w.W, 1); + weekday = dfl(w.E, 1); + } else { + lang = getLangDefinition(config._l); + dow = lang._week.dow; + doy = lang._week.doy; + + weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year); + week = dfl(w.w, 1); + + if (w.d != null) { + // weekday -- low day numbers are considered next week + weekday = w.d; + if (weekday < dow) { + ++week; + } + } else if (w.e != null) { + // local weekday -- counting starts from begining of week + weekday = w.e + dow; + } else { + // default to begining of week + weekday = dow; + } + } + temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow); + + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; + } + // convert an array to a date. // the array should mirror the parameters below // note: all values past the year are optional and will default to the lowest possible value. // [year, month, day , hour, minute, second, millisecond] function dateFromConfig(config) { - var i, date, input = [], currentDate, - yearToUse, fixYear, w, temp, lang, weekday, week; + var i, date, input = [], currentDate, yearToUse; if (config._d) { return; @@ -26520,39 +26639,12 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? //compute day of the year from weeks and weekdays if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { - fixYear = function (val) { - var intVal = parseInt(val, 10); - return val ? - (val.length < 3 ? (intVal > 68 ? 1900 + intVal : 2000 + intVal) : intVal) : - (config._a[YEAR] == null ? moment().weekYear() : config._a[YEAR]); - }; - - w = config._w; - if (w.GG != null || w.W != null || w.E != null) { - temp = dayOfYearFromWeeks(fixYear(w.GG), w.W || 1, w.E, 4, 1); - } - else { - lang = getLangDefinition(config._l); - weekday = w.d != null ? parseWeekday(w.d, lang) : - (w.e != null ? parseInt(w.e, 10) + lang._week.dow : 0); - - week = parseInt(w.w, 10) || 1; - - //if we're parsing 'd', then the low day numbers may be next week - if (w.d != null && weekday < lang._week.dow) { - week++; - } - - temp = dayOfYearFromWeeks(fixYear(w.gg), week, weekday, lang._week.doy, lang._week.dow); - } - - config._a[YEAR] = temp.year; - config._dayOfYear = temp.dayOfYear; + dayOfYearFromWeekInfo(config); } //if the day of the year is set, figure out what it is if (config._dayOfYear) { - yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR]; + yearToUse = dfl(config._a[YEAR], currentDate[YEAR]); if (config._dayOfYear > daysInYear(yearToUse)) { config._pf._overflowDayOfYear = true; @@ -26577,11 +26669,12 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; } - // add the offsets to the time to be parsed so that we can have a clean array for checking isValid - input[HOUR] += toInt((config._tzm || 0) / 60); - input[MINUTE] += toInt((config._tzm || 0) % 60); - config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input); + // Apply timezone offset from input. The actual zone can be changed + // with parseZone. + if (config._tzm != null) { + config._d.setUTCMinutes(config._d.getUTCMinutes() + config._tzm); + } } function dateFromObject(config) { @@ -26621,6 +26714,11 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? // date from string and format string function makeDateFromStringAndFormat(config) { + if (config._f === moment.ISO_8601) { + parseISO(config); + return; + } + config._a = []; config._pf.empty = true; @@ -26733,7 +26831,7 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? } // date from iso format - function makeDateFromString(config) { + function parseISO(config) { var i, l, string = config._i, match = isoRegex.exec(string); @@ -26757,8 +26855,16 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? config._f += "Z"; } makeDateFromStringAndFormat(config); + } else { + config._isValid = false; } - else { + } + + // date from iso format or fallback + function makeDateFromString(config) { + parseISO(config); + if (config._isValid === false) { + delete config._isValid; moment.createFromInputFallback(config); } } @@ -26839,15 +26945,15 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? hours = round(minutes / 60), days = round(hours / 24), years = round(days / 365), - args = seconds < 45 && ['s', seconds] || + args = seconds < relativeTimeThresholds.s && ['s', seconds] || minutes === 1 && ['m'] || - minutes < 45 && ['mm', minutes] || + minutes < relativeTimeThresholds.m && ['mm', minutes] || hours === 1 && ['h'] || - hours < 22 && ['hh', hours] || + hours < relativeTimeThresholds.h && ['hh', hours] || days === 1 && ['d'] || - days <= 25 && ['dd', days] || - days <= 45 && ['M'] || - days < 345 && ['MM', round(days / 30)] || + days <= relativeTimeThresholds.dd && ['dd', days] || + days <= relativeTimeThresholds.dm && ['M'] || + days < relativeTimeThresholds.dy && ['MM', round(days / 30)] || years === 1 && ['y'] || ['yy', years]; args[2] = withoutSuffix; args[3] = milliseconds > 0; @@ -26893,6 +26999,7 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) { var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear; + d = d === 0 ? 7 : d; weekday = weekday != null ? weekday : firstDayOfWeek; daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0); dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1; @@ -26968,6 +27075,40 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? config._d = new Date(config._i); }); + // Pick a moment m from moments so that m[fn](other) is true for all + // other. This relies on the function fn to be transitive. + // + // moments should either be an array of moment objects or an array, whose + // first element is an array of moment objects. + function pickBy(fn, moments) { + var res, i; + if (moments.length === 1 && isArray(moments[0])) { + moments = moments[0]; + } + if (!moments.length) { + return moment(); + } + res = moments[0]; + for (i = 1; i < moments.length; ++i) { + if (moments[i][fn](res)) { + res = moments[i]; + } + } + return res; + } + + moment.min = function () { + var args = [].slice.call(arguments, 0); + + return pickBy('isBefore', args); + }; + + moment.max = function () { + var args = [].slice.call(arguments, 0); + + return pickBy('isAfter', args); + }; + // creating with utc moment.utc = function (input, format, lang, strict) { var c; @@ -27064,6 +27205,9 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? // default format moment.defaultFormat = isoFormat; + // constant that refers to the ISO standard + moment.ISO_8601 = function () {}; + // Plugins that add properties should also add the key here (null value), // so we can properly clone ourselves. moment.momentProperties = momentProperties; @@ -27072,6 +27216,15 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? // It is intended to keep the offset in sync with the timezone. moment.updateOffset = function () {}; + // This function allows you to set a threshold for relative time strings + moment.relativeTimeThreshold = function(threshold, limit) { + if (relativeTimeThresholds[threshold] === undefined) { + return false; + } + relativeTimeThresholds[threshold] = limit; + return true; + }; + // This function will load languages and then set the global language. If // no arguments are passed in, it will simply return the current global // language key. @@ -27227,7 +27380,9 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? add : function (input, val) { var dur; // switch args to support add('s', 1) and add(1, 's') - if (typeof input === 'string') { + if (typeof input === 'string' && typeof val === 'string') { + dur = moment.duration(isNaN(+val) ? +input : +val, isNaN(+val) ? val : input); + } else if (typeof input === 'string') { dur = moment.duration(+val, input); } else { dur = moment.duration(input, val); @@ -27239,7 +27394,9 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? subtract : function (input, val) { var dur; // switch args to support subtract('s', 1) and subtract(1, 's') - if (typeof input === 'string') { + if (typeof input === 'string' && typeof val === 'string') { + dur = moment.duration(isNaN(+val) ? +input : +val, isNaN(+val) ? val : input); + } else if (typeof input === 'string') { dur = moment.duration(+val, input); } else { dur = moment.duration(input, val); @@ -27290,10 +27447,11 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? return this.from(moment(), withoutSuffix); }, - calendar : function () { + calendar : function (time) { // We want to compare the start of today, vs this. // Getting start-of-today depends on whether we're zone'd or not. - var sod = makeAs(moment(), this).startOf('day'), + var now = time || moment(), + sod = makeAs(now, this).startOf('day'), diff = this.diff(sod, 'days', true), format = diff < -6 ? 'sameElse' : diff < -1 ? 'lastWeek' : @@ -27388,15 +27546,21 @@ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? return +this.clone().startOf(units) === +makeAs(input, this).startOf(units); }, - min: function (other) { - other = moment.apply(null, arguments); - return other < this ? this : other; - }, - - max: function (other) { - other = moment.apply(null, arguments); - return other > this ? this : other; - }, + min: deprecate( + "moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548", + function (other) { + other = moment.apply(null, arguments); + return other < this ? this : other; + } + ), + + max: deprecate( + "moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548", + function (other) { + other = moment.apply(null, arguments); + return other > this ? this : other; + } + ), // keepTime = true means only change the timezone, without affecting // the local hour. So 5:31:26 +0300 --[zone(2, true)]--> 5:31:26 +0200 diff --git a/examples/graph2d/01_basic.html b/examples/graph2d/01_basic.html index c4355f68..b02bc807 100644 --- a/examples/graph2d/01_basic.html +++ b/examples/graph2d/01_basic.html @@ -51,7 +51,7 @@ content: names[1], className: "graphGroup1", options: { -// yAxisOrientation: 'right', + yAxisOrientation: 'right', drawPoints: true, // square, circle shaded: { orientation: 'top' // top, bottom diff --git a/src/graph/graphMixins/physics/PhysicsMixin.js b/src/graph/graphMixins/physics/PhysicsMixin.js index 2a419591..a1e374b2 100644 --- a/src/graph/graphMixins/physics/PhysicsMixin.js +++ b/src/graph/graphMixins/physics/PhysicsMixin.js @@ -303,7 +303,7 @@ var physicsMixin = { _loadPhysicsConfiguration: function () { if (this.physicsConfiguration === undefined) { this.backupConstants = {}; - util.copyObject(this.constants, this.backupConstants); + util.deepExtend(this.backupConstants,this.constants); var hierarchicalLayoutDirections = ["LR", "RL", "UD", "DU"]; this.physicsConfiguration = document.createElement('div'); diff --git a/src/timeline/component/DataAxis.js b/src/timeline/component/DataAxis.js index eb398e88..41624c93 100644 --- a/src/timeline/component/DataAxis.js +++ b/src/timeline/component/DataAxis.js @@ -15,11 +15,12 @@ function DataAxis (body, options) { showMajorLabels: true, majorLinesOffset: 7, minorLinesOffset: 4, - labelOffsetX: 9, - labelOffsetY: -6, + labelOffsetX: 10, + labelOffsetY: 2, iconWidth: 20, width: '40px', - height: '300px' + height: '300px', + visible: true }; this.props = {}; @@ -196,8 +197,6 @@ DataAxis.prototype.redraw = function () { var props = this.props; var frame = this.dom.frame; - - // update classname frame.className = 'dataaxis'; @@ -295,7 +294,7 @@ DataAxis.prototype._redrawLabels = function () { var isMajor = step.isMajor(); if (this.options['showMinorLabels'] && isMajor == false) { - this._redrawLabel(y - 2, step.current, orientation, 'yAxis minor'); + this._redrawLabel(y - 2, step.current, orientation, 'yAxis minor', this.props.minorCharHeight); } if (isMajor && this.options['showMajorLabels']) { @@ -303,7 +302,7 @@ DataAxis.prototype._redrawLabels = function () { if (xFirstMajorLabel == undefined) { xFirstMajorLabel = y; } - this._redrawLabel(y - 2, step.current, orientation, 'yAxis major'); + this._redrawLabel(y - 2, step.current, orientation, 'yAxis major', this.props.majorCharHeight); } this._redrawMajorLine(y, orientation); } @@ -315,7 +314,7 @@ DataAxis.prototype._redrawLabels = function () { max++; } - var offset = this.drawIcons == true ? this.options.iconWidth + this.options.labelOffsetX : this.options.labelOffsetX; + var offset = this.drawIcons == true ? this.options.iconWidth + this.options.labelOffsetX + 15 : this.options.labelOffsetX + 15; if (this.maxLabelSize > (this.width - offset)) { this.width = this.maxLabelSize + offset; this.options.width = this.width + "px"; @@ -360,7 +359,7 @@ DataAxis.prototype.convertValue = function(value) { * @param {String} orientation "top" or "bottom" (default) * @private */ -DataAxis.prototype._redrawLabel = function (y, text, orientation, className) { +DataAxis.prototype._redrawLabel = function (y, text, orientation, className, characterHeight) { // reuse redundant label var label = this.dom.redundant.labels.shift(); @@ -386,13 +385,16 @@ DataAxis.prototype._redrawLabel = function (y, text, orientation, className) { label.style.textAlign = "left"; } - label.style.top = y + this.options.labelOffsetY + 'px'; + label.style.top = y - 0.5 * characterHeight + this.options.labelOffsetY + 'px'; + text += ''; var largestWidth = this.props.majorCharWidth > this.props.minorCharWidth ? this.props.majorCharWidth : this.props.minorCharWidth; if (this.maxLabelSize < text.length * largestWidth) { this.maxLabelSize = text.length * largestWidth; } + + }; /** @@ -469,7 +471,7 @@ DataAxis.prototype._calculateCharSize = function () { var textMinor = document.createTextNode('0'); var measureCharMinor = document.createElement('DIV'); - measureCharMinor.className = 'text minor measure'; + measureCharMinor.className = 'yAxis minor measure'; measureCharMinor.appendChild(textMinor); this.dom.frame.appendChild(measureCharMinor); @@ -482,7 +484,7 @@ DataAxis.prototype._calculateCharSize = function () { if (!('majorCharHeight' in this.props)) { var textMajor = document.createTextNode('0'); var measureCharMajor = document.createElement('DIV'); - measureCharMajor.className = 'text major measure'; + measureCharMajor.className = 'yAxis major measure'; measureCharMajor.appendChild(textMajor); this.dom.frame.appendChild(measureCharMajor); diff --git a/src/timeline/component/GraphGroup.js b/src/timeline/component/GraphGroup.js index 28b98f27..017fa494 100644 --- a/src/timeline/component/GraphGroup.js +++ b/src/timeline/component/GraphGroup.js @@ -5,7 +5,8 @@ * @param {ItemSet} itemSet */ function GraphGroup (group, options, linegraph) { - this.options = util.copyObject(options,{}); + var fields = ['yAxisOrientation','barGraph','drawPoints','catmullRom'] + this.options = util.selectiveDeepExtend(fields,{},options); this.linegraph = linegraph; this.usingDefaultStyle = group.className === undefined; this.update(group); diff --git a/src/timeline/component/Legend.js b/src/timeline/component/Legend.js index 0a9be747..0ca76307 100644 --- a/src/timeline/component/Legend.js +++ b/src/timeline/component/Legend.js @@ -6,7 +6,8 @@ function Legend(body, options, linegraph) { this.linegraph = linegraph; this.defaultOptions = { orientation: 'left', // left, right - position: 'left' // left, center, right + position: 'left', // left, center, right + visible: true } this.options = util.extend({},this.defaultOptions); diff --git a/src/timeline/component/Linegraph.js b/src/timeline/component/Linegraph.js index 0c247eeb..94a1c581 100644 --- a/src/timeline/component/Linegraph.js +++ b/src/timeline/component/Linegraph.js @@ -25,22 +25,20 @@ function Linegraph(body, options) { alpha: 0.5 }, dataAxis: { - showMinorLabels: true, - showMajorLabels: true, - majorLinesOffset: 27, - minorLinesOffset: 24, - labelOffsetX: 2, - labelOffsetY: 0, - width: '60px' - }, - dataAxisRight: { showMinorLabels: true, showMajorLabels: true, majorLinesOffset: 7, minorLinesOffset: 4, - labelOffsetX: 9, - labelOffsetY: -6, - width: '60px' + labelOffsetX: 10, + labelOffsetY: 2, + iconWidth: 20, + width: '40px', + visible:true + }, + legend: { + orientation: 'left', // left, right + position: 'left', // left, center, right + visible: true } }; @@ -133,10 +131,9 @@ Linegraph.prototype._create = function(){ frame.appendChild(this.svg); // panel with time axis - this.yAxisLeft = new DataAxis(this.body, { - orientation: 'left', - height: this.svg.style.height - }); + this.options.dataAxis.orientation = 'left'; + this.options.dataAxis.height = this.svg.style.height; + this.yAxisLeft = new DataAxis(this.body, this.options.dataAxis); this.yAxisRight = new DataAxis(this.body, { orientation: 'right', @@ -156,8 +153,8 @@ Linegraph.prototype._create = function(){ */ Linegraph.prototype.setOptions = function(options) { if (options) { - var fields = ['yAxisOrientation']; - util.selectiveExtend(fields, this.options, options); + var fields = ['yAxisOrientation','dataAxis','legend']; + util.selectiveDeepExtend(fields, this.options, options); if (options.catmullRom) { if (typeof options.catmullRom == 'object') { @@ -175,6 +172,8 @@ Linegraph.prototype.setOptions = function(options) { } } } + + console.log("OPTIONS:",this.options , options); this._mergeOptions(this.options, options,'catmullRom'); this._mergeOptions(this.options, options,'drawPoints'); this._mergeOptions(this.options, options,'shaded'); @@ -190,7 +189,7 @@ Linegraph.prototype.setOptions = function(options) { * @param [String] option | this is the option key in the options argument * @private */ -Linegraph.prototype._mergeOptions = function (mergeTarget, options,option) { +Linegraph.prototype._mergeOptions = function (mergeTarget, options, option) { if (options[option]) { if (typeof options[option] == 'boolean') { mergeTarget[option].enabled = options[option]; diff --git a/src/timeline/component/css/dataaxis.css b/src/timeline/component/css/dataaxis.css index d42d5bf4..883600a9 100644 --- a/src/timeline/component/css/dataaxis.css +++ b/src/timeline/component/css/dataaxis.css @@ -16,29 +16,35 @@ } - -.vis.timeline .dataaxis .text.measure { +.vis.timeline .dataaxis .yAxis.major { + width: 100%; position: absolute; + color: #4d4d4d; + white-space: nowrap; +} + +.vis.timeline .dataaxis .yAxis.major.measure{ padding-left: 0; padding-right: 0; margin-left: 0; margin-right: 0; visibility: hidden; -} - -.vis.timeline .dataaxis .yAxis.major { - font-size:12px; - width: 100%; - position: absolute; - color: #4d4d4d; - white-space: nowrap; + width: auto; } .vis.timeline .dataaxis .yAxis.minor{ - font-size:12px; position: absolute; width: 100%; color: #979797; white-space: nowrap; } + +.vis.timeline .dataaxis .yAxis.minor.measure{ + padding-left: 0; + padding-right: 0; + margin-left: 0; + margin-right: 0; + visibility: hidden; + width: auto; +} \ No newline at end of file diff --git a/src/util.js b/src/util.js index ce8bf89b..0334939d 100644 --- a/src/util.js +++ b/src/util.js @@ -110,10 +110,10 @@ util.selectiveExtend = function (props, a, b) { throw new Error('Array with property names expected as first argument'); } - for (var i = 1, len = arguments.length; i < len; i++) { + for (var i = 2; i < arguments.length; i++) { var other = arguments[i]; - for (var p = 0, pp = props.length; p < pp; p++) { + for (var p = 0; p < props.length; p++) { var prop = props[p]; if (other.hasOwnProperty(prop)) { a[prop] = other[prop]; @@ -124,6 +124,46 @@ util.selectiveExtend = function (props, a, b) { return a; }; +/** + * Extend object a with selected properties of object b or a series of objects + * Only properties with defined values are copied + * @param {Array.} props + * @param {Object} a + * @param {... Object} b + * @return {Object} a + */ +util.selectiveDeepExtend = function (props, a, b) { + // TODO: add support for Arrays to deepExtend + if (Array.isArray(b)) { + throw new TypeError('Arrays are not supported by deepExtend'); + } + for (var i = 2; i < arguments.length; i++) { + var other = arguments[i]; + for (var p = 0; p < props.length; p++) { + var prop = props[p]; + if (other.hasOwnProperty(prop)) { + if (b[prop] && b[prop].constructor === Object) { + if (a[prop] === undefined) { + a[prop] = {}; + } + if (a[prop].constructor === Object) { + util.deepExtend(a[prop], b[prop]); + } + else { + a[prop] = b[prop]; + } + } else if (Array.isArray(b[prop])) { + throw new TypeError('Arrays are not supported by deepExtend'); + } else { + a[prop] = b[prop]; + } + + } + } + } + return a; +}; + /** * Deep extend an object a with the properties of object b * @param {Object} a