Merge branch 'master' into 76_mount_dom
diff --git a/player/index.html b/player/index.html
index 38c55be..53001b0 100644
--- a/player/index.html
+++ b/player/index.html
@@ -172,27 +172,39 @@
     var animData = {
         container: elem,
         renderer: 'svg',
-        loop: false,
+        loop: true,
         autoplay: true,
         rendererSettings: {
-            progressiveLoad:true,
+            progressiveLoad: true,
             preserveAspectRatio: 'xMidYMid meet',
             imagePreserveAspectRatio: 'xMidYMid meet',
             title: 'TEST TITLE',
             description: 'TEST DESCRIPTION',
+            mount: true,
         },
-        path: 'exports/render/data.json'
+        path: 'exports/bm/data.json'
     };
-    // lottie.setQuality('low');
-    anim = lottie.loadAnimation(animData);
-    anim.setSubframe(false);
-    anim.onError = function(errorType, nativeError, errorProps) {
-        console.log(errorType)
-    }
 
-    anim.addEventListener('error', function(error) {
-        console.log(error)
-    })
+    function load() {
+        // lottie.setQuality('low');
+        anim = lottie.loadAnimation(animData);
+        // elem.style.width = '300px'
+        anim.setSubframe(false);
+        anim.onError = function(errorType, nativeError, errorProps) {
+            console.log(errorType)
+        }
+
+        anim.addEventListener('error', function(error) {
+            console.log(error)
+        })
+
+        /*setTimeout(() => {
+            anim.renderer.mount()
+        }, 2100)*/
+    }
+        
+    setTimeout(load, 0)
+    
 
 </script>
 </body>
diff --git a/player/js/renderers/SVGRenderer.js b/player/js/renderers/SVGRenderer.js
index 86838a2..bca69e6 100644
--- a/player/js/renderers/SVGRenderer.js
+++ b/player/js/renderers/SVGRenderer.js
@@ -37,9 +37,11 @@
         viewBoxSize: (config && config.viewBoxSize) || false,
         className: (config && config.className) || '',
         id: (config && config.id) || '',
-        focusable: config && config.focusable
+        focusable: config && config.focusable,
+        shouldMount: !(config && config.mount === false)
     };
 
+
     this.globalData = {
         _mdf: false,
         frameNum: -1,
@@ -106,9 +108,13 @@
         this.svgElement.setAttribute('focusable', this.renderConfig.focusable);
     }
     this.svgElement.setAttribute('preserveAspectRatio',this.renderConfig.preserveAspectRatio);
+
+    if(this.renderConfig.shouldMount) {
+        this.mount()
+    }
     //this.layerElement.style.transform = 'translate3d(0,0,0)';
     //this.layerElement.style.transformOrigin = this.layerElement.style.mozTransformOrigin = this.layerElement.style.webkitTransformOrigin = this.layerElement.style['-webkit-transform'] = "0px 0px 0px";
-    this.animationItem.wrapper.appendChild(this.svgElement);
+    
     //Mask animation
     var defs = this.globalData.defs;
 
@@ -254,3 +260,7 @@
 SVGRenderer.prototype.show = function(){
     this.layerElement.style.display = 'block';
 };
+
+SVGRenderer.prototype.mount = function() {
+    this.animationItem.wrapper.appendChild(this.svgElement.convert());
+}
\ No newline at end of file
diff --git a/player/js/utils/helpers/svg_elements.js b/player/js/utils/helpers/svg_elements.js
index 2cf5066..7d97c48 100644
--- a/player/js/utils/helpers/svg_elements.js
+++ b/player/js/utils/helpers/svg_elements.js
@@ -1,4 +1,120 @@
-function createNS(type) {
-	//return {appendChild:function(){},setAttribute:function(){},style:{}}
-	return document.createElementNS(svgNS, type);
-}
\ No newline at end of file
+var createNS = (function() {
+
+	function createDOMElement(type) {
+		// return {appendChild:function(){},insertBefore:function(){},setAttribute:function(){},style:{}}
+		return document.createElementNS(svgNS, type);
+	}
+
+	function VirtualElement(type) {
+		this.DOMElement = null
+		this.type = type
+		this.children = []
+		this.attributes = {}
+		this.attributesNS = {}
+		this.styleData = {}
+		this.style = {}
+	}
+
+	var virtualElementPrototype = {
+		appendChild: function(element) {
+			if (!this.DOMElement) {
+				this.children.push(element);
+			} else {
+				this.DOMElement.appendChild(element.convert());
+			}
+		},
+
+		insertBefore: function(element, child) {
+			if (!this.DOMElement) {
+				var i = 0, len = this.children.length;
+				while (i < len) {
+					if (this.children[i] === child) {
+						this.children.splice(i, 0, element);
+						break;
+					}
+					i += 1
+				}
+			} else {
+				this.DOMElement.insertBefore(element.convert(), child.convert());
+			}
+			
+		},
+
+		setAttribute: function(key, value) {
+			if(value != this.attributes[key]) {
+				this.attributes[key] = value;
+				if (this.DOMElement) {
+					this.DOMElement.setAttribute(key, value);
+				}
+			}
+		},
+
+		setAttributeNS: function(namespace, key, value) {
+			if(value != this.attributes[key]) {
+				this.attributesNS[namespace + '---' + key] = value;
+				if (this.DOMElement) {
+					this.DOMElement.attributesNS(namespace, key, value);
+				}
+			}
+		},
+
+		convert: function() { 
+			if (!this.DOMElement) {
+				var DOMElement = createDOMElement(this.type)
+				this.DOMElement = DOMElement
+
+				for (var attr in this.attributes) {
+					DOMElement.setAttribute(attr, this.attributes[attr]);
+				}
+
+				for (var attr in this.attributesNS) {
+					var nsValue = attr.split('---');
+					DOMElement.setAttributeNS(nsValue[0], nsValue[1], this.attributesNS[attr]);
+				}
+
+				for (var styleKey in this.style) {
+					DOMElement.style[styleKey] = this.style[styleKey]
+				}
+
+				var i, len = this.children.length;
+				for (i = 0; i < len; i += 1) {
+					DOMElement.appendChild(this.children[i].convert());
+				}
+
+				this.setAttribute = DOMElement.setAttribute.bind(DOMElement)
+				this.setAttributeNS = DOMElement.setAttributeNS.bind(DOMElement)
+				this.style = DOMElement.style
+				// this.appendChild = DOMElement.appendChild.bind(DOMElement)
+				// this.insertBefore = DOMElement.insertBefore.bind(DOMElement)
+
+			}
+			return this.DOMElement
+		}
+	}
+
+	/*Object.defineProperty(virtualElementPrototype, 'style', {
+        get: function() {
+            if (!this.DOMElement) {
+            	return this.styleData;
+            } else {
+            	return this.DOMElement.style;
+            }
+        }
+    });*/
+
+	VirtualElement.prototype = virtualElementPrototype;
+
+	return function(type, isMounted) {
+		if (isMounted) {
+			return createDOMElement(type)
+		} else {
+			return new VirtualElement(type)
+		}
+	}
+}())
+
+
+/*function createNS(type) {
+	return {appendChild:function(){},insertBefore:function(){},setAttribute:function(){},style:{}}
+	// return document.createElementNS(svgNS, type);
+}*/
\ No newline at end of file
diff --git a/player/js/utils/shapes/TrimModifier.js b/player/js/utils/shapes/TrimModifier.js
index a5df938..27f504f 100644
--- a/player/js/utils/shapes/TrimModifier.js
+++ b/player/js/utils/shapes/TrimModifier.js
@@ -104,6 +104,8 @@
     var pathsData, pathData, totalShapeLength, totalModifierLength = 0;
 
     if (e === s) {
+        // TODO this is updating path values more than needed. It would be good to try to avoid.
+        // But since it is an edge case it's not that bad.
         for (i = 0; i < len; i += 1) {
             this.shapes[i].localShapeCollection.releaseShapes();
             this.shapes[i].shape._mdf = true;