ElmRuntime.Render.Element = function() { 'use strict'; var Utils = ElmRuntime.use(ElmRuntime.Render.Utils); var newElement = Utils.newElement, addTo = Utils.addTo, extract = Utils.extract, addTransform = Utils.addTransform, removeTransform = Utils.removeTransform; function setProps(props, e) { e.style.width = (props.width |0) + 'px'; e.style.height = (props.height|0) + 'px'; if (props.opacity !== 1) { e.style.opacity = props.opacity; } if (props.color.ctor === 'Just') { e.style.backgroundColor = extract(props.color._0); } if (props.tag !== '') { e.id = props.tag; } if (props.href !== '') { var a = newElement('a'); a.href = props.href; addTo(a,e); return a; } return e; } function image(props, img) { switch (img._0.ctor) { case 'Plain': return plainImage(img._3); case 'Fitted': return fittedImage(props.width, props.height, img._3); case 'Cropped': return croppedImage(img,props.width,props.height,img._3); } } function plainImage(src) { var img = newElement('img'); img.src = src; img.name = src; img.style.display = "block"; return img; } function fittedImage(w, h, src) { var e = newElement('div'); e.style.position = "relative"; e.style.overflow = "hidden"; var img = newElement('img'); img.onload = function() { img.style.position = 'absolute'; img.style.margin = 'auto'; var sw = w, sh = h; if (w / h > this.width / this.height) { sh = Math.round(this.height * w / this.width); } else { sw = Math.round(this.width * h / this.height); } img.style.width = sw + 'px'; img.style.height = sh + 'px'; img.style.left = ((w - sw) / 2) + 'px'; img.style.top = ((h - sh) / 2) + 'px'; }; img.src = src; img.name = src; addTo(e,img); return e; } function croppedImage(elem, w, h, src) { var pos = elem._0._0; var e = newElement('div'); e.style.position = "relative"; e.style.overflow = "hidden"; var img = newElement('img'); img.onload = function() { img.style.position = 'absolute'; img.style.margin = 'auto'; var sw = w / elem._1, sh = h / elem._2; img.style.width = ((this.width * sw)|0) + 'px'; img.style.height = ((this.height * sh)|0) + 'px'; img.style.left = ((- pos._0 * sw)|0) + 'px'; img.style.top = ((- pos._1 * sh)|0) + 'px'; }; img.src = src; img.name = src; addTo(e,img); return e; } function goIn(e) { e.style.position = 'absolute'; return e; } function goDown(e) { return e } function goRight(e) { e.style.styleFloat = e.style.cssFloat = "left"; return e; } function flowWith(f, array) { var container = newElement('div'); for (var i = array.length; i--; ) { addTo(container, f(render(array[i]))); } return container; } function flow(dir,elist) { var array = fromList(elist); switch(dir.ctor) { case "DDown": array.reverse(); case "DUp": return flowWith(goDown,array); case "DRight": array.reverse(); case "DLeft": return flowWith(goRight,array); case "DOut": array.reverse(); case "DIn": return flowWith(goIn,array); } } function toPos(pos) { switch(pos[0]) { case "Absolute": return pos[1] + "px"; case "Relative": return (pos[1] * 100) + "%"; } } function setPos(pos,w,h,e) { e.style.position = 'absolute'; e.style.margin = 'auto'; var transform = ''; switch(pos.horizontal) { case 'P': e.style.right = toPos(pos.x); break; case 'Z': transform = 'translateX(' + ((-w/2)|0) + 'px) '; case 'N': e.style.left = toPos(pos.x); break; } switch(pos.vertical) { case 'N': e.style.bottom = toPos(pos.x); break; case 'Z': transform += 'translateY(' + ((-h/2)|0) + 'px)'; case 'P': e.style.top = toPos(pos.x); break; } if (transform !== '') addTransform(e.style, transform); return e; } function container(pos,elem) { var e = render(elem); setPos(pos, elem.props.width, elem.props.height, e); var div = newElement('div'); div.style.position = 'relative'; div.style.overflow = 'hidden'; addTo(div,e); return div; } function rawHtml(html) { var e = newElement('div'); e.innerHTML = html; return e; } function render(elem) { return setProps(elem.props, makeElement(elem)); } function makeElement(e) { var elem = e.element; switch(elem.ctor) { case 'Image': return image(e.props, elem); case 'Flow': return flow(elem._0, elem._1); case 'Container': return container(elem._0, elem._1); case 'Spacer': return newElement('div'); case 'RawHtml': return rawHtml(elem._0); case 'Custom': return elem.render(elem.model); } } function update(node, curr, next) { if (node.tagName === 'A') { node = node.firstChild; } if (curr.props.id === next.props.id) return false; if (curr.element.ctor !== next.element.ctor) { node.parentNode.replaceChild(render(next),node); return true; } var nextE = next.element, currE = curr.element; switch(nextE.ctor) { case "Spacer": break; case "RawHtml": if (nextE._0 !== currE._0) node.innerHTML = nextE._0; break; case "Image": if (nextE._0.ctor === 'Plain') { if (nextE._3 !== currE._3) node.src = nextE._3; } else if (!eq(nextE,currE) || next.props.width !== curr.props.width || next.props.height !== curr.props.height) { node.parentNode.replaceChild(render(next),node); return true; } break; case "Flow": if (nextE._0.ctor !== currE._0.ctor) { node.parentNode.replaceChild(render(next),node); return true; } var nexts = nextE._1; var kids = node.childNodes; if (nexts.length !== kids.length) { node.parentNode.replaceChild(render(next),node); return true; } var currs = currE._1; var goDir = function(x) { return x; }; switch(nextE[1][0]) { case "DDown": case "DUp": goDir = goDown; break; case "DRight": case "DLeft": goDir = goRight; break; case "DOut": case "DIn": goDir = goIn; break; } for (var i = kids.length; i-- ;) { update(kids[i],currs[i],nexts[i]); goDir(kids[i]); } break; case "Container": var inner = node.firstChild; if (!update(inner, currE._1, nextE._1)) { if (nextE._0.horizontal.ctor !== currE._0.horizontal.ctor) { inner.style.left = inner.style.right = 'none'; removeTransform(inner.style); } if (nextE._0.vertical.ctor !== currE._0.vertical.ctor) { inner.style.top = inner.style.bottom = 'none'; removeTransform(inner.style); } } setPos(nextE._0, next.props.width, next.props.height, node.firstChild); break; case "Custom": node.parentNode.replaceChild(render(next),node); return true; } var props = next.props, currP = curr.props, e = node; if (props.width !== currP.width) e.style.width = (props.width |0) + 'px'; if (props.height !== currP.height) e.style.height = (props.height|0) + 'px'; if (props.opacity !== 1 && props.opacity !== currP.opacity) { e.style.opacity = props.opacity; } var nextColor = (props.color.ctor === 'Just' ? extract(props.color._0) : 'transparent'); if (e.style.backgroundColor !== nextColor) e.style.backgroundColor = nextColor; if (props.tag !== currP.tag) { e.id = props.tag; } if (props.href !== currP.href) { if (currP.href === '') { var a = newElement('a'); a.href = props.href; addTo(a,e); e.parentNode.replaceChild(a,e); } else { node.parentNode.href = props.href; } } } return { render:render, update:update }; };