📜 ⬆️ ⬇️

Repeatable, another way to render lists

(from the series “small mechanization of web pages”)

What is Repeatable?


Repeatable is a way to output (populations) all sorts of lists, tables, and so on through data arrays. This mechanism
uses the template described in the markup code itself (as opposed to, say, {{mustache}} templates).

Expressions and conditional inclusion are supported. And all this in 90 lines of code .
')
Repeatable functionality is in every adult web framework. But if you do not want for one reason or another to get tied up with monsters, then here's a mechanism for you that, as they say, is not asking.

Example


Let's say there is such data:
var data = [ { name: "Olga", age: 20, email: "aaa@example.com" }, { name: "Peter", age: 30, email: "bbb@example.com" }, { name: "Ivan", age: 15, email: "ccc@example.com" }, ]; 

And we need to withdraw from something like this:
 <ul id="people"> <li><a href="mailto:{{this.email}}">{{this.name}}</a> <b if="this.age > 18">18+</b> </li> <li>No data available</li> </ul> 

The first <li> actually a write template. For each record in the input set, this element will be repeated with substitutions and goulash maidens . The second <li> will be displayed if the Repetable is “fed” with an empty array.

If we have all this described, then the actual population of our list is one line:
 var list = $("ul#people").repeatable(); // declaring the repeatable list.value = data; // that's data population, sic! 

Here is a living example .

Microformat templates



The text inside the markup or the attribute value may contain an expression in the “mustache” brackets: {{ ...expr ...}} .
When filling out the list, such expressions will be calculated and replaced by their string values.
Special variables available in expressions


Conditional inclusion

Any element within a repeatable pattern can be declared as conditional. To do this, you need to describe the attribute if="...expr..." . When generating the list, the expression will be calculated and if it is “truthy”, then the element will be displayed, if not, it will be deleted.

Home repeatable plugin - here
The repeatable source here is complete for those who missed the link at the beginning:
 /** * @author Andrew Fedoniouk <andrew@terrainformatica.com> * @name jQuery repeatable() * @license WTFPL (http://sam.zoy.org/wtfpl/) * @purpose template-less population of repeatables (lists) */ (function ($) { function repeatable(el) { var $el = $(el); var template = $el.find(">*").remove(); var nrTemplate = template.length > 1 ? $(template[1]) : null; // "no records" template template = $(template[0]); var compiled = {}; // compiled expressions var vector = null; // data var index = 0; // current index being processed //function evalExpr(str) { return eval("(" + str + ")"); } function compiledExpr(str) { var expr = compiled[str]; if( !expr ) compiled[str] = expr = new Function("$index","$first","$last","$total", "return (" + str + ")"); return expr; } function replace(text, data) { function subst(a, b) { var expr = compiledExpr(b); var s = expr.call(data, index, index==0,index==vector.length - 1, vector.length); return s === undefined ? "" : s; } return text.replace(/{{(.*)}}/g, subst); } function instantiate(el, data) { var attributes = el.attributes; for (var i = 0; i < attributes.length; ++i) { var attribute = attributes[i]; if (attribute.name == "if") { var str = attribute.value; var expr = compiledExpr(str); var tokeep = expr.call(data, index, index == 0, index == vector.length - 1, vector.length); if (!tokeep) { el.parentElement.removeChild(el); return; } } else if (attribute.value.indexOf("{{") >= 0) attribute.value = replace(attribute.value, data); } for (var nn, n = el.firstChild; n; n = nn) { var nn = n.nextSibling; if (n.nodeType == 1) // element instantiate(n, data); else if (n.nodeType == 3) // text { var t = n.textContent; if (t.indexOf("{{") >= 0) n.textContent = replace(t, data); } } } function getValue() { return vector; } function setValue(newValue) { vector = newValue; var t = template[0]; if( !vector || vector.length == 0 ) { $el.empty(); if(nrTemplate) $el.append(nrTemplate); // no records } else { var fragment = document.createDocumentFragment(); for (index = 0; index < vector.length; ++index) { var nel = t.cloneNode(true); instantiate(nel, vector[index]); fragment.appendChild(nel); } $el.empty(); $el.append(fragment); } } el.getValue = getValue; el.setValue = setValue; // redefine its 'value' property, setting value to some array will cause popupaltion of the repeatable by that data. try { Object.defineProperty(el, "value", { get: getValue, set: setValue, enumerable: true, configurable: true }); } catch(e) {} return el; } $.fn.repeatable = function () { var el = null; this.each(function () { el = repeatable(this); }); return el; // returns last matched element! }; })(jQuery); 

Successes.

Source: https://habr.com/ru/post/211590/


All Articles