3a59e9c757a7b695917399421bd9d47dda1f0d62
[mkws-moved-to-github.git] / src / mkws-handlebars.js
1 // Handlebars helpers
2
3 Handlebars.registerHelper('mkws-json', function(obj) {
4   return mkws.$.toJSON(obj);
5 });
6
7
8 // This is intended to handle paragraphs from Wikipedia, hence the
9 // rather hacky code to remove numbered references.
10 //
11 Handlebars.registerHelper('mkws-paragraphs', function(obj, nPara, nSent) {
12   var acc = [];
13
14   // For some reason, Handlebars provides the value
15   // {"hash":{},"data":{}} for parameters that are not provided. So we
16   // have to be prepared for actual numbers, explicitly undefined
17   // values and this dumb magic value.
18   if (obj && (nPara === undefined || nPara.hasOwnProperty('hash') || nPara == 0 || nPara > obj.length)) {
19     nPara = obj.length;
20   }
21   if (nSent === undefined || nSent.hasOwnProperty('hash') || nSent == 0) {
22     nSent = Infinity;
23   }
24
25   for (var i = 0; i < nPara; i++) {
26     // Remove numbered references such as "[1,3,4]" from text
27     var text = obj[i].replace(/\[[0-9,]+\]/g, '');
28     // Next line from http://stackoverflow.com/questions/18914629/split-string-into-sentences-in-javascript
29     var sentences = text.replace(/([.?!])\s*(?=[A-Z])/g, "$1|").split("|");
30     if (sentences.length > nSent)
31       sentences.length = nSent;
32
33     acc.push('<p>', sentences.join(' '), '</p>');
34     nSent -= sentences.length;
35     if (nSent == 0)
36       break;
37   }
38
39   return acc.join('');
40 });
41
42
43 Handlebars.registerHelper('mkws-translate', function(s) {
44   return mkws.M(s);
45 });
46
47
48 // We need {{mkws-attr '@name'}} because Handlebars can't parse {{@name}}
49 Handlebars.registerHelper('mkws-attr', function(attrName) {
50   return this[attrName];
51 });
52
53
54 /*
55  * Use as follows: {{#mkws-if-any NAME1 having="NAME2"}}
56  * Applicable when NAME1 is the name of an array
57  * The guarded code runs only if at least one element of the NAME1
58  * array has a subelement called NAME2.
59  */
60 Handlebars.registerHelper('mkws-if-any', function(items, options) {
61   var having = options.hash.having;
62   for (var i in items) {
63     var item = items[i]
64     if (!having || item[having]) {
65       return options.fn(this);
66     }
67   }
68   return "";
69 });
70
71
72 Handlebars.registerHelper('mkws-first', function(items, options) {
73   var having = options.hash.having;
74   for (var i in items) {
75     var item = items[i]
76     if (!having || item[having]) {
77       return options.fn(item);
78     }
79   }
80   return "";
81 });
82
83
84 var _urlRegexp = /^(https?:)?\/\//;
85 Handlebars.registerHelper('mkws-best-url', function(items) {
86   for (var i in items) {
87     var item = items[i]
88     if (item.match(_urlRegexp)) {
89       mkws.debug("'" + item + "' *is* a URL");
90       return item;
91     }
92     mkws.debug("'" + item + "' is not a URL");
93   }
94   return "";
95 });
96 Handlebars.registerHelper('mkws-other-urls', function(items) {
97   var res = [];
98   for (var i in items) {
99     var item = items[i]
100     if (item.match(_urlRegexp)) {
101       res.push(item);
102     }
103   }
104   return res;
105 });
106
107
108
109 Handlebars.registerHelper('mkws-commaList', function(items, options) {
110   var out = "";
111
112   for (var i in items) {
113     if (i > 0) out += ", ";
114     out += options.fn(items[i])
115   }
116
117   return out;
118 });
119
120
121 Handlebars.registerHelper('mkws-index1', function(obj) {
122   return obj.data.index + 1;
123 });
124
125 Handlebars.registerHelper('mkws-repeat', function(count, options) {
126   var out = "";
127   for (var i = 0; i < count; i++) {
128     out += options.fn(this);
129   }
130   return out;
131 });
132
133 // Ridiculous that Handlebars has no way to do "or"
134 Handlebars.registerHelper('mkws-if-either', function(cond1, cond2, options) {
135   if (typeof cond1 === 'function') { cond1 = cond1.call(this); }
136   if (typeof cond2 === 'function') { cond2 = cond2.call(this); }
137
138   if (cond1 || cond2) {
139     return options.fn(this);
140   } else {
141     return options.inverse(this);
142   }
143 });
144
145 // Ridiculous that this, too, is not part of regular Handlebars
146 // This code is by Mike Griffin, taken from this blog comment:
147 //      http://doginthehat.com.au/2012/02/comparison-block-helper-for-handlebars-templates/#comment-44
148
149 Handlebars.registerHelper('compare', function (lvalue, operator, rvalue, options) {
150   var operators, result;
151
152   if (arguments.length < 3) {
153     throw new Error("Handlerbars Helper 'compare' needs 2 parameters");
154   }
155
156   if (options === undefined) {
157     options = rvalue;
158     rvalue = operator;
159     operator = "===";
160   }
161
162   operators = {
163     '==': function (l, r) { return l == r; },
164     '===': function (l, r) { return l === r; },
165     '!=': function (l, r) { return l != r; },
166     '!==': function (l, r) { return l !== r; },
167     '<': function (l, r) { return l < r; },
168     '>': function (l, r) { return l > r; },
169     '<=': function (l, r) { return l <= r; },
170     '>=': function (l, r) { return l >= r; },
171     'typeof': function (l, r) { return typeof l == r; },
172     'matches': function (l, r) { return l.match(r); }
173   };
174
175   if (!operators[operator]) {
176     throw new Error("Handlerbars Helper 'compare' doesn't know the operator " + operator);
177   }
178
179   result = operators[operator](lvalue, rvalue);
180
181   if (result) {
182     return options.fn(this);
183   } else {
184     return options.inverse(this);
185   }
186 });