rgraph-rails 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +1 -0
  3. data/README.md +5 -5
  4. data/lib/rgraph-rails/version.rb +1 -1
  5. data/rgraph-rails.gemspec +2 -2
  6. data/vendor/assets/images/bg.png +0 -0
  7. data/vendor/assets/images/bullet.png +0 -0
  8. data/vendor/assets/images/facebook-large.png +0 -0
  9. data/vendor/assets/images/google-plus-large.png +0 -0
  10. data/vendor/assets/images/logo.png +0 -0
  11. data/vendor/assets/images/meter-image-sd-needle.png +0 -0
  12. data/vendor/assets/images/meter-image-sd.png +0 -0
  13. data/vendor/assets/images/meter-sketch-needle.png +0 -0
  14. data/vendor/assets/images/meter-sketch.png +0 -0
  15. data/vendor/assets/images/odometer-background.png +0 -0
  16. data/vendor/assets/images/rgraph.jpg +0 -0
  17. data/vendor/assets/images/title.png +0 -0
  18. data/vendor/assets/images/twitter-large.png +0 -0
  19. data/vendor/assets/javascripts/RGraph.bar.js +258 -30
  20. data/vendor/assets/javascripts/RGraph.bipolar.js +4 -3
  21. data/vendor/assets/javascripts/RGraph.common.annotate.js +4 -3
  22. data/vendor/assets/javascripts/RGraph.common.context.js +4 -3
  23. data/vendor/assets/javascripts/RGraph.common.core.js +227 -105
  24. data/vendor/assets/javascripts/RGraph.common.csv.js +4 -3
  25. data/vendor/assets/javascripts/RGraph.common.deprecated.js +4 -3
  26. data/vendor/assets/javascripts/RGraph.common.dynamic.js +5 -4
  27. data/vendor/assets/javascripts/RGraph.common.effects.js +4 -3
  28. data/vendor/assets/javascripts/RGraph.common.key.js +4 -3
  29. data/vendor/assets/javascripts/RGraph.common.resizing.js +4 -3
  30. data/vendor/assets/javascripts/RGraph.common.sheets.js +357 -0
  31. data/vendor/assets/javascripts/RGraph.common.tooltips.js +6 -4
  32. data/vendor/assets/javascripts/RGraph.common.zoom.js +4 -3
  33. data/vendor/assets/javascripts/RGraph.drawing.background.js +4 -3
  34. data/vendor/assets/javascripts/RGraph.drawing.circle.js +4 -3
  35. data/vendor/assets/javascripts/RGraph.drawing.image.js +4 -3
  36. data/vendor/assets/javascripts/RGraph.drawing.marker1.js +4 -3
  37. data/vendor/assets/javascripts/RGraph.drawing.marker2.js +4 -3
  38. data/vendor/assets/javascripts/RGraph.drawing.marker3.js +1 -1
  39. data/vendor/assets/javascripts/RGraph.drawing.poly.js +1 -1
  40. data/vendor/assets/javascripts/RGraph.drawing.rect.js +1 -1
  41. data/vendor/assets/javascripts/RGraph.drawing.text.js +1 -1
  42. data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +1 -1
  43. data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +33 -30
  44. data/vendor/assets/javascripts/RGraph.fuel.js +14 -16
  45. data/vendor/assets/javascripts/RGraph.funnel.js +1 -1
  46. data/vendor/assets/javascripts/RGraph.gantt.js +1 -1
  47. data/vendor/assets/javascripts/RGraph.gauge.js +3 -5
  48. data/vendor/assets/javascripts/RGraph.hbar.js +738 -212
  49. data/vendor/assets/javascripts/RGraph.hprogress.js +30 -33
  50. data/vendor/assets/javascripts/RGraph.line.js +246 -31
  51. data/vendor/assets/javascripts/RGraph.meter.js +72 -36
  52. data/vendor/assets/javascripts/RGraph.modaldialog.js +1 -1
  53. data/vendor/assets/javascripts/RGraph.odo.js +3 -5
  54. data/vendor/assets/javascripts/RGraph.pie.js +23 -15
  55. data/vendor/assets/javascripts/RGraph.radar.js +1 -1
  56. data/vendor/assets/javascripts/RGraph.rose.js +2 -2
  57. data/vendor/assets/javascripts/RGraph.rscatter.js +116 -27
  58. data/vendor/assets/javascripts/RGraph.scatter.js +14 -15
  59. data/vendor/assets/javascripts/RGraph.thermometer.js +8 -10
  60. data/vendor/assets/javascripts/RGraph.vprogress.js +8 -10
  61. data/vendor/assets/javascripts/RGraph.waterfall.js +1 -1
  62. data/vendor/assets/stylesheets/website.css +32 -2
  63. metadata +6 -5
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -7,8 +7,9 @@
7
7
  * | |
8
8
  * | RGraph is dual licensed under the Open Source GPL (General Public License) |
9
9
  * | v2.0 license and a commercial license which means that you're not bound by |
10
- * | the terms of the GPL. The commercial license is just �99 (GBP) and you can |
11
- * | read about it here: |
10
+ * | the terms of the GPL. The commercial license starts at just �99 (GBP) and |
11
+ * | you can read about it here: |
12
+ * | |
12
13
  * | http://www.rgraph.net/license |
13
14
  * o--------------------------------------------------------------------------------o
14
15
  */
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -7,8 +7,9 @@
7
7
  * | |
8
8
  * | RGraph is dual licensed under the Open Source GPL (General Public License) |
9
9
  * | v2.0 license and a commercial license which means that you're not bound by |
10
- * | the terms of the GPL. The commercial license is just �99 (GBP) and you can |
11
- * | read about it here: |
10
+ * | the terms of the GPL. The commercial license starts at just �99 (GBP) and |
11
+ * | you can read about it here: |
12
+ * | |
12
13
  * | http://www.rgraph.net/license |
13
14
  * o--------------------------------------------------------------------------------o
14
15
  */
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -7,8 +7,9 @@
7
7
  * | |
8
8
  * | RGraph is dual licensed under the Open Source GPL (General Public License) |
9
9
  * | v2.0 license and a commercial license which means that you're not bound by |
10
- * | the terms of the GPL. The commercial license is just �99 (GBP) and you can |
11
- * | read about it here: |
10
+ * | the terms of the GPL. The commercial license starts at just �99 (GBP) and |
11
+ * | you can read about it here: |
12
+ * | |
12
13
  * | http://www.rgraph.net/license |
13
14
  * o--------------------------------------------------------------------------------o
14
15
  */
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -7,8 +7,9 @@
7
7
  * | |
8
8
  * | RGraph is dual licensed under the Open Source GPL (General Public License) |
9
9
  * | v2.0 license and a commercial license which means that you're not bound by |
10
- * | the terms of the GPL. The commercial license is just �99 (GBP) and you can |
11
- * | read about it here: |
10
+ * | the terms of the GPL. The commercial license starts at just �99 (GBP) and |
11
+ * | you can read about it here: |
12
+ * | |
12
13
  * | http://www.rgraph.net/license |
13
14
  * o--------------------------------------------------------------------------------o
14
15
  */
@@ -357,6 +358,50 @@
357
358
 
358
359
 
359
360
 
361
+ //
362
+ // An array_trim function that removes the empty elements off
363
+ //both ends
364
+ //
365
+ RG.arrayTrim = function (arr)
366
+ {
367
+ var out = [], content = false;
368
+
369
+ // Trim the start
370
+ for (var i=0; i<arr.length; i++) {
371
+
372
+ if (arr[i]) {
373
+ content = true;
374
+ }
375
+
376
+ if (content) {
377
+ out.push(arr[i]);
378
+ }
379
+ }
380
+
381
+ // Reverse the array and trim the start again
382
+ out = RG.arrayReverse(out);
383
+
384
+ var out2 = [], content = false ;
385
+ for (var i=0; i<out.length; i++) {
386
+
387
+ if (out[i]) {
388
+ content = true;
389
+ }
390
+
391
+ if (content) {
392
+ out2.push(out[i]);
393
+ }
394
+ }
395
+
396
+ // Now reverse the array and return it
397
+ out2 = RG.arrayReverse(out2);
398
+
399
+ return out2;
400
+ };
401
+
402
+
403
+
404
+
360
405
  /**
361
406
  * Makes a clone of an object
362
407
  *
@@ -394,7 +439,8 @@
394
439
 
395
440
 
396
441
  /**
397
- * Returns the maximum numeric value which is in an array
442
+ * Returns the maximum numeric value which is in an array. This function IS NOT
443
+ * recursive
398
444
  *
399
445
  * @param array arr The array (can also be a number, in which case it's returned as-is)
400
446
  * @param int Whether to ignore signs (ie negative/positive)
@@ -588,8 +634,12 @@
588
634
  RG.arrayReverse =
589
635
  RG.array_reverse = function (arr)
590
636
  {
637
+ if (!arr) {
638
+ return;
639
+ }
640
+
591
641
  var newarr=[];
592
-
642
+
593
643
  for(var i=arr.length - 1; i>=0; i-=1) {
594
644
  newarr.push(arr[i]);
595
645
  }
@@ -600,6 +650,42 @@
600
650
 
601
651
 
602
652
 
653
+ /**
654
+ * Returns the absolute value of a number. You can also pass in an
655
+ * array and it will run the abs() function on each element. It
656
+ * operates recursively so sub-arrays are also traversed.
657
+ *
658
+ * @param array arr The number or array to work on
659
+ */
660
+ RG.abs = function (value)
661
+ {
662
+ if (typeof value === 'string') {
663
+ value = parseFloat(value) || 0;
664
+ }
665
+
666
+ if (typeof value === 'number') {
667
+ return ma.abs(value);
668
+ }
669
+
670
+ if (typeof value === 'object') {
671
+ for (i in value) {
672
+ if ( typeof i === 'string'
673
+ || typeof i === 'number'
674
+ || typeof i === 'object') {
675
+
676
+ value[i] = RG.abs(value[i]);
677
+ }
678
+ }
679
+
680
+ return value;
681
+ }
682
+
683
+ return 0;
684
+ };
685
+
686
+
687
+
688
+
603
689
  /**
604
690
  * Clears the canvas by setting the width. You can specify a colour if you wish.
605
691
  *
@@ -1963,9 +2049,9 @@
1963
2049
  RG.draw3DAxes =
1964
2050
  RG.Draw3DAxes = function (obj)
1965
2051
  {
1966
- var prop = obj.properties;
1967
- var co = obj.context;
1968
- var ca = obj.canvas;
2052
+ var prop = obj.properties,
2053
+ co = obj.context,
2054
+ ca = obj.canvas;
1969
2055
 
1970
2056
  var gutterLeft = obj.gutterLeft,
1971
2057
  gutterRight = obj.gutterRight,
@@ -1975,38 +2061,94 @@
1975
2061
  graphArea = ca.height - gutterTop - gutterBottom,
1976
2062
  halfGraphArea = graphArea / 2,
1977
2063
  offsetx = prop['chart.variant.threed.offsetx'],
1978
- offsety = prop['chart.variant.threed.offsety']
2064
+ offsety = prop['chart.variant.threed.offsety'],
2065
+ xaxis = prop['chart.variant.threed.xaxis'],
2066
+ yaxis = prop['chart.variant.threed.yaxis']
2067
+
1979
2068
 
1980
- if (!prop['chart.noaxes'] && !prop['chart.noyaxis']) {
1981
- RG.path(co, [
1982
- 'b',
1983
- // Y axis
1984
- 'm', gutterLeft,gutterTop,
1985
- 'l',gutterLeft + offsetx,gutterTop - offsety,
1986
- 'l',gutterLeft + offsetx,ca.height - gutterBottom - offsety,
1987
- 'l',gutterLeft,ca.height - gutterBottom
1988
- ]);
2069
+ //
2070
+ // Draw the 3D Y axis
2071
+ //
2072
+ if (yaxis) {
2073
+ RG.draw3DYAxis(obj);
1989
2074
  }
1990
2075
 
2076
+
2077
+
1991
2078
  // X axis
1992
- if (xaxispos === 'center') {
1993
- RG.path(co, [
1994
- 'm',gutterLeft,gutterTop + halfGraphArea,
1995
- 'l',gutterLeft + offsetx,gutterTop + halfGraphArea - offsety,
2079
+ if (xaxis) {
2080
+ if (xaxispos === 'center') {
2081
+ RG.path(co, [
2082
+ 'b',
2083
+ 'm',gutterLeft,gutterTop + halfGraphArea,
2084
+ 'l',gutterLeft + offsetx,gutterTop + halfGraphArea - offsety,
2085
+
2086
+ 'l',ca.width - gutterRight + offsetx,gutterTop + halfGraphArea - offsety,
2087
+ 'l',ca.width - gutterRight,gutterTop + halfGraphArea,
2088
+ 'c',
2089
+ 's','#aaa',
2090
+ 'f','#ddd'
2091
+ ]);
2092
+ } else {
2093
+ RG.path(co, [
2094
+ 'b',
2095
+ 'm',gutterLeft,ca.height - gutterBottom,
2096
+ 'l',gutterLeft + offsetx,ca.height - gutterBottom - offsety,
2097
+ 'l',ca.width - gutterRight + offsetx,ca.height - gutterBottom - offsety,
2098
+ 'l',ca.width - gutterRight,ca.height - gutterBottom,
2099
+ 'c','s','#aaa','f','#ddd'
2100
+ ]);
2101
+ }
2102
+ }
2103
+ };
2104
+
2105
+
2106
+
2107
+
2108
+ /**
2109
+ * Draws the3D Y axis/background
2110
+ *
2111
+ * @param object obj The chart object
2112
+ */
2113
+ RG.draw3DYAxis = function (obj)
2114
+ {
2115
+ var prop = obj.properties,
2116
+ co = obj.context,
2117
+ ca = obj.canvas;
2118
+
2119
+ var gutterLeft = obj.gutterLeft,
2120
+ gutterRight = obj.gutterRight,
2121
+ gutterTop = obj.gutterTop,
2122
+ gutterBottom = obj.gutterBottom,
2123
+ xaxispos = prop['chart.xaxispos'],
2124
+ graphArea = ca.height - gutterTop - gutterBottom,
2125
+ halfGraphArea = graphArea / 2,
2126
+ offsetx = prop['chart.variant.threed.offsetx'],
2127
+ offsety = prop['chart.variant.threed.offsety']
2128
+
2129
+
2130
+
2131
+ // Y axis
2132
+ // Commented out the if condition because of drawing oddities
2133
+ //if (!prop['chart.noaxes'] && !prop['chart.noyaxis']) {
2134
+
2135
+ if (obj.type === 'hbar' && prop['chart.yaxispos'] === 'center') {
2136
+ var x = ((ca.width - gutterLeft - gutterRight) / 2) + gutterLeft;
2137
+ } else if (obj.type === 'hbar' && prop['chart.yaxispos'] === 'right') {
2138
+ var x = ca.width - gutterRight;
2139
+ } else {
2140
+ var x = gutterLeft;
2141
+ }
1996
2142
 
1997
- 'l',ca.width - gutterRight + offsetx,gutterTop + halfGraphArea - offsety,
1998
- 'l',ca.width - gutterRight,gutterTop + halfGraphArea,
1999
- 'c','s','#aaa','f','#ddd'
2000
- ]);
2001
- } else {
2002
2143
  RG.path(co, [
2003
- 'm',gutterLeft,ca.height - gutterBottom,
2004
- 'l',gutterLeft + offsetx,ca.height - gutterBottom - offsety,
2005
- 'l',ca.width - gutterRight + offsetx,ca.height - gutterBottom - offsety,
2006
- 'l',ca.width - gutterRight,ca.height - gutterBottom,
2007
- 'c','s','#aaa','f','#ddd'
2144
+ 'b',
2145
+ 'm', x,gutterTop,
2146
+ 'l',x + offsetx,gutterTop - offsety,
2147
+ 'l',x + offsetx,ca.height - gutterBottom - offsety,
2148
+ 'l',x,ca.height - gutterBottom,
2149
+ 's','#aaa','f','#ddd'
2008
2150
  ]);
2009
- }
2151
+ //}
2010
2152
  };
2011
2153
 
2012
2154
 
@@ -3844,7 +3986,7 @@
3844
3986
  if (obj.isRGraph && typeof obj.type === 'string') {
3845
3987
  var co = obj.context;
3846
3988
  } else {
3847
- var co = obj;
3989
+ var co = obj,
3848
3990
  obj = obj.canvas.__object__;
3849
3991
  }
3850
3992
 
@@ -4551,50 +4693,31 @@
4551
4693
  *
4552
4694
  * So you can use it like these examples show:
4553
4695
  *
4554
- * 1. RG.pa2(context, 'b r 0 0 50 50 f red');
4555
- * 2. RG.pa2(context, 'b a 50 50 50 0 3.14 false f red');
4556
- * 3. RG.pa2(context, 'b m 5 100 bc 5 0 100 0 100 100 s red');
4557
- * 4. RG.pa2(context, 'b m 5 100 at 50 0 95 100 50 s red');
4558
- * 5. RG.pa2(context, 'sa b r 0 0 50 50 c b r 5 5 590 240 f red rs');
4559
- * 6. RG.pa2(context, 'ld [2,6] ldo 4 b r 5 5 590 240 f red');
4560
- * 7. RG.pa2(context, 'ga 0.25 b r 5 5 590 240 f red');
4696
+ * 1. RG.path2(context, 'b r 0 0 50 50 f red');
4697
+ * 2. RG.path2(context, 'b a 50 50 50 0 3.14 false f red');
4698
+ * 3. RG.path2(context, 'b m 5 100 bc 5 0 100 0 100 100 s red');
4699
+ * 4. RG.path2(context, 'b m 5 100 at 50 0 95 100 50 s red');
4700
+ * 5. RG.path2(context, 'sa b r 0 0 50 50 c b r 5 5 590 240 f red rs');
4701
+ * 6. RG.path2(context, 'ld [2,6] ldo 4 b r 5 5 590 240 f red');
4702
+ * 7. RG.path2(context, 'ga 0.25 b r 5 5 590 240 f red');
4561
4703
  *
4562
4704
  * @param array p The path details
4563
4705
  */
4564
4706
  RG.path2 = function (co, p)
4565
4707
  {
4708
+ // Save this functions arguments
4709
+ var args = arguments;
4710
+
4711
+
4712
+ // If the path was a string - split it then collapse quoted bits together
4566
4713
  if (typeof p === 'string') {
4567
-
4568
- // Clear leading and trailing whitespace
4569
- p = p.trim();
4570
-
4571
-
4572
-
4573
-
4574
- // Allow for % placeholder substitution
4575
- if (p.indexOf('%') !== -1) {
4576
-
4577
- p = p.split(/%/);
4578
-
4579
- for (var i=1; i<p.length; i+=1) {
4580
- p[i] = arguments[i+1].toString() + ' ' + p[i];
4581
- }
4582
-
4583
- p = p.join(' ');
4584
- }
4585
-
4586
-
4587
-
4588
-
4589
- // Split up the path
4590
- p = p.split(/ +/);
4714
+ p = splitstring(p);
4591
4715
  }
4592
4716
 
4593
- // Collapse args that are in single or double quotes
4594
- p = collapseQuoted(p);
4717
+ // Store the last path on the RGraph object
4718
+ RG.path2.last = RG.arrayClone(p);
4595
4719
 
4596
-
4597
- // Go through the path information
4720
+ // Go through the path information.
4598
4721
  for (var i=0,len=p.length; i<len; i+=1) {
4599
4722
 
4600
4723
  switch (p[i]) {
@@ -4630,7 +4753,7 @@
4630
4753
  case 'tf':co.transform(parseFloat(p[i+1]),parseFloat(p[i+2]),parseFloat(p[i+3]),parseFloat(p[i+4]),parseFloat(p[i+5]),parseFloat(p[i+6]));i+=6;break;
4631
4754
  case 'stf':co.setTransform(parseFloat(p[i+1]),parseFloat(p[i+2]),parseFloat(p[i+3]),parseFloat(p[i+4]),parseFloat(p[i+5]),parseFloat(p[i+6]));i+=6;break;
4632
4755
  case 'cr':co.clearRect(parseFloat(p[i+1]),parseFloat(p[i+2]),parseFloat(p[i+3]),parseFloat(p[i+4]));i+=4;break;
4633
- case 'ld':var parts = p[i+1].split(/,/);for (var j=0;j<parts.length; j++){parts[j] = parts[j].replace(/^\[/, '');parts[j] = parts[j].replace(/\]$/, '');}co.setLineDash(parts);i+=1;break;
4756
+ case 'ld':var parts = p[i+1];co.setLineDash(parts);i+=1;break;
4634
4757
  case 'ldo':co.lineDashOffset=p[i+1];i++;break;
4635
4758
  case 'fo':co.font=p[i+1];i++;break;
4636
4759
  case 'ft':co.fillText(p[i+1], parseFloat(p[i+2]), parseFloat(p[i+3]));i+=3;break;
@@ -4648,52 +4771,51 @@
4648
4771
  }
4649
4772
  }
4650
4773
 
4651
- //
4652
- // This function looks for quoted args and collapses them
4653
- //
4654
- function collapseQuoted (arr)
4774
+ function splitstring (p)
4655
4775
  {
4656
- var buffer = '', quote, index,out = [],quotes = ['"', "'"];
4776
+ var ret = [], buffer = '', inquote = false, quote = '', substitutionIndex = 2;
4657
4777
 
4658
- for (var j=0; j<quotes.length; j+=1) {
4659
- for (var i=0; i<arr.length; i+=1) {
4778
+ for (var i=0; i<p.length; i+=1) {
4660
4779
 
4661
- // Start and close quotes in the same part
4662
- if (arr[i].match('/^' + quotes[j] + '/') && arr[i].match('/' + quotes[j] + '$/')) {
4663
- arr[i] = arr[i].substr(1, arr[i].length - 2);
4664
- }
4780
+ var chr = p[i],
4781
+ isWS = chr.match(/ /);
4782
+
4783
+ if (isWS) {
4784
+ if (!inquote) {
4665
4785
 
4666
- // Start quoted part
4667
- if (buffer.length === 0 && arr[i].indexOf(quotes[j]) !== -1) {
4668
- buffer = arr[i].substr(arr[i].indexOf(quotes[j]) + 1, arr[i].length);
4669
- quote = quotes[j];
4670
- index = i;
4671
-
4672
- // End quoted part
4673
- } else if (quote && arr[i].indexOf(quote) !== -1) {
4674
-
4675
- buffer = buffer + ' ' + arr[i].substr(0, arr[i].length - 1);
4676
- arr[index] = buffer;
4677
- arr[i] = '';
4678
- quote = '';
4786
+ // Get rid of any enclosing quotes
4787
+ if (buffer[0] === '"' || buffer[0] === "'") {
4788
+ buffer = buffer.substr(1, buffer.length - 2);
4789
+ }
4790
+
4791
+
4792
+ // String substitution
4793
+ if (buffer.trim() === '%' && typeof args[substitutionIndex] !== 'undefined') {
4794
+ buffer = args[substitutionIndex++];
4795
+ }
4796
+
4797
+ ret.push(buffer);
4679
4798
  buffer = '';
4680
-
4681
- // Add to quoted part
4682
- } else if (quote) {
4683
- buffer += ' ' + arr[i];
4684
- arr[i] = '';
4799
+ } else {
4800
+ buffer += chr;
4801
+ }
4802
+ } else {
4803
+ if (chr === "'" || chr === '"') {
4804
+ inquote = !inquote;
4685
4805
  }
4806
+
4807
+ buffer += chr;
4686
4808
  }
4687
4809
  }
4688
4810
 
4689
- // Trim the array down
4690
- for (i=0; i<arr.length; i+=1) {
4691
- if (arr[i].length) {
4692
- out.push(arr[i]);
4693
- }
4811
+ // Do the last bit (including substitution)
4812
+ if (buffer.trim() === '%' && args[substitutionIndex]) {
4813
+ buffer = args[substitutionIndex++];
4694
4814
  }
4695
4815
 
4696
- return out;
4816
+ ret.push(buffer);
4817
+
4818
+ return ret;
4697
4819
  }
4698
4820
  };
4699
4821