• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IgniteUI / ignite-ui / 16021704676

02 Jul 2025 09:42AM UTC coverage: 84.594%. First build
16021704676

Pull #2279

github

web-flow
Merge 049474f24 into d2229a7bb
Pull Request #2279: feat(*): separating block templating from regular one

16140 of 21217 branches covered (76.07%)

171 of 174 new or added lines in 2 files covered. (98.28%)

24172 of 28574 relevant lines covered (84.59%)

404.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.48
/src/js/modules/infragistics.templating.js
1
/*!@license
2
 * Infragistics.Web.ClientUI Templating Engine <build_number>
3
 *
4
 * Copyright (c) 2011-<year> Infragistics Inc.
5
 *
6
 * Engine used for data templating
7
 *
8
 * http://www.infragistics.com/
9
 *
10
 * Depends on:
11
 *        jquery.js
12
 *  infragistics.util.jquery.js
13
 */
14

15
 /*
16
        1. comment RegExp matches comments in the template string in the form # My comment #.
17
                Unterminated comments would not be matched
18
        2. sub (substitute) RegExp matches templated data items to be replaced in the form of ${DataItem}.
19
        3. block RegExp matches terminated block statements
20
                e.g. {{if condition}} do something {{else}} do something else {{/if}}
21
                limitation: Regular expressions are equivalent to finite automatons as described by theory of computation and more precisely the formal languages and automata computability theory. This means that they are limited to recognizing languages of the type AB^nC but noy languages of the type [AB]^n which are recognized by context-free grammars (Regular expressions are still a subset of context-free grammars). However the A^nB^n is recognized due to the fact that we can use greedy regular expressions allowing us to match the last existing token of a type. Thus nested if-statements would not be recognized without stack-tokenizing the block statement.
22
 */
23
"use strict";
24
(function (factory) {
1✔
25
        if (typeof define === "function" && define.amd) {
1!
26

27
                // AMD. Register as an anonymous module.
28
                define( [
×
29
                        "jquery",
30
                        "./infragistics.util",
31
                        "./infragistics.util.jquery"
32
                ], factory );
33
        } else {
34

35
                // Browser globals
36
                factory(jQuery);
1✔
37
        }
38
}
39
(function ($) {
40

41
        $.ig = $.ig || {};
1!
42

43
        $.extend($.ig, {
1✔
44
        /* pluginName="igTemplating" */
45
                tmpl: function (template, data, args) {
46
                        /*  Populates the given template with the provided data. If data is a function that requires arguments, the arguments need to be provided as an array following the data. tmpl(template, data[, args])
47
                                paramType="string" optional="false" Specifies the template string
48
                                paramType="object|array|function" optional="false" Specifies the data to be templated in the template. If function is provided, then it has to be object or array returning function, possible receiving arguments array which can be specified as the third parameter
49
                                paramType="array" optional="true" If function is provided as the second parameter, then this parameter is the arguments for the function.
50
                                returnType="string" Returns the templated data as a string. Returns the original template if nothing is to be templated. */
51
                    var tmpl = template, cacheConst;
3,970✔
52

53
                        // K.D. May 28th, 2012 Bug #112490 Removing linebreaks in the template before rendering it.
54
                        //D.U. February 28th 2014 Checking if tmpl is initialized
55
                        if (tmpl) {
3,970!
56
                            tmpl = tmpl.replace($.ig.regExp.lineBreak, "");
3,970✔
57

58
                                // Removing comments
59
                                tmpl = tmpl.replace($.ig.regExp.comment, "");
3,970✔
60
                                if (typeof data === "function") {
3,970✔
61
                                        if (args) {
4✔
62
                                                data = data.apply(this, args);
1✔
63
                                        } else {
64
                                                data = data.call();
3✔
65
                                        }
66
                                }
67
                                if ($.ig._internalTmplCache && $.ig._internalTmplCache.hasOwnProperty(tmpl)) {
3,970✔
68
                                        $.ig.tokens = $.ig._internalTmplCache[ tmpl ].tokens;
3,919✔
69
                                        $.ig.args = $.ig._internalTmplCache[ tmpl ].args;
3,919✔
70
                                        $.ig.i = $.ig._internalTmplCache[ tmpl ].i;
3,919✔
71
                                        $.ig._hasBlock = $.ig._internalTmplCache[ tmpl ]._hasBlock;
3,919✔
72
                                        tmpl = $.ig._internalTmplCache[ tmpl ].tmpl;
3,919✔
73
                                } else {
74
                                        $.ig.tokens = [ ];
51✔
75
                                        $.ig.args = [ ];
51✔
76
                                        $.ig.i = 0;
51✔
77
                                        $.ig._tokenizeTemplate(tmpl);
51✔
78
                                        cacheConst = tmpl;
51✔
79
                                        $.ig._internalTmplCache[ cacheConst ] = {};
51✔
80
                                        $.ig._internalTmplCache[ cacheConst ].tokens = $.ig.tokens;
51✔
81
                                        if ($.ig.regExp.block.test(tmpl)) {
51✔
82
                                                $.ig._hasBlock = true;
14✔
83
                                                if (typeof $.ig._tokenizeDirectives === "function") {
14!
84
                                                        tmpl = $.ig._tokenizeDirectives(tmpl);
14✔
85
                                                } else {
NEW
86
                                                        console.warn($.ig._getLocaleString("noAdvancedTemplating"));
×
87
                                                }
88
                                        } else {
89
                                                $.ig._hasBlock = false;
37✔
90
                                        }
91
                                        $.ig._internalTmplCache[ cacheConst ].args = $.ig.args;
51✔
92
                                        $.ig._internalTmplCache[ cacheConst ].i = $.ig.i;
51✔
93
                                        $.ig._internalTmplCache[ cacheConst ]._hasBlock = $.ig._hasBlock;
51✔
94
                                        $.ig._internalTmplCache[ cacheConst ].tmpl = tmpl;
51✔
95
                                }
96
                                if (!$.ig.tokens.length) {
3,970✔
97

98
                                        // Nothing got tokenized
99
                                        return tmpl;// An exception can be thrown here
2✔
100
                                }
101
                                if ($.ig._hasBlock) {
3,968✔
102
                                        if (typeof $.ig._compileTemplate === "function") {
15!
103
                                                // K.D. August 27th, 2013 Bug #150299 Using the advanced templating engine
104
                                                tmpl = $.ig._compileTemplate(tmpl, data);
15✔
105
                                        } else {
NEW
106
                                                console.warn($.ig._getLocaleString("noAdvancedTemplating"));
×
107
                                        }
108
                                } else {
109
                                        tmpl = $.ig._populateTemplate(tmpl, data);
3,953✔
110
                                }
111
                                delete $.ig.args;
3,966✔
112
                                delete $.ig.tokens;
3,966✔
113
                                delete $.ig._hasBlock;
3,966✔
114
                                delete $.ig.i;
3,966✔
115
                        }
116
                        return tmpl;
3,966✔
117
                },
118
                clearTmplCache: function () {
119
                        delete $.ig._internalTmplCache;
1✔
120
                        $.ig._internalTmplCache = {};
1✔
121
                },
122
                /* type="RegExp" Used to tokenize the template string. */
123
                regExp: {
124
                        /* type="RegExp" Matches any comment in the template
125
                                Use tmpl.replace($.ig.regExp.comment, "") in order to remove comments from the tmpl string
126
                        */
127

128
                        // K.D. August 27th, 2013 Bug #150299 Making the comment to have to be preceded by a white space.
129
                        // This avoids issues with double anchors with href="#"
130
                        comment: /\s#[^#]*#/g,
131
                        /* type="RegExp" Matches any substitution element in the template that is to be encoded before rendering
132
                                Use $.ig.regExp.sub.exec(tmpl) in order to get the substitution element in the tmpl string
133
                        */
134
                        sub: /\$\{([\w\$\-]+(?:\.[\w\$\-]+|\s[\w\$\-]+)*)\}/,
135
                        /* type="RegExp" Matches any substitution element in the template that is to be rendered as it is
136
                                Use $.ig.regExp.sub.exec(tmpl) in order to get the substitution element in the tmpl string
137
                        */
138
                        nonEncodeSub: /\{\{html\s+((?:[\w\$-]+)(?:\.(?:[\w\$-]+)|\s(?:[\w\$-]+))*)\}\}/,
139
                        forSub: /\$\{([\w\$]+\.[\w\$]+(?:\.[\w\$]+)*)\}/,
140
                        arg: /args\[\d+\](?!.*\+)/,
141
                        /* type="RegExp" Matches any block directive in the template
142
                                Use $.ig.regExp.block.exec(tmpl) in order to get the block directive in the tmpl string
143
                        */
144
                        block: /\{\{(\w+).*?\}\}+(.*)(\{\{\/\1\}\})/,
145
                        /* type="RegExp" Matches any continuation inside a block directive in the template
146
                                Use $.ig.regExp.blockCont.exec(tmpl) in order to get the directive within a block in the tmpl string
147
                        */
148
                        blockCont: /\{\{(?!\/)(\S+)(.*)\}\}(.*)/,
149
                        /* type="RegExp" Matches any continuation inside a block directive in the template
150
                                Use $.ig.regExp.blockCont.exec(tmpl) in order to get the directive within a block in the tmpl string
151
                        */
152
                        blockDirective: /\{\{\S+.*?\}\}/,
153
                        /* type="RegExp" Matches index substitution $i
154
                                Use $.ig.regExp.index.test(tmpl) in order to test for index variable in the tmpl string
155
                        */
156
                        index: /\$i/g,
157
                        /* type="RegExp" Matches linebreaks and carriages */
158
                        lineBreak: /(\r\n|\n|\r)/gm,
159
                        /* Characters to encode */
160
                        lt: /</g,
161
                        gt: />/g,
162
                        ap: /'/g,
163
                        ic: /"/g,
164
                        amp: /&/g
165
                },
166
                /* Used to compile template directives. */
167
                _directives: {
168
                        "if": {
169
                                start: "if (",
170
                                close: ") {",
171
                                end: " }"
172
                        },
173
                        "elseif": {
174
                                start: " } else if (",
175
                                close: ") {",
176
                                end: ""
177
                        },
178
                        "else": {
179
                                start: " } else {",
180
                                close: "",
181
                                end: ""
182
                        },
183
                        "each": {
184
                                start: "for (var i = 0; i < $data.length; i++) {",
185
                                close: "",
186
                                end: " }"
187
                        }
188
                },
189
                _internalTmplCache: {},
190
                _tokenizeTemplate: function (template) {
191
                        var tempToken, splitName;
192
                        if ($.ig.regExp.sub.test(template)) {
51✔
193
                                tempToken = $.ig.regExp.sub.exec(template);
47✔
194
                                while (tempToken !== null) {
47✔
195
                                    splitName = tempToken[ 1 ].split(".");
87✔
196

197
                                        // K.D. September 25th, 2012 Bug #122463 The property can contain $ in its name.
198
                                        tempToken[ 1 ] = tempToken[ 1 ].replace(/\\/g, "\\\\").replace(/\$/g, "\\$");
87✔
199
                                        template = template.replace(new RegExp("\\$\\{" + tempToken[ 1 ] + "\\}", "g"), "");
87✔
200
                                        tempToken[ 3 ] = new RegExp("\\$\\{" + tempToken[ 1 ] + "\\}", "g");
87✔
201
                                        tempToken[ 1 ] = splitName;
87✔
202
                                        tempToken[ 2 ] = true;
87✔
203
                                        $.ig.tokens.push(tempToken);
87✔
204
                                        tempToken = $.ig.regExp.sub.exec(template);
87✔
205
                                }
206
                        }
207
                        if ($.ig.regExp.nonEncodeSub.test(template)) {
51✔
208
                                tempToken = $.ig.regExp.nonEncodeSub.exec(template);
5✔
209
                                while (tempToken !== null) {
5✔
210
                                    splitName = tempToken[ 1 ].split(".");
7✔
211

212
                                        // K.D. September 25th, 2012 Bug #122463 The property can contain $ in its name.
213
                                        tempToken[ 1 ] = tempToken[ 1 ].replace(/\\/g, "\\\\").replace(/\$/g, "\\$");
7✔
214
                                        template = template.replace(new RegExp("\\{\\{html\\s+" + tempToken[ 1 ] + "\\}\\}", "g"), "");
7✔
215
                                        tempToken[ 3 ] = new RegExp("\\{\\{html\\s+" + tempToken[ 1 ] + "\\}\\}", "g");
7✔
216
                                        tempToken[ 1 ] = splitName;
7✔
217
                                        tempToken[ 2 ] = false;
7✔
218
                                        $.ig.tokens.push(tempToken);
7✔
219
                                        tempToken = $.ig.regExp.nonEncodeSub.exec(template);
7✔
220
                                }
221
                        }
222
                },
223
                _populateTemplate: function (template, data) {
224
                        var i, j, result = "", temp;
3,953✔
225
                        if ($.ig.util.getType(data) !== "array") {
3,953✔
226
                                for (i = 0; i < $.ig.tokens.length; i++) {
3,932✔
227
                                        template = $.ig._populateArgumentValue(data, $.ig.tokens[ i ], template);
6,304✔
228
                                }
229
                                result = template;
3,932✔
230
                        } else {
231
                                for (j = 0; j < data.length; j++) {
21✔
232
                                        temp = template;
3,044✔
233
                                        for (i = 0; i < $.ig.tokens.length; i++) {
3,044✔
234
                                                temp = $.ig._populateArgumentValue(data[ j ], $.ig.tokens[ i ], temp);
9,065✔
235
                                        }
236
                                        temp = temp.replace($.ig.regExp.index, j);
3,044✔
237
                                        result += temp;
3,044✔
238
                                }
239
                        }
240
                        return result;
3,953✔
241
                },
242
                _getLocaleString: function(key) {
243
                        return $.ig.util ?
2!
244
                                $.ig.util.getLocaleValue("Templating", key) :
245
                                $.ig.Templating.locale[key];
246
                },
247
                _getArgumentValue: function (data, token, arg) {
248
                        var tempData, l;
249
                        if (token[ 1 ].length && token[ 1 ].length > 1) {
62✔
250
                                tempData = data;
20✔
251
                                for (l = 0; l < token[ 1 ].length; l++) {
20✔
252

253
                                        // K.D. August 14th, 2012 Bug #118861 When a prop is undefined/null we should not try to evaluate a prop
254
                                        if (tempData && tempData.hasOwnProperty(token[ 1 ][ l ])) {
40✔
255
                                                tempData = tempData[ token[ 1 ][ l ] ];
39✔
256
                                        } else {
257
                                                tempData = "";
1✔
258
                                                break;
1✔
259
                                        }
260
                                }
261
                                if (token[ 2 ] && typeof tempData === "string") {
20✔
262
                                        arg = $.ig.encode(tempData);
2✔
263
                                } else {
264
                                        arg = tempData;
18✔
265
                                }
266
                        } else {
267
                                if (token[ 2 ] && typeof data[ token[ 1 ] ] === "string") {
42✔
268
                                        arg = $.ig.encode(data[ token[ 1 ] ]);
5✔
269
                                } else {
270
                                        arg = data[ token[ 1 ] ];
37✔
271
                                }
272
                        }
273
                        return arg;
62✔
274
                },
275
                _populateArgumentValue: function (data, token, arg) {
276
                        var tempData, l, self = this;
15,548✔
277
                        if (token[ 1 ].length && token[ 1 ].length > 1) {
15,548✔
278
                                tempData = data;
68✔
279
                                for (l = 0; l < token[ 1 ].length; l++) {
68✔
280

281
                                        // K.D. August 14th, 2012 Bug #118861 When a prop is undefined we should not try to evaluate a prop
282
                                        if (tempData && tempData.hasOwnProperty(token[ 1 ][ l ])) {
136✔
283
                                            tempData = typeof tempData[ token[ 1 ][ l ] ] === "function" ?
116✔
284
                        tempData[ token[ 1 ][ l ] ]() : tempData[ token[ 1 ][ l ] ];
285
                                        } else {
286
                                                tempData = "";
20✔
287
                                                break;
20✔
288
                                        }
289
                                }
290
                                if (token[ 2 ] && typeof tempData === "string") {
68✔
291

292
                                        // K.D. June 14th, 2012 Bug #114536 Switching to a function to ignore flag parameters
293
                                        // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/replace
294
                                        arg = arg.replace(token[ 3 ], function () {
28✔
295
                                                return self.encode(tempData);
9✔
296
                                        });
297
                                } else {
298

299
                                        // K.D. June 14th, 2012 Bug #114536 Switching to a function to ignore flag parameters
300
                                        // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/replace
301
                                    arg = arg.replace(token[ 3 ], function () {
40✔
302

303
                                                // K.D. May 7th, 2013 Bug #140356 null values are being returned as "null" and should be ""
304
                                                return tempData === null ? "" : tempData;
27!
305
                                        });
306
                                }
307
                        } else {
308
                            if (token[ 2 ]) {
15,480✔
309

310
                                        // K.D. June 14th, 2012 Bug #114536 Switching to a function to ignore flag parameters
311
                                        // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/replace
312
                                arg = arg.replace(token[ 3 ], function () {
15,472✔
313

314
                    // K.D. June 25th, 2014 Bug #173722 Handling function types
315
                                    return self.encode(typeof data[ token[ 1 ] ] === "function" ?
15,925✔
316
                        data[ token[ 1 ] ]() : data[ token[ 1 ] ]);
317
                                        });
318
                            } else {
319

320
                                        // K.D. June 14th, 2012 Bug #114536 Switching to a function to ignore flag parameters
321
                                        // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/replace
322
                                arg = arg.replace(token[ 3 ], function () {
8✔
323

324
                                                // K.D. May 7th, 2013 Bug #140356 null values are being returned as "null" and should be ""
325
                                    return data[ token[ 1 ] ] === null ? "" : typeof data[ token[ 1 ] ] === "function" ?
8!
326
                        data[ token[ 1 ] ]() : data[ token[ 1 ] ];
327
                                        });
328
                                }
329
                        }
330
                        return arg;
15,548✔
331
                }
332
        });
333

334
}));// REMOVE_FROM_COMBINED_FILES
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc