IE11 CSS parsing in regression tests, MKWS-386
[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 Handlebars.registerHelper('mkws-commaList', function(items, options) {
85   var out = "";
86
87   for (var i in items) {
88     if (i > 0) out += ", ";
89     out += options.fn(items[i])
90   }
91
92   return out;
93 });
94
95
96 Handlebars.registerHelper('mkws-index1', function(obj) {
97   return obj.data.index + 1;
98 });
99
100 Handlebars.registerHelper('mkws-repeat', function(count, options) {
101   var out = "";
102   for (var i = 0; i < count; i++) {
103     out += options.fn(this);
104   }
105   return out;
106 });
107
108 // Ridiculous that Handlebars has no way to do "or"
109 Handlebars.registerHelper('mkws-if-either', function(cond1, cond2, options) {
110   if (typeof cond1 === 'function') { cond1 = cond1.call(this); }
111   if (typeof cond2 === 'function') { cond2 = cond2.call(this); }
112
113   if (cond1 || cond2) {
114     return options.fn(this);
115   } else {
116     return options.inverse(this);
117   }
118 });
119
120 // Ridiculous that this, too, is not part of regular Handlebars
121 // This code is by Mike Griffin, taken from this blog comment:
122 //      http://doginthehat.com.au/2012/02/comparison-block-helper-for-handlebars-templates/#comment-44
123
124 Handlebars.registerHelper('compare', function (lvalue, operator, rvalue, options) {
125   var operators, result;
126
127   if (arguments.length < 3) {
128     throw new Error("Handlerbars Helper 'compare' needs 2 parameters");
129   }
130
131   if (options === undefined) {
132     options = rvalue;
133     rvalue = operator;
134     operator = "===";
135   }
136
137   operators = {
138     '==': function (l, r) { return l == r; },
139     '===': function (l, r) { return l === r; },
140     '!=': function (l, r) { return l != r; },
141     '!==': function (l, r) { return l !== r; },
142     '<': function (l, r) { return l < r; },
143     '>': function (l, r) { return l > r; },
144     '<=': function (l, r) { return l <= r; },
145     '>=': function (l, r) { return l >= r; },
146     'typeof': function (l, r) { return typeof l == r; },
147     'matches': function (l, r) { return l.match(r); }
148   };
149
150   if (!operators[operator]) {
151     throw new Error("Handlerbars Helper 'compare' doesn't know the operator " + operator);
152   }
153
154   result = operators[operator](lvalue, rvalue);
155
156   if (result) {
157     return options.fn(this);
158   } else {
159     return options.inverse(this);
160   }
161 });