2ElmRuntime.Render.Element = function() {
5var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
6var newElement = Utils.newElement, extract = Utils.extract,
7 addTransform = Utils.addTransform, removeTransform = Utils.removeTransform,
8 fromList = Utils.fromList, eq = Utils.eq;
10function setProps(elem, e) {
11 var props = elem.props;
12 var element = elem.element;
13 var width = props.width - (element.adjustWidth || 0);
14 var height = props.height - (element.adjustHeight || 0);
15 e.style.width = (width |0) + 'px';
16 e.style.height = (height|0) + 'px';
17 if (props.opacity !== 1) {
18 e.style.opacity = props.opacity;
20 if (props.color.ctor === 'Just') {
21 e.style.backgroundColor = extract(props.color._0);
23 if (props.tag !== '') { e.id = props.tag; }
24 if (props.href !== '') {
25 var a = newElement('a');
27 a.style.width = '100%';
28 a.style.height = '100%';
31 a.style.display = 'block';
32 a.style.position = 'absolute';
33 e.style.position = 'relative';
34 a.style.pointerEvents = 'auto';
37 if (props.hover.ctor !== '_Tuple0') {
38 addHover(e, props.hover);
40 if (props.click.ctor !== '_Tuple0') {
41 addClick(e, props.click);
46function addClick(e, handler) {
47 e.style.pointerEvents = 'auto';
48 e.elm_click_handler = handler;
49 function trigger(ev) {
50 e.elm_click_handler(Utils.Tuple0);
53 e.elm_click_trigger = trigger;
54 e.addEventListener('click', trigger);
57function removeClick(e, handler) {
58 if (e.elm_click_trigger) {
59 e.removeEventListener('click', e.elm_click_trigger);
63function addHover(e, handler) {
64 e.style.pointerEvents = 'auto';
65 e.elm_hover_handler = handler;
66 e.elm_hover_count = 0;
69 if (e.elm_hover_count++ > 0) return;
70 e.elm_hover_handler(true);
71 evt.stopPropagation();
74 if (e.contains(evt.toElement || evt.relatedTarget)) return;
75 e.elm_hover_count = 0;
76 e.elm_hover_handler(false);
77 evt.stopPropagation();
79 e.elm_hover_over = over;
80 e.elm_hover_out = out;
81 e.addEventListener('mouseover', over);
82 e.addEventListener('mouseout', out);
85function removeHover(e) {
86 if (e.elm_hover_over) {
87 e.removeEventListener('mouseover', e.elm_hover_over);
89 if (e.elm_hover_out) {
90 e.removeEventListener('mouseout', e.elm_hover_out);
94function image(props, img) {
95 switch (img._0.ctor) {
96 case 'Plain': return plainImage(img._3);
97 case 'Fitted': return fittedImage(props.width, props.height, img._3);
98 case 'Cropped': return croppedImage(img,props.width,props.height,img._3);
99 case 'Tiled': return tiledImage(img._3);
103function plainImage(src) {
104 var img = newElement('img');
107 img.style.display = "block";
111function tiledImage(src) {
112 var div = newElement('div');
113 div.style.backgroundImage = 'url(' + src + ')';
117function fittedImage(w, h, src) {
118 var div = newElement('div');
119 div.style.background = 'url(' + src + ') no-repeat center';
120 div.style.webkitBackgroundSize = 'cover';
121 div.style.MozBackgroundSize = 'cover';
122 div.style.OBackgroundSize = 'cover';
123 div.style.backgroundSize = 'cover';
127function croppedImage(elem, w, h, src) {
128 var pos = elem._0._0;
129 var e = newElement('div');
130 e.style.overflow = "hidden";
132 var img = newElement('img');
133 img.onload = function() {
134 var sw = w / elem._1, sh = h / elem._2;
135 img.style.width = ((this.width * sw)|0) + 'px';
136 img.style.height = ((this.height * sh)|0) + 'px';
137 img.style.marginLeft = ((- pos._0 * sw)|0) + 'px';
138 img.style.marginTop = ((- pos._1 * sh)|0) + 'px';
146function goIn(e) { e.style.position = 'absolute'; return e; }
147function goDown(e) { return e }
148function goRight(e) { e.style.styleFloat = e.style.cssFloat = "left"; return e; }
149function flowWith(f, array) {
150 var container = newElement('div');
151 if (f == goIn) container.style.pointerEvents = 'none';
153 for (var i = array.length; i--; ) {
154 container.appendChild(f(render(array[i])));
159function flow(dir,elist) {
160 var array = fromList(elist);
162 case "DDown": array.reverse();
163 case "DUp": return flowWith(goDown,array);
164 case "DRight": array.reverse();
165 case "DLeft": return flowWith(goRight,array);
166 case "DOut": array.reverse();
167 case "DIn": return flowWith(goIn,array);
173 case "Absolute": return pos._0 + "px";
174 case "Relative": return (pos._0 * 100) + "%";
178// must clear right, left, top, bottom, and transform
179// before calling this function
180function setPos(pos,elem,e) {
181 var element = elem.element;
182 var props = elem.props;
183 var w = props.width + (element.adjustWidth ? element.adjustWidth : 0);
184 var h = props.height + (element.adjustHeight ? element.adjustHeight : 0);
186 e.style.position = 'absolute';
187 e.style.margin = 'auto';
189 switch(pos.horizontal.ctor) {
190 case 'P': e.style.right = toPos(pos.x); e.style.removeProperty('left'); break;
191 case 'Z': transform = 'translateX(' + ((-w/2)|0) + 'px) ';
192 case 'N': e.style.left = toPos(pos.x); e.style.removeProperty('right'); break;
194 switch(pos.vertical.ctor) {
195 case 'N': e.style.bottom = toPos(pos.y); e.style.removeProperty('top'); break;
196 case 'Z': transform += 'translateY(' + ((-h/2)|0) + 'px)';
197 case 'P': e.style.top = toPos(pos.y); e.style.removeProperty('bottom'); break;
199 if (transform !== '') addTransform(e.style, transform);
203function container(pos,elem) {
204 var e = render(elem);
205 setPos(pos, elem, e);
206 var div = newElement('div');
207 div.style.position = 'relative';
208 div.style.overflow = 'hidden';
213function rawHtml(elem) {
214 var html = elem.html;
215 var args = elem.args;
216 var guid = elem.guid;
217 var align = elem.align;
219 var div = newElement('div');
220 div.innerHTML = html;
221 div.style.visibility = "hidden";
222 if (align) div.style.textAlign = align;
223 document.body.appendChild(div);
225 for (var i = args.length; i--; ) {
227 var span = document.getElementById('md-' + guid + '-' + i);
229 span.innerHTML = arg;
231 span.style.display = 'block';
232 span.style.width = arg.props.width + 'px';
233 span.style.height = arg.props.height + 'px';
234 span.appendChild(render(arg));
237 document.body.removeChild(div);
238 div.style.visibility = 'visible';
239 div.style.pointerEvents = 'auto';
243function render(elem) { return setProps(elem, makeElement(elem)); }
244function makeElement(e) {
245 var elem = e.element;
247 case 'Image': return image(e.props, elem);
248 case 'Flow': return flow(elem._0, elem._1);
249 case 'Container': return container(elem._0, elem._1);
250 case 'Spacer': return newElement('div');
251 case 'RawHtml': return rawHtml(elem);
252 case 'Custom': return elem.render(elem.model);
256function update(node, curr, next) {
257 if (node.tagName === 'A') { node = node.firstChild; }
258 if (curr.props.id === next.props.id) return updateProps(node, curr, next);
259 if (curr.element.ctor !== next.element.ctor) {
260 node.parentNode.replaceChild(render(next),node);
263 var nextE = next.element, currE = curr.element;
265 case "Spacer": break;
267 // only markdown blocks have guids, so this must be a text block
268 if (nextE.guid === null) {
269 if(currE.html.valueOf() !== nextE.html.valueOf()) {
270 node.innerHTML = nextE.html;
274 if (nextE.guid !== currE.guid) {
275 node.parentNode.replaceChild(render(next),node);
278 var nargs = nextE.args;
279 var cargs = currE.args;
280 for (var i = nargs.length; i--; ) {
283 if (narg == carg) continue;
284 var span = document.getElementById('md-' + currE.guid + '-' + i);
285 if (narg.isElement) {
286 if (carg.isElement) {
287 update(span, carg, narg);
289 span.style.display = 'block';
290 var e = render(narg);
295 span.style.display = 'inline';
296 span.innerHTML = narg;
301 if (nextE._0.ctor === 'Plain') {
302 if (nextE._3 !== currE._3) node.src = nextE._3;
303 } else if (!eq(nextE,currE) ||
304 next.props.width !== curr.props.width ||
305 next.props.height !== curr.props.height) {
306 node.parentNode.replaceChild(render(next),node);
311 var arr = fromList(nextE._1);
312 for (var i = arr.length; i--; ) { arr[i] = arr[i].element.ctor; }
313 if (nextE._0.ctor !== currE._0.ctor) {
314 node.parentNode.replaceChild(render(next),node);
317 var nexts = fromList(nextE._1);
318 var kids = node.childNodes;
319 if (nexts.length !== kids.length) {
320 node.parentNode.replaceChild(render(next),node);
323 var currs = fromList(currE._1);
324 var goDir = function(x) { return x; };
325 switch(nextE._0.ctor) {
326 case "DDown": case "DUp": goDir = goDown; break;
327 case "DRight": case "DLeft": goDir = goRight; break;
328 case "DOut": case "DIn": goDir = goIn; break;
330 for (var i = kids.length; i-- ;) {
331 update(kids[i],currs[i],nexts[i]);
336 update(node.firstChild, currE._1, nextE._1);
337 setPos(nextE._0, nextE._1, node.firstChild);
340 if (currE.type === nextE.type) {
341 var done = nextE.update(node, currE.model, nextE.model);
344 return node.parentNode.replaceChild(render(next), node);
347 updateProps(node, curr, next);
350function updateProps(node, curr, next) {
351 var props = next.props;
352 var currP = curr.props;
354 var element = next.element;
355 var width = props.width - (element.adjustWidth || 0);
356 var height = props.height - (element.adjustHeight || 0);
357 if (width !== currP.width) {
358 e.style.width = (width|0) + 'px';
360 if (height !== currP.height) {
361 e.style.height = (height|0) + 'px';
363 if (props.opacity !== currP.opacity) {
364 e.style.opacity = props.opacity;
366 var nextColor = (props.color.ctor === 'Just' ?
367 extract(props.color._0) : '');
368 if (e.style.backgroundColor !== nextColor) {
369 e.style.backgroundColor = (nextColor === '' ? 'transparent' : nextColor);
371 if (props.tag !== currP.tag) { e.id = props.tag; }
372 if (props.href !== currP.href) {
373 if (currP.href === '') {
374 var a = newElement('a');
376 a.style.width = '100%';
377 a.style.height = '100%';
380 a.style.display = 'block';
381 a.style.position = 'absolute';
382 e.style.position = 'relative';
383 a.style.pointerEvents = 'auto';
386 node.lastNode.href = props.href;
390 // update hover handlers
391 if (props.hover.ctor === '_Tuple0') {
393 } else if (e.elm_hover_handler) {
394 e.elm_hover_handler = props.hover;
396 addHover(e, props.hover);
399 // update click handlers
400 if (props.click.ctor === '_Tuple0') {
402 } else if (e.elm_click_handler) {
403 e.elm_click_handler = props.click;
405 addClick(e, props.click);
409return { render:render, update:update };
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list