      1 function getById(id) {
      2   return typeof id === 'string' ? document.getElementById(id) : id;
      3 }
      4
      5 function toArray(arrayLike) {
      6   var arr = [ ], i = arrayLike.length;
      7   while (i--) {
      8     arr[i] = arrayLike[i];
      9   }
     10   return arr;
     11 }
     12
     13 function makeElement(tagName, attributes) {
     14   var el = document.createElement(tagName);
     15   for (var prop in attributes) {
     16     if (prop === 'class') {
     17       el.className = attributes[prop];
     18     }
     19     else if (prop === 'for') {
     20       el.htmlFor = attributes[prop];
     21     }
     22     else {
     23       el.setAttribute(prop, attributes[prop]);
     24     }
     25   }
     26   return el;
     27 }
     28
     29 function addClass(element, className) {
     30   if ((' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) {
     31     element.className += (element.className ? ' ' : '') + className;
     32   }
     33 }
     34
     35 function wrapElement(element, wrapper, attributes) {
     36   if (typeof wrapper === 'string') {
     37     wrapper = makeElement(wrapper, attributes);
     38   }
     39   if (element.parentNode) {
     40     element.parentNode.replaceChild(wrapper, element);
     41   }
     42   wrapper.appendChild(element);
     43   return wrapper;
     44 }
     45
     46 // TODO (kangax): need to fix this method
     47 function getElementOffset(element) {
     48   var valueT = 0, valueL = 0;
     49   do {
     50     valueT += element.offsetTop  || 0;
     51     valueL += element.offsetLeft || 0;
     52     element = element.offsetParent;
     53   }
     54   while (element);
     55   return ({ left: valueL, top: valueT });
     56 }
     57
     58 (function () {
     59   var style = document.documentElement.style;
     60
     61   var selectProp = 'userSelect' in style
     62     ? 'userSelect'
     63     : 'MozUserSelect' in style
     64       ? 'MozUserSelect'
     65       : 'WebkitUserSelect' in style
     66         ? 'WebkitUserSelect'
     67         : 'KhtmlUserSelect' in style
     68           ? 'KhtmlUserSelect'
     69           : '';
     70
     71   function makeElementUnselectable(element) {
     72     if (typeof element.onselectstart !== 'undefined') {
     73       element.onselectstart = fabric.util.falseFunction;
     74     }
     75     if (selectProp) {
     76       element.style[selectProp] = 'none';
     77     }
     78     else if (typeof element.unselectable == 'string') {
     79       element.unselectable = 'on';
     80     }
     81     return element;
     82   }
     83
     84   fabric.util.makeElementUnselectable = makeElementUnselectable;
     85 })();
     86
     87 (function(){
     88
     89   function getScript(url, callback) {
     90   	var headEl = document.getElementsByTagName("head")[0],
     91   	    scriptEl = document.createElement('script'),
     92   	    loading = true;
     93
     94   	scriptEl.type = 'text/javascript';
     95   	scriptEl.setAttribute('runat', 'server');
     96
     97   	/** @ignore */
     98   	scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) {
     99   	  if (loading) {
    100   	    if (typeof this.readyState == 'string' &&
    101   	        this.readyState !== 'loaded' &&
    102   	        this.readyState !== 'complete') return;
    103     	  loading = false;
    104     		callback(e || window.event);
    105     		scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null;
    106     	}
    107   	};
    108   	scriptEl.src = url;
    109   	headEl.appendChild(scriptEl);
    110   	// causes issue in Opera
    111   	// headEl.removeChild(scriptEl);
    112   }
    113
    114   function getScriptJaxer(url, callback) {
    115     Jaxer.load(url);
    116     callback();
    117   }
    118
    119   fabric.util.getScript = getScript;
    120
    121   var Jaxer = this.Jaxer;
    122   if (Jaxer && Jaxer.load) {
    123     fabric.util.getScript = getScriptJaxer;
    124   }
    125 })();
    126
    127 function animate(options) {
    128   options || (options = { });
    129   var start = +new Date(),
    130       duration = options.duration || 500,
    131       finish = start + duration, time, pos,
    132       onChange = options.onChange || function() { },
    133       easing = options.easing || function(pos) { return (-Math.cos(pos * Math.PI) / 2) + 0.5; },
    134       startValue = 'startValue' in options ? options.startValue : 0,
    135       endValue = 'endValue' in options ? options.endValue : 100,
    136       isReversed = startValue > endValue
    137
    138   options.onStart && options.onStart();
    139
    140   var interval = setInterval(function() {
    141     time = +new Date();
    142     pos = time > finish ? 1 : (time - start) / duration;
    143     onChange(isReversed
    144       ? (startValue - (startValue - endValue) * easing(pos))
    145       : (startValue + (endValue - startValue) * easing(pos)));
    146     if (time > finish) {
    147       clearInterval(interval);
    148       options.onComplete && options.onComplete();
    149     }
    150   }, 10);
    151 }
    152
    153 fabric.util.getById = getById;
    154 fabric.util.toArray = toArray;
    155 fabric.util.makeElement = makeElement;
    156 fabric.util.addClass = addClass;
    157 fabric.util.wrapElement = wrapElement;
    158 fabric.util.getElementOffset = getElementOffset;
    159 fabric.util.animate = animate;