source: main/trunk/model-interfaces-dev/heritage-nz/iframe/heritage-nz-dl_files/angularui.js@ 32796

Last change on this file since 32796 was 32796, checked in by davidb, 5 years ago

Initial set of files to provide look and feel of Heritage NZ site, plus SVN clickable map in an iframe

  • Property svn:executable set to *
File size: 9.8 KB
Line 
1/**
2 * Enhanced Select2 Dropmenus
3 *
4 * @AJAX Mode - When in this mode, your value will be an object (or array of objects) of the data used by Select2
5 * This change is so that you do not have to do an additional query yourself on top of Select2's own query
6 * @params [options] {object} The configuration options passed to $.fn.select2(). Refer to the documentation
7 */
8angular.module('ui.select2', []).value('uiSelect2Config', {}).directive('uiSelect2', ['uiSelect2Config', '$timeout', function (uiSelect2Config, $timeout) {
9 var options = {};
10 if (uiSelect2Config) {
11 angular.extend(options, uiSelect2Config);
12 }
13 return {
14 require: 'ngModel',
15 priority: 1,
16 compile: function (tElm, tAttrs) {
17 var watch,
18 repeatOption,
19 repeatAttr,
20 isSelect = tElm.is('select'),
21 isMultiple = angular.isDefined(tAttrs.multiple);
22
23 // Enable watching of the options dataset if in use
24 if (tElm.is('select')) {
25 repeatOption = tElm.find('optgroup[ng-repeat], optgroup[data-ng-repeat], option[ng-repeat], option[data-ng-repeat]');
26
27 if (repeatOption.length) {
28 repeatAttr = repeatOption.attr('ng-repeat') || repeatOption.attr('data-ng-repeat');
29 watch = jQuery.trim(repeatAttr.split('|')[0]).split(' ').pop();
30 }
31 }
32
33 return function (scope, elm, attrs, controller) {
34 // instance-specific options
35 var opts = angular.extend({}, options, scope.$eval(attrs.uiSelect2));
36
37 /*
38 Convert from Select2 view-model to Angular view-model.
39 */
40 var convertToAngularModel = function (select2_data) {
41 var model;
42 if (opts.simple_tags) {
43 model = [];
44 angular.forEach(select2_data, function (value, index) {
45 model.push(value.id);
46 });
47 } else {
48 model = select2_data;
49 }
50 return model;
51 };
52
53 /*
54 Convert from Angular view-model to Select2 view-model.
55 */
56 var convertToSelect2Model = function (angular_data) {
57 var model = [];
58 if (!angular_data) {
59 return model;
60 }
61
62 if (opts.simple_tags) {
63 model = [];
64 angular.forEach(
65 angular_data,
66 function (value, index) {
67 model.push({ 'id': value, 'text': value });
68 });
69 } else {
70 model = angular_data;
71 }
72 return model;
73 };
74
75 if (isSelect) {
76 // Use <select multiple> instead
77 delete opts.multiple;
78 delete opts.initSelection;
79 } else if (isMultiple) {
80 opts.multiple = true;
81 }
82
83 if (controller) {
84 // Watch the model for programmatic changes
85 scope.$watch(tAttrs.ngModel, function (current, old) {
86 if (!current) {
87 return;
88 }
89 if (current === old) {
90 return;
91 }
92 controller.$render();
93 }, true);
94 controller.$render = function () {
95 if (isSelect) {
96 elm.select2('val', controller.$viewValue);
97 } else {
98 if (opts.multiple) {
99 var viewValue = controller.$viewValue;
100 if (angular.isString(viewValue)) {
101 viewValue = viewValue.split(opts.separator);
102 }
103 elm.select2(
104 'data', convertToSelect2Model(viewValue));
105 } else {
106 if (angular.isObject(controller.$viewValue)) {
107 elm.select2('data', controller.$viewValue);
108 } else if (!controller.$viewValue) {
109 elm.select2('data', null);
110 } else {
111 elm.select2('val', controller.$viewValue);
112 }
113 }
114 }
115 };
116
117 // Watch the options dataset for changes
118 if (watch) {
119 scope.$watch(watch, function (newVal, oldVal, scope) {
120 if (angular.equals(newVal, oldVal)) {
121 return;
122 }
123 // Delayed so that the options have time to be rendered
124 $timeout(function () {
125 elm.select2('val', controller.$viewValue);
126 // Refresh angular to remove the superfluous option
127 elm.trigger('change');
128 if (newVal && !oldVal && controller.$setPristine) {
129 controller.$setPristine(true);
130 }
131 });
132 });
133 }
134
135 // Update valid and dirty statuses
136 controller.$parsers.push(function (value) {
137 var div = elm.prev();
138 div
139 .toggleClass('ng-invalid', !controller.$valid)
140 .toggleClass('ng-valid', controller.$valid)
141 .toggleClass('ng-invalid-required', !controller.$valid)
142 .toggleClass('ng-valid-required', controller.$valid)
143 .toggleClass('ng-dirty', controller.$dirty)
144 .toggleClass('ng-pristine', controller.$pristine);
145 return value;
146 });
147
148 if (!isSelect) {
149 // Set the view and model value and update the angular template manually for the ajax/multiple select2.
150 elm.bind("change", function (e) {
151 e.stopImmediatePropagation();
152
153 if (scope.$$phase || scope.$root.$$phase) {
154 return;
155 }
156 scope.$apply(function () {
157 controller.$setViewValue(
158 convertToAngularModel(elm.select2('data')));
159 });
160 });
161
162 if (opts.initSelection) {
163 var initSelection = opts.initSelection;
164 opts.initSelection = function (element, callback) {
165 initSelection(element, function (value) {
166 var isPristine = controller.$pristine;
167 controller.$setViewValue(convertToAngularModel(value));
168 callback(value);
169 if (isPristine) {
170 controller.$setPristine();
171 }
172 elm.prev().toggleClass('ng-pristine', controller.$pristine);
173 });
174 };
175 }
176 }
177 }
178
179 elm.bind("$destroy", function () {
180 elm.select2("destroy");
181 });
182
183 attrs.$observe('disabled', function (value) {
184 elm.select2('enable', !value);
185 });
186
187 attrs.$observe('readonly', function (value) {
188 elm.select2('readonly', !!value);
189 });
190
191 if (attrs.ngMultiple) {
192 scope.$watch(attrs.ngMultiple, function (newVal) {
193 attrs.$set('multiple', !!newVal);
194 elm.select2(opts);
195 });
196 }
197
198 // Initialize the plugin late so that the injected DOM does not disrupt the template compiler
199 $timeout(function () {
200 elm.select2(opts);
201
202 // Set initial value - I'm not sure about this but it seems to need to be there
203 elm.select2('data', controller.$modelValue);
204 // important!
205 controller.$render();
206
207 // Not sure if I should just check for !isSelect OR if I should check for 'tags' key
208 if (!opts.initSelection && !isSelect) {
209 var isPristine = controller.$pristine;
210 controller.$setViewValue(
211 convertToAngularModel(elm.select2('data'))
212 );
213 if (isPristine) {
214 controller.$setPristine();
215 }
216 elm.prev().toggleClass('ng-pristine', controller.$pristine);
217 }
218 });
219 };
220 }
221 };
222}]);
Note: See TracBrowser for help on using the repository browser.