/
template-compiler.js
148 lines (125 loc) · 4.22 KB
/
template-compiler.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import {inject} from 'aurelia-framework';
import {TemplatingEngine} from 'aurelia-templating';
/**
* An adaptor which uses Aurelia's enhance capability to
* compile any template Kendo wants to have compiled
*/
@inject(TemplatingEngine)
export class TemplateCompiler {
/**
* We don't need to initialize the TemplateCompiler every time a Kendo controls
* is initialized
*/
isInitialized = false;
constructor(templatingEngine) {
this.templatingEngine = templatingEngine;
}
/**
* Initialize the template compiler and
* patch the angular property to retrieve compilation requests
* from Kendo controls
* @param $parent The overrideContext to use when a template gets compiled
*/
initialize() {
if (this.isInitialized) return;
// all controls derive from kendo.ui.Widget
// override the angular property on these objects, and point it towards handleTemplateEvents
let _this = this;
kendo.ui.Widget.prototype.angular = function(_event, _args) {
_this.handleTemplateEvents(this, _event, _args);
};
kendo.mobile.ui.Widget.prototype.angular = function(_event, _args) {
_this.handleTemplateEvents(this, _event, _args);
};
this.isInitialized = true;
}
/**
* Gets called by Kendo, and filters out compile and cleanup events,
* then calls the compile or cleanup function with the needed arguments
* @param _event Events like 'compile' or 'cleanup'
* @param _args optional array of dataitems
*/
handleTemplateEvents(widget, _event: string, _args?) {
if (_event !== 'compile' && _event !== 'cleanup') return;
let $parent = widget._$parent;
if (!$parent) return;
let args = _args();
let elements = args.elements; // extract elements from the args
let data = args.data; // extract the dataitems from the args
switch (_event) {
case 'compile':
// we need to pass elements and data to compile
// so that Aurelia can enhance this elements with the correct
// binding context
this.compile($parent, elements, data);
break;
case 'cleanup':
// we don't care about dataitems when we do the cleanup
// so we just pass in the DOM elements
this.cleanup(elements);
break;
default:
break;
}
}
/**
* loops through each element, and find the matching dataitem
* and calls enhanceView(element, dataItem) for each element there is
* @param elements an array of Elements or a jQuery selector
* @param data optionally an array of dataitems
*/
compile($parent, elements, data) {
for (let i = 0; i < elements.length; i++) {
let element = elements[i];
let ctx;
if (data && data[i]) {
let _data = data[i];
ctx = _data.dataItem;
}
if (element instanceof jQuery) {
element.each((index, elem) => this.enhanceView($parent, elem, ctx));
} else {
this.enhanceView($parent, element, ctx);
}
}
}
/**
* uses the enhance function of Aurelia's TemplatingEngine
* to "compile" existing DOM elements
* @param element The Element to compile
* @param ctx The dataitem (context) to compile the Element with
*/
enhanceView($parent, element, ctx) {
let view = this.templatingEngine.enhance(element);
view.bind(ctx, $parent); // call the bind() function on the view with the dataItem we got from Kendo
view.attached(); // attach it to the DOM
// when we do cleanup, we need to get the view instance
// so we can call detached/unbind
// so we store this view instance in the DOM element using JQuery.data
$(element).data('viewInstance', view);
}
/**
* loops through each element kendo asks us to clean up
* calls cleanupView() for each element
* @param element An array of elements
*/
cleanup(elements) {
if (!elements) return;
for (let i = 0; i < elements.length; i++) {
let element = elements[i];
this.cleanupView(element);
}
}
/**
* cleans up the view kendo has asked us to clean up
*/
cleanupView(element) {
// extract Aurelia's View instance from the element
// we stored this in the enhanceView function
let view = $(element).data('viewInstance');
if (!view) return;
// unbind and detach the view
view.detached();
view.unbind();
}
}