forked from kendo-labs/angular-kendo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
angular-kendo.js
134 lines (117 loc) · 5.23 KB
/
angular-kendo.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
(function(angular, _, jQuery, kendo) {
"use strict";
var main = angular.module('kendo', ['kendo.directives', 'kendo.services']);
var directives = angular.module('kendo.directives', []);
var services = angular.module('kendo.services', []);
var widgets = _.filter(_.keys(jQuery.fn), function(prop){
return !!prop.match(/^kendo(?:(?!Mobile))/);
});
// setting up a value service containing the names of available kendo widgets
services.value('kendoWidgets', widgets);
// here we create a directive for each kendo widgets
angular.forEach( widgets, function(kendoWidget) {
directives.directive(kendoWidget, [ '$parse', '$timeout', function($parse, $timeout) {
var options;
return {
restrict: 'ACE',
transclude: true,
require: ['?ngModel','?kendoSource'],
controller: [ '$scope', '$attrs', '$element', '$transclude', function($scope, $attrs, $element, $transclude) {
// The options expression is evaluated once
options = angular.copy($scope.$eval($attrs[kendoWidget])) || {};
$transclude(function(clone){
$element.append(clone);
});
}],
link: function(scope, element, attrs, ctrls) {
var ngModel = ctrls[0],
kendoSource = ctrls[1], widget;
// bind kendo widget to element only once interpolation on attributes is done
$timeout( function() {
// mixing the data that's set on the element in the options
angular.extend(options, element.data());
if( kendoSource ) {
//override the datasource property received in options, if any
options.dataSource = kendoSource.getDataSource();
}
// add on-* event handlers to options
addEventHandlers(options, scope, attrs);
// bind the kendo widget to element and get a reference on the widget
widget = element[kendoWidget](options).data(kendoWidget);
// if ngModel is on the element, we setup bidi data binding
if (ngModel) {
if( !widget.value ) {
throw new Error('ng-model used but ' + kendoWidget + ' does not define a value accessor');
}
// angular will invoke $render when the view
// needs to be updated with the view value.
ngModel.$render = function() {
// udate the widget with the view value
widget.value(ngModel.$viewValue);
};
// when the kendo widget's value changes...
widget.bind("change", function(e) {
// make sure this gets executed in the angularjs lifecycle
scope.$apply(function() {
// set the ngModel's view value
ngModel.$setViewValue(widget.value());
});
});
}
});
}
};
// Create an event handler function for each on-* attribute on the element and add to dest.
function addEventHandlers(dest, scope, attrs) {
var eventHandlers = _.reduce(_.keys(attrs), function(memo, att) {
var match = att.match(/^on(.+)/), eventName, fn;
if( match ) {
//lowercase the first letter
eventName = match[1].charAt(0).toLowerCase() + match[1].slice(1);
//parse the expression
fn = $parse(attrs[att]);
//add a kendo event listener to the memo
memo[eventName] = function(e) {
// make sure this gets invoked in the angularjs lifecycle
scope.$apply(function() {
//invoke the parsed expression with a kendoEvent local that the expression can use.
fn(scope, {kendoEvent: e});
});
};
}
return memo;
}, {});
// mix the eventHandlers in the options object
angular.extend(dest, eventHandlers);
}
}] );
});
directives.directive('kendoSource', [function() {
return {
restrict: 'A',
controller: ['$scope', '$attrs', function($scope, $attrs) {
var dataSource = toDataSource($scope.$eval($attrs.kendoSource));
// reference equality watch
$scope.$watch($attrs.kendoSource, function(ds) {
dataSource = toDataSource(ds);
});
this.getDataSource = function() {
return dataSource;
};
}]
};
function toDataSource(ds) {
if( ds instanceof kendo.data.DataSource ) {
return ds;
} else if( angular.isObject(ds) ) {
return new kendo.data.DataSource(ds);
} else if( angular.isArray(ds) ) {
return new kendo.data.DataSource({
data: ds
});
} else {
throw new Error('kendo-source must be a kendo datasource object');
}
}
}]);
})(angular, _, jQuery, kendo);