UNPKG

splunk-sdk

Version:

SDK for usage with the Splunk REST API

1,981 lines (1,770 loc) 794 kB
(function() { var __exportName = 'splunkjs'; (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ // Copyright 2011 Splunk, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"): you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations // under the License. // This file is the entry point for client-side code, so it "exports" the // important functionality to the "window", such that others can easily // include it. (function(exportName) { if (!window[exportName]) { window[exportName] = {}; } if (!window[exportName].UI) { window[exportName].UI = {}; } window[exportName].UI.Charting = require('../ui/charting.js'); })(__exportName); },{"../ui/charting.js":3}],2:[function(require,module,exports){ /*! Simple JavaScript Inheritance * By John Resig http://ejohn.org/ * MIT Licensed. * Inspired by base2 and Prototype */ (function(){ var root = exports || this; var initializing = false; var fnTest = (/xyz/.test(function() { return xyz; }) ? /\b_super\b/ : /.*/); // The base Class implementation (does nothing) root.Class = function(){}; // Create a new Class that inherits from this class root.Class.extend = function(prop) { var _super = this.prototype; // Instantiate a base class (but only create the instance, // don't run the init constructor) initializing = true; var prototype = new this(); initializing = false; // Copy the properties over onto the new prototype for (var name in prop) { // Check if we're overwriting an existing function prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn){ return function() { var tmp = this._super; // Add a new ._super() method that is the same method // but on the super-class this._super = _super[name]; // The method only need to be bound temporarily, so we // remove it when we're done executing var ret = fn.apply(this, arguments); this._super = tmp; return ret; }; })(name, prop[name]) : prop[name]; } // The dummy class constructor function Class() { // All construction is actually done in the init method if ( !initializing && this.init ) this.init.apply(this, arguments); } // Populate our constructed prototype object Class.prototype = prototype; // Enforce the constructor to be what we expect Class.constructor = Class; // And make this class extendable Class.extend = arguments.callee; return Class; }; })(); },{}],3:[function(require,module,exports){ // Copyright 2011 Splunk, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"): you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations // under the License. (function() { var utils = require('../utils'); var Class = require('../jquery.class').Class; var SplunkCharts = require('./charting/js_charting').Splunk; var root = exports || this; var JSCharting = SplunkCharts.JSCharting; root.ChartType = { LINE: "line", AREA: "area", COLUMN: "column", BAR: "bar", PIE: "pie", SCATTER: "scatter", HYBRID: "hybrid", RADIALGAUGE: "radialGauge", FILLERGAUGE: "fillerGauge", MARKERGAUGE: "markerGauge" }; root.Chart = Class.extend({ init: function(el, chartType, orientation, isSplitSeries) { this.el = $(el); this.chartType = chartType; this.chart = JSCharting.createChart(this.el.eq(0)[0], { chart: chartType, "chart.orientation": orientation, "layout.splitSeries": isSplitSeries }); }, destroy: function() { this.chart.destroy(); this.chart = null; }, setData: function(data, properties) { var fieldInfo = JSCharting.extractFieldInfo(data); var chartData = JSCharting.extractChartReadyData(data, fieldInfo); if (!properties.chart) { properties.chart = this.chartType; } this.chart.prepare(chartData, fieldInfo, properties); }, draw: function() { this.chart.draw(function(){}); } }); })(); },{"../jquery.class":2,"../utils":11,"./charting/js_charting":7}],4:[function(require,module,exports){ // ==ClosureCompiler== // @compilation_level SIMPLE_OPTIMIZATIONS /** * @license Highcharts JS v2.1.7 (2011-10-19) * * (c) 2009-2011 Torstein Hønsi * * License: www.highcharts.com/license */ // JSLint options: /*global document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $ */ (function () { // encapsulated variables var doc = document, win = window, math = Math, mathRound = math.round, mathFloor = math.floor, mathCeil = math.ceil, mathMax = math.max, mathMin = math.min, mathAbs = math.abs, mathCos = math.cos, mathSin = math.sin, mathPI = math.PI, deg2rad = mathPI * 2 / 360, // some variables userAgent = navigator.userAgent, isIE = /msie/i.test(userAgent) && !win.opera, docMode8 = doc.documentMode === 8, isWebKit = /AppleWebKit/.test(userAgent), isFirefox = /Firefox/.test(userAgent), SVG_NS = 'http://www.w3.org/2000/svg', hasSVG = !!doc.createElementNS && !!doc.createElementNS(SVG_NS, 'svg').createSVGRect, hasRtlBug = isFirefox && parseInt(userAgent.split('Firefox/')[1], 10) < 4, // issue #38 Renderer, hasTouch = doc.documentElement.ontouchstart !== undefined, symbolSizes = {}, idCounter = 0, timeFactor = 1, // 1 = JavaScript time, 1000 = Unix time garbageBin, defaultOptions, dateFormat, // function globalAnimation, pathAnim, // some constants for frequently used strings UNDEFINED, DIV = 'div', ABSOLUTE = 'absolute', RELATIVE = 'relative', HIDDEN = 'hidden', PREFIX = 'highcharts-', VISIBLE = 'visible', PX = 'px', NONE = 'none', M = 'M', L = 'L', /* * Empirical lowest possible opacities for TRACKER_FILL * IE6: 0.002 * IE7: 0.002 * IE8: 0.002 * IE9: 0.00000000001 (unlimited) * FF: 0.00000000001 (unlimited) * Chrome: 0.000001 * Safari: 0.000001 * Opera: 0.00000000001 (unlimited) */ TRACKER_FILL = 'rgba(192,192,192,' + (hasSVG ? 0.000001 : 0.002) + ')', // invisible but clickable NORMAL_STATE = '', HOVER_STATE = 'hover', SELECT_STATE = 'select', // time methods, changed based on whether or not UTC is used makeTime, getMinutes, getHours, getDay, getDate, getMonth, getFullYear, setMinutes, setHours, setDate, setMonth, setFullYear, // check for a custom HighchartsAdapter defined prior to this file globalAdapter = win.HighchartsAdapter, adapter = globalAdapter || {}, // Utility functions. If the HighchartsAdapter is not defined, adapter is an empty object // and all the utility functions will be null. In that case they are populated by the // default adapters below. each = adapter.each, grep = adapter.grep, map = adapter.map, merge = adapter.merge, addEvent = adapter.addEvent, removeEvent = adapter.removeEvent, fireEvent = adapter.fireEvent, animate = adapter.animate, stop = adapter.stop, // lookup over the types and the associated classes seriesTypes = {}; /** * Extend an object with the members of another * @param {Object} a The object to be extended * @param {Object} b The object to add to the first one */ function extend(a, b) { var n; if (!a) { a = {}; } for (n in b) { a[n] = b[n]; } return a; } /** * Shortcut for parseInt * @param {Object} s */ function pInt(s, mag) { return parseInt(s, mag || 10); } /** * Check for string * @param {Object} s */ function isString(s) { return typeof s === 'string'; } /** * Check for object * @param {Object} obj */ function isObject(obj) { return typeof obj === 'object'; } /** * Check for array * @param {Object} obj */ function isArray(obj) { return Object.prototype.toString.call(obj) === '[object Array]'; } /** * Check for number * @param {Object} n */ function isNumber(n) { return typeof n === 'number'; } function log2lin(num) { return math.log(num) / math.LN10; } function lin2log(num) { return math.pow(10, num); } /** * Remove last occurence of an item from an array * @param {Array} arr * @param {Mixed} item */ function erase(arr, item) { var i = arr.length; while (i--) { if (arr[i] === item) { arr.splice(i, 1); break; } } //return arr; } /** * Returns true if the object is not null or undefined. Like MooTools' $.defined. * @param {Object} obj */ function defined(obj) { return obj !== UNDEFINED && obj !== null; } /** * Set or get an attribute or an object of attributes. Can't use jQuery attr because * it attempts to set expando properties on the SVG element, which is not allowed. * * @param {Object} elem The DOM element to receive the attribute(s) * @param {String|Object} prop The property or an abject of key-value pairs * @param {String} value The value if a single property is set */ function attr(elem, prop, value) { var key, setAttribute = 'setAttribute', ret; // if the prop is a string if (isString(prop)) { // set the value if (defined(value)) { elem[setAttribute](prop, value); // get the value } else if (elem && elem.getAttribute) { // elem not defined when printing pie demo... ret = elem.getAttribute(prop); } // else if prop is defined, it is a hash of key/value pairs } else if (defined(prop) && isObject(prop)) { for (key in prop) { elem[setAttribute](key, prop[key]); } } return ret; } /** * Check if an element is an array, and if not, make it into an array. Like * MooTools' $.splat. */ function splat(obj) { return isArray(obj) ? obj : [obj]; } /** * Return the first value that is defined. Like MooTools' $.pick. */ function pick() { var args = arguments, i, arg, length = args.length; for (i = 0; i < length; i++) { arg = args[i]; if (typeof arg !== 'undefined' && arg !== null) { return arg; } } } /** * Set CSS on a given element * @param {Object} el * @param {Object} styles Style object with camel case property names */ function css(el, styles) { if (isIE) { if (styles && styles.opacity !== UNDEFINED) { styles.filter = 'alpha(opacity=' + (styles.opacity * 100) + ')'; } } extend(el.style, styles); } /** * Utility function to create element with attributes and styles * @param {Object} tag * @param {Object} attribs * @param {Object} styles * @param {Object} parent * @param {Object} nopad */ function createElement(tag, attribs, styles, parent, nopad) { var el = doc.createElement(tag); if (attribs) { extend(el, attribs); } if (nopad) { css(el, {padding: 0, border: NONE, margin: 0}); } if (styles) { css(el, styles); } if (parent) { parent.appendChild(el); } return el; } /** * Extend a prototyped class by new members * @param {Object} parent * @param {Object} members */ function extendClass(parent, members) { var object = function () {}; object.prototype = new parent(); extend(object.prototype, members); return object; } /** * Format a number and return a string based on input settings * @param {Number} number The input number to format * @param {Number} decimals The amount of decimals * @param {String} decPoint The decimal point, defaults to the one given in the lang options * @param {String} thousandsSep The thousands separator, defaults to the one given in the lang options */ function numberFormat(number, decimals, decPoint, thousandsSep) { var lang = defaultOptions.lang, // http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_number_format/ n = number, c = isNaN(decimals = mathAbs(decimals)) ? 2 : decimals, d = decPoint === undefined ? lang.decimalPoint : decPoint, t = thousandsSep === undefined ? lang.thousandsSep : thousandsSep, s = n < 0 ? "-" : "", i = String(pInt(n = mathAbs(+n || 0).toFixed(c))), j = i.length > 3 ? i.length % 3 : 0; return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + mathAbs(n - i).toFixed(c).slice(2) : ""); } /** * Based on http://www.php.net/manual/en/function.strftime.php * @param {String} format * @param {Number} timestamp * @param {Boolean} capitalize */ dateFormat = function (format, timestamp, capitalize) { function pad(number) { return number.toString().replace(/^([0-9])$/, '0$1'); } if (!defined(timestamp) || isNaN(timestamp)) { return 'Invalid date'; } format = pick(format, '%Y-%m-%d %H:%M:%S'); var date = new Date(timestamp * timeFactor), key, // used in for constuct below // get the basic time values hours = date[getHours](), day = date[getDay](), dayOfMonth = date[getDate](), month = date[getMonth](), fullYear = date[getFullYear](), lang = defaultOptions.lang, langWeekdays = lang.weekdays, /* // uncomment this and the 'W' format key below to enable week numbers weekNumber = function() { var clone = new Date(date.valueOf()), day = clone[getDay]() == 0 ? 7 : clone[getDay](), dayNumber; clone.setDate(clone[getDate]() + 4 - day); dayNumber = mathFloor((clone.getTime() - new Date(clone[getFullYear](), 0, 1, -6)) / 86400000); return 1 + mathFloor(dayNumber / 7); }, */ // list all format keys replacements = { // Day 'a': langWeekdays[day].substr(0, 3), // Short weekday, like 'Mon' 'A': langWeekdays[day], // Long weekday, like 'Monday' 'd': pad(dayOfMonth), // Two digit day of the month, 01 to 31 'e': dayOfMonth, // Day of the month, 1 through 31 // Week (none implemented) //'W': weekNumber(), // Month 'b': lang.shortMonths[month], // Short month, like 'Jan' 'B': lang.months[month], // Long month, like 'January' 'm': pad(month + 1), // Two digit month number, 01 through 12 // Year 'y': fullYear.toString().substr(2, 2), // Two digits year, like 09 for 2009 'Y': fullYear, // Four digits year, like 2009 // Time 'H': pad(hours), // Two digits hours in 24h format, 00 through 23 'I': pad((hours % 12) || 12), // Two digits hours in 12h format, 00 through 11 'l': (hours % 12) || 12, // Hours in 12h format, 1 through 12 'M': pad(date[getMinutes]()), // Two digits minutes, 00 through 59 'p': hours < 12 ? 'AM' : 'PM', // Upper case AM or PM 'P': hours < 12 ? 'am' : 'pm', // Lower case AM or PM 'S': pad(date.getSeconds()) // Two digits seconds, 00 through 59 }; // do the replaces for (key in replacements) { format = format.replace('%' + key, replacements[key]); } // Optionally capitalize the string and return return capitalize ? format.substr(0, 1).toUpperCase() + format.substr(1) : format; }; /** * Loop up the node tree and add offsetWidth and offsetHeight to get the * total page offset for a given element. Used by Opera and iOS on hover and * all browsers on point click. * * @param {Object} el * */ function getPosition(el) { var p = { left: el.offsetLeft, top: el.offsetTop }; el = el.offsetParent; while (el) { p.left += el.offsetLeft; p.top += el.offsetTop; if (el !== doc.body && el !== doc.documentElement) { p.left -= el.scrollLeft; p.top -= el.scrollTop; } el = el.offsetParent; } return p; } /** * Helper class that contains variuos counters that are local to the chart. */ function ChartCounters() { this.color = 0; this.symbol = 0; } ChartCounters.prototype = { /** * Wraps the color counter if it reaches the specified length. */ wrapColor: function (length) { if (this.color >= length) { this.color = 0; } }, /** * Wraps the symbol counter if it reaches the specified length. */ wrapSymbol: function (length) { if (this.symbol >= length) { this.symbol = 0; } } }; /** * Utility method extracted from Tooltip code that places a tooltip in a chart without spilling over * and not covering the point it self. */ function placeBox(boxWidth, boxHeight, outerLeft, outerTop, outerWidth, outerHeight, point) { // keep the box within the chart area var pointX = point.x, pointY = point.y, x = pointX - boxWidth + outerLeft - 25, y = pointY - boxHeight + outerTop + 10, alignedRight; // it is too far to the left, adjust it if (x < 7) { x = outerLeft + pointX + 15; } // Test to see if the tooltip is to far to the right, // if it is, move it back to be inside and then up to not cover the point. if ((x + boxWidth) > (outerLeft + outerWidth)) { // PATCH by Simon Fishel // // if the tooltip is too wide for the plot area, clip it left not right // // - x -= (x + boxWidth) - (outerLeft + outerWidth); // + if(boxWidth > outerWidth) { // + x = 7; // + } // + else { // + x -= (x + boxWidth) - (outerLeft + outerWidth); // + } if(boxWidth > outerWidth) { x = 7; } else { x -= (x + boxWidth) - (outerLeft + outerWidth); } y -= boxHeight; alignedRight = true; } if (y < 5) { y = 5; // above // If the tooltip is still covering the point, move it below instead if (alignedRight && pointY >= y && pointY <= (y + boxHeight)) { y = pointY + boxHeight - 5; // below } } else if (y + boxHeight > outerTop + outerHeight) { y = outerTop + outerHeight - boxHeight - 5; // below } return {x: x, y: y}; } /** * Utility method that sorts an object array and keeping the order of equal items. * ECMA script standard does not specify the behaviour when items are equal. */ function stableSort(arr, sortFunction) { var length = arr.length, i; // Add index to each item for (i = 0; i < length; i++) { arr[i].ss_i = i; // stable sort index } arr.sort(function (a, b) { var sortValue = sortFunction(a, b); return sortValue === 0 ? a.ss_i - b.ss_i : sortValue; }); // Remove index from items for (i = 0; i < length; i++) { delete arr[i].ss_i; // stable sort index } } /** * Utility method that destroys any SVGElement or VMLElement that are properties on the given object. * It loops all properties and invokes destroy if there is a destroy method. The property is * then delete'ed. */ function destroyObjectProperties(obj) { var n; for (n in obj) { // If the object is non-null and destroy is defined if (obj[n] && obj[n].destroy) { // Invoke the destroy obj[n].destroy(); } // Delete the property from the object. delete obj[n]; } } /** * Path interpolation algorithm used across adapters */ pathAnim = { /** * Prepare start and end values so that the path can be animated one to one */ init: function (elem, fromD, toD) { fromD = fromD || ''; var shift = elem.shift, bezier = fromD.indexOf('C') > -1, numParams = bezier ? 7 : 3, endLength, slice, i, start = fromD.split(' '), end = [].concat(toD), // copy startBaseLine, endBaseLine, sixify = function (arr) { // in splines make move points have six parameters like bezier curves i = arr.length; while (i--) { if (arr[i] === M) { arr.splice(i + 1, 0, arr[i + 1], arr[i + 2], arr[i + 1], arr[i + 2]); } } }; if (bezier) { sixify(start); sixify(end); } // pull out the base lines before padding if (elem.isArea) { startBaseLine = start.splice(start.length - 6, 6); endBaseLine = end.splice(end.length - 6, 6); } // if shifting points, prepend a dummy point to the end path if (shift) { end = [].concat(end).splice(0, numParams).concat(end); elem.shift = false; // reset for following animations } // copy and append last point until the length matches the end length if (start.length) { endLength = end.length; while (start.length < endLength) { //bezier && sixify(start); slice = [].concat(start).splice(start.length - numParams, numParams); if (bezier) { // disable first control point slice[numParams - 6] = slice[numParams - 2]; slice[numParams - 5] = slice[numParams - 1]; } start = start.concat(slice); } } if (startBaseLine) { // append the base lines for areas start = start.concat(startBaseLine); end = end.concat(endBaseLine); } return [start, end]; }, /** * Interpolate each value of the path and return the array */ step: function (start, end, pos, complete) { var ret = [], i = start.length, startVal; if (pos === 1) { // land on the final path without adjustment points appended in the ends ret = complete; } else if (i === end.length && pos < 1) { while (i--) { startVal = parseFloat(start[i]); ret[i] = isNaN(startVal) ? // a letter instruction like M or L start[i] : pos * (parseFloat(end[i] - startVal)) + startVal; } } else { // if animation is finished or length not matching, land on right value ret = end; } return ret; } }; /** * Set the global animation to either a given value, or fall back to the * given chart's animation option * @param {Object} animation * @param {Object} chart */ function setAnimation(animation, chart) { globalAnimation = pick(animation, chart.animation); } /* * Define the adapter for frameworks. If an external adapter is not defined, * Highcharts reverts to the built-in jQuery adapter. */ if (globalAdapter && globalAdapter.init) { // Initialize the adapter with the pathAnim object that takes care // of path animations. globalAdapter.init(pathAnim); } if (!globalAdapter && win.jQuery) { var jQ = jQuery; /** * Utility for iterating over an array. Parameters are reversed compared to jQuery. * @param {Array} arr * @param {Function} fn */ each = function (arr, fn) { var i = 0, len = arr.length; for (; i < len; i++) { if (fn.call(arr[i], arr[i], i, arr) === false) { return i; } } }; /** * Filter an array */ grep = jQ.grep; /** * Map an array * @param {Array} arr * @param {Function} fn */ map = function (arr, fn) { //return jQuery.map(arr, fn); var results = [], i = 0, len = arr.length; for (; i < len; i++) { results[i] = fn.call(arr[i], arr[i], i, arr); } return results; }; /** * Deep merge two objects and return a third object */ merge = function () { var args = arguments; return jQ.extend(true, null, args[0], args[1], args[2], args[3]); }; /** * Add an event listener * @param {Object} el A HTML element or custom object * @param {String} event The event type * @param {Function} fn The event handler */ addEvent = function (el, event, fn) { jQ(el).bind(event, fn); }; /** * Remove event added with addEvent * @param {Object} el The object * @param {String} eventType The event type. Leave blank to remove all events. * @param {Function} handler The function to remove */ removeEvent = function (el, eventType, handler) { // workaround for jQuery issue with unbinding custom events: // http://forum.jquery.com/topic/javascript-error-when-unbinding-a-custom-event-using-jquery-1-4-2 var func = doc.removeEventListener ? 'removeEventListener' : 'detachEvent'; if (doc[func] && !el[func]) { el[func] = function () {}; } jQ(el).unbind(eventType, handler); }; /** * Fire an event on a custom object * @param {Object} el * @param {String} type * @param {Object} eventArguments * @param {Function} defaultFunction */ fireEvent = function (el, type, eventArguments, defaultFunction) { var event = jQ.Event(type), detachedType = 'detached' + type; extend(event, eventArguments); // Prevent jQuery from triggering the object method that is named the // same as the event. For example, if the event is 'select', jQuery // attempts calling el.select and it goes into a loop. if (el[type]) { el[detachedType] = el[type]; el[type] = null; } // trigger it jQ(el).trigger(event); // attach the method if (el[detachedType]) { el[type] = el[detachedType]; el[detachedType] = null; } if (defaultFunction && !event.isDefaultPrevented()) { defaultFunction(event); } }; /** * Animate a HTML element or SVG element wrapper * @param {Object} el * @param {Object} params * @param {Object} options jQuery-like animation options: duration, easing, callback */ animate = function (el, params, options) { var $el = jQ(el); if (params.d) { el.toD = params.d; // keep the array form for paths, used in jQ.fx.step.d params.d = 1; // because in jQuery, animating to an array has a different meaning } $el.stop(); $el.animate(params, options); }; /** * Stop running animation */ stop = function (el) { jQ(el).stop(); }; // extend jQuery /*jslint unparam: true*//* allow unused param x in this function */ jQ.extend(jQ.easing, { easeOutQuad: function (x, t, b, c, d) { return -c * (t /= d) * (t - 2) + b; } }); /*jslint unparam: false*/ // extend the animate function to allow SVG animations var oldStepDefault = jQuery.fx.step._default, oldCur = jQuery.fx.prototype.cur; // do the step jQ.fx.step._default = function (fx) { var elem = fx.elem; if (elem.attr) { // is SVG element wrapper elem.attr(fx.prop, fx.now); } else { oldStepDefault.apply(this, arguments); } }; // animate paths jQ.fx.step.d = function (fx) { var elem = fx.elem; // Normally start and end should be set in state == 0, but sometimes, // for reasons unknown, this doesn't happen. Perhaps state == 0 is skipped // in these cases if (!fx.started) { var ends = pathAnim.init(elem, elem.d, elem.toD); fx.start = ends[0]; fx.end = ends[1]; fx.started = true; } // interpolate each value of the path elem.attr('d', pathAnim.step(fx.start, fx.end, fx.pos, elem.toD)); }; // get the current value jQ.fx.prototype.cur = function () { var elem = this.elem, r; if (elem.attr) { // is SVG element wrapper r = elem.attr(this.prop); } else { r = oldCur.apply(this, arguments); } return r; }; } /** * Add a global listener for mousemove events */ /*addEvent(doc, 'mousemove', function(e) { if (globalMouseMove) { globalMouseMove(e); } });*/ /** * Set the time methods globally based on the useUTC option. Time method can be either * local time or UTC (default). */ function setTimeMethods() { var useUTC = defaultOptions.global.useUTC; makeTime = useUTC ? Date.UTC : function (year, month, date, hours, minutes, seconds) { return new Date( year, month, pick(date, 1), pick(hours, 0), pick(minutes, 0), pick(seconds, 0) ).getTime(); }; getMinutes = useUTC ? 'getUTCMinutes' : 'getMinutes'; getHours = useUTC ? 'getUTCHours' : 'getHours'; getDay = useUTC ? 'getUTCDay' : 'getDay'; getDate = useUTC ? 'getUTCDate' : 'getDate'; getMonth = useUTC ? 'getUTCMonth' : 'getMonth'; getFullYear = useUTC ? 'getUTCFullYear' : 'getFullYear'; setMinutes = useUTC ? 'setUTCMinutes' : 'setMinutes'; setHours = useUTC ? 'setUTCHours' : 'setHours'; setDate = useUTC ? 'setUTCDate' : 'setDate'; setMonth = useUTC ? 'setUTCMonth' : 'setMonth'; setFullYear = useUTC ? 'setUTCFullYear' : 'setFullYear'; } /** * Merge the default options with custom options and return the new options structure * @param {Object} options The new custom options */ function setOptions(options) { defaultOptions = merge(defaultOptions, options); // apply UTC setTimeMethods(); return defaultOptions; } /** * Get the updated default options. Merely exposing defaultOptions for outside modules * isn't enough because the setOptions method creates a new object. */ function getOptions() { return defaultOptions; } /** * Discard an element by moving it to the bin and delete * @param {Object} The HTML node to discard */ function discardElement(element) { // create a garbage bin element, not part of the DOM if (!garbageBin) { garbageBin = createElement(DIV); } // move the node and empty bin if (element) { garbageBin.appendChild(element); } garbageBin.innerHTML = ''; } /* **************************************************************************** * Handle the options * *****************************************************************************/ var defaultLabelOptions = { enabled: true, // rotation: 0, align: 'center', x: 0, y: 15, /*formatter: function() { return this.value; },*/ style: { color: '#666', fontSize: '11px', lineHeight: '14px' } }; defaultOptions = { colors: ['#4572A7', '#AA4643', '#89A54E', '#80699B', '#3D96AE', '#DB843D', '#92A8CD', '#A47D7C', '#B5CA92'], symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'], lang: { loading: 'Loading...', months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], decimalPoint: '.', resetZoom: 'Reset zoom', resetZoomTitle: 'Reset zoom level 1:1', thousandsSep: ',' }, global: { useUTC: true }, chart: { //animation: true, //alignTicks: false, //reflow: true, //className: null, //events: { load, selection }, //margin: [null], //marginTop: null, //marginRight: null, //marginBottom: null, //marginLeft: null, borderColor: '#4572A7', //borderWidth: 0, borderRadius: 5, defaultSeriesType: 'line', ignoreHiddenSeries: true, //inverted: false, //shadow: false, spacingTop: 10, spacingRight: 10, spacingBottom: 15, spacingLeft: 10, style: { fontFamily: '"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif', // default font fontSize: '12px' }, backgroundColor: '#FFFFFF', //plotBackgroundColor: null, plotBorderColor: '#C0C0C0' //plotBorderWidth: 0, //plotShadow: false, //zoomType: '' }, title: { text: 'Chart title', align: 'center', // floating: false, // margin: 15, // x: 0, // verticalAlign: 'top', y: 15, style: { color: '#3E576F', fontSize: '16px' } }, subtitle: { text: '', align: 'center', // floating: false // x: 0, // verticalAlign: 'top', y: 30, style: { color: '#6D869F' } }, plotOptions: { line: { // base series options allowPointSelect: false, showCheckbox: false, animation: { duration: 1000 }, //connectNulls: false, //cursor: 'default', //dashStyle: null, //enableMouseTracking: true, events: {}, //legendIndex: 0, lineWidth: 2, shadow: true, // stacking: null, marker: { enabled: true, //symbol: null, lineWidth: 0, radius: 4, lineColor: '#FFFFFF', //fillColor: null, states: { // states for a single point hover: { //radius: base + 2 }, select: { fillColor: '#FFFFFF', lineColor: '#000000', lineWidth: 2 } } }, point: { events: {} }, dataLabels: merge(defaultLabelOptions, { enabled: false, y: -6, formatter: function () { return this.y; } }), //pointStart: 0, //pointInterval: 1, showInLegend: true, states: { // states for the entire series hover: { //enabled: false, //lineWidth: base + 1, marker: { // lineWidth: base + 1, // radius: base + 1 } }, select: { marker: {} } }, stickyTracking: true //zIndex: null } }, labels: { //items: [], style: { //font: defaultFont, position: ABSOLUTE, color: '#3E576F' } }, legend: { enabled: true, align: 'center', //floating: false, layout: 'horizontal', labelFormatter: function () { return this.name; }, borderWidth: 1, borderColor: '#909090', borderRadius: 5, // margin: 10, // reversed: false, shadow: false, // backgroundColor: null, style: { padding: '5px' }, itemStyle: { cursor: 'pointer', color: '#3E576F' }, itemHoverStyle: { cursor: 'pointer', color: '#000000' }, itemHiddenStyle: { color: '#C0C0C0' }, itemCheckboxStyle: { position: ABSOLUTE, width: '13px', // for IE precision height: '13px' }, // itemWidth: undefined, symbolWidth: 16, symbolPadding: 5, verticalAlign: 'bottom', // width: undefined, x: 0, y: 0 }, loading: { hideDuration: 100, labelStyle: { fontWeight: 'bold', position: RELATIVE, top: '1em' }, showDuration: 100, style: { position: ABSOLUTE, backgroundColor: 'white', opacity: 0.5, textAlign: 'center' } }, tooltip: { enabled: true, //crosshairs: null, backgroundColor: 'rgba(255, 255, 255, .85)', borderWidth: 2, borderRadius: 5, //formatter: defaultFormatter, shadow: true, //shared: false, snap: hasTouch ? 25 : 10, style: { color: '#333333', fontSize: '12px', padding: '5px', whiteSpace: 'nowrap' } }, toolbar: { itemStyle: { color: '#4572A7', cursor: 'pointer' } }, credits: { enabled: true, text: 'Highcharts.com', href: 'http://www.highcharts.com', position: { align: 'right', x: -10, verticalAlign: 'bottom', y: -5 }, style: { cursor: 'pointer', color: '#909090', fontSize: '10px' } } }; // Axis defaults var defaultXAxisOptions = { // allowDecimals: null, // alternateGridColor: null, // categories: [], dateTimeLabelFormats: { second: '%H:%M:%S', minute: '%H:%M', hour: '%H:%M', day: '%e. %b', week: '%e. %b', month: '%b \'%y', year: '%Y' }, endOnTick: false, gridLineColor: '#C0C0C0', // gridLineDashStyle: 'solid', // docs // gridLineWidth: 0, // reversed: false, labels: defaultLabelOptions, // { step: null }, lineColor: '#C0D0E0', lineWidth: 1, //linkedTo: null, max: null, min: null, minPadding: 0.01, maxPadding: 0.01, //maxZoom: null, minorGridLineColor: '#E0E0E0', // minorGridLineDashStyle: null, minorGridLineWidth: 1, minorTickColor: '#A0A0A0', //minorTickInterval: null, minorTickLength: 2, minorTickPosition: 'outside', // inside or outside //minorTickWidth: 0, //opposite: false, //offset: 0, //plotBands: [{ // events: {}, // zIndex: 1, // labels: { align, x, verticalAlign, y, style, rotation, textAlign } //}], //plotLines: [{ // events: {} // dashStyle: {} // zIndex: // labels: { align, x, verticalAlign, y, style, rotation, textAlign } //}], //reversed: false, // showFirstLabel: true, // showLastLabel: false, startOfWeek: 1, startOnTick: false, tickColor: '#C0D0E0', //tickInterval: null, tickLength: 5, tickmarkPlacement: 'between', // on or between tickPixelInterval: 100, tickPosition: 'outside', tickWidth: 1, title: { //text: null, align: 'middle', // low, middle or high //margin: 0 for horizontal, 10 for vertical axes, //rotation: 0, //side: 'outside', style: { color: '#6D869F', //font: defaultFont.replace('normal', 'bold') fontWeight: 'bold' } //x: 0, //y: 0 }, type: 'linear' // linear, logarithmic or datetime }, defaultYAxisOptions = merge(defaultXAxisOptions, { endOnTick: true, gridLineWidth: 1, tickPixelInterval: 72, showLastLabel: true, labels: { align: 'right', x: -8, y: 3 }, lineWidth: 0, maxPadding: 0.05, minPadding: 0.05, startOnTick: true, tickWidth: 0, title: { rotation: 270, text: 'Y-values' }, stackLabels: { enabled: false, //align: dynamic, //y: dynamic, //x: dynamic, //verticalAlign: dynamic, //textAlign: dynamic, //rotation: 0, formatter: function () { return this.total; }, style: defaultLabelOptions.style } }), defaultLeftAxisOptions = { labels: { align: 'right', x: -8, y: null }, title: { rotation: 270 } }, defaultRightAxisOptions = { labels: { align: 'left', x: 8, y: null }, title: { rotation: 90 } }, defaultBottomAxisOptions = { // horizontal axis labels: { align: 'center', x: 0, y: 14 // staggerLines: null }, title: { rotation: 0 } }, defaultTopAxisOptions = merge(defaultBottomAxisOptions, { labels: { y: -5 // staggerLines: null } }); // Series defaults var defaultPlotOptions = defaultOptions.plotOptions, defaultSeriesOptions = defaultPlotOptions.line; //defaultPlotOptions.line = merge(defaultSeriesOptions); defaultPlotOptions.spline = merge(defaultSeriesOptions); defaultPlotOptions.scatter = merge(defaultSeriesOptions, { lineWidth: 0, states: { hover: { lineWidth: 0 } } }); defaultPlotOptions.area = merge(defaultSeriesOptions, { // threshold: 0, // lineColor: null, // overrides color, but lets fillColor be unaltered // fillOpacity: 0.75, // fillColor: null }); defaultPlotOptions.areaspline = merge(defaultPlotOptions.area); defaultPlotOptions.column = merge(defaultSeriesOptions, { borderColor: '#FFFFFF', borderWidth: 1, borderRadius: 0, //colorByPoint: undefined, groupPadding: 0.2, marker: null, // point options are specified in the base options pointPadding: 0.1, //pointWidth: null, minPointLength: 0, states: { hover: { brightness: 0.1, shadow: false }, select: { color: '#C0C0C0', borderColor: '#000000', shadow: false } }, dataLabels: { y: null, verticalAlign: null } }); defaultPlotOptions.bar = merge(defaultPlotOptions.column, { dataLabels: { align: 'left', x: 5, y: 0 } }); defaultPlotOptions.pie = merge(defaultSeriesOptions, { //dragType: '', // n/a borderColor: '#FFFFFF', borderWidth: 1, center: ['50%', '50%'], colorByPoint: true, // always true for pies dataLabels: { // align: null, // connectorWidth: 1, // connectorColor: point.color, // connectorPadding: 5, distance: 30, enabled: true, formatter: function () { return this.point.name; }, // softConnector: true, y: 5 }, //innerSize: 0, legendType: 'point', marker: null, // point options are specified in the base options size: '75%', showInLegend: false, slicedOffset: 10, states: { hover: { brightness: 0.1, shadow: false } } }); // set the default time methods setTimeMethods(); /** * Handle color operations. The object methods are chainable. * @param {String} input The input color in either rbga or hex format */ var Color = function (input) { // declare variables var rgba = [], result; /** * Parse the input color to rgba array * @param {String} input */ function init(input) { // rgba result = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/.exec(input); if (result) { rgba = [pInt(result[1]), pInt(result[2]), pInt(result[3]), parseFloat(result[4], 10)]; } else { // hex result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(input); if (result) { rgba = [pInt(result[1], 16), pInt(result[2], 16), pInt(result[3], 16), 1]; } } } /** * Return the color a specified format * @param {String} format */ function get(format) { var ret; // it's NaN if gradient colors on a column chart if (rgba && !isNaN(rgba[0])) { if (format === 'rgb') { ret = 'rgb(' + rgba[0] + ',' + rgba[1] + ',' + rgba[2] + ')'; } else if (format === 'a') { ret = rgba[3]; } else { ret = 'rgba(' + rgba.join(',') + ')'; } } else { ret = input; } return ret; } /** * Brighten the color * @param {Number} alpha */ function brighten(alpha) { if (isNumber(alpha) && alpha !== 0) { var i; for (i = 0; i < 3; i++) { rgba[i] += pInt(alpha * 255); if (rgba[i] < 0) { rgba[i] = 0; } if (rgba[i] > 255) { rgba[i] = 255; } } } return this; } /** * Set the color's opacity to a given alpha value * @param {Number} alpha */ function setOpacity(alpha) { rgba[3] = alpha; return this; } // initialize: parse the input init(input); // public methods return { get: get, brighten: brighten, setOpacity: setOpacity }; }; /** * A wrapper object for SVG elements */ function SVGElement() {} SVGElement.prototype = { /** * Initialize the SVG renderer * @param {Object} renderer * @param {String} nodeName */ init: function (renderer, nodeName) { this.element = doc.createElementNS(SVG_NS, nodeName); this.renderer = renderer; }, /** * Animate a given attribute * @param {Object} params * @param {Number} options The same options as in jQuery animation * @param {Function} complete Function to perform at the end of animation */ animate: function (params, options, complete) { var animOptions = pick(options, globalAnimation, true); if (animOptions) { animOptions = merge(animOptions); if (complete) { // allows using a callback with the global animation without overwriting it animOptions.complete = complete; } animate(this, params, animOptions); } else { this.attr(params); if (complete) { complete(); } } }, /** * Set or get a given attribute * @param {Object|String} hash * @param {Mixed|Undefined} val */ attr: function (hash, val) { var key, value, i, child, element = this.element, nodeName = element.nodeName, renderer = this.renderer, skipAttr, shadows = this.shadows, htmlNode = this.htmlNode, hasSetSymbolSize, ret = this; // single key-value pair if (isString(hash) && defined(val)) { key = hash; hash = {}; hash[key] = val; } // used as a getter: first argument is a string, second is undefined if (isString(hash)) { key = hash; if (nodeName === 'circle') { key = { x: 'cx', y: 'cy' }[key] || key; } else if (key === 'strokeWidth') { key = 'stroke-width'; } ret = attr(element, key) || this[key] || 0; if (key !== 'd' && key !== 'visibility') { // 'd' is string in animation step ret = parseFloat(ret); } // setter } else { for (key in hash) { skipAttr = false; // reset value = hash[key]; // paths if (key === 'd') { if (value && value.join) { // join path value = value.join(' '); } if (/(NaN| {2}|^$)/.test(value)) { value = 'M 0 0'; } this.d = value; // shortcut for animations // update child tspans x values } else if (key === 'x' && nodeName === 'text') { for (i = 0; i < element.childNodes.length; i++) { child = element.childNodes[i]; // if the x values are equal, the tspan represents a linebreak if (attr(child, 'x') === attr(element, 'x')) { //child.setAttribute('x', value); attr(child, 'x', value); } } if (this.rotation) { attr(element, 'transform', 'rotate(' + this.rotation + ' ' + value + ' ' + pInt(hash.y || attr(element, 'y')) + ')'); } // apply gradients } else if (key === 'fill') { value = renderer.color(value, element, key); // circle x and y } else if (nodeName === 'circle' && (key === 'x' || key === 'y')) { key = { x: 'cx', y: 'cy' }[key] || key; // translation and text rotation } else if (key === 'translateX' || key === 'translateY' || key === 'rotation' || key === 'verticalAlign') { this[key] = value; this.updateTransform(); skipAttr = true; // apply opacity as subnode (required by legacy WebKit and Batik) } else if (key === 'stroke') { value = renderer.color(value, element, key); // emulate VML's dashstyle implementation } else if (key === 'dashstyle') { key = 'stroke-dasharray'; value = value && value.toLowerCase(); if (value === 'solid') { value = NONE; } else if (value) { value = value .replace('shortdashdotdot', '3,1,1,1,1,1,') .replace('shortdashdot', '3,1,1,1') .replace('shortdot', '1,1,') .replace('shortdash', '3,1,') .replace('longdash', '8,3,') .replace(/dot/g, '1,3,') .replace('dash', '4,3,') .replace(/,$/, '') .split(','); // ending comma i = value.length; while (i--) { value[i] = pInt(value[i]) * hash['stroke-width']; } value = value.join(','); } // special } else if (key === 'isTracker') { this[key] = value; // IE9/MooTools combo: MooTools returns objects instead of numbers and IE9 Beta 2 // is unable to cast them. Test again with final IE9. } else if (key === 'width') { value = pInt(value); // Text alignment } else if (key === 'align') { key = 'text-anchor'; value = { left: 'start', center: 'middle', right: 'end' }[value]; // Title requires a subnode, #431 } else if (key === 'title') { var title = doc.createElementNS(SVG_NS, 'title'); title.appendChild(doc.createTextNode(value)); element.appendChild(title); } // jQuery animate changes case if (key === 'strokeWidth') { key = 'stroke-width'; } // Chrome/Win < 6 bug (http://code.google.com/p/chromium/issues/detail?id=15461) if (isWebKit && key === 'stroke-width' && value === 0) { value = 0.000001; } // symbols if (this.symbolName && /^(x|y|r|start|end|innerR)/.test(key)) { if (!hasSetSymbolSize) { this.symbolAttr(hash); hasSetSymbolSize = true; } skipAttr = true; } // let the shadow follow the main element if (shadows && /^(width|height|visibility|x|y|d)$/.test(key)) { i = shadows.length; while (i--) { attr(shadows[i], key, value); } } // validate heights if ((key === 'width' || key === 'height') && nodeName === 'rect' && value < 0) { value = 0; } if (key === 'text') { // only one node allowed this.textStr = value; if (this.added) { renderer.buildText(this); } } else if (!skipAttr) { //element.setAttribute(key, value); attr(element, key, value); } // Issue #38 if (htmlNode && (key === 'x' || key === 'y' || key === 'translateX' || key === 'translateY' || key === 'visibility')) { var wrapper = this, bBox, arr = htmlNode.length ? htmlNode : [this], length = arr.length, itemWrapper, j; for (j = 0; j < length; j++) { itemWrapper = arr[j]; bBox = itemWrapper.getBBox(); htmlNode = itemWrapper.htmlNode; // reassign to child item css(htmlNode, extend(wrapper.styles, { left: (bBox.x + (wrapper.translateX || 0)) + PX, top: (bBox.y + (wrapper.translateY || 0)) + PX })); if (key === 'visibility') { css(htmlNode, { visibility: value }); } } } } } return ret; }, /** * If one o