ElmRuntime.Render.Element = function() { 'use strict'; var Utils = ElmRuntime.use(ElmRuntime.Render.Utils); var newElement = Utils.newElement, extract = Utils.extract, addTransform = Utils.addTransform, removeTransform = Utils.removeTransform, fromList = Utils.fromList, eq = Utils.eq; 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; a.appendChild(e); return a; } if (props.hover.ctor !== '_Tuple0') { var overCount = 0; e.addEventListener('mouseover', function() { if (overCount++ > 0) return; props.hover(true); }); e.addEventListener('mouseout', function(evt) { if (e.contains(evt.toElement || evt.relatedTarget)) return; overCount = 0; props.hover(false); }); } 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); case 'Tiled': return tiledImage(img._3); } } function plainImage(src) { var img = newElement('img'); img.src = src; img.name = src; img.style.display = "block"; return img; } function tiledImage(src) { var div = newElement('div'); div.style.backgroundImage = 'url(' + src + ')'; return div; } function fittedImage(w, h, src) { var div = newElement('div'); div.style.background = 'url(' + src + ') no-repeat center'; div.style.webkitBackgroundSize = 'cover'; div.style.MozBackgroundSize = 'cover'; div.style.OBackgroundSize = 'cover'; div.style.backgroundSize = 'cover'; return div; } function croppedImage(elem, w, h, src) { var pos = elem._0._0; var e = newElement('div'); e.style.overflow = "hidden"; var img = newElement('img'); img.onload = function() { 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.marginLeft = ((- pos._0 * sw)|0) + 'px'; img.style.marginTop = ((- pos._1 * sh)|0) + 'px'; }; img.src = src; img.name = src; e.appendChild(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--; ) { container.appendChild(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.ctor) { case "Absolute": return pos._0 + "px"; case "Relative": return (pos._0 * 100) + "%"; } } function setPos(pos,w,h,e) { e.style.position = 'absolute'; e.style.margin = 'auto'; var transform = ''; switch(pos.horizontal.ctor) { 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.ctor) { case 'N': e.style.bottom = toPos(pos.y); break; case 'Z': transform += 'translateY(' + ((-h/2)|0) + 'px)'; case 'P': e.style.top = toPos(pos.y); 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'; div.appendChild(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 updateProps(node, curr, next); 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": var arr = fromList(nextE._1); for (var i = arr.length; i--; ) { arr[i] = arr[i].element.ctor; } if (nextE._0.ctor !== currE._0.ctor) { node.parentNode.replaceChild(render(next),node); return true; } var nexts = fromList(nextE._1); var kids = node.childNodes; if (nexts.length !== kids.length) { node.parentNode.replaceChild(render(next),node); return true; } var currs = fromList(currE._1); var goDir = function(x) { return x; }; switch(nextE._0.ctor) { 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, nextE._1.props.width, nextE._1.props.height, inner); break; case "Custom": if (currE.type === nextE.type) { var done = nextE.update(node, currE.model, nextE.model); if (done) return; } else { return node.parentNode.replaceChild(render(next), node); } } updateProps(node, curr, next); } function updateProps(node, curr, next) { 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; a.appendChild(e); e.parentNode.replaceChild(a,e); } else { node.parentNode.href = props.href; } } } return { render:render, update:update }; };