@@ -1,469 +0,0 @@
2−ElmRuntime.Render.Element = function() {
5−var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
6−var newElement = Utils.newElement;
7−var colorToCss = Utils.colorToCss;
8−var addTransform = Utils.addTransform;
9−var removeTransform = Utils.removeTransform;
10−var fromList = Utils.fromList;
13−function setProps(elem, node) {
14− var props = elem.props;
16− var element = elem.element;
17− var width = props.width - (element.adjustWidth || 0);
18− var height = props.height - (element.adjustHeight || 0);
19− node.style.width = (width |0) + 'px';
20− node.style.height = (height|0) + 'px';
22− if (props.opacity !== 1) {
23− node.style.opacity = props.opacity;
26− if (props.color.ctor === 'Just') {
27− node.style.backgroundColor = colorToCss(props.color._0);
30− if (props.tag !== '') {
34− if (props.hover.ctor !== '_Tuple0') {
35− addHover(node, props.hover);
38− if (props.click.ctor !== '_Tuple0') {
39− addClick(node, props.click);
42− if (props.href !== '') {
43− var anchor = newElement('a');
44− anchor.href = props.href;
45− anchor.style.display = 'block';
46− anchor.style.pointerEvents = 'auto';
47− anchor.appendChild(node);
54−function addClick(e, handler) {
55− e.style.pointerEvents = 'auto';
56− e.elm_click_handler = handler;
57− function trigger(ev) {
58− e.elm_click_handler(Utils.Tuple0);
59− ev.stopPropagation();
61− e.elm_click_trigger = trigger;
62− e.addEventListener('click', trigger);
65−function removeClick(e, handler) {
66− if (e.elm_click_trigger) {
67− e.removeEventListener('click', e.elm_click_trigger);
68− e.elm_click_trigger = null;
69− e.elm_click_handler = null;
73−function addHover(e, handler) {
74− e.style.pointerEvents = 'auto';
75− e.elm_hover_handler = handler;
76− e.elm_hover_count = 0;
79− if (e.elm_hover_count++ > 0) return;
80− e.elm_hover_handler(true);
81− evt.stopPropagation();
84− if (e.contains(evt.toElement || evt.relatedTarget)) return;
85− e.elm_hover_count = 0;
86− e.elm_hover_handler(false);
87− evt.stopPropagation();
89− e.elm_hover_over = over;
90− e.elm_hover_out = out;
91− e.addEventListener('mouseover', over);
92− e.addEventListener('mouseout', out);
95−function removeHover(e) {
96− e.elm_hover_handler = null;
97− if (e.elm_hover_over) {
98− e.removeEventListener('mouseover', e.elm_hover_over);
99− e.elm_hover_over = null;
101− if (e.elm_hover_out) {
102− e.removeEventListener('mouseout', e.elm_hover_out);
103− e.elm_hover_out = null;
107−function image(props, img) {
108− switch (img._0.ctor) {
109− case 'Plain': return plainImage(img._3);
110− case 'Fitted': return fittedImage(props.width, props.height, img._3);
111− case 'Cropped': return croppedImage(img,props.width,props.height,img._3);
112− case 'Tiled': return tiledImage(img._3);
116−function plainImage(src) {
117− var img = newElement('img');
120− img.style.display = "block";
124−function tiledImage(src) {
125− var div = newElement('div');
126− div.style.backgroundImage = 'url(' + src + ')';
130−function fittedImage(w, h, src) {
131− var div = newElement('div');
132− div.style.background = 'url(' + src + ') no-repeat center';
133− div.style.webkitBackgroundSize = 'cover';
134− div.style.MozBackgroundSize = 'cover';
135− div.style.OBackgroundSize = 'cover';
136− div.style.backgroundSize = 'cover';
140−function croppedImage(elem, w, h, src) {
141− var pos = elem._0._0;
142− var e = newElement('div');
143− e.style.overflow = "hidden";
145− var img = newElement('img');
146− img.onload = function() {
147− var sw = w / elem._1, sh = h / elem._2;
148− img.style.width = ((this.width * sw)|0) + 'px';
149− img.style.height = ((this.height * sh)|0) + 'px';
150− img.style.marginLeft = ((- pos._0 * sw)|0) + 'px';
151− img.style.marginTop = ((- pos._1 * sh)|0) + 'px';
159−function goOut(e) { e.style.position = 'absolute'; return e; }
160−function goDown(e) { return e }
161−function goRight(e) { e.style.styleFloat = e.style.cssFloat = "left"; return e; }
163−var directionTable = {
171−function needsReversal(dir) {
172− return dir == 'DUp' || dir == 'DLeft' || dir == 'DIn';
175−function flow(dir,elist) {
176− var array = fromList(elist);
177− var container = newElement('div');
178− var goDir = directionTable[dir];
179− if (goDir == goOut) {
180− container.style.pointerEvents = 'none';
182− if (needsReversal(dir)) {
185− var len = array.length;
186− for (var i = 0; i < len; ++i) {
187− container.appendChild(goDir(render(array[i])));
192−function toPos(pos) {
194− case "Absolute": return pos._0 + "px";
195− case "Relative": return (pos._0 * 100) + "%";
199−// must clear right, left, top, bottom, and transform
200−// before calling this function
201−function setPos(pos,elem,e) {
202− var element = elem.element;
203− var props = elem.props;
204− var w = props.width + (element.adjustWidth ? element.adjustWidth : 0);
205− var h = props.height + (element.adjustHeight ? element.adjustHeight : 0);
207− e.style.position = 'absolute';
208− e.style.margin = 'auto';
210− switch(pos.horizontal.ctor) {
211− case 'P': e.style.right = toPos(pos.x); e.style.removeProperty('left'); break;
212− case 'Z': transform = 'translateX(' + ((-w/2)|0) + 'px) ';
213− case 'N': e.style.left = toPos(pos.x); e.style.removeProperty('right'); break;
215− switch(pos.vertical.ctor) {
216− case 'N': e.style.bottom = toPos(pos.y); e.style.removeProperty('top'); break;
217− case 'Z': transform += 'translateY(' + ((-h/2)|0) + 'px)';
218− case 'P': e.style.top = toPos(pos.y); e.style.removeProperty('bottom'); break;
220− if (transform !== '') addTransform(e.style, transform);
224−function container(pos,elem) {
225− var e = render(elem);
226− setPos(pos, elem, e);
227− var div = newElement('div');
228− div.style.position = 'relative';
229− div.style.overflow = 'hidden';
234−function rawHtml(elem) {
235− var html = elem.html;
236− var args = elem.args;
237− var guid = elem.guid;
238− var align = elem.align;
240− var div = newElement('div');
241− div.innerHTML = html;
242− div.style.visibility = "hidden";
243− if (align) div.style.textAlign = align;
244− document.body.appendChild(div);
246− for (var i = args.length; i--; ) {
248− var span = document.getElementById('md-' + guid + '-' + i);
250− span.innerHTML = arg;
252− span.style.display = 'block';
253− span.style.width = arg.props.width + 'px';
254− span.style.height = arg.props.height + 'px';
255− span.appendChild(render(arg));
258− document.body.removeChild(div);
259− div.style.visibility = 'visible';
260− div.style.pointerEvents = 'auto';
264−function render(elem) {
265− return setProps(elem, makeElement(elem));
267−function makeElement(e) {
268− var elem = e.element;
270− case 'Image': return image(e.props, elem);
271− case 'Flow': return flow(elem._0.ctor, elem._1);
272− case 'Container': return container(elem._0, elem._1);
273− case 'Spacer': return newElement('div');
274− case 'RawHtml': return rawHtml(elem);
275− case 'Custom': return elem.render(elem.model);
279−function update(node, curr, next) {
280− if (node.tagName === 'A') {
281− node = node.firstChild;
283− if (curr.props.id === next.props.id) {
284− return updateProps(node, curr, next);
286− if (curr.element.ctor !== next.element.ctor) {
287− node.parentNode.replaceChild(render(next),node);
290− var nextE = next.element, currE = curr.element;
291− switch(nextE.ctor) {
292− case "Spacer": break;
294− // only markdown blocks have guids, so this must be a text block
295− if (nextE.guid === null) {
296− if(currE.html.valueOf() !== nextE.html.valueOf()) {
297− node.innerHTML = nextE.html;
301− if (nextE.guid !== currE.guid) {
302− node.parentNode.replaceChild(render(next),node);
305− var nargs = nextE.args;
306− var cargs = currE.args;
307− for (var i = nargs.length; i--; ) {
308− var narg = nargs[i];
310− if (narg == carg) continue;
311− var span = document.getElementById('md-' + currE.guid + '-' + i);
312− if (narg.isElement) {
313− if (carg.isElement) {
314− update(span, carg, narg);
316− span.style.display = 'block';
317− var e = render(narg);
318− span.innerHTML = '';
319− span.appendChild(e);
322− span.style.display = 'inline';
323− span.innerHTML = narg;
328− if (nextE._0.ctor === 'Plain') {
329− if (nextE._3 !== currE._3) node.src = nextE._3;
330− } else if (!eq(nextE,currE) ||
331− next.props.width !== curr.props.width ||
332− next.props.height !== curr.props.height) {
333− node.parentNode.replaceChild(render(next),node);
338− var arr = fromList(nextE._1);
339− for (var i = arr.length; i--; ) { arr[i] = arr[i].element.ctor; }
340− if (nextE._0.ctor !== currE._0.ctor) {
341− node.parentNode.replaceChild(render(next),node);
344− var nexts = fromList(nextE._1);
345− var kids = node.childNodes;
346− if (nexts.length !== kids.length) {
347− node.parentNode.replaceChild(render(next),node);
350− var currs = fromList(currE._1);
351− var dir = nextE._0.ctor;
352− var goDir = directionTable[dir];
353− var toReverse = needsReversal(dir);
354− var len = kids.length;
355− for (var i = len; i-- ;) {
356− update(kids[toReverse ? len - i - 1 : i],currs[i],nexts[i]);
361− update(node.firstChild, currE._1, nextE._1);
362− setPos(nextE._0, nextE._1, node.firstChild);
365− if (currE.type === nextE.type) {
366− var done = nextE.update(node, currE.model, nextE.model);
369− return node.parentNode.replaceChild(render(next), node);
372− updateProps(node, curr, next);
375−function updateProps(node, curr, next) {
376− var nextProps = next.props;
377− var currProps = curr.props;
379− var element = next.element;
380− var width = nextProps.width - (element.adjustWidth || 0);
381− var height = nextProps.height - (element.adjustHeight || 0);
382− if (width !== currProps.width) {
383− node.style.width = (width|0) + 'px';
385− if (height !== currProps.height) {
386− node.style.height = (height|0) + 'px';
389− if (nextProps.opacity !== currProps.opacity) {
390− node.style.opacity = nextProps.opacity;
393− var nextColor = nextProps.color.ctor === 'Just'
394− ? colorToCss(nextProps.color._0)
396− if (node.style.backgroundColor !== nextColor) {
397− node.style.backgroundColor = nextColor;
400− if (nextProps.tag !== currProps.tag) {
401− node.id = nextProps.tag;
404− if (nextProps.href !== currProps.href) {
405− if (currProps.href === '') {
406− // add a surrounding href
407− var anchor = newElement('a');
408− anchor.href = nextProps.href;
409− anchor.style.display = 'block';
410− anchor.style.pointerEvents = 'auto';
412− node.parentNode.replaceChild(anchor, node);
413− anchor.appendChild(node);
414− } else if (nextProps.href === '') {
415− // remove the surrounding href
416− var anchor = node.parentNode;
417− anchor.parentNode.replaceChild(node, anchor);
419− // just update the link
420− node.parentNode.href = nextProps.href;
424− // update click and hover handlers
425− var removed = false;
427− // update hover handlers
428− if (currProps.hover.ctor === '_Tuple0') {
429− if (nextProps.hover.ctor !== '_Tuple0') {
430− addHover(node, nextProps.hover);
434− if (nextProps.hover.ctor === '_Tuple0') {
439− node.elm_hover_handler = nextProps.hover;
443− // update click handlers
444− if (currProps.click.ctor === '_Tuple0') {
445− if (nextProps.click.ctor !== '_Tuple0') {
446− addClick(node, nextProps.click);
450− if (nextProps.click.ctor === '_Tuple0') {
454− node.elm_click_handler = nextProps.click;
458− // stop capturing clicks if
460− && nextProps.hover.ctor === '_Tuple0'
461− && nextProps.click.ctor === '_Tuple0')
463− node.style.pointerEvents = 'none';
467−return { render:render, update:update };