2ElmRuntime.Render.Element = function() {
5var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
6var newElement = Utils.newElement, colorToCss = Utils.colorToCss,
7 addTransform = Utils.addTransform, removeTransform = Utils.removeTransform,
8 fromList = Utils.fromList, eq = Utils.eq;
10function setProps(elem, node) {
11 var props = elem.props;
13 var element = elem.element;
14 var width = props.width - (element.adjustWidth || 0);
15 var height = props.height - (element.adjustHeight || 0);
16 node.style.width = (width |0) + 'px';
17 node.style.height = (height|0) + 'px';
19 if (props.opacity !== 1) {
20 node.style.opacity = props.opacity;
23 if (props.color.ctor === 'Just') {
24 node.style.backgroundColor = colorToCss(props.color._0);
27 if (props.tag !== '') {
31 if (props.href !== '') {
32 var a = newElement('a');
34 a.style.width = '100%';
35 a.style.height = '100%';
38 a.style.display = 'block';
39 a.style.position = 'absolute';
40 node.style.position = 'relative';
41 a.style.pointerEvents = 'auto';
45 if (props.hover.ctor !== '_Tuple0') {
46 addHover(node, props.hover);
49 if (props.click.ctor !== '_Tuple0') {
50 addClick(node, props.click);
56function addClick(e, handler) {
57 e.style.pointerEvents = 'auto';
58 e.elm_click_handler = handler;
59 function trigger(ev) {
60 e.elm_click_handler(Utils.Tuple0);
63 e.elm_click_trigger = trigger;
64 e.addEventListener('click', trigger);
67function removeClick(e, handler) {
68 if (e.elm_click_trigger) {
69 e.removeEventListener('click', e.elm_click_trigger);
73function 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);
95function removeHover(e) {
96 if (e.elm_hover_over) {
97 e.removeEventListener('mouseover', e.elm_hover_over);
99 if (e.elm_hover_out) {
100 e.removeEventListener('mouseout', e.elm_hover_out);
104function image(props, img) {
105 switch (img._0.ctor) {
106 case 'Plain': return plainImage(img._3);
107 case 'Fitted': return fittedImage(props.width, props.height, img._3);
108 case 'Cropped': return croppedImage(img,props.width,props.height,img._3);
109 case 'Tiled': return tiledImage(img._3);
113function plainImage(src) {
114 var img = newElement('img');
117 img.style.display = "block";
121function tiledImage(src) {
122 var div = newElement('div');
123 div.style.backgroundImage = 'url(' + src + ')';
127function fittedImage(w, h, src) {
128 var div = newElement('div');
129 div.style.background = 'url(' + src + ') no-repeat center';
130 div.style.webkitBackgroundSize = 'cover';
131 div.style.MozBackgroundSize = 'cover';
132 div.style.OBackgroundSize = 'cover';
133 div.style.backgroundSize = 'cover';
137function croppedImage(elem, w, h, src) {
138 var pos = elem._0._0;
139 var e = newElement('div');
140 e.style.overflow = "hidden";
142 var img = newElement('img');
143 img.onload = function() {
144 var sw = w / elem._1, sh = h / elem._2;
145 img.style.width = ((this.width * sw)|0) + 'px';
146 img.style.height = ((this.height * sh)|0) + 'px';
147 img.style.marginLeft = ((- pos._0 * sw)|0) + 'px';
148 img.style.marginTop = ((- pos._1 * sh)|0) + 'px';
156function goOut(e) { e.style.position = 'absolute'; return e; }
157function goDown(e) { return e }
158function goRight(e) { e.style.styleFloat = e.style.cssFloat = "left"; return e; }
160var directionTable = {
168function needsReversal(dir) {
169 return dir == 'DUp' || dir == 'DLeft' || dir == 'DIn';
172function flow(dir,elist) {
173 var array = fromList(elist);
174 var container = newElement('div');
175 var goDir = directionTable[dir];
176 if (goDir == goOut) {
177 container.style.pointerEvents = 'none';
179 if (needsReversal(dir)) {
182 var len = array.length;
183 for (var i = 0; i < len; ++i) {
184 container.appendChild(goDir(render(array[i])));
191 case "Absolute": return pos._0 + "px";
192 case "Relative": return (pos._0 * 100) + "%";
196// must clear right, left, top, bottom, and transform
197// before calling this function
198function setPos(pos,elem,e) {
199 var element = elem.element;
200 var props = elem.props;
201 var w = props.width + (element.adjustWidth ? element.adjustWidth : 0);
202 var h = props.height + (element.adjustHeight ? element.adjustHeight : 0);
204 e.style.position = 'absolute';
205 e.style.margin = 'auto';
207 switch(pos.horizontal.ctor) {
208 case 'P': e.style.right = toPos(pos.x); e.style.removeProperty('left'); break;
209 case 'Z': transform = 'translateX(' + ((-w/2)|0) + 'px) ';
210 case 'N': e.style.left = toPos(pos.x); e.style.removeProperty('right'); break;
212 switch(pos.vertical.ctor) {
213 case 'N': e.style.bottom = toPos(pos.y); e.style.removeProperty('top'); break;
214 case 'Z': transform += 'translateY(' + ((-h/2)|0) + 'px)';
215 case 'P': e.style.top = toPos(pos.y); e.style.removeProperty('bottom'); break;
217 if (transform !== '') addTransform(e.style, transform);
221function container(pos,elem) {
222 var e = render(elem);
223 setPos(pos, elem, e);
224 var div = newElement('div');
225 div.style.position = 'relative';
226 div.style.overflow = 'hidden';
231function rawHtml(elem) {
232 var html = elem.html;
233 var args = elem.args;
234 var guid = elem.guid;
235 var align = elem.align;
237 var div = newElement('div');
238 div.innerHTML = html;
239 div.style.visibility = "hidden";
240 if (align) div.style.textAlign = align;
241 document.body.appendChild(div);
243 for (var i = args.length; i--; ) {
245 var span = document.getElementById('md-' + guid + '-' + i);
247 span.innerHTML = arg;
249 span.style.display = 'block';
250 span.style.width = arg.props.width + 'px';
251 span.style.height = arg.props.height + 'px';
252 span.appendChild(render(arg));
255 document.body.removeChild(div);
256 div.style.visibility = 'visible';
257 div.style.pointerEvents = 'auto';
261function render(elem) { return setProps(elem, makeElement(elem)); }
262function makeElement(e) {
263 var elem = e.element;
265 case 'Image': return image(e.props, elem);
266 case 'Flow': return flow(elem._0.ctor, elem._1);
267 case 'Container': return container(elem._0, elem._1);
268 case 'Spacer': return newElement('div');
269 case 'RawHtml': return rawHtml(elem);
270 case 'Custom': return elem.render(elem.model);
274function update(node, curr, next) {
275 if (node.tagName === 'A') { node = node.firstChild; }
276 if (curr.props.id === next.props.id) return updateProps(node, curr, next);
277 if (curr.element.ctor !== next.element.ctor) {
278 node.parentNode.replaceChild(render(next),node);
281 var nextE = next.element, currE = curr.element;
283 case "Spacer": break;
285 // only markdown blocks have guids, so this must be a text block
286 if (nextE.guid === null) {
287 if(currE.html.valueOf() !== nextE.html.valueOf()) {
288 node.innerHTML = nextE.html;
292 if (nextE.guid !== currE.guid) {
293 node.parentNode.replaceChild(render(next),node);
296 var nargs = nextE.args;
297 var cargs = currE.args;
298 for (var i = nargs.length; i--; ) {
301 if (narg == carg) continue;
302 var span = document.getElementById('md-' + currE.guid + '-' + i);
303 if (narg.isElement) {
304 if (carg.isElement) {
305 update(span, carg, narg);
307 span.style.display = 'block';
308 var e = render(narg);
313 span.style.display = 'inline';
314 span.innerHTML = narg;
319 if (nextE._0.ctor === 'Plain') {
320 if (nextE._3 !== currE._3) node.src = nextE._3;
321 } else if (!eq(nextE,currE) ||
322 next.props.width !== curr.props.width ||
323 next.props.height !== curr.props.height) {
324 node.parentNode.replaceChild(render(next),node);
329 var arr = fromList(nextE._1);
330 for (var i = arr.length; i--; ) { arr[i] = arr[i].element.ctor; }
331 if (nextE._0.ctor !== currE._0.ctor) {
332 node.parentNode.replaceChild(render(next),node);
335 var nexts = fromList(nextE._1);
336 var kids = node.childNodes;
337 if (nexts.length !== kids.length) {
338 node.parentNode.replaceChild(render(next),node);
341 var currs = fromList(currE._1);
342 var dir = nextE._0.ctor;
343 var goDir = directionTable[dir];
344 var toReverse = needsReversal(dir);
345 var len = kids.length;
346 for (var i = len; i-- ;) {
347 update(kids[toReverse ? len - i - 1 : i],currs[i],nexts[i]);
352 update(node.firstChild, currE._1, nextE._1);
353 setPos(nextE._0, nextE._1, node.firstChild);
356 if (currE.type === nextE.type) {
357 var done = nextE.update(node, currE.model, nextE.model);
360 return node.parentNode.replaceChild(render(next), node);
363 updateProps(node, curr, next);
366function updateProps(node, curr, next) {
367 var nextProps = next.props;
368 var currProps = curr.props;
370 var element = next.element;
371 var width = nextProps.width - (element.adjustWidth || 0);
372 var height = nextProps.height - (element.adjustHeight || 0);
373 if (width !== currProps.width) {
374 node.style.width = (width|0) + 'px';
376 if (height !== currProps.height) {
377 node.style.height = (height|0) + 'px';
380 if (nextProps.opacity !== currProps.opacity) {
381 node.style.opacity = nextProps.opacity;
384 var nextColor = nextProps.color.ctor === 'Just'
385 ? colorToCss(nextProps.color._0)
387 if (node.style.backgroundColor !== nextColor) {
388 node.style.backgroundColor = nextColor;
391 if (nextProps.tag !== currProps.tag) {
392 node.id = nextProps.tag;
395 if (nextProps.href !== currProps.href) {
396 if (currProps.href === '') {
397 var a = newElement('a');
398 a.href = nextProps.href;
399 a.style.width = '100%';
400 a.style.height = '100%';
403 a.style.display = 'block';
404 a.style.position = 'absolute';
405 node.style.position = 'relative';
406 a.style.pointerEvents = 'auto';
409 node.lastNode.href = nextProps.href;
413 // update hover handlers
414 if (nextProps.hover.ctor === '_Tuple0') {
416 } else if (node.elm_hover_handler) {
417 node.elm_hover_handler = nextProps.hover;
419 addHover(node, nextProps.hover);
422 // update click handlers
423 if (nextProps.click.ctor === '_Tuple0') {
425 } else if (node.elm_click_handler) {
426 node.elm_click_handler = nextProps.click;
428 addClick(node, nextProps.click);
432return { 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