jqplot.themeEngine.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. /**
  2. * jqPlot
  3. * Pure JavaScript plotting plugin using jQuery
  4. *
  5. * Version: @VERSION
  6. * Revision: @REVISION
  7. *
  8. * Copyright (c) 2009-2013 Chris Leonello
  9. * jqPlot is currently available for use in all personal or commercial projects
  10. * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL
  11. * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can
  12. * choose the license that best suits your project and use it accordingly.
  13. *
  14. * Although not required, the author would appreciate an email letting him
  15. * know of any substantial use of jqPlot. You can reach the author at:
  16. * chris at jqplot dot com or see http://www.jqplot.com/info.php .
  17. *
  18. * If you are feeling kind and generous, consider supporting the project by
  19. * making a donation at: http://www.jqplot.com/donate.php .
  20. *
  21. * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
  22. *
  23. * version 2007.04.27
  24. * author Ash Searle
  25. * http://hexmen.com/blog/2007/03/printf-sprintf/
  26. * http://hexmen.com/js/sprintf.js
  27. * The author (Ash Searle) has placed this code in the public domain:
  28. * "This code is unrestricted: you are free to use it however you like."
  29. *
  30. */
  31. (function($) {
  32. /**
  33. * Class: $.jqplot.ThemeEngine
  34. * Theme Engine provides a programatic way to change some of the more
  35. * common jqplot styling options such as fonts, colors and grid options.
  36. * A theme engine instance is created with each plot. The theme engine
  37. * manages a collection of themes which can be modified, added to, or
  38. * applied to the plot.
  39. *
  40. * The themeEngine class is not instantiated directly.
  41. * When a plot is initialized, the current plot options are scanned
  42. * an a default theme named "Default" is created. This theme is
  43. * used as the basis for other themes added to the theme engine and
  44. * is always available.
  45. *
  46. * A theme is a simple javascript object with styling parameters for
  47. * various entities of the plot. A theme has the form:
  48. *
  49. *
  50. * > {
  51. * > _name:f "Default",
  52. * > target: {
  53. * > backgroundColor: "transparent"
  54. * > },
  55. * > legend: {
  56. * > textColor: null,
  57. * > fontFamily: null,
  58. * > fontSize: null,
  59. * > border: null,
  60. * > background: null
  61. * > },
  62. * > title: {
  63. * > textColor: "rgb(102, 102, 102)",
  64. * > fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif",
  65. * > fontSize: "19.2px",
  66. * > textAlign: "center"
  67. * > },
  68. * > seriesStyles: {},
  69. * > series: [{
  70. * > color: "#4bb2c5",
  71. * > lineWidth: 2.5,
  72. * > linePattern: "solid",
  73. * > shadow: true,
  74. * > fillColor: "#4bb2c5",
  75. * > showMarker: true,
  76. * > markerOptions: {
  77. * > color: "#4bb2c5",
  78. * > show: true,
  79. * > style: 'filledCircle',
  80. * > lineWidth: 1.5,
  81. * > size: 4,
  82. * > shadow: true
  83. * > }
  84. * > }],
  85. * > grid: {
  86. * > drawGridlines: true,
  87. * > gridLineColor: "#cccccc",
  88. * > gridLineWidth: 1,
  89. * > backgroundColor: "#fffdf6",
  90. * > borderColor: "#999999",
  91. * > borderWidth: 2,
  92. * > shadow: true
  93. * > },
  94. * > axesStyles: {
  95. * > label: {},
  96. * > ticks: {}
  97. * > },
  98. * > axes: {
  99. * > xaxis: {
  100. * > borderColor: "#999999",
  101. * > borderWidth: 2,
  102. * > ticks: {
  103. * > show: true,
  104. * > showGridline: true,
  105. * > showLabel: true,
  106. * > showMark: true,
  107. * > size: 4,
  108. * > textColor: "",
  109. * > whiteSpace: "nowrap",
  110. * > fontSize: "12px",
  111. * > fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif"
  112. * > },
  113. * > label: {
  114. * > textColor: "rgb(102, 102, 102)",
  115. * > whiteSpace: "normal",
  116. * > fontSize: "14.6667px",
  117. * > fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif",
  118. * > fontWeight: "400"
  119. * > }
  120. * > },
  121. * > yaxis: {
  122. * > borderColor: "#999999",
  123. * > borderWidth: 2,
  124. * > ticks: {
  125. * > show: true,
  126. * > showGridline: true,
  127. * > showLabel: true,
  128. * > showMark: true,
  129. * > size: 4,
  130. * > textColor: "",
  131. * > whiteSpace: "nowrap",
  132. * > fontSize: "12px",
  133. * > fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif"
  134. * > },
  135. * > label: {
  136. * > textColor: null,
  137. * > whiteSpace: null,
  138. * > fontSize: null,
  139. * > fontFamily: null,
  140. * > fontWeight: null
  141. * > }
  142. * > },
  143. * > x2axis: {...
  144. * > },
  145. * > ...
  146. * > y9axis: {...
  147. * > }
  148. * > }
  149. * > }
  150. *
  151. * "seriesStyles" is a style object that will be applied to all series in the plot.
  152. * It will forcibly override any styles applied on the individual series. "axesStyles" is
  153. * a style object that will be applied to all axes in the plot. It will also forcibly
  154. * override any styles on the individual axes.
  155. *
  156. * The example shown above has series options for a line series. Options for other
  157. * series types are shown below:
  158. *
  159. * Bar Series:
  160. *
  161. * > {
  162. * > color: "#4bb2c5",
  163. * > seriesColors: ["#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"],
  164. * > lineWidth: 2.5,
  165. * > shadow: true,
  166. * > barPadding: 2,
  167. * > barMargin: 10,
  168. * > barWidth: 15.09375,
  169. * > highlightColors: ["rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)"]
  170. * > }
  171. *
  172. * Pie Series:
  173. *
  174. * > {
  175. * > seriesColors: ["#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"],
  176. * > padding: 20,
  177. * > sliceMargin: 0,
  178. * > fill: true,
  179. * > shadow: true,
  180. * > startAngle: 0,
  181. * > lineWidth: 2.5,
  182. * > highlightColors: ["rgb(129,201,214)", "rgb(240,189,104)", "rgb(214,202,165)", "rgb(137,180,158)", "rgb(168,180,137)", "rgb(180,174,89)", "rgb(180,113,161)", "rgb(129,141,236)", "rgb(227,205,120)", "rgb(255,138,76)", "rgb(76,169,219)", "rgb(215,126,190)", "rgb(220,232,135)", "rgb(200,167,96)", "rgb(103,202,235)", "rgb(208,154,215)"]
  183. * > }
  184. *
  185. * Funnel Series:
  186. *
  187. * > {
  188. * > color: "#4bb2c5",
  189. * > lineWidth: 2,
  190. * > shadow: true,
  191. * > padding: {
  192. * > top: 20,
  193. * > right: 20,
  194. * > bottom: 20,
  195. * > left: 20
  196. * > },
  197. * > sectionMargin: 6,
  198. * > seriesColors: ["#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"],
  199. * > highlightColors: ["rgb(147,208,220)", "rgb(242,199,126)", "rgb(220,210,178)", "rgb(154,191,172)", "rgb(180,191,154)", "rgb(191,186,112)", "rgb(191,133,174)", "rgb(147,157,238)", "rgb(231,212,139)", "rgb(255,154,102)", "rgb(102,181,224)", "rgb(221,144,199)", "rgb(225,235,152)", "rgb(200,167,96)", "rgb(124,210,238)", "rgb(215,169,221)"]
  200. * > }
  201. *
  202. */
  203. $.jqplot.ThemeEngine = function(){
  204. // Group: Properties
  205. //
  206. // prop: themes
  207. // hash of themes managed by the theme engine.
  208. // Indexed by theme name.
  209. this.themes = {};
  210. // prop: activeTheme
  211. // Pointer to currently active theme
  212. this.activeTheme=null;
  213. };
  214. // called with scope of plot
  215. $.jqplot.ThemeEngine.prototype.init = function() {
  216. // get the Default theme from the current plot settings.
  217. var th = new $.jqplot.Theme({_name:'Default'});
  218. var n, i, nn;
  219. for (n in th.target) {
  220. if (n == "textColor") {
  221. th.target[n] = this.target.css('color');
  222. }
  223. else {
  224. th.target[n] = this.target.css(n);
  225. }
  226. }
  227. if (this.title.show && this.title._elem) {
  228. for (n in th.title) {
  229. if (n == "textColor") {
  230. th.title[n] = this.title._elem.css('color');
  231. }
  232. else {
  233. th.title[n] = this.title._elem.css(n);
  234. }
  235. }
  236. }
  237. for (n in th.grid) {
  238. th.grid[n] = this.grid[n];
  239. }
  240. if (th.grid.backgroundColor == null && this.grid.background != null) {
  241. th.grid.backgroundColor = this.grid.background;
  242. }
  243. if (this.legend.show && this.legend._elem) {
  244. for (n in th.legend) {
  245. if (n == 'textColor') {
  246. th.legend[n] = this.legend._elem.css('color');
  247. }
  248. else {
  249. th.legend[n] = this.legend._elem.css(n);
  250. }
  251. }
  252. }
  253. var s;
  254. for (i=0; i<this.series.length; i++) {
  255. s = this.series[i];
  256. if (s.renderer.constructor == $.jqplot.LineRenderer) {
  257. th.series.push(new LineSeriesProperties());
  258. }
  259. else if (s.renderer.constructor == $.jqplot.BarRenderer) {
  260. th.series.push(new BarSeriesProperties());
  261. }
  262. else if (s.renderer.constructor == $.jqplot.PieRenderer) {
  263. th.series.push(new PieSeriesProperties());
  264. }
  265. else if (s.renderer.constructor == $.jqplot.DonutRenderer) {
  266. th.series.push(new DonutSeriesProperties());
  267. }
  268. else if (s.renderer.constructor == $.jqplot.FunnelRenderer) {
  269. th.series.push(new FunnelSeriesProperties());
  270. }
  271. else if (s.renderer.constructor == $.jqplot.MeterGaugeRenderer) {
  272. th.series.push(new MeterSeriesProperties());
  273. }
  274. else {
  275. th.series.push({});
  276. }
  277. for (n in th.series[i]) {
  278. th.series[i][n] = s[n];
  279. }
  280. }
  281. var a, ax;
  282. for (n in this.axes) {
  283. ax = this.axes[n];
  284. a = th.axes[n] = new AxisProperties();
  285. a.borderColor = ax.borderColor;
  286. a.borderWidth = ax.borderWidth;
  287. if (ax._ticks && ax._ticks[0]) {
  288. for (nn in a.ticks) {
  289. if (ax._ticks[0].hasOwnProperty(nn)) {
  290. a.ticks[nn] = ax._ticks[0][nn];
  291. }
  292. else if (ax._ticks[0]._elem){
  293. a.ticks[nn] = ax._ticks[0]._elem.css(nn);
  294. }
  295. }
  296. }
  297. if (ax._label && ax._label.show) {
  298. for (nn in a.label) {
  299. // a.label[nn] = ax._label._elem.css(nn);
  300. if (ax._label[nn]) {
  301. a.label[nn] = ax._label[nn];
  302. }
  303. else if (ax._label._elem){
  304. if (nn == 'textColor') {
  305. a.label[nn] = ax._label._elem.css('color');
  306. }
  307. else {
  308. a.label[nn] = ax._label._elem.css(nn);
  309. }
  310. }
  311. }
  312. }
  313. }
  314. this.themeEngine._add(th);
  315. this.themeEngine.activeTheme = this.themeEngine.themes[th._name];
  316. };
  317. /**
  318. * Group: methods
  319. *
  320. * method: get
  321. *
  322. * Get and return the named theme or the active theme if no name given.
  323. *
  324. * parameter:
  325. *
  326. * name - name of theme to get.
  327. *
  328. * returns:
  329. *
  330. * Theme instance of given name.
  331. */
  332. $.jqplot.ThemeEngine.prototype.get = function(name) {
  333. if (!name) {
  334. // return the active theme
  335. return this.activeTheme;
  336. }
  337. else {
  338. return this.themes[name];
  339. }
  340. };
  341. function numericalOrder(a,b) { return a-b; }
  342. /**
  343. * method: getThemeNames
  344. *
  345. * Return the list of theme names in this manager in alpha-numerical order.
  346. *
  347. * parameter:
  348. *
  349. * None
  350. *
  351. * returns:
  352. *
  353. * A the list of theme names in this manager in alpha-numerical order.
  354. */
  355. $.jqplot.ThemeEngine.prototype.getThemeNames = function() {
  356. var tn = [];
  357. for (var n in this.themes) {
  358. tn.push(n);
  359. }
  360. return tn.sort(numericalOrder);
  361. };
  362. /**
  363. * method: getThemes
  364. *
  365. * Return a list of themes in alpha-numerical order by name.
  366. *
  367. * parameter:
  368. *
  369. * None
  370. *
  371. * returns:
  372. *
  373. * A list of themes in alpha-numerical order by name.
  374. */
  375. $.jqplot.ThemeEngine.prototype.getThemes = function() {
  376. var tn = [];
  377. var themes = [];
  378. for (var n in this.themes) {
  379. tn.push(n);
  380. }
  381. tn.sort(numericalOrder);
  382. for (var i=0; i<tn.length; i++) {
  383. themes.push(this.themes[tn[i]]);
  384. }
  385. return themes;
  386. };
  387. $.jqplot.ThemeEngine.prototype.activate = function(plot, name) {
  388. // sometimes need to redraw whole plot.
  389. var redrawPlot = false;
  390. if (!name && this.activeTheme && this.activeTheme._name) {
  391. name = this.activeTheme._name;
  392. }
  393. if (!this.themes.hasOwnProperty(name)) {
  394. throw new Error("No theme of that name");
  395. }
  396. else {
  397. var th = this.themes[name];
  398. this.activeTheme = th;
  399. var val, checkBorderColor = false, checkBorderWidth = false;
  400. var arr = ['xaxis', 'x2axis', 'yaxis', 'y2axis'];
  401. for (i=0; i<arr.length; i++) {
  402. var ax = arr[i];
  403. if (th.axesStyles.borderColor != null) {
  404. plot.axes[ax].borderColor = th.axesStyles.borderColor;
  405. }
  406. if (th.axesStyles.borderWidth != null) {
  407. plot.axes[ax].borderWidth = th.axesStyles.borderWidth;
  408. }
  409. }
  410. for (var axname in plot.axes) {
  411. var axis = plot.axes[axname];
  412. if (axis.show) {
  413. var thaxis = th.axes[axname] || {};
  414. var thaxstyle = th.axesStyles;
  415. var thax = $.jqplot.extend(true, {}, thaxis, thaxstyle);
  416. val = (th.axesStyles.borderColor != null) ? th.axesStyles.borderColor : thax.borderColor;
  417. if (thax.borderColor != null) {
  418. axis.borderColor = thax.borderColor;
  419. redrawPlot = true;
  420. }
  421. val = (th.axesStyles.borderWidth != null) ? th.axesStyles.borderWidth : thax.borderWidth;
  422. if (thax.borderWidth != null) {
  423. axis.borderWidth = thax.borderWidth;
  424. redrawPlot = true;
  425. }
  426. if (axis._ticks && axis._ticks[0]) {
  427. for (var nn in thax.ticks) {
  428. // val = null;
  429. // if (th.axesStyles.ticks && th.axesStyles.ticks[nn] != null) {
  430. // val = th.axesStyles.ticks[nn];
  431. // }
  432. // else if (thax.ticks[nn] != null){
  433. // val = thax.ticks[nn]
  434. // }
  435. val = thax.ticks[nn];
  436. if (val != null) {
  437. axis.tickOptions[nn] = val;
  438. axis._ticks = [];
  439. redrawPlot = true;
  440. }
  441. }
  442. }
  443. if (axis._label && axis._label.show) {
  444. for (var nn in thax.label) {
  445. // val = null;
  446. // if (th.axesStyles.label && th.axesStyles.label[nn] != null) {
  447. // val = th.axesStyles.label[nn];
  448. // }
  449. // else if (thax.label && thax.label[nn] != null){
  450. // val = thax.label[nn]
  451. // }
  452. val = thax.label[nn];
  453. if (val != null) {
  454. axis.labelOptions[nn] = val;
  455. redrawPlot = true;
  456. }
  457. }
  458. }
  459. }
  460. }
  461. for (var n in th.grid) {
  462. if (th.grid[n] != null) {
  463. plot.grid[n] = th.grid[n];
  464. }
  465. }
  466. if (!redrawPlot) {
  467. plot.grid.draw();
  468. }
  469. if (plot.legend.show) {
  470. for (n in th.legend) {
  471. if (th.legend[n] != null) {
  472. plot.legend[n] = th.legend[n];
  473. }
  474. }
  475. }
  476. if (plot.title.show) {
  477. for (n in th.title) {
  478. if (th.title[n] != null) {
  479. plot.title[n] = th.title[n];
  480. }
  481. }
  482. }
  483. var i;
  484. for (i=0; i<th.series.length; i++) {
  485. var opts = {};
  486. var redrawSeries = false;
  487. for (n in th.series[i]) {
  488. val = (th.seriesStyles[n] != null) ? th.seriesStyles[n] : th.series[i][n];
  489. if (val != null) {
  490. opts[n] = val;
  491. if (n == 'color') {
  492. plot.series[i].renderer.shapeRenderer.fillStyle = val;
  493. plot.series[i].renderer.shapeRenderer.strokeStyle = val;
  494. plot.series[i][n] = val;
  495. }
  496. else if ((n == 'lineWidth') || (n == 'linePattern')) {
  497. plot.series[i].renderer.shapeRenderer[n] = val;
  498. plot.series[i][n] = val;
  499. }
  500. else if (n == 'markerOptions') {
  501. merge (plot.series[i].markerOptions, val);
  502. merge (plot.series[i].markerRenderer, val);
  503. }
  504. else {
  505. plot.series[i][n] = val;
  506. }
  507. redrawPlot = true;
  508. }
  509. }
  510. }
  511. if (redrawPlot) {
  512. plot.target.empty();
  513. plot.draw();
  514. }
  515. for (n in th.target) {
  516. if (th.target[n] != null) {
  517. plot.target.css(n, th.target[n]);
  518. }
  519. }
  520. }
  521. };
  522. $.jqplot.ThemeEngine.prototype._add = function(theme, name) {
  523. if (name) {
  524. theme._name = name;
  525. }
  526. if (!theme._name) {
  527. theme._name = Date.parse(new Date());
  528. }
  529. if (!this.themes.hasOwnProperty(theme._name)) {
  530. this.themes[theme._name] = theme;
  531. }
  532. else {
  533. throw new Error("jqplot.ThemeEngine Error: Theme already in use");
  534. }
  535. };
  536. // method remove
  537. // Delete the named theme, return true on success, false on failure.
  538. /**
  539. * method: remove
  540. *
  541. * Remove the given theme from the themeEngine.
  542. *
  543. * parameters:
  544. *
  545. * name - name of the theme to remove.
  546. *
  547. * returns:
  548. *
  549. * true on success, false on failure.
  550. */
  551. $.jqplot.ThemeEngine.prototype.remove = function(name) {
  552. if (name == 'Default') {
  553. return false;
  554. }
  555. return delete this.themes[name];
  556. };
  557. /**
  558. * method: newTheme
  559. *
  560. * Create a new theme based on the default theme, adding it the themeEngine.
  561. *
  562. * parameters:
  563. *
  564. * name - name of the new theme.
  565. * obj - optional object of styles to be applied to this new theme.
  566. *
  567. * returns:
  568. *
  569. * new Theme object.
  570. */
  571. $.jqplot.ThemeEngine.prototype.newTheme = function(name, obj) {
  572. if (typeof(name) == 'object') {
  573. obj = obj || name;
  574. name = null;
  575. }
  576. if (obj && obj._name) {
  577. name = obj._name;
  578. }
  579. else {
  580. name = name || Date.parse(new Date());
  581. }
  582. // var th = new $.jqplot.Theme(name);
  583. var th = this.copy(this.themes['Default']._name, name);
  584. $.jqplot.extend(th, obj);
  585. return th;
  586. };
  587. // function clone(obj) {
  588. // return eval(obj.toSource());
  589. // }
  590. function clone(obj){
  591. if(obj == null || typeof(obj) != 'object'){
  592. return obj;
  593. }
  594. var temp = new obj.constructor();
  595. for(var key in obj){
  596. temp[key] = clone(obj[key]);
  597. }
  598. return temp;
  599. }
  600. $.jqplot.clone = clone;
  601. function merge(obj1, obj2) {
  602. if (obj2 == null || typeof(obj2) != 'object') {
  603. return;
  604. }
  605. for (var key in obj2) {
  606. if (key == 'highlightColors') {
  607. obj1[key] = clone(obj2[key]);
  608. }
  609. if (obj2[key] != null && typeof(obj2[key]) == 'object') {
  610. if (!obj1.hasOwnProperty(key)) {
  611. obj1[key] = {};
  612. }
  613. merge(obj1[key], obj2[key]);
  614. }
  615. else {
  616. obj1[key] = obj2[key];
  617. }
  618. }
  619. }
  620. $.jqplot.merge = merge;
  621. // Use the jQuery 1.3.2 extend function since behaviour in jQuery 1.4 seems problematic
  622. $.jqplot.extend = function() {
  623. // copy reference to target object
  624. var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
  625. // Handle a deep copy situation
  626. if ( typeof target === "boolean" ) {
  627. deep = target;
  628. target = arguments[1] || {};
  629. // skip the boolean and the target
  630. i = 2;
  631. }
  632. // Handle case when target is a string or something (possible in deep copy)
  633. if ( typeof target !== "object" && !toString.call(target) === "[object Function]" ) {
  634. target = {};
  635. }
  636. for ( ; i < length; i++ ){
  637. // Only deal with non-null/undefined values
  638. if ( (options = arguments[ i ]) != null ) {
  639. // Extend the base object
  640. for ( var name in options ) {
  641. var src = target[ name ], copy = options[ name ];
  642. // Prevent never-ending loop
  643. if ( target === copy ) {
  644. continue;
  645. }
  646. // Recurse if we're merging object values
  647. if ( deep && copy && typeof copy === "object" && !copy.nodeType ) {
  648. target[ name ] = $.jqplot.extend( deep,
  649. // Never move original objects, clone them
  650. src || ( copy.length != null ? [ ] : { } )
  651. , copy );
  652. }
  653. // Don't bring in undefined values
  654. else if ( copy !== undefined ) {
  655. target[ name ] = copy;
  656. }
  657. }
  658. }
  659. }
  660. // Return the modified object
  661. return target;
  662. };
  663. /**
  664. * method: rename
  665. *
  666. * Rename a theme.
  667. *
  668. * parameters:
  669. *
  670. * oldName - current name of the theme.
  671. * newName - desired name of the theme.
  672. *
  673. * returns:
  674. *
  675. * new Theme object.
  676. */
  677. $.jqplot.ThemeEngine.prototype.rename = function (oldName, newName) {
  678. if (oldName == 'Default' || newName == 'Default') {
  679. throw new Error ("jqplot.ThemeEngine Error: Cannot rename from/to Default");
  680. }
  681. if (this.themes.hasOwnProperty(newName)) {
  682. throw new Error ("jqplot.ThemeEngine Error: New name already in use.");
  683. }
  684. else if (this.themes.hasOwnProperty(oldName)) {
  685. var th = this.copy (oldName, newName);
  686. this.remove(oldName);
  687. return th;
  688. }
  689. throw new Error("jqplot.ThemeEngine Error: Old name or new name invalid");
  690. };
  691. /**
  692. * method: copy
  693. *
  694. * Create a copy of an existing theme in the themeEngine, adding it the themeEngine.
  695. *
  696. * parameters:
  697. *
  698. * sourceName - name of the existing theme.
  699. * targetName - name of the copy.
  700. * obj - optional object of style parameter to apply to the new theme.
  701. *
  702. * returns:
  703. *
  704. * new Theme object.
  705. */
  706. $.jqplot.ThemeEngine.prototype.copy = function (sourceName, targetName, obj) {
  707. if (targetName == 'Default') {
  708. throw new Error ("jqplot.ThemeEngine Error: Cannot copy over Default theme");
  709. }
  710. if (!this.themes.hasOwnProperty(sourceName)) {
  711. var s = "jqplot.ThemeEngine Error: Source name invalid";
  712. throw new Error(s);
  713. }
  714. if (this.themes.hasOwnProperty(targetName)) {
  715. var s = "jqplot.ThemeEngine Error: Target name invalid";
  716. throw new Error(s);
  717. }
  718. else {
  719. var th = clone(this.themes[sourceName]);
  720. th._name = targetName;
  721. $.jqplot.extend(true, th, obj);
  722. this._add(th);
  723. return th;
  724. }
  725. };
  726. $.jqplot.Theme = function(name, obj) {
  727. if (typeof(name) == 'object') {
  728. obj = obj || name;
  729. name = null;
  730. }
  731. name = name || Date.parse(new Date());
  732. this._name = name;
  733. this.target = {
  734. backgroundColor: null
  735. };
  736. this.legend = {
  737. textColor: null,
  738. fontFamily: null,
  739. fontSize: null,
  740. border: null,
  741. background: null
  742. };
  743. this.title = {
  744. textColor: null,
  745. fontFamily: null,
  746. fontSize: null,
  747. textAlign: null
  748. };
  749. this.seriesStyles = {};
  750. this.series = [];
  751. this.grid = {
  752. drawGridlines: null,
  753. gridLineColor: null,
  754. gridLineWidth: null,
  755. backgroundColor: null,
  756. borderColor: null,
  757. borderWidth: null,
  758. shadow: null
  759. };
  760. this.axesStyles = {label:{}, ticks:{}};
  761. this.axes = {};
  762. if (typeof(obj) == 'string') {
  763. this._name = obj;
  764. }
  765. else if(typeof(obj) == 'object') {
  766. $.jqplot.extend(true, this, obj);
  767. }
  768. };
  769. var AxisProperties = function() {
  770. this.borderColor = null;
  771. this.borderWidth = null;
  772. this.ticks = new AxisTicks();
  773. this.label = new AxisLabel();
  774. };
  775. var AxisTicks = function() {
  776. this.show = null;
  777. this.showGridline = null;
  778. this.showLabel = null;
  779. this.showMark = null;
  780. this.size = null;
  781. this.textColor = null;
  782. this.whiteSpace = null;
  783. this.fontSize = null;
  784. this.fontFamily = null;
  785. };
  786. var AxisLabel = function() {
  787. this.textColor = null;
  788. this.whiteSpace = null;
  789. this.fontSize = null;
  790. this.fontFamily = null;
  791. this.fontWeight = null;
  792. };
  793. var LineSeriesProperties = function() {
  794. this.color=null;
  795. this.lineWidth=null;
  796. this.linePattern=null;
  797. this.shadow=null;
  798. this.fillColor=null;
  799. this.showMarker=null;
  800. this.markerOptions = new MarkerOptions();
  801. };
  802. var MarkerOptions = function() {
  803. this.show = null;
  804. this.style = null;
  805. this.lineWidth = null;
  806. this.size = null;
  807. this.color = null;
  808. this.shadow = null;
  809. };
  810. var BarSeriesProperties = function() {
  811. this.color=null;
  812. this.seriesColors=null;
  813. this.lineWidth=null;
  814. this.shadow=null;
  815. this.barPadding=null;
  816. this.barMargin=null;
  817. this.barWidth=null;
  818. this.highlightColors=null;
  819. };
  820. var PieSeriesProperties = function() {
  821. this.seriesColors=null;
  822. this.padding=null;
  823. this.sliceMargin=null;
  824. this.fill=null;
  825. this.shadow=null;
  826. this.startAngle=null;
  827. this.lineWidth=null;
  828. this.highlightColors=null;
  829. };
  830. var DonutSeriesProperties = function() {
  831. this.seriesColors=null;
  832. this.padding=null;
  833. this.sliceMargin=null;
  834. this.fill=null;
  835. this.shadow=null;
  836. this.startAngle=null;
  837. this.lineWidth=null;
  838. this.innerDiameter=null;
  839. this.thickness=null;
  840. this.ringMargin=null;
  841. this.highlightColors=null;
  842. };
  843. var FunnelSeriesProperties = function() {
  844. this.color=null;
  845. this.lineWidth=null;
  846. this.shadow=null;
  847. this.padding=null;
  848. this.sectionMargin=null;
  849. this.seriesColors=null;
  850. this.highlightColors=null;
  851. };
  852. var MeterSeriesProperties = function() {
  853. this.padding=null;
  854. this.backgroundColor=null;
  855. this.ringColor=null;
  856. this.tickColor=null;
  857. this.ringWidth=null;
  858. this.intervalColors=null;
  859. this.intervalInnerRadius=null;
  860. this.intervalOuterRadius=null;
  861. this.hubRadius=null;
  862. this.needleThickness=null;
  863. this.needlePad=null;
  864. };
  865. })(jQuery);