fabric-rails 0.0.8 → 0.9.16

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.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 1.0.11 (19 February 2013)
2
+
3
+ - fabric.js version 1.0.11
4
+
5
+ ## 1.0.10 (18 February 2013)
6
+
7
+ - fabric.js version 1.0.10
8
+
1
9
  ## 0.0.8 (19 September 2012)
2
10
 
3
11
  - fabric.js version 0.9.8
data/Gemfile.lock CHANGED
@@ -1,59 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fabric-rails (0.0.7)
5
- railties (>= 3.2.0, < 5.0)
6
- thor (~> 0.14)
4
+ fabric-rails (1.0.10)
7
5
 
8
6
  GEM
9
7
  remote: http://rubygems.org/
10
8
  specs:
11
- actionpack (3.2.1)
12
- activemodel (= 3.2.1)
13
- activesupport (= 3.2.1)
14
- builder (~> 3.0.0)
15
- erubis (~> 2.7.0)
16
- journey (~> 1.0.1)
17
- rack (~> 1.4.0)
18
- rack-cache (~> 1.1)
19
- rack-test (~> 0.6.1)
20
- sprockets (~> 2.1.2)
21
- activemodel (3.2.1)
22
- activesupport (= 3.2.1)
23
- builder (~> 3.0.0)
24
- activesupport (3.2.1)
25
- i18n (~> 0.6)
26
- multi_json (~> 1.0)
27
- builder (3.0.0)
28
- erubis (2.7.0)
29
- hike (1.2.1)
30
- i18n (0.6.0)
31
- journey (1.0.3)
32
- json (1.6.5)
33
- multi_json (1.1.0)
34
- rack (1.4.1)
35
- rack-cache (1.2)
36
- rack (>= 0.4)
37
- rack-ssl (1.3.2)
38
- rack
39
- rack-test (0.6.1)
40
- rack (>= 1.0)
41
- railties (3.2.1)
42
- actionpack (= 3.2.1)
43
- activesupport (= 3.2.1)
44
- rack-ssl (~> 1.3.2)
45
- rake (>= 0.8.7)
46
- rdoc (~> 3.4)
47
- thor (~> 0.14.6)
48
- rake (0.9.2.2)
49
- rdoc (3.12)
50
- json (~> 1.4)
51
- sprockets (2.1.2)
52
- hike (~> 1.2)
53
- rack (~> 1.0)
54
- tilt (~> 1.1, != 1.3.0)
55
- thor (0.14.6)
56
- tilt (1.3.3)
57
9
 
58
10
  PLATFORMS
59
11
  ruby
data/fabric-rails.gemspec CHANGED
@@ -14,8 +14,8 @@ Gem::Specification.new do |s|
14
14
  s.required_rubygems_version = ">= 1.3.6"
15
15
  s.rubyforge_project = "fabric-rails"
16
16
 
17
- s.add_dependency "railties", ">= 3.2.0", "< 5.0"
18
- s.add_dependency "thor", "~> 0.14"
17
+ # s.add_dependency "railties", ">= 3.2.0", "< 5.0"
18
+ # s.add_dependency "thor", "~> 0.14"
19
19
 
20
20
  s.files = `git ls-files`.split("\n")
21
21
  s.executables = []
@@ -1,6 +1,6 @@
1
1
  module Fabric
2
2
  module Rails
3
- VERSION = "0.0.8"
4
- FABRIC_VERSION = "0.9.8"
3
+ VERSION = "0.9.16"
4
+ FABRIC_VERSION = "0.9.16"
5
5
  end
6
6
  end
@@ -1,7 +1,7 @@
1
1
  /* build: `node build.js modules=ALL` */
2
2
  /*! Fabric.js Copyright 2008-2012, Printio (Juriy Zaytsev, Maxim Chernyak) */
3
3
 
4
- var fabric = fabric || { version: "0.9.8" };
4
+ var fabric = fabric || { version: "0.9.16" };
5
5
 
6
6
  if (typeof exports != 'undefined') {
7
7
  exports.fabric = fabric;
@@ -1784,7 +1784,12 @@ fabric.Observable = {
1784
1784
  this.__eventListeners = { };
1785
1785
  }
1786
1786
  if (this.__eventListeners[eventName]) {
1787
- fabric.util.removeFromArray(this.__eventListeners[eventName], handler);
1787
+ if (handler) {
1788
+ fabric.util.removeFromArray(this.__eventListeners[eventName], handler);
1789
+ }
1790
+ else {
1791
+ this.__eventListeners[eventName].length = 0;
1792
+ }
1788
1793
  }
1789
1794
  },
1790
1795
 
@@ -1796,7 +1801,7 @@ fabric.Observable = {
1796
1801
  */
1797
1802
  fire: function(eventName, options) {
1798
1803
  if (!this.__eventListeners) {
1799
- this.__eventListeners = { }
1804
+ this.__eventListeners = { };
1800
1805
  }
1801
1806
  var listenersForEvent = this.__eventListeners[eventName];
1802
1807
  if (!listenersForEvent) return;
@@ -1842,7 +1847,7 @@ fabric.Observable.off = fabric.Observable.stopObserving;
1842
1847
  array.splice(idx, 1);
1843
1848
  }
1844
1849
  return array;
1845
- };
1850
+ }
1846
1851
 
1847
1852
  /**
1848
1853
  * Returns random number between 2 specified ones.
@@ -1914,19 +1919,19 @@ fabric.Observable.off = fabric.Observable.stopObserving;
1914
1919
 
1915
1920
  var start = +new Date(),
1916
1921
  duration = options.duration || 500,
1917
- finish = start + duration, time, pos,
1922
+ finish = start + duration, time,
1918
1923
  onChange = options.onChange || function() { },
1919
1924
  abort = options.abort || function() { return false; },
1920
1925
  easing = options.easing || function(t, b, c, d) {return -c * Math.cos(t/d * (Math.PI/2)) + c + b;},
1921
1926
  startValue = 'startValue' in options ? options.startValue : 0,
1922
- endValue = 'endValue' in options ? options.endValue : 100;
1927
+ endValue = 'endValue' in options ? options.endValue : 100,
1923
1928
  byValue = options.byValue || endValue - startValue;
1924
1929
 
1925
1930
  options.onStart && options.onStart();
1926
1931
 
1927
1932
  (function tick() {
1928
1933
  time = +new Date();
1929
- currentTime = time > finish ? duration : (time - start);
1934
+ var currentTime = time > finish ? duration : (time - start);
1930
1935
  onChange(easing(currentTime, startValue, byValue, duration));
1931
1936
  if (time > finish || abort()) {
1932
1937
  options.onComplete && options.onComplete();
@@ -1941,7 +1946,7 @@ fabric.Observable.off = fabric.Observable.stopObserving;
1941
1946
  fabric.window.mozRequestAnimationFrame ||
1942
1947
  fabric.window.oRequestAnimationFrame ||
1943
1948
  fabric.window.msRequestAnimationFrame ||
1944
- function(callback, element) {
1949
+ function(callback) {
1945
1950
  fabric.window.setTimeout(callback, 1000 / 60);
1946
1951
  };
1947
1952
  /**
@@ -2014,6 +2019,15 @@ fabric.Observable.off = fabric.Observable.stopObserving;
2014
2019
  });
2015
2020
  }
2016
2021
 
2022
+ /**
2023
+ * Groups SVG elements (usually those retrieved from SVG document)
2024
+ * @static
2025
+ * @memberOf fabric.util
2026
+ * @method groupSVGElements
2027
+ * @param {Array} elements
2028
+ * @param {Object} options optional
2029
+ * @return {String} path optional
2030
+ */
2017
2031
  function groupSVGElements(elements, options, path) {
2018
2032
  var object = elements.length > 1
2019
2033
  ? new fabric.PathGroup(elements, options)
@@ -2037,9 +2051,9 @@ fabric.Observable.off = fabric.Observable.stopObserving;
2037
2051
  fabric.util.groupSVGElements = groupSVGElements;
2038
2052
  })();
2039
2053
  (function() {
2040
-
2054
+
2041
2055
  var slice = Array.prototype.slice;
2042
-
2056
+
2043
2057
  if (!Array.prototype.indexOf) {
2044
2058
  Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
2045
2059
  if (this === void 0 || this === null) {
@@ -2069,7 +2083,7 @@ fabric.Observable.off = fabric.Observable.stopObserving;
2069
2083
  }
2070
2084
  }
2071
2085
  return -1;
2072
- }
2086
+ };
2073
2087
  }
2074
2088
 
2075
2089
  if (!Array.prototype.forEach) {
@@ -2077,7 +2091,7 @@ fabric.Observable.off = fabric.Observable.stopObserving;
2077
2091
  for (var i = 0, len = this.length >>> 0; i < len; i++) {
2078
2092
  if (i in this) {
2079
2093
  fn.call(context, this[i], i, this);
2080
- }
2094
+ }
2081
2095
  }
2082
2096
  };
2083
2097
  }
@@ -2186,8 +2200,8 @@ fabric.Observable.off = fabric.Observable.stopObserving;
2186
2200
  */
2187
2201
  function max(array, byProperty) {
2188
2202
  if (!array || array.length === 0) return undefined;
2189
-
2190
- var i = array.length - 1,
2203
+
2204
+ var i = array.length - 1,
2191
2205
  result = byProperty ? array[i][byProperty] : array[i];
2192
2206
  if (byProperty) {
2193
2207
  while (i--) {
@@ -2215,8 +2229,8 @@ fabric.Observable.off = fabric.Observable.stopObserving;
2215
2229
  */
2216
2230
  function min(array, byProperty) {
2217
2231
  if (!array || array.length === 0) return undefined;
2218
-
2219
- var i = array.length - 1,
2232
+
2233
+ var i = array.length - 1,
2220
2234
  result = byProperty ? array[i][byProperty] : array[i];
2221
2235
 
2222
2236
  if (byProperty) {
@@ -2242,7 +2256,7 @@ fabric.Observable.off = fabric.Observable.stopObserving;
2242
2256
  min: min,
2243
2257
  max: max
2244
2258
  };
2245
-
2259
+
2246
2260
  })();
2247
2261
  (function(){
2248
2262
 
@@ -2333,11 +2347,11 @@ fabric.util.string = {
2333
2347
  }());
2334
2348
 
2335
2349
  (function() {
2336
-
2350
+
2337
2351
  var slice = Array.prototype.slice,
2338
2352
  apply = Function.prototype.apply,
2339
- dummy = function() { };
2340
-
2353
+ Dummy = function() { };
2354
+
2341
2355
  if (!Function.prototype.bind) {
2342
2356
  /**
2343
2357
  * Cross-browser approximation of ES5 Function.prototype.bind (not fully spec conforming)
@@ -2349,22 +2363,22 @@ fabric.util.string = {
2349
2363
  Function.prototype.bind = function(thisArg) {
2350
2364
  var fn = this, args = slice.call(arguments, 1), bound;
2351
2365
  if (args.length) {
2352
- bound = function() {
2353
- return apply.call(fn, this instanceof dummy ? this : thisArg, args.concat(slice.call(arguments)));
2366
+ bound = function() {
2367
+ return apply.call(fn, this instanceof Dummy ? this : thisArg, args.concat(slice.call(arguments)));
2354
2368
  };
2355
2369
  }
2356
2370
  else {
2357
- bound = function() {
2358
- return apply.call(fn, this instanceof dummy ? this : thisArg, arguments);
2371
+ bound = function() {
2372
+ return apply.call(fn, this instanceof Dummy ? this : thisArg, arguments);
2359
2373
  };
2360
2374
  }
2361
- dummy.prototype = this.prototype;
2362
- bound.prototype = new dummy;
2363
-
2375
+ Dummy.prototype = this.prototype;
2376
+ bound.prototype = new Dummy();
2377
+
2364
2378
  return bound;
2365
2379
  };
2366
2380
  }
2367
-
2381
+
2368
2382
  })();
2369
2383
  (function() {
2370
2384
 
@@ -2381,7 +2395,7 @@ fabric.util.string = {
2381
2395
  var addMethods = function(klass, source, parent) {
2382
2396
  for (var property in source) {
2383
2397
 
2384
- if (property in klass.prototype && typeof klass.prototype[property] == 'function') {
2398
+ if (property in klass.prototype && typeof klass.prototype[property] === 'function') {
2385
2399
 
2386
2400
  klass.prototype[property] = (function(property) {
2387
2401
  return function() {
@@ -2394,7 +2408,7 @@ fabric.util.string = {
2394
2408
  if (property !== 'initialize') {
2395
2409
  return returnValue;
2396
2410
  }
2397
- }
2411
+ };
2398
2412
  })(property);
2399
2413
  }
2400
2414
  else {
@@ -2412,7 +2426,7 @@ fabric.util.string = {
2412
2426
  }
2413
2427
  };
2414
2428
 
2415
- function subclass() { };
2429
+ function Subclass() { }
2416
2430
 
2417
2431
  /**
2418
2432
  * Helper for creation of "classes"
@@ -2434,8 +2448,8 @@ fabric.util.string = {
2434
2448
  klass.subclasses = [ ];
2435
2449
 
2436
2450
  if (parent) {
2437
- subclass.prototype = parent.prototype;
2438
- klass.prototype = new subclass;
2451
+ Subclass.prototype = parent.prototype;
2452
+ klass.prototype = new Subclass();
2439
2453
  parent.subclasses.push(klass);
2440
2454
  }
2441
2455
  for (var i = 0, length = properties.length; i < length; i++) {
@@ -2450,7 +2464,7 @@ fabric.util.string = {
2450
2464
 
2451
2465
  fabric.util.createClass = createClass;
2452
2466
  })();
2453
- (function (global) {
2467
+ (function () {
2454
2468
 
2455
2469
  /* EVENT HANDLING */
2456
2470
 
@@ -2635,26 +2649,26 @@ fabric.util.string = {
2635
2649
  return { x: pointerX(event), y: pointerY(event) };
2636
2650
  }
2637
2651
 
2638
- function pointerX(event) {
2652
+ var pointerX = function(event) {
2639
2653
  var docElement = fabric.document.documentElement,
2640
2654
  body = fabric.document.body || { scrollLeft: 0 };
2641
2655
 
2642
2656
  // looks like in IE (<9) clientX at certain point (apparently when mouseup fires on VML element)
2643
2657
  // is represented as COM object, with all the consequences, like "unknown" type and error on [[Get]]
2644
2658
  // need to investigate later
2645
- return event.pageX || ((typeof event.clientX != 'unknown' ? event.clientX : 0) +
2659
+ return event.pageX || ((typeof event.clientX !== 'unknown' ? event.clientX : 0) +
2646
2660
  (docElement.scrollLeft || body.scrollLeft) -
2647
2661
  (docElement.clientLeft || 0));
2648
- }
2662
+ };
2649
2663
 
2650
- function pointerY(event) {
2664
+ var pointerY = function(event) {
2651
2665
  var docElement = fabric.document.documentElement,
2652
2666
  body = fabric.document.body || { scrollTop: 0 };
2653
2667
 
2654
- return event.pageY || ((typeof event.clientY != 'unknown' ? event.clientY : 0) +
2668
+ return event.pageY || ((typeof event.clientY !== 'unknown' ? event.clientY : 0) +
2655
2669
  (docElement.scrollTop || body.scrollTop) -
2656
2670
  (docElement.clientTop || 0));
2657
- }
2671
+ };
2658
2672
 
2659
2673
  if (fabric.isTouchSupported) {
2660
2674
  pointerX = function(event) {
@@ -2669,7 +2683,7 @@ fabric.util.string = {
2669
2683
 
2670
2684
  fabric.util.object.extend(fabric.util, fabric.Observable);
2671
2685
 
2672
- })(this);
2686
+ })();
2673
2687
  (function () {
2674
2688
 
2675
2689
  /**
@@ -2681,7 +2695,7 @@ fabric.util.string = {
2681
2695
  * @return {HTMLElement} Element that was passed as a first argument
2682
2696
  */
2683
2697
  function setStyle(element, styles) {
2684
- var elementStyle = element.style, match;
2698
+ var elementStyle = element.style;
2685
2699
  if (!elementStyle) {
2686
2700
  return element;
2687
2701
  }
@@ -2708,8 +2722,6 @@ fabric.util.string = {
2708
2722
  var parseEl = fabric.document.createElement('div'),
2709
2723
  supportsOpacity = typeof parseEl.style.opacity === 'string',
2710
2724
  supportsFilters = typeof parseEl.style.filter === 'string',
2711
- view = fabric.document.defaultView,
2712
- supportsGCS = view && typeof view.getComputedStyle !== 'undefined',
2713
2725
  reOpacity = /alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/,
2714
2726
 
2715
2727
  /** @ignore */
@@ -2744,7 +2756,7 @@ fabric.util.string = {
2744
2756
 
2745
2757
  })();
2746
2758
  (function() {
2747
-
2759
+
2748
2760
  var _slice = Array.prototype.slice;
2749
2761
 
2750
2762
  /**
@@ -2765,12 +2777,13 @@ fabric.util.string = {
2765
2777
  * @param {Object} arrayLike
2766
2778
  * @return {Array}
2767
2779
  */
2768
- function toArray(arrayLike) {
2780
+ var toArray = function(arrayLike) {
2769
2781
  return _slice.call(arrayLike, 0);
2770
- }
2782
+ };
2771
2783
 
2784
+ var sliceCanConvertNodelists;
2772
2785
  try {
2773
- var sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array;
2786
+ sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array;
2774
2787
  }
2775
2788
  catch(err) { }
2776
2789
 
@@ -2818,7 +2831,7 @@ fabric.util.string = {
2818
2831
  function addClass(element, className) {
2819
2832
  if ((' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) {
2820
2833
  element.className += (element.className ? ' ' : '') + className;
2821
- }
2834
+ }
2822
2835
  }
2823
2836
 
2824
2837
  /**
@@ -2856,7 +2869,7 @@ fabric.util.string = {
2856
2869
  valueT += element.offsetTop || 0;
2857
2870
  valueL += element.offsetLeft || 0;
2858
2871
  element = element.offsetParent;
2859
- }
2872
+ }
2860
2873
  while (element);
2861
2874
  return ({ left: valueL, top: valueT });
2862
2875
  }
@@ -2866,12 +2879,12 @@ fabric.util.string = {
2866
2879
 
2867
2880
  var selectProp = 'userSelect' in style
2868
2881
  ? 'userSelect'
2869
- : 'MozUserSelect' in style
2870
- ? 'MozUserSelect'
2871
- : 'WebkitUserSelect' in style
2872
- ? 'WebkitUserSelect'
2873
- : 'KhtmlUserSelect' in style
2874
- ? 'KhtmlUserSelect'
2882
+ : 'MozUserSelect' in style
2883
+ ? 'MozUserSelect'
2884
+ : 'WebkitUserSelect' in style
2885
+ ? 'WebkitUserSelect'
2886
+ : 'KhtmlUserSelect' in style
2887
+ ? 'KhtmlUserSelect'
2875
2888
  : '';
2876
2889
 
2877
2890
  /**
@@ -2888,7 +2901,7 @@ fabric.util.string = {
2888
2901
  if (selectProp) {
2889
2902
  element.style[selectProp] = 'none';
2890
2903
  }
2891
- else if (typeof element.unselectable == 'string') {
2904
+ else if (typeof element.unselectable === 'string') {
2892
2905
  element.unselectable = 'on';
2893
2906
  }
2894
2907
  return element;
@@ -2908,7 +2921,7 @@ fabric.util.string = {
2908
2921
  if (selectProp) {
2909
2922
  element.style[selectProp] = '';
2910
2923
  }
2911
- else if (typeof element.unselectable == 'string') {
2924
+ else if (typeof element.unselectable === 'string') {
2912
2925
  element.unselectable = '';
2913
2926
  }
2914
2927
  return element;
@@ -2928,28 +2941,28 @@ fabric.util.string = {
2928
2941
  * @param {Function} callback Callback to execute when script is finished loading
2929
2942
  */
2930
2943
  function getScript(url, callback) {
2931
- var headEl = fabric.document.getElementsByTagName("head")[0],
2932
- scriptEl = fabric.document.createElement('script'),
2933
- loading = true;
2934
-
2935
- scriptEl.type = 'text/javascript';
2936
- scriptEl.setAttribute('runat', 'server');
2937
-
2938
- /** @ignore */
2939
- scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) {
2940
- if (loading) {
2941
- if (typeof this.readyState == 'string' &&
2942
- this.readyState !== 'loaded' &&
2943
- this.readyState !== 'complete') return;
2944
- loading = false;
2945
- callback(e || fabric.window.event);
2946
- scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null;
2947
- }
2948
- };
2949
- scriptEl.src = url;
2950
- headEl.appendChild(scriptEl);
2951
- // causes issue in Opera
2952
- // headEl.removeChild(scriptEl);
2944
+ var headEl = fabric.document.getElementsByTagName("head")[0],
2945
+ scriptEl = fabric.document.createElement('script'),
2946
+ loading = true;
2947
+
2948
+ scriptEl.type = 'text/javascript';
2949
+ scriptEl.setAttribute('runat', 'server');
2950
+
2951
+ /** @ignore */
2952
+ scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) {
2953
+ if (loading) {
2954
+ if (typeof this.readyState === 'string' &&
2955
+ this.readyState !== 'loaded' &&
2956
+ this.readyState !== 'complete') return;
2957
+ loading = false;
2958
+ callback(e || fabric.window.event);
2959
+ scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null;
2960
+ }
2961
+ };
2962
+ scriptEl.src = url;
2963
+ headEl.appendChild(scriptEl);
2964
+ // causes issue in Opera
2965
+ // headEl.removeChild(scriptEl);
2953
2966
  }
2954
2967
 
2955
2968
  fabric.util.getScript = getScript;
@@ -2961,14 +2974,14 @@ fabric.util.string = {
2961
2974
  fabric.util.addClass = addClass;
2962
2975
  fabric.util.wrapElement = wrapElement;
2963
2976
  fabric.util.getElementOffset = getElementOffset;
2964
-
2977
+
2965
2978
  })();
2966
2979
  (function(){
2967
-
2980
+
2968
2981
  function addParamToUrl(url, param) {
2969
2982
  return url + (/\?/.test(url) ? '&' : '?') + param;
2970
2983
  }
2971
-
2984
+
2972
2985
  var makeXHR = (function() {
2973
2986
  var factories = [
2974
2987
  function() { return new ActiveXObject("Microsoft.XMLHTTP"); },
@@ -2987,8 +3000,8 @@ fabric.util.string = {
2987
3000
  }
2988
3001
  })();
2989
3002
 
2990
- function emptyFn() { };
2991
-
3003
+ function emptyFn() { }
3004
+
2992
3005
  /**
2993
3006
  * Cross-browser abstraction for sending XMLHttpRequest
2994
3007
  * @method request
@@ -3005,34 +3018,34 @@ fabric.util.string = {
3005
3018
 
3006
3019
  var method = options.method ? options.method.toUpperCase() : 'GET',
3007
3020
  onComplete = options.onComplete || function() { },
3008
- request = makeXHR(),
3021
+ xhr = makeXHR(),
3009
3022
  body;
3010
-
3023
+
3011
3024
  /** @ignore */
3012
- request.onreadystatechange = function() {
3013
- if (request.readyState === 4) {
3014
- onComplete(request);
3015
- request.onreadystatechange = emptyFn;
3025
+ xhr.onreadystatechange = function() {
3026
+ if (xhr.readyState === 4) {
3027
+ onComplete(xhr);
3028
+ xhr.onreadystatechange = emptyFn;
3016
3029
  }
3017
3030
  };
3018
-
3031
+
3019
3032
  if (method === 'GET') {
3020
3033
  body = null;
3021
- if (typeof options.parameters == 'string') {
3034
+ if (typeof options.parameters === 'string') {
3022
3035
  url = addParamToUrl(url, options.parameters);
3023
3036
  }
3024
3037
  }
3025
3038
 
3026
- request.open(method, url, true);
3027
-
3039
+ xhr.open(method, url, true);
3040
+
3028
3041
  if (method === 'POST' || method === 'PUT') {
3029
- request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
3042
+ xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
3030
3043
  }
3031
3044
 
3032
- request.send(body);
3033
- return request;
3034
- };
3035
-
3045
+ xhr.send(body);
3046
+ return xhr;
3047
+ }
3048
+
3036
3049
  fabric.util.request = request;
3037
3050
  })();
3038
3051
  (function() {
@@ -3058,7 +3071,8 @@ fabric.util.string = {
3058
3071
  * @memberOf fabric.util.ease
3059
3072
  */
3060
3073
  function easeInOutQuad(t, b, c, d) {
3061
- if ((t/=d/2) < 1) return c/2*t*t + b;
3074
+ t /= (d/2);
3075
+ if (t < 1) return c/2*t*t + b;
3062
3076
  return -c/2 * ((--t)*(t-2) - 1) + b;
3063
3077
  }
3064
3078
 
@@ -3083,7 +3097,8 @@ fabric.util.string = {
3083
3097
  * @memberOf fabric.util.ease
3084
3098
  */
3085
3099
  function easeInOutCubic(t, b, c, d) {
3086
- if ((t/=d/2) < 1) return c/2*t*t*t + b;
3100
+ t /= d/2;
3101
+ if (t < 1) return c/2*t*t*t + b;
3087
3102
  return c/2*((t-=2)*t*t + 2) + b;
3088
3103
  }
3089
3104
 
@@ -3108,7 +3123,8 @@ fabric.util.string = {
3108
3123
  * @memberOf fabric.util.ease
3109
3124
  */
3110
3125
  function easeInOutQuart(t, b, c, d) {
3111
- if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
3126
+ t /= d/2;
3127
+ if (t < 1) return c/2*t*t*t*t + b;
3112
3128
  return -c/2 * ((t-=2)*t*t*t - 2) + b;
3113
3129
  }
3114
3130
 
@@ -3133,7 +3149,8 @@ fabric.util.string = {
3133
3149
  * @memberOf fabric.util.ease
3134
3150
  */
3135
3151
  function easeInOutQuint(t, b, c, d) {
3136
- if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
3152
+ t /= d/2;
3153
+ if (t < 1) return c/2*t*t*t*t*t + b;
3137
3154
  return c/2*((t-=2)*t*t*t*t + 2) + b;
3138
3155
  }
3139
3156
 
@@ -3166,7 +3183,7 @@ fabric.util.string = {
3166
3183
  * @memberOf fabric.util.ease
3167
3184
  */
3168
3185
  function easeInExpo(t, b, c, d) {
3169
- return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
3186
+ return (t===0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
3170
3187
  }
3171
3188
 
3172
3189
  /**
@@ -3174,7 +3191,7 @@ fabric.util.string = {
3174
3191
  * @memberOf fabric.util.ease
3175
3192
  */
3176
3193
  function easeOutExpo(t, b, c, d) {
3177
- return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
3194
+ return (t===d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
3178
3195
  }
3179
3196
 
3180
3197
  /**
@@ -3182,9 +3199,10 @@ fabric.util.string = {
3182
3199
  * @memberOf fabric.util.ease
3183
3200
  */
3184
3201
  function easeInOutExpo(t, b, c, d) {
3185
- if (t==0) return b;
3186
- if (t==d) return b+c;
3187
- if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
3202
+ if (t===0) return b;
3203
+ if (t===d) return b+c;
3204
+ t /= d/2;
3205
+ if (t < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
3188
3206
  return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
3189
3207
  }
3190
3208
 
@@ -3209,7 +3227,8 @@ fabric.util.string = {
3209
3227
  * @memberOf fabric.util.ease
3210
3228
  */
3211
3229
  function easeInOutCirc(t, b, c, d) {
3212
- if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
3230
+ t /= d/2;
3231
+ if (t < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
3213
3232
  return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
3214
3233
  }
3215
3234
 
@@ -3219,9 +3238,12 @@ fabric.util.string = {
3219
3238
  */
3220
3239
  function easeInElastic(t, b, c, d) {
3221
3240
  var s=1.70158;var p=0;var a=c;
3222
- if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
3223
- if (a < Math.abs(c)) { a=c; var s=p/4; }
3224
- else var s = p/(2*Math.PI) * Math.asin (c/a);
3241
+ if (t===0) return b;
3242
+ t /= d;
3243
+ if (t===1) return b+c;
3244
+ if (!p) p=d*0.3;
3245
+ if (a < Math.abs(c)) { a=c; s=p/4; }
3246
+ else s = p/(2*Math.PI) * Math.asin (c/a);
3225
3247
  return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
3226
3248
  }
3227
3249
 
@@ -3231,9 +3253,12 @@ fabric.util.string = {
3231
3253
  */
3232
3254
  function easeOutElastic(t, b, c, d) {
3233
3255
  var s=1.70158;var p=0;var a=c;
3234
- if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
3235
- if (a < Math.abs(c)) { a=c; var s=p/4; }
3236
- else var s = p/(2*Math.PI) * Math.asin (c/a);
3256
+ if (t===0) return b;
3257
+ t /= d;
3258
+ if (t===1) return b+c;
3259
+ if (!p) p=d*0.3;
3260
+ if (a < Math.abs(c)) { a=c; s=p/4; }
3261
+ else s = p/(2*Math.PI) * Math.asin (c/a);
3237
3262
  return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
3238
3263
  }
3239
3264
 
@@ -3243,11 +3268,14 @@ fabric.util.string = {
3243
3268
  */
3244
3269
  function easeInOutElastic(t, b, c, d) {
3245
3270
  var s=1.70158;var p=0;var a=c;
3246
- if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
3247
- if (a < Math.abs(c)) { a=c; var s=p/4; }
3248
- else var s = p/(2*Math.PI) * Math.asin (c/a);
3249
- if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
3250
- return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
3271
+ if (t===0) return b;
3272
+ t /= d/2;
3273
+ if (t===2) return b+c;
3274
+ if (!p) p=d*(0.3*1.5);
3275
+ if (a < Math.abs(c)) { a=c; s=p/4; }
3276
+ else s = p/(2*Math.PI) * Math.asin (c/a);
3277
+ if (t < 1) return -0.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
3278
+ return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b;
3251
3279
  }
3252
3280
 
3253
3281
  /**
@@ -3255,7 +3283,7 @@ fabric.util.string = {
3255
3283
  * @memberOf fabric.util.ease
3256
3284
  */
3257
3285
  function easeInBack(t, b, c, d, s) {
3258
- if (s == undefined) s = 1.70158;
3286
+ if (s === undefined) s = 1.70158;
3259
3287
  return c*(t/=d)*t*((s+1)*t - s) + b;
3260
3288
  }
3261
3289
 
@@ -3264,7 +3292,7 @@ fabric.util.string = {
3264
3292
  * @memberOf fabric.util.ease
3265
3293
  */
3266
3294
  function easeOutBack(t, b, c, d, s) {
3267
- if (s == undefined) s = 1.70158;
3295
+ if (s === undefined) s = 1.70158;
3268
3296
  return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
3269
3297
  }
3270
3298
 
@@ -3273,8 +3301,9 @@ fabric.util.string = {
3273
3301
  * @memberOf fabric.util.ease
3274
3302
  */
3275
3303
  function easeInOutBack(t, b, c, d, s) {
3276
- if (s == undefined) s = 1.70158;
3277
- if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
3304
+ if (s === undefined) s = 1.70158;
3305
+ t /= d/2;
3306
+ if (t < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
3278
3307
  return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
3279
3308
  }
3280
3309
 
@@ -3294,11 +3323,11 @@ fabric.util.string = {
3294
3323
  if ((t/=d) < (1/2.75)) {
3295
3324
  return c*(7.5625*t*t) + b;
3296
3325
  } else if (t < (2/2.75)) {
3297
- return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
3326
+ return c*(7.5625*(t-=(1.5/2.75))*t + 0.75) + b;
3298
3327
  } else if (t < (2.5/2.75)) {
3299
- return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
3328
+ return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b;
3300
3329
  } else {
3301
- return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
3330
+ return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b;
3302
3331
  }
3303
3332
  }
3304
3333
 
@@ -3307,8 +3336,8 @@ fabric.util.string = {
3307
3336
  * @memberOf fabric.util.ease
3308
3337
  */
3309
3338
  function easeInOutBounce(t, b, c, d) {
3310
- if (t < d/2) return easeInBounce (t*2, 0, c, d) * .5 + b;
3311
- return easeOutBounce (t*2-d, 0, c, d) * .5 + c*.5 + b;
3339
+ if (t < d/2) return easeInBounce (t*2, 0, c, d) * 0.5 + b;
3340
+ return easeOutBounce (t*2-d, 0, c, d) * 0.5 + c*0.5 + b;
3312
3341
  }
3313
3342
 
3314
3343
  /** @namespace fabric.util.ease */
@@ -3435,7 +3464,7 @@ fabric.util.string = {
3435
3464
 
3436
3465
  ownAttributes = extend(ownAttributes, extend(getGlobalStylesForElement(element), fabric.parseStyleAttribute(element)));
3437
3466
  return extend(parentAttributes, ownAttributes);
3438
- };
3467
+ }
3439
3468
 
3440
3469
  /**
3441
3470
  * Parses "transform" attribute, returning an array of values
@@ -3566,9 +3595,9 @@ fabric.util.string = {
3566
3595
  matrix = args;
3567
3596
  break;
3568
3597
  }
3569
- })
3598
+ });
3570
3599
  return matrix;
3571
- }
3600
+ };
3572
3601
  })();
3573
3602
 
3574
3603
  /**
@@ -3588,17 +3617,21 @@ fabric.util.string = {
3588
3617
  var asPairs = points.indexOf(',') > -1;
3589
3618
 
3590
3619
  points = points.split(/\s+/);
3591
- var parsedPoints = [ ];
3620
+ var parsedPoints = [ ], i, len;
3592
3621
 
3593
3622
  // points could look like "10,20 30,40" or "10 20 30 40"
3594
3623
  if (asPairs) {
3595
- for (var i = 0, len = points.length; i < len; i++) {
3596
- var pair = points[i].split(',');
3597
- parsedPoints.push({ x: parseFloat(pair[0]), y: parseFloat(pair[1]) });
3598
- }
3624
+ i = 0;
3625
+ len = points.length;
3626
+ for (; i < len; i++) {
3627
+ var pair = points[i].split(',');
3628
+ parsedPoints.push({ x: parseFloat(pair[0]), y: parseFloat(pair[1]) });
3629
+ }
3599
3630
  }
3600
3631
  else {
3601
- for (var i = 0, len = points.length; i < len; i+=2) {
3632
+ i = 0;
3633
+ len = points.length;
3634
+ for (; i < len; i+=2) {
3602
3635
  parsedPoints.push({ x: parseFloat(points[i]), y: parseFloat(points[i+1]) });
3603
3636
  }
3604
3637
  }
@@ -3609,7 +3642,7 @@ fabric.util.string = {
3609
3642
  }
3610
3643
 
3611
3644
  return parsedPoints;
3612
- };
3645
+ }
3613
3646
 
3614
3647
  /**
3615
3648
  * Parses "style" attribute, retuning an object with values
@@ -3622,22 +3655,24 @@ fabric.util.string = {
3622
3655
  function parseStyleAttribute(element) {
3623
3656
  var oStyle = { },
3624
3657
  style = element.getAttribute('style');
3625
- if (style) {
3626
- if (typeof style == 'string') {
3627
- style = style.replace(/;$/, '').split(';').forEach(function (current) {
3628
- var attr = current.split(':');
3629
- oStyle[normalizeAttr(attr[0].trim().toLowerCase())] = attr[1].trim();
3630
- });
3631
- } else {
3632
- for (var prop in style) {
3633
- if (typeof style[prop] !== 'undefined') {
3634
- oStyle[normalizeAttr(prop.toLowerCase())] = style[prop];
3635
- }
3636
- }
3658
+
3659
+ if (!style) return oStyle;
3660
+
3661
+ if (typeof style === 'string') {
3662
+ style = style.replace(/;$/, '').split(';').forEach(function (current) {
3663
+ var attr = current.split(':');
3664
+ oStyle[normalizeAttr(attr[0].trim().toLowerCase())] = attr[1].trim();
3665
+ });
3666
+ }
3667
+ else {
3668
+ for (var prop in style) {
3669
+ if (typeof style[prop] === 'undefined') continue;
3670
+ oStyle[normalizeAttr(prop.toLowerCase())] = style[prop];
3637
3671
  }
3638
3672
  }
3673
+
3639
3674
  return oStyle;
3640
- };
3675
+ }
3641
3676
 
3642
3677
  function resolveGradients(instances) {
3643
3678
  for (var i = instances.length; i--; ) {
@@ -3666,7 +3701,7 @@ fabric.util.string = {
3666
3701
  * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.
3667
3702
  */
3668
3703
  function parseElements(elements, callback, options, reviver) {
3669
- var instances = Array(elements.length), i = elements.length;
3704
+ var instances = new Array(elements.length), i = elements.length;
3670
3705
 
3671
3706
  function checkIfDone() {
3672
3707
  if (--i === 0) {
@@ -3707,7 +3742,7 @@ fabric.util.string = {
3707
3742
  checkIfDone();
3708
3743
  }
3709
3744
  }
3710
- };
3745
+ }
3711
3746
 
3712
3747
  /**
3713
3748
  * Returns CSS rules for a given SVG document
@@ -3731,12 +3766,12 @@ fabric.util.string = {
3731
3766
  styleContents = styleContents.replace(/\/\*[\s\S]*?\*\//g, '');
3732
3767
 
3733
3768
  rules = styleContents.match(/[^{]*\{[\s\S]*?\}/g);
3734
- rules = rules.map(function(rule) { return rule.trim() });
3769
+ rules = rules.map(function(rule) { return rule.trim(); });
3735
3770
 
3736
3771
  rules.forEach(function(rule) {
3737
- var match = rule.match(/([\s\S]*?)\s*\{([^}]*)\}/),
3738
- rule = match[1],
3739
- declaration = match[2].trim(),
3772
+ var match = rule.match(/([\s\S]*?)\s*\{([^}]*)\}/);
3773
+ rule = match[1];
3774
+ var declaration = match[2].trim(),
3740
3775
  propertyValuePairs = declaration.replace(/;$/, '').split(/\s*;\s*/);
3741
3776
 
3742
3777
  if (!allRules[rule]) {
@@ -3898,7 +3933,7 @@ fabric.util.string = {
3898
3933
  * @param {String} url
3899
3934
  * @param {Function} callback
3900
3935
  */
3901
- get: function (url, callback) {
3936
+ get: function () {
3902
3937
  /* NOOP */
3903
3938
  },
3904
3939
 
@@ -3907,7 +3942,7 @@ fabric.util.string = {
3907
3942
  * @param {String} url
3908
3943
  * @param {Object} object
3909
3944
  */
3910
- set: function (url, object) {
3945
+ set: function () {
3911
3946
  /* NOOP */
3912
3947
  }
3913
3948
  };
@@ -3991,7 +4026,7 @@ fabric.util.string = {
3991
4026
  }
3992
4027
  }
3993
4028
  else if (fabric.window.ActiveXObject) {
3994
- var doc = new ActiveXObject('Microsoft.XMLDOM');
4029
+ doc = new ActiveXObject('Microsoft.XMLDOM');
3995
4030
  doc.async = 'false';
3996
4031
  //IE chokes on DOCTYPE
3997
4032
  doc.loadXML(string.replace(/<!DOCTYPE[\s\S]*?(\[[\s\S]*\])*?>/i,''));
@@ -4045,7 +4080,7 @@ fabric.util.string = {
4045
4080
  createSVGFontFacesMarkup: createSVGFontFacesMarkup
4046
4081
  });
4047
4082
 
4048
- })(typeof exports != 'undefined' ? exports : this);
4083
+ })(typeof exports !== 'undefined' ? exports : this);
4049
4084
 
4050
4085
  (function() {
4051
4086
 
@@ -4140,10 +4175,8 @@ fabric.util.string = {
4140
4175
  */
4141
4176
 
4142
4177
  var colorStopEls = el.getElementsByTagName('stop'),
4143
- el,
4144
4178
  offset,
4145
4179
  colorStops = { },
4146
- colorStopFromStyle,
4147
4180
  coords = {
4148
4181
  x1: el.getAttribute('x1') || 0,
4149
4182
  y1: el.getAttribute('y1') || 0,
@@ -4215,15 +4248,17 @@ fabric.util.string = {
4215
4248
  function getGradientDefs(doc) {
4216
4249
  var linearGradientEls = doc.getElementsByTagName('linearGradient'),
4217
4250
  radialGradientEls = doc.getElementsByTagName('radialGradient'),
4218
- el,
4251
+ el, i,
4219
4252
  gradientDefs = { };
4220
4253
 
4221
- for (var i = linearGradientEls.length; i--; ) {
4254
+ i = linearGradientEls.length;
4255
+ for (; i--; ) {
4222
4256
  el = linearGradientEls[i];
4223
4257
  gradientDefs[el.getAttribute('id')] = el;
4224
4258
  }
4225
4259
 
4226
- for (var i = radialGradientEls.length; i--; ) {
4260
+ i = radialGradientEls.length;
4261
+ for (; i--; ) {
4227
4262
  el = radialGradientEls[i];
4228
4263
  gradientDefs[el.getAttribute('id')] = el;
4229
4264
  }
@@ -4235,20 +4270,20 @@ fabric.util.string = {
4235
4270
 
4236
4271
  })();
4237
4272
  (function(global) {
4238
-
4273
+
4239
4274
  "use strict";
4240
-
4275
+
4241
4276
  /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */
4242
-
4277
+
4243
4278
  var fabric = global.fabric || (global.fabric = { });
4244
4279
 
4245
- if (fabric.Point) {
4280
+ if (fabric.Point) {
4246
4281
  fabric.warn('fabric.Point is already defined');
4247
4282
  return;
4248
4283
  }
4249
4284
 
4250
4285
  fabric.Point = Point;
4251
-
4286
+
4252
4287
  /**
4253
4288
  * @name Point
4254
4289
  * @memberOf fabric
@@ -4262,11 +4297,11 @@ fabric.util.string = {
4262
4297
  this.init(x, y);
4263
4298
  }
4264
4299
  }
4265
-
4300
+
4266
4301
  Point.prototype = /** @scope fabric.Point.prototype */ {
4267
-
4302
+
4268
4303
  constructor: Point,
4269
-
4304
+
4270
4305
  /**
4271
4306
  * @method init
4272
4307
  * @param {Number} x
@@ -4276,7 +4311,7 @@ fabric.util.string = {
4276
4311
  this.x = x;
4277
4312
  this.y = y;
4278
4313
  },
4279
-
4314
+
4280
4315
  /**
4281
4316
  * @method add
4282
4317
  * @param {fabric.Point} that
@@ -4285,7 +4320,7 @@ fabric.util.string = {
4285
4320
  add: function (that) {
4286
4321
  return new Point(this.x + that.x, this.y + that.y);
4287
4322
  },
4288
-
4323
+
4289
4324
  /**
4290
4325
  * @method addEquals
4291
4326
  * @param {fabric.Point} that
@@ -4296,7 +4331,7 @@ fabric.util.string = {
4296
4331
  this.y += that.y;
4297
4332
  return this;
4298
4333
  },
4299
-
4334
+
4300
4335
  /**
4301
4336
  * @method scalarAdd
4302
4337
  * @param {Number} scalar
@@ -4305,7 +4340,7 @@ fabric.util.string = {
4305
4340
  scalarAdd: function (scalar) {
4306
4341
  return new Point(this.x + scalar, this.y + scalar);
4307
4342
  },
4308
-
4343
+
4309
4344
  /**
4310
4345
  * @method scalarAddEquals
4311
4346
  * @param {Number} scalar
@@ -4316,7 +4351,7 @@ fabric.util.string = {
4316
4351
  this.y += scalar;
4317
4352
  return this;
4318
4353
  },
4319
-
4354
+
4320
4355
  /**
4321
4356
  * @method subtract
4322
4357
  * @param {fabric.Point} that
@@ -4325,7 +4360,7 @@ fabric.util.string = {
4325
4360
  subtract: function (that) {
4326
4361
  return new Point(this.x - that.x, this.y - that.y);
4327
4362
  },
4328
-
4363
+
4329
4364
  /**
4330
4365
  * @method subtractEquals
4331
4366
  * @param {fabric.Point} that
@@ -4336,89 +4371,89 @@ fabric.util.string = {
4336
4371
  this.y -= that.y;
4337
4372
  return this;
4338
4373
  },
4339
-
4374
+
4340
4375
  scalarSubtract: function (scalar) {
4341
4376
  return new Point(this.x - scalar, this.y - scalar);
4342
4377
  },
4343
-
4378
+
4344
4379
  scalarSubtractEquals: function (scalar) {
4345
4380
  this.x -= scalar;
4346
4381
  this.y -= scalar;
4347
4382
  return this;
4348
4383
  },
4349
-
4384
+
4350
4385
  multiply: function (scalar) {
4351
4386
  return new Point(this.x * scalar, this.y * scalar);
4352
4387
  },
4353
-
4388
+
4354
4389
  multiplyEquals: function (scalar) {
4355
4390
  this.x *= scalar;
4356
4391
  this.y *= scalar;
4357
4392
  return this;
4358
4393
  },
4359
-
4394
+
4360
4395
  divide: function (scalar) {
4361
4396
  return new Point(this.x / scalar, this.y / scalar);
4362
4397
  },
4363
-
4398
+
4364
4399
  divideEquals: function (scalar) {
4365
4400
  this.x /= scalar;
4366
4401
  this.y /= scalar;
4367
4402
  return this;
4368
4403
  },
4369
-
4404
+
4370
4405
  eq: function (that) {
4371
- return (this.x == that.x && this.y == that.y);
4406
+ return (this.x === that.x && this.y === that.y);
4372
4407
  },
4373
-
4408
+
4374
4409
  lt: function (that) {
4375
4410
  return (this.x < that.x && this.y < that.y);
4376
4411
  },
4377
-
4412
+
4378
4413
  lte: function (that) {
4379
4414
  return (this.x <= that.x && this.y <= that.y);
4380
4415
  },
4381
-
4416
+
4382
4417
  gt: function (that) {
4383
4418
  return (this.x > that.x && this.y > that.y);
4384
4419
  },
4385
-
4420
+
4386
4421
  gte: function (that) {
4387
4422
  return (this.x >= that.x && this.y >= that.y);
4388
4423
  },
4389
-
4424
+
4390
4425
  lerp: function (that, t) {
4391
4426
  return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t);
4392
4427
  },
4393
-
4428
+
4394
4429
  distanceFrom: function (that) {
4395
4430
  var dx = this.x - that.x,
4396
4431
  dy = this.y - that.y;
4397
4432
  return Math.sqrt(dx * dx + dy * dy);
4398
4433
  },
4399
-
4434
+
4400
4435
  min: function (that) {
4401
4436
  return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y));
4402
4437
  },
4403
-
4438
+
4404
4439
  max: function (that) {
4405
4440
  return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y));
4406
4441
  },
4407
-
4442
+
4408
4443
  toString: function () {
4409
4444
  return this.x + "," + this.y;
4410
4445
  },
4411
-
4446
+
4412
4447
  setXY: function (x, y) {
4413
4448
  this.x = x;
4414
4449
  this.y = y;
4415
4450
  },
4416
-
4451
+
4417
4452
  setFromPoint: function (that) {
4418
4453
  this.x = that.x;
4419
4454
  this.y = that.y;
4420
4455
  },
4421
-
4456
+
4422
4457
  swap: function (that) {
4423
4458
  var x = this.x,
4424
4459
  y = this.y;
@@ -4428,8 +4463,8 @@ fabric.util.string = {
4428
4463
  that.y = y;
4429
4464
  }
4430
4465
  };
4431
-
4432
- })(typeof exports != 'undefined' ? exports : this);
4466
+
4467
+ })(typeof exports !== 'undefined' ? exports : this);
4433
4468
  (function(global) {
4434
4469
 
4435
4470
  "use strict";
@@ -4492,7 +4527,7 @@ fabric.util.string = {
4492
4527
  ua_t = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x),
4493
4528
  ub_t = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x),
4494
4529
  u_b = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);
4495
- if (u_b != 0) {
4530
+ if (u_b !== 0) {
4496
4531
  var ua = ua_t / u_b,
4497
4532
  ub = ub_t / u_b;
4498
4533
  if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {
@@ -4504,7 +4539,7 @@ fabric.util.string = {
4504
4539
  }
4505
4540
  }
4506
4541
  else {
4507
- if (ua_t == 0 || ub_t == 0) {
4542
+ if (ua_t === 0 || ub_t === 0) {
4508
4543
  result = new Intersection("Coincident");
4509
4544
  }
4510
4545
  else {
@@ -4578,18 +4613,18 @@ fabric.util.string = {
4578
4613
  return result;
4579
4614
  };
4580
4615
 
4581
- })(typeof exports != 'undefined' ? exports : this);
4616
+ })(typeof exports !== 'undefined' ? exports : this);
4582
4617
  (function(global) {
4583
-
4618
+
4584
4619
  "use strict";
4585
-
4620
+
4586
4621
  var fabric = global.fabric || (global.fabric = { });
4587
-
4622
+
4588
4623
  if (fabric.Color) {
4589
4624
  fabric.warn('fabric.Color is already defined.');
4590
4625
  return;
4591
4626
  }
4592
-
4627
+
4593
4628
  /**
4594
4629
  * The purpose of {@link fabric.Color} is to abstract and encapsulate common color operations;
4595
4630
  * {@link fabric.Color} is a constructor and creates instances of {@link fabric.Color} objects.
@@ -4606,11 +4641,11 @@ fabric.util.string = {
4606
4641
  this._tryParsingColor(color);
4607
4642
  }
4608
4643
  }
4609
-
4644
+
4610
4645
  fabric.Color = Color;
4611
-
4646
+
4612
4647
  fabric.Color.prototype = /** @scope fabric.Color.prototype */ {
4613
-
4648
+
4614
4649
  /**
4615
4650
  * @private
4616
4651
  * @method _tryParsingColor
@@ -4672,19 +4707,19 @@ fabric.util.string = {
4672
4707
  var source = this.getSource();
4673
4708
 
4674
4709
  var r = source[0].toString(16);
4675
- r = (r.length == 1) ? ('0' + r) : r;
4710
+ r = (r.length === 1) ? ('0' + r) : r;
4676
4711
 
4677
4712
  var g = source[1].toString(16);
4678
- g = (g.length == 1) ? ('0' + g) : g;
4713
+ g = (g.length === 1) ? ('0' + g) : g;
4679
4714
 
4680
4715
  var b = source[2].toString(16);
4681
- b = (b.length == 1) ? ('0' + b) : b;
4716
+ b = (b.length === 1) ? ('0' + b) : b;
4682
4717
 
4683
4718
  return r.toUpperCase() + g.toUpperCase() + b.toUpperCase();
4684
4719
  },
4685
4720
 
4686
4721
  /**
4687
- * Gets value of alpha channel for this color
4722
+ * Gets value of alpha channel for this color
4688
4723
  * @method getAlpha
4689
4724
  * @return {Number} 0-1
4690
4725
  */
@@ -4726,8 +4761,9 @@ fabric.util.string = {
4726
4761
  toBlackWhite: function(threshold) {
4727
4762
  var source = this.getSource(),
4728
4763
  average = (source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0),
4729
- currentAlpha = source[3],
4730
- threshold = threshold || 127;
4764
+ currentAlpha = source[3];
4765
+
4766
+ threshold = threshold || 127;
4731
4767
 
4732
4768
  average = (Number(average) < Number(threshold)) ? 0 : 255;
4733
4769
  this.setSource([average, average, average, currentAlpha]);
@@ -4760,14 +4796,14 @@ fabric.util.string = {
4760
4796
  return this;
4761
4797
  }
4762
4798
  };
4763
-
4799
+
4764
4800
  /**
4765
4801
  * Regex matching color in RGB or RGBA formats (ex: rgb(0, 0, 0), rgb(255, 100, 10, 0.5), rgb(1,1,1))
4766
4802
  * @static
4767
4803
  * @field
4768
4804
  */
4769
4805
  fabric.Color.reRGBa = /^rgba?\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*(\d+(?:\.\d+)?))?\)$/;
4770
-
4806
+
4771
4807
  /**
4772
4808
  * Regex matching color in HEX format (ex: #FF5555, 010155, aff)
4773
4809
  * @static
@@ -4784,7 +4820,7 @@ fabric.util.string = {
4784
4820
  fabric.Color.fromRgb = function(color) {
4785
4821
  return Color.fromSource(Color.sourceFromRgb(color));
4786
4822
  };
4787
-
4823
+
4788
4824
  /**
4789
4825
  * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format
4790
4826
  * @method sourceFromRgb
@@ -4822,7 +4858,7 @@ fabric.util.string = {
4822
4858
  fabric.Color.fromHex = function(color) {
4823
4859
  return Color.fromSource(Color.sourceFromHex(color));
4824
4860
  };
4825
-
4861
+
4826
4862
  /**
4827
4863
  * Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HEX format
4828
4864
  * @static
@@ -4846,7 +4882,7 @@ fabric.util.string = {
4846
4882
  ];
4847
4883
  }
4848
4884
  };
4849
-
4885
+
4850
4886
  /**
4851
4887
  * Returns new color object, when given color in array representation (ex: [200, 100, 100, 0.5])
4852
4888
  * @static
@@ -4859,8 +4895,8 @@ fabric.util.string = {
4859
4895
  return oColor;
4860
4896
  };
4861
4897
 
4862
- })(typeof exports != 'undefined' ? exports : this);
4863
- (function (global) {
4898
+ })(typeof exports !== 'undefined' ? exports : this);
4899
+ (function () {
4864
4900
 
4865
4901
  "use strict";
4866
4902
 
@@ -4924,6 +4960,28 @@ fabric.util.string = {
4924
4960
  */
4925
4961
  backgroundImageStretch: true,
4926
4962
 
4963
+ /**
4964
+ * Overlay image of canvas instance
4965
+ * Should be set via `setOverlayImage`
4966
+ * @property
4967
+ * @type String
4968
+ */
4969
+ overlayImage: '',
4970
+
4971
+ /**
4972
+ * Left offset of overlay image (if present)
4973
+ * @property
4974
+ * @type Number
4975
+ */
4976
+ overlayImageLeft: 0,
4977
+
4978
+ /**
4979
+ * Top offset of overlay image (if present)
4980
+ * @property
4981
+ * @type Number
4982
+ */
4983
+ overlayImageTop: 0,
4984
+
4927
4985
  /**
4928
4986
  * Indicates whether toObject/toDatalessObject should include default values
4929
4987
  * @property
@@ -4965,17 +5023,10 @@ fabric.util.string = {
4965
5023
  * @method onBeforeScaleRotate
4966
5024
  * @param {fabric.Object} target Object that's about to be scaled/rotated
4967
5025
  */
4968
- onBeforeScaleRotate: function (target) {
5026
+ onBeforeScaleRotate: function () {
4969
5027
  /* NOOP */
4970
5028
  },
4971
5029
 
4972
- /**
4973
- * Callback; invoked on every redraw of canvas and is being passed a number indicating current fps
4974
- * @method onFpsUpdate
4975
- * @param {Number} fps
4976
- */
4977
- onFpsUpdate: null,
4978
-
4979
5030
  _initStatic: function(el, options) {
4980
5031
  this._objects = [];
4981
5032
 
@@ -5343,39 +5394,25 @@ fabric.util.string = {
5343
5394
  this.clearContext(canvasToDrawOn);
5344
5395
  }
5345
5396
 
5346
- var length = this._objects.length,
5347
- activeGroup = this.getActiveGroup(),
5348
- startTime = new Date();
5397
+ var activeGroup = this.getActiveGroup();
5349
5398
 
5350
5399
  if (this.clipTo) {
5351
- canvasToDrawOn.save();
5352
- canvasToDrawOn.beginPath();
5353
- this.clipTo(canvasToDrawOn);
5354
- canvasToDrawOn.clip();
5400
+ this._clipCanvas(canvasToDrawOn);
5355
5401
  }
5356
5402
 
5357
5403
  canvasToDrawOn.fillStyle = this.backgroundColor;
5358
5404
  canvasToDrawOn.fillRect(0, 0, this.width, this.height);
5359
5405
 
5360
- if (typeof this.backgroundImage == 'object') {
5361
- canvasToDrawOn.save();
5362
- canvasToDrawOn.globalAlpha = this.backgroundImageOpacity;
5363
-
5364
- if (this.backgroundImageStretch) {
5365
- canvasToDrawOn.drawImage(this.backgroundImage, 0, 0, this.width, this.height);
5366
- }
5367
- else {
5368
- canvasToDrawOn.drawImage(this.backgroundImage, 0, 0);
5369
- }
5370
- canvasToDrawOn.restore();
5406
+ if (typeof this.backgroundImage === 'object') {
5407
+ this._drawBackroundImage(canvasToDrawOn);
5371
5408
  }
5372
5409
 
5373
- if (length) {
5374
- for (var i = 0; i < length; ++i) {
5375
- if (!activeGroup ||
5376
- (activeGroup && this._objects[i] && !activeGroup.contains(this._objects[i]))) {
5377
- this._draw(canvasToDrawOn, this._objects[i]);
5378
- }
5410
+ this.fire('before:render');
5411
+
5412
+ for (var i = 0, length = this._objects.length; i < length; ++i) {
5413
+ if (!activeGroup ||
5414
+ (activeGroup && this._objects[i] && !activeGroup.contains(this._objects[i]))) {
5415
+ this._draw(canvasToDrawOn, this._objects[i]);
5379
5416
  }
5380
5417
  }
5381
5418
 
@@ -5389,23 +5426,38 @@ fabric.util.string = {
5389
5426
  }
5390
5427
 
5391
5428
  if (this.overlayImage) {
5392
- this.contextContainer.drawImage(this.overlayImage, 0, 0);
5429
+ this.contextContainer.drawImage(this.overlayImage, this.overlayImageLeft, this.overlayImageTop);
5393
5430
  }
5394
5431
 
5395
5432
  if (this.controlsAboveOverlay) {
5396
5433
  this.drawControls(this.contextContainer);
5397
5434
  }
5398
5435
 
5399
- if (this.onFpsUpdate) {
5400
- var elapsedTime = new Date() - startTime;
5401
- this.onFpsUpdate(~~(1000 / elapsedTime));
5402
- }
5403
-
5404
5436
  this.fire('after:render');
5405
5437
 
5406
5438
  return this;
5407
5439
  },
5408
5440
 
5441
+ _clipCanvas: function(canvasToDrawOn) {
5442
+ canvasToDrawOn.save();
5443
+ canvasToDrawOn.beginPath();
5444
+ this.clipTo(canvasToDrawOn);
5445
+ canvasToDrawOn.clip();
5446
+ },
5447
+
5448
+ _drawBackroundImage: function(canvasToDrawOn) {
5449
+ canvasToDrawOn.save();
5450
+ canvasToDrawOn.globalAlpha = this.backgroundImageOpacity;
5451
+
5452
+ if (this.backgroundImageStretch) {
5453
+ canvasToDrawOn.drawImage(this.backgroundImage, 0, 0, this.width, this.height);
5454
+ }
5455
+ else {
5456
+ canvasToDrawOn.drawImage(this.backgroundImage, 0, 0);
5457
+ }
5458
+ canvasToDrawOn.restore();
5459
+ },
5460
+
5409
5461
  /**
5410
5462
  * Method to render only the top canvas.
5411
5463
  * Also used to render the group selection box.
@@ -5417,7 +5469,7 @@ fabric.util.string = {
5417
5469
  this.clearContext(this.contextTop || this.contextContainer);
5418
5470
 
5419
5471
  if (this.overlayImage) {
5420
- this.contextContainer.drawImage(this.overlayImage, 0, 0);
5472
+ this.contextContainer.drawImage(this.overlayImage, this.overlayImageLeft, this.overlayImageTop);
5421
5473
  }
5422
5474
 
5423
5475
  // we render the top context - last object
@@ -5470,8 +5522,12 @@ fabric.util.string = {
5470
5522
  * @return {String}
5471
5523
  */
5472
5524
  toDataURL: function (format, quality) {
5525
+ var canvasEl = this.upperCanvasEl || this.lowerCanvasEl;
5526
+
5473
5527
  this.renderAll(true);
5474
- var data = (this.upperCanvasEl || this.lowerCanvasEl).toDataURL('image/' + format, quality);
5528
+ var data = (fabric.StaticCanvas.supports('toDataURLWithQuality'))
5529
+ ? canvasEl.toDataURL('image/' + format, quality)
5530
+ : canvasEl.toDataURL('image/' + format);
5475
5531
  this.renderAll();
5476
5532
  return data;
5477
5533
  },
@@ -5634,8 +5690,9 @@ fabric.util.string = {
5634
5690
  var data = {
5635
5691
  objects: this._objects.map(function (instance) {
5636
5692
  // TODO (kangax): figure out how to clean this up
5693
+ var originalValue;
5637
5694
  if (!this.includeDefaultValues) {
5638
- var originalValue = instance.includeDefaultValues;
5695
+ originalValue = instance.includeDefaultValues;
5639
5696
  instance.includeDefaultValues = false;
5640
5697
  }
5641
5698
  var object = instance[methodName]();
@@ -5929,7 +5986,7 @@ fabric.util.string = {
5929
5986
  *
5930
5987
  * @method supports
5931
5988
  * @param methodName {String} Method to check support for;
5932
- * Could be one of "getImageData" or "toDataURL"
5989
+ * Could be one of "getImageData", "toDataURL" or "toDataURLWithQuality"
5933
5990
  * @return {Boolean | null} `true` if method is supported (or at least exists),
5934
5991
  * `null` if canvas element or context can not be initialized
5935
5992
  */
@@ -5956,6 +6013,14 @@ fabric.util.string = {
5956
6013
  case 'toDataURL':
5957
6014
  return typeof el.toDataURL !== 'undefined';
5958
6015
 
6016
+ case 'toDataURLWithQuality':
6017
+ try {
6018
+ el.toDataURL('image/jpeg', 0);
6019
+ return true;
6020
+ }
6021
+ catch (e) { }
6022
+ return false;
6023
+
5959
6024
  default:
5960
6025
  return null;
5961
6026
  }
@@ -5970,8 +6035,7 @@ fabric.util.string = {
5970
6035
  */
5971
6036
  fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject;
5972
6037
 
5973
- })(typeof exports != 'undefined' ? exports : this);
5974
-
6038
+ })();
5975
6039
  (function() {
5976
6040
 
5977
6041
  var extend = fabric.util.object.extend,
@@ -6013,13 +6077,14 @@ fabric.util.string = {
6013
6077
 
6014
6078
  this._initStatic(el, options);
6015
6079
  this._initInteractive();
6080
+ this._createCacheCanvas();
6016
6081
 
6017
6082
  fabric.Canvas.activeInstance = this;
6018
6083
  };
6019
6084
 
6020
6085
  function ProtoProxy(){ }
6021
6086
  ProtoProxy.prototype = fabric.StaticCanvas.prototype;
6022
- fabric.Canvas.prototype = new ProtoProxy;
6087
+ fabric.Canvas.prototype = new ProtoProxy();
6023
6088
 
6024
6089
  var InteractiveMethods = /** @scope fabric.Canvas.prototype */ {
6025
6090
 
@@ -6107,6 +6172,24 @@ fabric.util.string = {
6107
6172
  */
6108
6173
  containerClass: 'canvas-container',
6109
6174
 
6175
+ /**
6176
+ * When true, object detection happens on per-pixel basis rather than on per-bounding-box
6177
+ * @property
6178
+ * @type Boolean
6179
+ */
6180
+ perPixelTargetFind: false,
6181
+
6182
+ /**
6183
+ * Number of pixels around target pixel to tolerate (consider active) during object detection
6184
+ * @property
6185
+ * @type Number
6186
+ */
6187
+ targetFindTolerance: 0,
6188
+
6189
+ /**
6190
+ * @method _initInteractive
6191
+ * @private
6192
+ */
6110
6193
  _initInteractive: function() {
6111
6194
  this._currentTransform = null;
6112
6195
  this._groupSelector = null;
@@ -6158,7 +6241,7 @@ fabric.util.string = {
6158
6241
  _this.__onMouseMove(e);
6159
6242
  };
6160
6243
 
6161
- this._onResize = function (e) {
6244
+ this._onResize = function () {
6162
6245
  _this.calcOffset();
6163
6246
  };
6164
6247
 
@@ -6185,6 +6268,8 @@ fabric.util.string = {
6185
6268
  */
6186
6269
  __onMouseUp: function (e) {
6187
6270
 
6271
+ var target;
6272
+
6188
6273
  if (this.isDrawingMode && this._isCurrentlyDrawing) {
6189
6274
  this._finalizeDrawingPath();
6190
6275
  this.fire('mouse:up', { e: e });
@@ -6193,9 +6278,9 @@ fabric.util.string = {
6193
6278
 
6194
6279
  if (this._currentTransform) {
6195
6280
 
6196
- var transform = this._currentTransform,
6197
- target = transform.target;
6281
+ var transform = this._currentTransform;
6198
6282
 
6283
+ target = transform.target;
6199
6284
  if (target._scaling) {
6200
6285
  target._scaling = false;
6201
6286
  }
@@ -6242,7 +6327,7 @@ fabric.util.string = {
6242
6327
  }, 50);
6243
6328
 
6244
6329
  this.fire('mouse:up', { target: target, e: e });
6245
- target && target.fire('mouseup', { e: e })
6330
+ target && target.fire('mouseup', { e: e });
6246
6331
  },
6247
6332
 
6248
6333
  /**
@@ -6257,7 +6342,7 @@ fabric.util.string = {
6257
6342
  __onMouseDown: function (e) {
6258
6343
 
6259
6344
  // accept only left clicks
6260
- var isLeftClick = 'which' in e ? e.which == 1 : e.button == 1;
6345
+ var isLeftClick = 'which' in e ? e.which === 1 : e.button === 1;
6261
6346
  if (!isLeftClick && !fabric.isTouchSupported) return;
6262
6347
 
6263
6348
  if (this.isDrawingMode) {
@@ -6293,7 +6378,7 @@ fabric.util.string = {
6293
6378
  // rotate and scale will happen at the same time
6294
6379
  this.stateful && target.saveState();
6295
6380
 
6296
- if (corner = target._findTargetCorner(e, this._offset)) {
6381
+ if ((corner = target._findTargetCorner(e, this._offset))) {
6297
6382
  this.onBeforeScaleRotate(target);
6298
6383
  }
6299
6384
 
@@ -6329,6 +6414,8 @@ fabric.util.string = {
6329
6414
  */
6330
6415
  __onMouseMove: function (e) {
6331
6416
 
6417
+ var target;
6418
+
6332
6419
  if (this.isDrawingMode) {
6333
6420
  if (this._isCurrentlyDrawing) {
6334
6421
  this._captureDrawingPath(e);
@@ -6337,11 +6424,12 @@ fabric.util.string = {
6337
6424
  return;
6338
6425
  }
6339
6426
 
6340
- var groupSelector = this._groupSelector;
6427
+ var groupSelector = this._groupSelector, pointer;
6341
6428
 
6342
6429
  // We initially clicked in an empty area, so we draw a box for multiple selection.
6343
6430
  if (groupSelector !== null) {
6344
- var pointer = getPointer(e);
6431
+ pointer = getPointer(e);
6432
+
6345
6433
  groupSelector.left = pointer.x - this._offset.left - groupSelector.ex;
6346
6434
  groupSelector.top = pointer.y - this._offset.top - groupSelector.ey;
6347
6435
  this.renderTop();
@@ -6355,7 +6443,7 @@ fabric.util.string = {
6355
6443
  // what part of the pictures we are hovering to change the caret symbol.
6356
6444
  // We won't do that while dragging or rotating in order to improve the
6357
6445
  // performance.
6358
- var target = this.findTarget(e);
6446
+ target = this.findTarget(e);
6359
6447
 
6360
6448
  if (!target) {
6361
6449
  // image/text was hovered-out from, we remove its borders
@@ -6377,8 +6465,9 @@ fabric.util.string = {
6377
6465
  }
6378
6466
  else {
6379
6467
  // object is being transformed (scaled/rotated/moved/etc.)
6380
- var pointer = getPointer(e),
6381
- x = pointer.x,
6468
+ pointer = getPointer(e);
6469
+
6470
+ var x = pointer.x,
6382
6471
  y = pointer.y;
6383
6472
 
6384
6473
  this._currentTransform.target.isMoving = true;
@@ -6495,6 +6584,49 @@ fabric.util.string = {
6495
6584
  return { x: x, y: y };
6496
6585
  },
6497
6586
 
6587
+ _isTargetTransparent: function (target, x, y) {
6588
+ var cacheContext = this.contextCache;
6589
+
6590
+ var hasBorders = target.hasBorders, transparentCorners = target.transparentCorners;
6591
+ target.hasBorders = target.transparentCorners = false;
6592
+
6593
+ this._draw(cacheContext, target);
6594
+
6595
+ target.hasBorders = hasBorders;
6596
+ target.transparentCorners = transparentCorners;
6597
+
6598
+ // If tolerance is > 0 adjust start coords to take into account. If moves off Canvas fix to 0
6599
+ if (this.targetFindTolerance > 0) {
6600
+ if (x > this.targetFindTolerance) {
6601
+ x -= this.targetFindTolerance;
6602
+ }
6603
+ else {
6604
+ x = 0;
6605
+ }
6606
+ if (y > this.targetFindTolerance) {
6607
+ y -= this.targetFindTolerance;
6608
+ }
6609
+ else {
6610
+ y = 0;
6611
+ }
6612
+ }
6613
+
6614
+ var isTransparent = true;
6615
+ var imageData = cacheContext.getImageData(
6616
+ x, y, (this.targetFindTolerance * 2) || 1, (this.targetFindTolerance * 2) || 1);
6617
+
6618
+ // Split image data - for tolerance > 1, pixelDataSize = 4;
6619
+ for (var i = 3; i < imageData.data.length; i += 4) {
6620
+ var temp = imageData.data[i];
6621
+ isTransparent = temp <= 0;
6622
+ if (isTransparent === false) break; //Stop if colour found
6623
+ }
6624
+
6625
+ imageData = null;
6626
+ this.clearContext(cacheContext);
6627
+ return isTransparent;
6628
+ },
6629
+
6498
6630
  /**
6499
6631
  * @private
6500
6632
  * @method _shouldClearSelection
@@ -6522,7 +6654,7 @@ fabric.util.string = {
6522
6654
  corner,
6523
6655
  pointer = getPointer(e);
6524
6656
 
6525
- if (corner = target._findTargetCorner(e, this._offset)) {
6657
+ if ((corner = target._findTargetCorner(e, this._offset))) {
6526
6658
  action = (corner === 'ml' || corner === 'mr')
6527
6659
  ? 'scaleX'
6528
6660
  : (corner === 'mt' || corner === 'mb')
@@ -6652,17 +6784,14 @@ fabric.util.string = {
6652
6784
  minY = utilMin(this._freeDrawingYPoints),
6653
6785
  maxX = utilMax(this._freeDrawingXPoints),
6654
6786
  maxY = utilMax(this._freeDrawingYPoints),
6655
- ctx = this.contextTop,
6656
6787
  path = [ ],
6657
- xPoint,
6658
- yPoint,
6659
6788
  xPoints = this._freeDrawingXPoints,
6660
6789
  yPoints = this._freeDrawingYPoints;
6661
6790
 
6662
6791
  path.push('M ', xPoints[0] - minX, ' ', yPoints[0] - minY, ' ');
6663
6792
 
6664
- for (var i = 1; xPoint = xPoints[i], yPoint = yPoints[i]; i++) {
6665
- path.push('L ', xPoint - minX, ' ', yPoint - minY, ' ');
6793
+ for (var i = 1, len = xPoints.length; i < len; i++) {
6794
+ path.push('L ', xPoints[i] - minX, ' ', yPoints[i] - minY, ' ');
6666
6795
  }
6667
6796
 
6668
6797
  // TODO (kangax): maybe remove Path creation from here, to decouple fabric.Canvas from fabric.Path,
@@ -6827,9 +6956,7 @@ fabric.util.string = {
6827
6956
  },
6828
6957
 
6829
6958
  _findSelectedObjects: function (e) {
6830
- var target,
6831
- targetRegion,
6832
- group = [ ],
6959
+ var group = [ ],
6833
6960
  x1 = this._groupSelector.ex,
6834
6961
  y1 = this._groupSelector.ey,
6835
6962
  x2 = x1 + this._groupSelector.left,
@@ -6858,7 +6985,7 @@ fabric.util.string = {
6858
6985
  this.setActiveObject(group[0], e);
6859
6986
  }
6860
6987
  else if (group.length > 1) {
6861
- var group = new fabric.Group(group);
6988
+ group = new fabric.Group(group);
6862
6989
  this.setActiveGroup(group);
6863
6990
  group.saveCoords();
6864
6991
  this.fire('selection:created', { target: group });
@@ -6887,9 +7014,25 @@ fabric.util.string = {
6887
7014
  }
6888
7015
 
6889
7016
  // then check all of the objects on canvas
7017
+ // Cache all targets where their bounding box contains point.
7018
+ var possibleTargets = [];
6890
7019
  for (var i = this._objects.length; i--; ) {
6891
7020
  if (this._objects[i] && this.containsPoint(e, this._objects[i])) {
6892
- target = this._objects[i];
7021
+ if (this.perPixelTargetFind || this._objects[i].perPixelTargetFind) {
7022
+ possibleTargets[possibleTargets.length] = this._objects[i];
7023
+ }
7024
+ else {
7025
+ target = this._objects[i];
7026
+ this.relatedTarget = target;
7027
+ break;
7028
+ }
7029
+ }
7030
+ }
7031
+ for (var j = 0, len = possibleTargets.length; j < len; j++) {
7032
+ pointer = this.getPointer(e);
7033
+ var isTransparent = this._isTargetTransparent(possibleTargets[j], pointer.x, pointer.y);
7034
+ if (!isTransparent) {
7035
+ target = possibleTargets[j];
6893
7036
  this.relatedTarget = target;
6894
7037
  break;
6895
7038
  }
@@ -6927,6 +7070,13 @@ fabric.util.string = {
6927
7070
  this.contextTop = this.upperCanvasEl.getContext('2d');
6928
7071
  },
6929
7072
 
7073
+ _createCacheCanvas: function () {
7074
+ this.cacheCanvasEl = this._createCanvasElement();
7075
+ this.cacheCanvasEl.setAttribute('width', this.width);
7076
+ this.cacheCanvasEl.setAttribute('height', this.height);
7077
+ this.contextCache = this.cacheCanvasEl.getContext('2d');
7078
+ },
7079
+
6930
7080
  /**
6931
7081
  * @private
6932
7082
  * @method _initWrapperElement
@@ -7279,95 +7429,96 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
7279
7429
  }
7280
7430
  }
7281
7431
 
7282
- var _this = this,
7283
- numLoadedObjects = 0,
7284
- numTotalObjects = objects.length;
7432
+ /** @ignore */
7433
+ function loadObject(obj, index) {
7285
7434
 
7286
- if (numTotalObjects === 0 && callback) {
7287
- callback();
7288
- }
7435
+ var pathProp = obj.paths ? 'paths' : 'path';
7436
+ var path = obj[pathProp];
7289
7437
 
7290
- try {
7291
- objects.forEach(function (obj, index) {
7292
-
7293
- var pathProp = obj.paths ? 'paths' : 'path';
7294
- var path = obj[pathProp];
7295
-
7296
- delete obj[pathProp];
7297
-
7298
- if (typeof path !== 'string') {
7299
- switch (obj.type) {
7300
- case 'image':
7301
- fabric[fabric.util.string.capitalize(obj.type)].fromObject(obj, function (o) {
7302
- onObjectLoaded(o, index);
7303
- });
7304
- break;
7305
- default:
7306
- var klass = fabric[fabric.util.string.camelize(fabric.util.string.capitalize(obj.type))];
7307
- if (klass && klass.fromObject) {
7308
- // restore path
7309
- if (path) {
7310
- obj[pathProp] = path;
7311
- }
7312
- onObjectLoaded(klass.fromObject(obj), index);
7313
- }
7314
- break;
7315
- }
7438
+ delete obj[pathProp];
7439
+
7440
+ if (typeof path !== 'string') {
7441
+ if (obj.type === 'image') {
7442
+ fabric[fabric.util.string.capitalize(obj.type)].fromObject(obj, function (o) {
7443
+ onObjectLoaded(o, index);
7444
+ });
7316
7445
  }
7317
7446
  else {
7318
- if (obj.type === 'image') {
7319
- fabric.util.loadImage(path, function (image) {
7320
- var oImg = new fabric.Image(image);
7447
+ var klass = fabric[fabric.util.string.camelize(fabric.util.string.capitalize(obj.type))];
7448
+ if (!klass || !klass.fromObject) return;
7321
7449
 
7322
- oImg.setSourcePath(path);
7450
+ // restore path
7451
+ if (path) {
7452
+ obj[pathProp] = path;
7453
+ }
7454
+ onObjectLoaded(klass.fromObject(obj), index);
7455
+ }
7456
+ }
7457
+ else {
7458
+ if (obj.type === 'image') {
7459
+ fabric.util.loadImage(path, function (image) {
7460
+ var oImg = new fabric.Image(image);
7323
7461
 
7324
- fabric.util.object.extend(oImg, obj);
7325
- oImg.setAngle(obj.angle);
7462
+ oImg.setSourcePath(path);
7326
7463
 
7327
- onObjectLoaded(oImg, index);
7328
- });
7329
- }
7330
- else if (obj.type === 'text') {
7464
+ fabric.util.object.extend(oImg, obj);
7465
+ oImg.setAngle(obj.angle);
7331
7466
 
7332
- if (obj.useNative) {
7333
- onObjectLoaded(fabric.Text.fromObject(obj), index);
7334
- }
7335
- else {
7336
- obj.path = path;
7337
- var object = fabric.Text.fromObject(obj);
7338
- var onscriptload = function () {
7339
- // TODO (kangax): find out why Opera refuses to work without this timeout
7340
- if (Object.prototype.toString.call(fabric.window.opera) === '[object Opera]') {
7341
- setTimeout(function () {
7342
- onObjectLoaded(object, index);
7343
- }, 500);
7344
- }
7345
- else {
7346
- onObjectLoaded(object, index);
7347
- }
7348
- }
7467
+ onObjectLoaded(oImg, index);
7468
+ });
7469
+ }
7470
+ else if (obj.type === 'text') {
7349
7471
 
7350
- fabric.util.getScript(path, onscriptload);
7351
- }
7472
+ if (obj.useNative) {
7473
+ onObjectLoaded(fabric.Text.fromObject(obj), index);
7352
7474
  }
7353
7475
  else {
7354
- fabric.loadSVGFromURL(path, function (elements, options) {
7355
- var object = fabric.util.groupSVGElements(elements, obj, path);
7356
-
7357
- // copy parameters from serialied json to object (left, top, scaleX, scaleY, etc.)
7358
- // skip this step if an object is a PathGroup, since we already passed it options object before
7359
- if (!(object instanceof fabric.PathGroup)) {
7360
- fabric.util.object.extend(object, obj);
7361
- if (typeof obj.angle !== 'undefined') {
7362
- object.setAngle(obj.angle);
7363
- }
7476
+ obj.path = path;
7477
+ var object = fabric.Text.fromObject(obj);
7478
+ var onscriptload = function () {
7479
+ // TODO (kangax): find out why Opera refuses to work without this timeout
7480
+ if (Object.prototype.toString.call(fabric.window.opera) === '[object Opera]') {
7481
+ setTimeout(function () {
7482
+ onObjectLoaded(object, index);
7483
+ }, 500);
7364
7484
  }
7485
+ else {
7486
+ onObjectLoaded(object, index);
7487
+ }
7488
+ };
7365
7489
 
7366
- onObjectLoaded(object, index);
7367
- });
7490
+ fabric.util.getScript(path, onscriptload);
7368
7491
  }
7369
7492
  }
7370
- }, this);
7493
+ else {
7494
+ fabric.loadSVGFromURL(path, function (elements) {
7495
+ var object = fabric.util.groupSVGElements(elements, obj, path);
7496
+
7497
+ // copy parameters from serialied json to object (left, top, scaleX, scaleY, etc.)
7498
+ // skip this step if an object is a PathGroup, since we already passed it options object before
7499
+ if (!(object instanceof fabric.PathGroup)) {
7500
+ fabric.util.object.extend(object, obj);
7501
+ if (typeof obj.angle !== 'undefined') {
7502
+ object.setAngle(obj.angle);
7503
+ }
7504
+ }
7505
+
7506
+ onObjectLoaded(object, index);
7507
+ });
7508
+ }
7509
+ }
7510
+ }
7511
+
7512
+ var _this = this,
7513
+ numLoadedObjects = 0,
7514
+ numTotalObjects = objects.length;
7515
+
7516
+ if (numTotalObjects === 0 && callback) {
7517
+ callback();
7518
+ }
7519
+
7520
+ try {
7521
+ objects.forEach(loadObject, this);
7371
7522
  }
7372
7523
  catch(e) {
7373
7524
  fabric.log(e.message);
@@ -7503,7 +7654,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
7503
7654
 
7504
7655
  var fabric = global.fabric || (global.fabric = { }),
7505
7656
  extend = fabric.util.object.extend,
7506
- clone = fabric.util.object.clone,
7507
7657
  toFixed = fabric.util.toFixed,
7508
7658
  capitalize = fabric.util.string.capitalize,
7509
7659
  getPointer = fabric.util.getPointer,
@@ -7593,6 +7743,12 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
7593
7743
  */
7594
7744
  cornersize: 12,
7595
7745
 
7746
+ /**
7747
+ * @property
7748
+ * @type Boolean
7749
+ */
7750
+ transparentCorners: true,
7751
+
7596
7752
  /**
7597
7753
  * @property
7598
7754
  * @type Number
@@ -7706,9 +7862,11 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
7706
7862
  * @property
7707
7863
  * @type Number
7708
7864
  */
7709
- _theta: 0,
7865
+ _theta: 0,
7866
+
7867
+ perPixelTargetFind: false,
7710
7868
 
7711
- includeDefaultValues: true,
7869
+ includeDefaultValues: true,
7712
7870
 
7713
7871
  /**
7714
7872
  * List of properties to consider when checking if state of an object is changed (fabric.Object#hasStateChanged);
@@ -7742,7 +7900,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
7742
7900
  initialize: function(options) {
7743
7901
  if (options) {
7744
7902
  this.setOptions(options);
7745
- this._initGradient(options);
7746
7903
  }
7747
7904
  },
7748
7905
 
@@ -7750,7 +7907,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
7750
7907
  * @method initGradient
7751
7908
  */
7752
7909
  _initGradient: function(options) {
7753
- if (options.fill && typeof options.fill == 'object' && !(options.fill instanceof fabric.Gradient)) {
7910
+ if (options.fill && typeof options.fill === 'object' && !(options.fill instanceof fabric.Gradient)) {
7754
7911
  this.set('fill', new fabric.Gradient(options.fill));
7755
7912
  }
7756
7913
  },
@@ -7767,6 +7924,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
7767
7924
  this.set(prop, options[prop]);
7768
7925
  }
7769
7926
  }
7927
+ this._initGradient(options);
7770
7928
  },
7771
7929
 
7772
7930
  /**
@@ -7812,7 +7970,9 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
7812
7970
  selectable: this.selectable,
7813
7971
  hasControls: this.hasControls,
7814
7972
  hasBorders: this.hasBorders,
7815
- hasRotatingPoint: this.hasRotatingPoint
7973
+ hasRotatingPoint: this.hasRotatingPoint,
7974
+ transparentCorners: this.transparentCorners,
7975
+ perPixelTargetFind: this.perPixelTargetFind
7816
7976
  };
7817
7977
 
7818
7978
  if (!this.includeDefaultValues) {
@@ -8025,7 +8185,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8025
8185
 
8026
8186
  if (this.active && !noTransform) {
8027
8187
  this.drawBorders(ctx);
8028
- this.hideCorners || this.drawCorners(ctx);
8188
+ this.drawCorners(ctx);
8029
8189
  }
8030
8190
  ctx.restore();
8031
8191
  },
@@ -8058,29 +8218,34 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8058
8218
  scale: function(value) {
8059
8219
  this.scaleX = value;
8060
8220
  this.scaleY = value;
8221
+ this.setCoords();
8061
8222
  return this;
8062
8223
  },
8063
8224
 
8064
8225
  /**
8065
- * Scales an object to a given width (scaling by x/y equally)
8226
+ * Scales an object to a given width, with respect to bounding box (scaling by x/y equally)
8066
8227
  * @method scaleToWidth
8067
8228
  * @param value {Number} new width value
8068
8229
  * @return {fabric.Object} thisArg
8069
8230
  * @chainable
8070
8231
  */
8071
8232
  scaleToWidth: function(value) {
8072
- return this.scale(value / this.width);
8233
+ // adjust to bounding rect factor so that rotated shapes would fit as well
8234
+ var boundingRectFactor = this.getBoundingRectWidth() / this.getWidth();
8235
+ return this.scale(value / this.width / boundingRectFactor);
8073
8236
  },
8074
8237
 
8075
8238
  /**
8076
- * Scales an object to a given height (scaling by x/y equally)
8239
+ * Scales an object to a given height, with respect to bounding box (scaling by x/y equally)
8077
8240
  * @method scaleToHeight
8078
8241
  * @param value {Number} new height value
8079
8242
  * @return {fabric.Object} thisArg
8080
8243
  * @chainable
8081
8244
  */
8082
8245
  scaleToHeight: function(value) {
8083
- return this.scale(value / this.height);
8246
+ // adjust to bounding rect factor so that rotated shapes would fit as well
8247
+ var boundingRectFactor = this.getBoundingRectHeight() / this.getHeight();
8248
+ return this.scale(value / this.height / boundingRectFactor);
8084
8249
  },
8085
8250
 
8086
8251
  /**
@@ -8130,6 +8295,11 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8130
8295
  this.currentWidth = (this.width + strokeWidth) * this.scaleX + padding * 2;
8131
8296
  this.currentHeight = (this.height + strokeWidth) * this.scaleY + padding * 2;
8132
8297
 
8298
+ //If width is negative, make postive. Fixes path selection issue
8299
+ if(this.currentWidth < 0){
8300
+ this.currentWidth = Math.abs(this.currentWidth);
8301
+ }
8302
+
8133
8303
  this._hypotenuse = Math.sqrt(
8134
8304
  Math.pow(this.currentWidth / 2, 2) +
8135
8305
  Math.pow(this.currentHeight / 2, 2));
@@ -8209,6 +8379,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8209
8379
  * @return {Number} width value
8210
8380
  */
8211
8381
  getBoundingRectWidth: function() {
8382
+ this.oCoords || this.setCoords();
8212
8383
  var xCoords = [this.oCoords.tl.x, this.oCoords.tr.x, this.oCoords.br.x, this.oCoords.bl.x];
8213
8384
  var minX = fabric.util.array.min(xCoords);
8214
8385
  var maxX = fabric.util.array.max(xCoords);
@@ -8221,6 +8392,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8221
8392
  * @return {Number} height value
8222
8393
  */
8223
8394
  getBoundingRectHeight: function() {
8395
+ this.oCoords || this.setCoords();
8224
8396
  var yCoords = [this.oCoords.tl.y, this.oCoords.tr.y, this.oCoords.br.y, this.oCoords.bl.y];
8225
8397
  var minY = fabric.util.array.min(yCoords);
8226
8398
  var maxY = fabric.util.array.max(yCoords);
@@ -8266,7 +8438,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8266
8438
  ~~(h + padding2 + strokeWidth * this.scaleY)
8267
8439
  );
8268
8440
 
8269
- if (this.hasRotatingPoint && !this.hideCorners && !this.lockRotation) {
8441
+ if (this.hasRotatingPoint && !this.lockRotation && this.hasControls) {
8270
8442
 
8271
8443
  var rotateHeight = (
8272
8444
  this.flipY
@@ -8274,8 +8446,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8274
8446
  : -h - (strokeWidth * this.scaleY) - (padding * 2)
8275
8447
  ) / 2;
8276
8448
 
8277
- var rotateWidth = (-w/2);
8278
-
8279
8449
  ctx.beginPath();
8280
8450
  ctx.moveTo(0, rotateHeight);
8281
8451
  ctx.lineTo(0, rotateHeight + (this.flipY ? this.rotatingPointOffset : -this.rotatingPointOffset));
@@ -8298,8 +8468,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8298
8468
  x = -this.width/2, y = -this.height/2,
8299
8469
  _this = this,
8300
8470
  padding = this.padding,
8301
- width = this.getWidth(),
8302
- height = this.getHeight(),
8303
8471
  dashedArrayLength = this.strokeDashArray.length;
8304
8472
 
8305
8473
  ctx.save();
@@ -8308,6 +8476,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8308
8476
  function renderSide(xMultiplier, yMultiplier) {
8309
8477
 
8310
8478
  var lineLength = 0,
8479
+ lengthDiff = 0,
8311
8480
  sideLength = (yMultiplier ? _this.height : _this.width) + padding * 2;
8312
8481
 
8313
8482
  while (lineLength < sideLength) {
@@ -8316,7 +8485,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8316
8485
  lineLength += lengthOfSubPath;
8317
8486
 
8318
8487
  if (lineLength > sideLength) {
8319
- var lengthDiff = lineLength - sideLength;
8488
+ lengthDiff = lineLength - sideLength;
8320
8489
  }
8321
8490
 
8322
8491
  // track coords
@@ -8372,7 +8541,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8372
8541
  scaleOffsetSizeX = (size2 - size) / this.scaleX,
8373
8542
  scaleOffsetSizeY = (size2 - size) / this.scaleY,
8374
8543
  height = this.height,
8375
- width = this.width;
8544
+ width = this.width,
8545
+ methodName = this.transparentCorners ? 'strokeRect' : 'fillRect';
8376
8546
 
8377
8547
  ctx.save();
8378
8548
 
@@ -8386,28 +8556,28 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8386
8556
  _top = top - scaleOffsetY - strokeWidth2 - paddingY;
8387
8557
 
8388
8558
  ctx.clearRect(_left, _top, sizeX, sizeY);
8389
- ctx.strokeRect(_left, _top, sizeX, sizeY);
8559
+ ctx[methodName](_left, _top, sizeX, sizeY);
8390
8560
 
8391
8561
  // top-right
8392
8562
  _left = left + width - scaleOffsetX + strokeWidth2 + paddingX;
8393
8563
  _top = top - scaleOffsetY - strokeWidth2 - paddingY;
8394
8564
 
8395
8565
  ctx.clearRect(_left, _top, sizeX, sizeY);
8396
- ctx.strokeRect(_left, _top, sizeX, sizeY);
8566
+ ctx[methodName](_left, _top, sizeX, sizeY);
8397
8567
 
8398
8568
  // bottom-left
8399
8569
  _left = left - scaleOffsetX - strokeWidth2 - paddingX;
8400
8570
  _top = top + height + scaleOffsetSizeY + strokeWidth2 + paddingY;
8401
8571
 
8402
8572
  ctx.clearRect(_left, _top, sizeX, sizeY);
8403
- ctx.strokeRect(_left, _top, sizeX, sizeY);
8573
+ ctx[methodName](_left, _top, sizeX, sizeY);
8404
8574
 
8405
8575
  // bottom-right
8406
8576
  _left = left + width + scaleOffsetSizeX + strokeWidth2 + paddingX;
8407
8577
  _top = top + height + scaleOffsetSizeY + strokeWidth2 + paddingY;
8408
8578
 
8409
8579
  ctx.clearRect(_left, _top, sizeX, sizeY);
8410
- ctx.strokeRect(_left, _top, sizeX, sizeY);
8580
+ ctx[methodName](_left, _top, sizeX, sizeY);
8411
8581
 
8412
8582
  if (!this.lockUniScaling) {
8413
8583
  // middle-top
@@ -8415,28 +8585,28 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8415
8585
  _top = top - scaleOffsetY - strokeWidth2 - paddingY;
8416
8586
 
8417
8587
  ctx.clearRect(_left, _top, sizeX, sizeY);
8418
- ctx.strokeRect(_left, _top, sizeX, sizeY);
8588
+ ctx[methodName](_left, _top, sizeX, sizeY);
8419
8589
 
8420
8590
  // middle-bottom
8421
8591
  _left = left + width/2 - scaleOffsetX;
8422
8592
  _top = top + height + scaleOffsetSizeY + strokeWidth2 + paddingY;
8423
8593
 
8424
8594
  ctx.clearRect(_left, _top, sizeX, sizeY);
8425
- ctx.strokeRect(_left, _top, sizeX, sizeY);
8595
+ ctx[methodName](_left, _top, sizeX, sizeY);
8426
8596
 
8427
8597
  // middle-right
8428
8598
  _left = left + width + scaleOffsetSizeX + strokeWidth2 + paddingX;
8429
8599
  _top = top + height/2 - scaleOffsetY;
8430
8600
 
8431
8601
  ctx.clearRect(_left, _top, sizeX, sizeY);
8432
- ctx.strokeRect(_left, _top, sizeX, sizeY);
8602
+ ctx[methodName](_left, _top, sizeX, sizeY);
8433
8603
 
8434
8604
  // middle-left
8435
8605
  _left = left - scaleOffsetX - strokeWidth2 - paddingX;
8436
8606
  _top = top + height/2 - scaleOffsetY;
8437
8607
 
8438
8608
  ctx.clearRect(_left, _top, sizeX, sizeY);
8439
- ctx.strokeRect(_left, _top, sizeX, sizeY);
8609
+ ctx[methodName](_left, _top, sizeX, sizeY);
8440
8610
  }
8441
8611
 
8442
8612
  // middle-top-rotate
@@ -8449,7 +8619,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8449
8619
  : (top - (this.rotatingPointOffset / this.scaleY) - sizeY/2 - strokeWidth2 - paddingY);
8450
8620
 
8451
8621
  ctx.clearRect(_left, _top, sizeX, sizeY);
8452
- ctx.strokeRect(_left, _top, sizeX, sizeY);
8622
+ ctx[methodName](_left, _top, sizeX, sizeY);
8453
8623
  }
8454
8624
 
8455
8625
  ctx.restore();
@@ -8511,12 +8681,11 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8511
8681
  */
8512
8682
  toDataURL: function(callback) {
8513
8683
  var el = fabric.document.createElement('canvas');
8514
- if (!el.getContext && typeof G_vmlCanvasManager != 'undefined') {
8684
+ if (!el.getContext && typeof G_vmlCanvasManager !== 'undefined') {
8515
8685
  G_vmlCanvasManager.initElement(el);
8516
8686
  }
8517
8687
 
8518
- this.setCoords();
8519
- el.width = this.getBoundingRectWidth();
8688
+ el.width = this.getBoundingRectWidth();
8520
8689
  el.height = this.getBoundingRectHeight();
8521
8690
 
8522
8691
  fabric.util.wrapElement(el, 'div');
@@ -8614,7 +8783,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8614
8783
  tr: new fabric.Point(oCoords.tr.x, oCoords.tr.y),
8615
8784
  bl: new fabric.Point(oCoords.bl.x, oCoords.bl.y),
8616
8785
  br: new fabric.Point(oCoords.br.x, oCoords.br.y)
8617
- }
8786
+ };
8618
8787
  }
8619
8788
  var thisCoords = getCoords(this.oCoords),
8620
8789
  otherCoords = getCoords(other.oCoords);
@@ -8648,8 +8817,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8648
8817
  var oCoords = this.oCoords,
8649
8818
  tl = new fabric.Point(oCoords.tl.x, oCoords.tl.y),
8650
8819
  tr = new fabric.Point(oCoords.tr.x, oCoords.tr.y),
8651
- bl = new fabric.Point(oCoords.bl.x, oCoords.bl.y),
8652
- br = new fabric.Point(oCoords.br.x, oCoords.br.y);
8820
+ bl = new fabric.Point(oCoords.bl.x, oCoords.bl.y);
8653
8821
 
8654
8822
  return tl.x > selectionTL.x
8655
8823
  && tr.x < selectionBR.x
@@ -8684,29 +8852,33 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8684
8852
  lines;
8685
8853
 
8686
8854
  for (var i in this.oCoords) {
8855
+
8687
8856
  if (i === 'mtr' && !this.hasRotatingPoint) {
8688
- return false;
8857
+ continue;
8689
8858
  }
8859
+
8690
8860
  if (this.lockUniScaling && (i === 'mt' || i === 'mr' || i === 'mb' || i === 'ml')) {
8691
- return false;
8861
+ continue;
8692
8862
  }
8693
8863
 
8694
8864
  lines = this._getImageLines(this.oCoords[i].corner, i);
8865
+
8695
8866
  // debugging
8867
+
8696
8868
  // canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);
8697
- // canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);
8698
- //
8699
- // canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);
8700
- // canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);
8701
- //
8702
- // canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);
8703
- // canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);
8704
- //
8705
- // canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);
8706
- // canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2);
8869
+ // canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);
8870
+
8871
+ // canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);
8872
+ // canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);
8873
+
8874
+ // canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);
8875
+ // canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);
8876
+
8877
+ // canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);
8878
+ // canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2);
8707
8879
 
8708
8880
  xpoints = this._findCrossPoints(ex, ey, lines);
8709
- if (xpoints % 2 == 1 && xpoints != 0) {
8881
+ if (xpoints % 2 === 1 && xpoints !== 0) {
8710
8882
  this.__corner = i;
8711
8883
  return i;
8712
8884
  }
@@ -8739,7 +8911,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8739
8911
  continue;
8740
8912
  }
8741
8913
  // optimisation 3: vertical line case
8742
- if ((iLine.o.x == iLine.d.x) && (iLine.o.x >= ex)) {
8914
+ if ((iLine.o.x === iLine.d.x) && (iLine.o.x >= ex)) {
8743
8915
  xi = iLine.o.x;
8744
8916
  yi = ey;
8745
8917
  }
@@ -8758,7 +8930,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8758
8930
  xcount += 1;
8759
8931
  }
8760
8932
  // optimisation 4: specific for square images
8761
- if (xcount == 2) {
8933
+ if (xcount === 2) {
8762
8934
  break;
8763
8935
  }
8764
8936
  }
@@ -8771,7 +8943,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8771
8943
  * @private
8772
8944
  * @param oCoords {Object} coordinates of the image corners
8773
8945
  */
8774
- _getImageLines: function(oCoords, i) {
8946
+ _getImageLines: function(oCoords) {
8775
8947
  return {
8776
8948
  topline: {
8777
8949
  o: oCoords.tl,
@@ -8789,7 +8961,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
8789
8961
  o: oCoords.bl,
8790
8962
  d: oCoords.tl
8791
8963
  }
8792
- }
8964
+ };
8793
8965
  },
8794
8966
 
8795
8967
  /**
@@ -9010,11 +9182,44 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9010
9182
  return this.toObject();
9011
9183
  },
9012
9184
 
9185
+ /**
9186
+ * @method setGradientFill
9187
+ */
9013
9188
  setGradientFill: function(options) {
9014
9189
  this.set('fill', fabric.Gradient.forObject(this, options));
9015
9190
  },
9016
9191
 
9017
- animate: function(property, to, options) {
9192
+ /**
9193
+ * @method animate
9194
+ *
9195
+ * As object — multiple properties
9196
+ *
9197
+ * object.animate({ left: ..., top: ... });
9198
+ * object.animate({ left: ..., top: ... }, { duration: ... });
9199
+ *
9200
+ * As string — one property
9201
+ *
9202
+ * object.animate('left', ...);
9203
+ * object.animate('left', { duration: ... });
9204
+ *
9205
+ */
9206
+ animate: function() {
9207
+ if (arguments[0] && typeof arguments[0] === 'object') {
9208
+ for (var prop in arguments[0]) {
9209
+ this._animate(prop, arguments[0][prop], arguments[1]);
9210
+ }
9211
+ }
9212
+ else {
9213
+ this._animate.apply(this, arguments);
9214
+ }
9215
+ return this;
9216
+ },
9217
+
9218
+ /**
9219
+ * @private
9220
+ * @method _animate
9221
+ */
9222
+ _animate: function(property, to, options) {
9018
9223
  var obj = this;
9019
9224
 
9020
9225
  options || (options = { });
@@ -9023,7 +9228,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9023
9228
  options.from = this.get(property);
9024
9229
  }
9025
9230
 
9026
- if (/[+-]/.test((to + '').charAt(0))) {
9231
+ if (/[+\-]/.test((to + '').charAt(0))) {
9027
9232
  to = this.get(property) + parseFloat(to);
9028
9233
  }
9029
9234
 
@@ -9176,7 +9381,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9176
9381
 
9177
9382
  });
9178
9383
 
9179
- })(typeof exports != 'undefined' ? exports : this);
9384
+ })(typeof exports !== 'undefined' ? exports : this);
9180
9385
 
9181
9386
  (function(global) {
9182
9387
 
@@ -9184,7 +9389,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9184
9389
 
9185
9390
  var fabric = global.fabric || (global.fabric = { }),
9186
9391
  extend = fabric.util.object.extend,
9187
- parentSet = fabric.Object.prototype.set,
9188
9392
  coordProps = { 'x1': 1, 'x2': 1, 'y1': 1, 'y2': 1 };
9189
9393
 
9190
9394
  if (fabric.Line) {
@@ -9212,6 +9416,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9212
9416
  * @return {fabric.Line} thisArg
9213
9417
  */
9214
9418
  initialize: function(points, options) {
9419
+ options = options || { };
9420
+
9215
9421
  if (!points) {
9216
9422
  points = [0, 0, 0, 0];
9217
9423
  }
@@ -9361,7 +9567,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9361
9567
  return new fabric.Line(points, object);
9362
9568
  };
9363
9569
 
9364
- })(typeof exports != 'undefined' ? exports : this);
9570
+ })(typeof exports !== 'undefined' ? exports : this);
9365
9571
  (function(global) {
9366
9572
 
9367
9573
  "use strict";
@@ -9436,7 +9642,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9436
9642
  _render: function(ctx, noTransform) {
9437
9643
  ctx.beginPath();
9438
9644
  // multiply by currently set alpha (the one that was set by path group where this object is contained, for example)
9439
- ctx.globalAlpha *= this.opacity;
9645
+ ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity;
9440
9646
  ctx.arc(noTransform ? this.left : 0, noTransform ? this.top : 0, this.radius, 0, piBy2, false);
9441
9647
  ctx.closePath();
9442
9648
  if (this.fill) {
@@ -9505,7 +9711,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9505
9711
  options || (options = { });
9506
9712
  var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES);
9507
9713
  if (!isValidRadius(parsedAttributes)) {
9508
- throw Error('value of `r` attribute is required and can not be negative');
9714
+ throw new Error('value of `r` attribute is required and can not be negative');
9509
9715
  }
9510
9716
  if ('left' in parsedAttributes) {
9511
9717
  parsedAttributes.left -= (options.width / 2) || 0;
@@ -9534,30 +9740,30 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9534
9740
  return new fabric.Circle(object);
9535
9741
  };
9536
9742
 
9537
- })(typeof exports != 'undefined' ? exports : this);
9743
+ })(typeof exports !== 'undefined' ? exports : this);
9538
9744
  (function(global) {
9539
-
9745
+
9540
9746
  "use strict";
9541
-
9747
+
9542
9748
  var fabric = global.fabric || (global.fabric = { });
9543
-
9749
+
9544
9750
  if (fabric.Triangle) {
9545
9751
  fabric.warn('fabric.Triangle is already defined');
9546
9752
  return;
9547
9753
  }
9548
-
9549
- /**
9754
+
9755
+ /**
9550
9756
  * @class Triangle
9551
9757
  * @extends fabric.Object
9552
9758
  */
9553
9759
  fabric.Triangle = fabric.util.createClass(fabric.Object, /** @scope fabric.Triangle.prototype */ {
9554
-
9760
+
9555
9761
  /**
9556
9762
  * @property
9557
9763
  * @type String
9558
9764
  */
9559
9765
  type: 'triangle',
9560
-
9766
+
9561
9767
  /**
9562
9768
  * Constructor
9563
9769
  * @method initialize
@@ -9566,28 +9772,28 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9566
9772
  */
9567
9773
  initialize: function(options) {
9568
9774
  options = options || { };
9569
-
9775
+
9570
9776
  this.callSuper('initialize', options);
9571
-
9777
+
9572
9778
  this.set('width', options.width || 100)
9573
9779
  .set('height', options.height || 100);
9574
9780
  },
9575
-
9781
+
9576
9782
  /**
9577
9783
  * @private
9578
9784
  * @method _render
9579
9785
  * @param ctx {CanvasRenderingContext2D} Context to render on
9580
9786
  */
9581
- _render: function(ctx) {
9787
+ _render: function(ctx) {
9582
9788
  var widthBy2 = this.width / 2,
9583
9789
  heightBy2 = this.height / 2;
9584
-
9790
+
9585
9791
  ctx.beginPath();
9586
9792
  ctx.moveTo(-widthBy2, heightBy2);
9587
9793
  ctx.lineTo(0, -heightBy2);
9588
9794
  ctx.lineTo(widthBy2, heightBy2);
9589
9795
  ctx.closePath();
9590
-
9796
+
9591
9797
  if (this.fill) {
9592
9798
  ctx.fill();
9593
9799
  }
@@ -9595,7 +9801,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9595
9801
  ctx.stroke();
9596
9802
  }
9597
9803
  },
9598
-
9804
+
9599
9805
  /**
9600
9806
  * Returns complexity of an instance
9601
9807
  * @method complexity
@@ -9604,7 +9810,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9604
9810
  complexity: function() {
9605
9811
  return 1;
9606
9812
  },
9607
-
9813
+
9608
9814
  /**
9609
9815
  * Returns svg representation of an instance
9610
9816
  * @method toSVG
@@ -9628,7 +9834,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9628
9834
  '/>';
9629
9835
  }
9630
9836
  });
9631
-
9837
+
9632
9838
  /**
9633
9839
  * Returns fabric.Triangle instance from an object representation
9634
9840
  * @static
@@ -9640,7 +9846,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9640
9846
  return new fabric.Triangle(object);
9641
9847
  };
9642
9848
 
9643
- })(typeof exports != 'undefined' ? exports : this);
9849
+ })(typeof exports !== 'undefined' ? exports : this);
9644
9850
  (function(global){
9645
9851
 
9646
9852
  "use strict";
@@ -9732,7 +9938,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9732
9938
  _render: function(ctx, noTransform) {
9733
9939
  ctx.beginPath();
9734
9940
  ctx.save();
9735
- ctx.globalAlpha *= this.opacity;
9941
+ ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity;
9736
9942
  if (this.transformMatrix && this.group) {
9737
9943
  ctx.translate(this.cx, this.cy);
9738
9944
  }
@@ -9805,7 +10011,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9805
10011
  return new fabric.Ellipse(object);
9806
10012
  };
9807
10013
 
9808
- })(typeof exports != 'undefined' ? exports : this);
10014
+ })(typeof exports !== 'undefined' ? exports : this);
9809
10015
  (function(global) {
9810
10016
 
9811
10017
  "use strict";
@@ -9824,18 +10030,21 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9824
10030
  fabric.Rect = fabric.util.createClass(fabric.Object, /** @scope fabric.Rect.prototype */ {
9825
10031
 
9826
10032
  /**
10033
+ * Type of the instance
9827
10034
  * @property
9828
10035
  * @type String
9829
10036
  */
9830
10037
  type: 'rect',
9831
10038
 
9832
10039
  /**
10040
+ * Horizontal border radius
9833
10041
  * @property
9834
10042
  * @type Number
9835
10043
  */
9836
10044
  rx: 0,
9837
10045
 
9838
10046
  /**
10047
+ * Vertical border radius
9839
10048
  * @property
9840
10049
  * @type Number
9841
10050
  */
@@ -9848,6 +10057,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9848
10057
  * @return {Object} thisArg
9849
10058
  */
9850
10059
  initialize: function(options) {
10060
+ options = options || { };
10061
+
9851
10062
  this._initStateProperties();
9852
10063
  this.callSuper('initialize', options);
9853
10064
  this._initRxRy();
@@ -9890,7 +10101,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9890
10101
  h = this.height;
9891
10102
 
9892
10103
  ctx.beginPath();
9893
- ctx.globalAlpha *= this.opacity;
10104
+ ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity;
9894
10105
 
9895
10106
  if (this.transformMatrix && this.group) {
9896
10107
  ctx.translate(
@@ -9926,7 +10137,11 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9926
10137
  }
9927
10138
  },
9928
10139
 
9929
- // since our coordinate system differs from that of SVG
10140
+ /**
10141
+ * @method _normalizeLeftTopProperties
10142
+ * @private
10143
+ * Since coordinate system differs from that of SVG
10144
+ */
9930
10145
  _normalizeLeftTopProperties: function(parsedAttributes) {
9931
10146
  if (parsedAttributes.left) {
9932
10147
  this.set('left', parsedAttributes.left + this.getWidth() / 2);
@@ -9940,6 +10155,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
9940
10155
  },
9941
10156
 
9942
10157
  /**
10158
+ * Returns complexity of an instance
9943
10159
  * @method complexity
9944
10160
  * @return {Number} complexity
9945
10161
  */
@@ -10025,7 +10241,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
10025
10241
  return new fabric.Rect(object);
10026
10242
  };
10027
10243
 
10028
- })(typeof exports != 'undefined' ? exports : this);
10244
+ })(typeof exports !== 'undefined' ? exports : this);
10029
10245
  (function(global) {
10030
10246
 
10031
10247
  "use strict";
@@ -10177,7 +10393,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
10177
10393
  return new fabric.Polyline(points, object);
10178
10394
  };
10179
10395
 
10180
- })(typeof exports != 'undefined' ? exports : this);
10396
+ })(typeof exports !== 'undefined' ? exports : this);
10181
10397
  (function(global) {
10182
10398
 
10183
10399
  "use strict";
@@ -10193,9 +10409,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
10193
10409
  return;
10194
10410
  }
10195
10411
 
10196
- function byX(p) { return p.x; }
10197
- function byY(p) { return p.y; }
10198
-
10199
10412
  /**
10200
10413
  * @class Polygon
10201
10414
  * @extends fabric.Object
@@ -10348,7 +10561,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
10348
10561
  return new fabric.Polygon(object.points, object);
10349
10562
  };
10350
10563
 
10351
- })(typeof exports != 'undefined' ? exports : this);
10564
+ })(typeof exports !== 'undefined' ? exports : this);
10352
10565
  (function(global) {
10353
10566
 
10354
10567
  var commandLengths = {
@@ -10417,7 +10630,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
10417
10630
  var sfactor_sq = 1 / d - 0.25;
10418
10631
  if (sfactor_sq < 0) sfactor_sq = 0;
10419
10632
  var sfactor = Math.sqrt(sfactor_sq);
10420
- if (sweep == large) sfactor = -sfactor;
10633
+ if (sweep === large) sfactor = -sfactor;
10421
10634
  var xc = 0.5 * (x0 + x1) - sfactor * (y1-y0);
10422
10635
  var yc = 0.5 * (y0 + y1) + sfactor * (x1-x0);
10423
10636
 
@@ -10425,9 +10638,9 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
10425
10638
  var th1 = Math.atan2(y1-yc, x1-xc);
10426
10639
 
10427
10640
  var th_arc = th1-th0;
10428
- if (th_arc < 0 && sweep == 1){
10641
+ if (th_arc < 0 && sweep === 1){
10429
10642
  th_arc += 2*Math.PI;
10430
- } else if (th_arc > 0 && sweep == 0) {
10643
+ } else if (th_arc > 0 && sweep === 0) {
10431
10644
  th_arc -= 2 * Math.PI;
10432
10645
  }
10433
10646
 
@@ -10481,10 +10694,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
10481
10694
  fabric.warn('fabric.Path is already defined');
10482
10695
  return;
10483
10696
  }
10484
- if (!fabric.Object) {
10485
- fabric.warn('fabric.Path requires fabric.Object');
10486
- return;
10487
- }
10488
10697
 
10489
10698
  /**
10490
10699
  * @private
@@ -10530,7 +10739,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
10530
10739
  this.setOptions(options);
10531
10740
 
10532
10741
  if (!path) {
10533
- throw Error('`path` argument is required');
10742
+ throw new Error('`path` argument is required');
10534
10743
  }
10535
10744
 
10536
10745
  var fromArray = _toString.call(path) === '[object Array]';
@@ -10982,7 +11191,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
10982
11191
  chunks,
10983
11192
  parsed;
10984
11193
 
10985
- for (var i = 0, j, chunksParsed, len = this.path.length; i < len; i++) {
11194
+ for (var i = 0, chunksParsed, len = this.path.length; i < len; i++) {
10986
11195
  currentPath = this.path[i];
10987
11196
  chunks = currentPath.slice(1).trim().replace(/(\d)-/g, '$1###-').split(/\s|,|###/);
10988
11197
  chunksParsed = [ currentPath.charAt(0) ];
@@ -11110,7 +11319,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11110
11319
  return new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options));
11111
11320
  };
11112
11321
 
11113
- })(typeof exports != 'undefined' ? exports : this);
11322
+ })(typeof exports !== 'undefined' ? exports : this);
11114
11323
  (function(global) {
11115
11324
 
11116
11325
  "use strict";
@@ -11118,7 +11327,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11118
11327
  var fabric = global.fabric || (global.fabric = { }),
11119
11328
  extend = fabric.util.object.extend,
11120
11329
  invoke = fabric.util.array.invoke,
11121
- parentSet = fabric.Object.prototype.set,
11122
11330
  parentToObject = fabric.Object.prototype.toObject,
11123
11331
  camelize = fabric.util.string.camelize,
11124
11332
  capitalize = fabric.util.string.capitalize;
@@ -11226,7 +11434,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11226
11434
  */
11227
11435
  toObject: function() {
11228
11436
  return extend(parentToObject.call(this), {
11229
- paths: invoke(this.getObjects(), 'clone'),
11437
+ paths: invoke(this.getObjects(), 'toObject'),
11230
11438
  sourcePath: this.sourcePath
11231
11439
  });
11232
11440
  },
@@ -11339,7 +11547,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11339
11547
  }
11340
11548
 
11341
11549
  /**
11342
- * Creates fabric.Triangle instance from an object representation
11550
+ * Creates fabric.PathGroup instance from an object representation
11343
11551
  * @static
11344
11552
  * @method fabric.PathGroup.fromObject
11345
11553
  * @param {Object} object
@@ -11350,7 +11558,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11350
11558
  return new fabric.PathGroup(paths, object);
11351
11559
  };
11352
11560
 
11353
- })(typeof exports != 'undefined' ? exports : this);
11561
+ })(typeof exports !== 'undefined' ? exports : this);
11354
11562
  (function(global){
11355
11563
 
11356
11564
  "use strict";
@@ -11386,6 +11594,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11386
11594
  * @return {Object} thisArg
11387
11595
  */
11388
11596
  initialize: function(objects, options) {
11597
+ options = options || { };
11598
+
11389
11599
  this.objects = objects || [];
11390
11600
  this.originalState = { };
11391
11601
 
@@ -11546,7 +11756,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11546
11756
  */
11547
11757
  toObject: function() {
11548
11758
  return extend(this.callSuper('toObject'), {
11549
- objects: invoke(this.objects, 'clone')
11759
+ objects: invoke(this.objects, 'toObject')
11550
11760
  });
11551
11761
  },
11552
11762
 
@@ -11561,8 +11771,11 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11561
11771
 
11562
11772
  var groupScaleFactor = Math.max(this.scaleX, this.scaleY);
11563
11773
 
11564
- for (var i = 0, len = this.objects.length, object; object = this.objects[i]; i++) {
11774
+ for (var i = 0, len = this.objects.length; i < len; i++) {
11775
+
11776
+ var object = this.objects[i];
11565
11777
  var originalScaleFactor = object.borderScaleFactor;
11778
+
11566
11779
  object.borderScaleFactor = groupScaleFactor;
11567
11780
  object.render(ctx);
11568
11781
  object.borderScaleFactor = originalScaleFactor;
@@ -11592,7 +11805,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11592
11805
  */
11593
11806
  complexity: function() {
11594
11807
  return this.getObjects().reduce(function(total, object) {
11595
- total += (typeof object.complexity == 'function') ? object.complexity() : 0;
11808
+ total += (typeof object.complexity === 'function') ? object.complexity() : 0;
11596
11809
  return total;
11597
11810
  }, 0);
11598
11811
  },
@@ -11621,8 +11834,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11621
11834
  var groupLeft = this.get('left'),
11622
11835
  groupTop = this.get('top'),
11623
11836
  groupAngle = this.getAngle() * (Math.PI / 180),
11624
- objectLeft = object.get('originalLeft'),
11625
- objectTop = object.get('originalTop'),
11626
11837
  rotatedTop = Math.cos(groupAngle) * object.get('top') + Math.sin(groupAngle) * object.get('left'),
11627
11838
  rotatedLeft = -Math.sin(groupAngle) * object.get('top') + Math.cos(groupAngle) * object.get('left');
11628
11839
 
@@ -11752,7 +11963,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11752
11963
  aX.push(o.oCoords[prop].x);
11753
11964
  aY.push(o.oCoords[prop].y);
11754
11965
  }
11755
- };
11966
+ }
11756
11967
 
11757
11968
  minX = min(aX);
11758
11969
  maxX = max(aX);
@@ -11834,7 +12045,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11834
12045
 
11835
12046
  fabric.Group.async = true;
11836
12047
 
11837
- })(typeof exports != 'undefined' ? exports : this);
12048
+ })(typeof exports !== 'undefined' ? exports : this);
11838
12049
  (function(global) {
11839
12050
 
11840
12051
  "use strict";
@@ -11848,11 +12059,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11848
12059
  if (global.fabric.Image) {
11849
12060
  fabric.warn('fabric.Image is already defined.');
11850
12061
  return;
11851
- };
11852
-
11853
- if (!fabric.Object) {
11854
- fabric.warn('fabric.Object is required for fabric.Image initialization');
11855
- return;
11856
12062
  }
11857
12063
 
11858
12064
  /**
@@ -11867,18 +12073,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11867
12073
  */
11868
12074
  active: false,
11869
12075
 
11870
- /**
11871
- * @property
11872
- * @type Boolean
11873
- */
11874
- bordervisibility: false,
11875
-
11876
- /**
11877
- * @property
11878
- * @type Boolean
11879
- */
11880
- cornervisibility: false,
11881
-
11882
12076
  /**
11883
12077
  * @property
11884
12078
  * @type String
@@ -11941,26 +12135,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
11941
12135
  };
11942
12136
  },
11943
12137
 
11944
- /**
11945
- * Sets border visibility
11946
- * @method setBorderVisibility
11947
- * @param {Boolean} visible When true, border is set to be visible
11948
- */
11949
- setBorderVisibility: function(visible) {
11950
- this._resetWidthHeight();
11951
- this._adjustWidthHeightToBorders(showBorder);
11952
- this.setCoords();
11953
- },
11954
-
11955
- /**
11956
- * Sets corner visibility
11957
- * @method setCornersVisibility
11958
- * @param {Boolean} visible When true, corners are set to be visible
11959
- */
11960
- setCornersVisibility: function(visible) {
11961
- this.cornervisibility = !!visible;
11962
- },
11963
-
11964
12138
  /**
11965
12139
  * Renders image on a specified context
11966
12140
  * @method render
@@ -12060,10 +12234,10 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
12060
12234
  var isLikelyNode = typeof Buffer !== 'undefined' && typeof window === 'undefined',
12061
12235
  imgEl = this._originalImage,
12062
12236
  canvasEl = fabric.document.createElement('canvas'),
12063
- replacement = isLikelyNode ? new (require('canvas').Image) : fabric.document.createElement('img'),
12237
+ replacement = isLikelyNode ? new (require('canvas').Image)() : fabric.document.createElement('img'),
12064
12238
  _this = this;
12065
12239
 
12066
- if (!canvasEl.getContext && typeof G_vmlCanvasManager != 'undefined') {
12240
+ if (!canvasEl.getContext && typeof G_vmlCanvasManager !== 'undefined') {
12067
12241
  G_vmlCanvasManager.initElement(canvasEl);
12068
12242
  }
12069
12243
 
@@ -12102,6 +12276,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
12102
12276
 
12103
12277
  /**
12104
12278
  * @private
12279
+ * @method _render
12105
12280
  */
12106
12281
  _render: function(ctx) {
12107
12282
  ctx.drawImage(
@@ -12115,20 +12290,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
12115
12290
 
12116
12291
  /**
12117
12292
  * @private
12118
- */
12119
- _adjustWidthHeightToBorders: function(showBorder) {
12120
- if (showBorder) {
12121
- this.currentBorder = this.borderwidth;
12122
- this.width += (2 * this.currentBorder);
12123
- this.height += (2 * this.currentBorder);
12124
- }
12125
- else {
12126
- this.currentBorder = 0;
12127
- }
12128
- },
12129
-
12130
- /**
12131
- * @private
12293
+ * @method _resetWidthHeight
12132
12294
  */
12133
12295
  _resetWidthHeight: function() {
12134
12296
  var element = this.getElement();
@@ -12140,6 +12302,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
12140
12302
  /**
12141
12303
  * The Image class's initialization method. This method is automatically
12142
12304
  * called by the constructor.
12305
+ * @private
12143
12306
  * @method _initElement
12144
12307
  * @param {HTMLImageElement|String} el The element representing the image
12145
12308
  */
@@ -12149,17 +12312,18 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
12149
12312
  },
12150
12313
 
12151
12314
  /**
12315
+ * @private
12152
12316
  * @method _initConfig
12153
12317
  * @param {Object} options Options object
12154
12318
  */
12155
12319
  _initConfig: function(options) {
12156
12320
  options || (options = { });
12157
12321
  this.setOptions(options);
12158
- this._setBorder();
12159
12322
  this._setWidthHeight(options);
12160
12323
  },
12161
12324
 
12162
12325
  /**
12326
+ * @private
12163
12327
  * @method _initFilters
12164
12328
  * @param {Object} object Object with filters property
12165
12329
  */
@@ -12173,29 +12337,17 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
12173
12337
 
12174
12338
  /**
12175
12339
  * @private
12176
- */
12177
- _setBorder: function() {
12178
- if (this.bordervisibility) {
12179
- this.currentBorder = this.borderwidth;
12180
- }
12181
- else {
12182
- this.currentBorder = 0;
12183
- }
12184
- },
12185
-
12186
- /**
12187
- * @private
12340
+ * @method _setWidthHeight
12341
+ * @param {Object} options Object with width/height properties
12188
12342
  */
12189
12343
  _setWidthHeight: function(options) {
12190
- var sidesBorderWidth = 2 * this.currentBorder;
12191
-
12192
12344
  this.width = 'width' in options
12193
12345
  ? options.width
12194
- : ((this.getElement().width || 0) + sidesBorderWidth);
12346
+ : (this.getElement().width || 0);
12195
12347
 
12196
12348
  this.height = 'height' in options
12197
12349
  ? options.height
12198
- : ((this.getElement().height || 0) + sidesBorderWidth);
12350
+ : (this.getElement().height || 0);
12199
12351
  },
12200
12352
 
12201
12353
  /**
@@ -12293,7 +12445,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, {
12293
12445
 
12294
12446
  fabric.Image.async = true;
12295
12447
 
12296
- })(typeof exports != 'undefined' ? exports : this);
12448
+ })(typeof exports !== 'undefined' ? exports : this);
12297
12449
 
12298
12450
  fabric.util.object.extend(fabric.Object.prototype, {
12299
12451
 
@@ -12855,29 +13007,29 @@ fabric.Image.filters.Tint = fabric.util.createClass( /** @scope fabric.Image.fil
12855
13007
  * @param {Object} canvasEl Canvas element to apply filter to
12856
13008
  */
12857
13009
  applyTo: function(canvasEl) {
12858
-
13010
+
12859
13011
  var context = canvasEl.getContext('2d'),
12860
13012
  imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
12861
13013
  data = imageData.data,
12862
- iLen = data.length, i,
12863
- r, g, b, a;
12864
-
12865
- var rgb = parseInt(this.color).toString(16);
12866
- var cr = parseInt('0x'+rgb.substr(0, 2));
12867
- var cg = parseInt('0x'+rgb.substr(2, 2));
12868
- var cb = parseInt('0x'+rgb.substr(4, 2));
12869
-
13014
+ iLen = data.length, i, a;
13015
+
13016
+ var rgb = parseInt(this.color, 10).toString(16);
13017
+
13018
+ var cr = parseInt('0x' + rgb.substr(0, 2), 16);
13019
+ var cg = parseInt('0x' + rgb.substr(2, 2), 16);
13020
+ var cb = parseInt('0x' + rgb.substr(4, 2), 16);
13021
+
12870
13022
  for (i = 0; i < iLen; i+=4) {
12871
13023
 
12872
13024
  a = data[i+3];
12873
-
12874
- if (a > 0){
13025
+
13026
+ if (a > 0){
12875
13027
  data[i] = cr;
12876
13028
  data[i+1] = cg;
12877
- data[i+2] = cb;
12878
- }
13029
+ data[i+2] = cb;
13030
+ }
12879
13031
  }
12880
-
13032
+
12881
13033
  context.putImageData(imageData, 0, 0);
12882
13034
  },
12883
13035
 
@@ -12909,10 +13061,6 @@ fabric.Image.filters.Tint.fromObject = function(object) {
12909
13061
  fabric.warn('fabric.Text is already defined');
12910
13062
  return;
12911
13063
  }
12912
- if (!fabric.Object) {
12913
- fabric.warn('fabric.Text requires fabric.Object');
12914
- return;
12915
- }
12916
13064
 
12917
13065
  /**
12918
13066
  * @class Text
@@ -13015,9 +13163,11 @@ fabric.Image.filters.Tint.fromObject = function(object) {
13015
13163
  * @return {fabric.Text} thisArg
13016
13164
  */
13017
13165
  initialize: function(text, options) {
13166
+ options = options || { };
13167
+
13018
13168
  this._initStateProperties();
13019
13169
  this.text = text;
13020
- this.setOptions(options || { });
13170
+ this.setOptions(options);
13021
13171
  this._theta = this.angle * Math.PI / 180;
13022
13172
  this._initDimensions();
13023
13173
  this.setCoords();
@@ -13031,7 +13181,7 @@ fabric.Image.filters.Tint.fromObject = function(object) {
13031
13181
  _initDimensions: function() {
13032
13182
  var canvasEl = fabric.document.createElement('canvas');
13033
13183
 
13034
- if (!canvasEl.getContext && typeof G_vmlCanvasManager != 'undefined') {
13184
+ if (!canvasEl.getContext && typeof G_vmlCanvasManager !== 'undefined') {
13035
13185
  G_vmlCanvasManager.initElement(canvasEl);
13036
13186
  }
13037
13187
 
@@ -13343,29 +13493,30 @@ fabric.Image.filters.Tint.fromObject = function(object) {
13343
13493
  _renderTextDecoration: function(ctx, textLines) {
13344
13494
 
13345
13495
  var halfOfVerticalBox = this._getTextHeight(ctx, textLines) / 2;
13496
+ var _this = this;
13346
13497
 
13347
13498
  function renderLinesAtOffset(offset) {
13348
13499
  for (var i = 0, len = textLines.length; i < len; i++) {
13349
13500
 
13350
13501
  var lineWidth = ctx.measureText(textLines[i]).width;
13351
- var lineLeftOffset = this._getLineLeftOffset(lineWidth);
13502
+ var lineLeftOffset = _this._getLineLeftOffset(lineWidth);
13352
13503
 
13353
13504
  ctx.fillRect(
13354
- (-this.width / 2) + lineLeftOffset,
13355
- (offset + (i * this.fontSize * this.lineHeight)) - halfOfVerticalBox,
13505
+ (-_this.width / 2) + lineLeftOffset,
13506
+ (offset + (i * _this.fontSize * _this.lineHeight)) - halfOfVerticalBox,
13356
13507
  lineWidth,
13357
13508
  1);
13358
13509
  }
13359
13510
  }
13360
13511
 
13361
13512
  if (this.textDecoration.indexOf('underline') > -1) {
13362
- renderLinesAtOffset.call(this, this.fontSize);
13513
+ renderLinesAtOffset(this.fontSize);
13363
13514
  }
13364
13515
  if (this.textDecoration.indexOf('line-through') > -1) {
13365
- renderLinesAtOffset.call(this, this.fontSize / 2);
13516
+ renderLinesAtOffset(this.fontSize / 2);
13366
13517
  }
13367
13518
  if (this.textDecoration.indexOf('overline') > -1) {
13368
- renderLinesAtOffset.call(this, 0);
13519
+ renderLinesAtOffset(0);
13369
13520
  }
13370
13521
  },
13371
13522
 
@@ -13393,7 +13544,7 @@ fabric.Image.filters.Tint.fromObject = function(object) {
13393
13544
  // Cufon doesn't play nice with textDecoration=underline if element doesn't have a parent
13394
13545
  container.appendChild(el);
13395
13546
 
13396
- if (typeof G_vmlCanvasManager == 'undefined') {
13547
+ if (typeof G_vmlCanvasManager === 'undefined') {
13397
13548
  el.innerHTML = this.text;
13398
13549
  }
13399
13550
  else {
@@ -13677,16 +13828,16 @@ fabric.Image.filters.Tint.fromObject = function(object) {
13677
13828
  }
13678
13829
 
13679
13830
  var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES);
13680
- var options = fabric.util.object.extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes);
13831
+ options = fabric.util.object.extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes);
13681
13832
  var text = new fabric.Text(element.textContent, options);
13682
13833
 
13683
13834
  return text;
13684
13835
  };
13685
13836
 
13686
- })(typeof exports != 'undefined' ? exports : this);
13837
+ })(typeof exports !== 'undefined' ? exports : this);
13687
13838
  (function() {
13688
13839
 
13689
- if (typeof document != 'undefined' && typeof window != 'undefined') {
13840
+ if (typeof document !== 'undefined' && typeof window !== 'undefined') {
13690
13841
  return;
13691
13842
  }
13692
13843
 
@@ -13700,7 +13851,7 @@ fabric.Image.filters.Tint.fromObject = function(object) {
13700
13851
  function request(url, encoding, callback) {
13701
13852
  var oURL = URL.parse(url),
13702
13853
  client = HTTP.createClient(oURL.port, oURL.hostname),
13703
- request = client.request('GET', oURL.pathname, { 'host': oURL.hostname });
13854
+ req = client.request('GET', oURL.pathname, { 'host': oURL.hostname });
13704
13855
 
13705
13856
  client.addListener('error', function(err) {
13706
13857
  if (err.errno === process.ECONNREFUSED) {
@@ -13711,8 +13862,8 @@ fabric.Image.filters.Tint.fromObject = function(object) {
13711
13862
  }
13712
13863
  });
13713
13864
 
13714
- request.end();
13715
- request.on('response', function (response) {
13865
+ req.end();
13866
+ req.on('response', function (response) {
13716
13867
  var body = "";
13717
13868
  if (encoding) {
13718
13869
  response.setEncoding(encoding);
@@ -13721,7 +13872,7 @@ fabric.Image.filters.Tint.fromObject = function(object) {
13721
13872
  callback(body);
13722
13873
  });
13723
13874
  response.on('data', function (chunk) {
13724
- if (response.statusCode == 200) {
13875
+ if (response.statusCode === 200) {
13725
13876
  body += chunk;
13726
13877
  }
13727
13878
  });
@@ -13787,8 +13938,8 @@ fabric.Image.filters.Tint.fromObject = function(object) {
13787
13938
  canvasEl.width = nodeCanvas.width;
13788
13939
  canvasEl.height = nodeCanvas.height;
13789
13940
 
13790
- var canvas = fabric.Canvas || fabric.StaticCanvas;
13791
- var fabricCanvas = new canvas(canvasEl);
13941
+ var FabricCanvas = fabric.Canvas || fabric.StaticCanvas;
13942
+ var fabricCanvas = new FabricCanvas(canvasEl);
13792
13943
  fabricCanvas.contextContainer = nodeCanvas.getContext('2d');
13793
13944
  fabricCanvas.nodeCanvas = nodeCanvas;
13794
13945
 
@@ -13798,9 +13949,6 @@ fabric.Image.filters.Tint.fromObject = function(object) {
13798
13949
  fabric.StaticCanvas.prototype.createPNGStream = function() {
13799
13950
  return this.nodeCanvas.createPNGStream();
13800
13951
  };
13801
- if (fabric.Canvas) {
13802
- fabric.Canvas.prototype.createPNGStream
13803
- }
13804
13952
 
13805
13953
  var origSetWidth = fabric.StaticCanvas.prototype.setWidth;
13806
13954
  fabric.StaticCanvas.prototype.setWidth = function(width) {
@@ -13822,4 +13970,4 @@ fabric.Image.filters.Tint.fromObject = function(object) {
13822
13970
  fabric.Canvas.prototype.setHeight = fabric.StaticCanvas.prototype.setHeight;
13823
13971
  }
13824
13972
 
13825
- })();
13973
+ })();