PluginProbe
User Access Manager / 2.2.15
User Access Manager v2.2.15
2.3.20 2.3.19 2.3.18 2.3.17 2.3.16 2.3.15 2.3.14 2.3.13 trunk 0.6 0.6.1 0.6.2 0.7 0.7 Beta 0.7.0.1 0.8 0.8.0.1 0.8.0.2 0.9 0.9.1 0.9.1.1 0.9.1.2 0.9.1.3 0.9.1.4 1.0 All 136 releases
user-access-manager / assets / js / jquery.uam-group-suggest.js

jquery.uam-group-suggest.js in User Access Manager 2.2.15, at assets/js/jquery.uam-group-suggest.js

317 lines 10.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function($) {
2 $.uamGroupSuggest = function(input, options) {
3 var $input = $(input).attr("autocomplete", "off");
4 var $list = $(options.listClass);
5 var $results = $("<ul>");
6
7 var timeout = false; // hold timeout ID for suggestion results to appear
8 var prevLength = 0; // last recorded length of $input.val()
9 var cache = []; // cache MRU list
10 var cacheSize = 0; // size of cache in chars (bytes?)
11
12 $results.addClass(options.resultsClass).appendTo('body');
13 resetPosition();
14
15 $(window).on('load', resetPosition) // just in case user is changing size of page while loading
16 .on('resize', resetPosition);
17
18 $input.blur(function() {
19 setTimeout(function() {
20 $results.hide()
21 }, 200);
22 });
23
24 $input.keydown(processKey);
25
26 function resetPosition() {
27 // requires jquery.dimension plugin
28 var offset = $input.offset();
29 $results.css({
30 top: (offset.top + input.offsetHeight) + 'px',
31 left: offset.left + 'px'
32 });
33 }
34
35 function processKey(e) {
36 // handling up/down/escape requires results to be visible
37 // handling enter/tab requires that AND a result to be selected
38 if ((/27$|38$|40$/.test(e.keyCode) && $results.is(':visible')) ||
39 (/^13$|^9$/.test(e.keyCode) && getCurrentResult())
40 ) {
41 if (e.preventDefault) {
42 e.preventDefault();
43 }
44
45 if (e.stopPropagation) {
46 e.stopPropagation();
47 }
48
49 e.cancelBubble = true;
50 e.returnValue = false;
51
52 switch(e.keyCode) {
53 case 38: // up
54 prevResult();
55 break;
56 case 40: // down
57 nextResult();
58 break;
59 case 9: // tab
60 case 13: // return
61 selectCurrentResult();
62 break;
63 case 27: // escape
64 $results.hide();
65 break;
66 default:
67 break;
68 }
69 } else if ($input.val().length !== prevLength) {
70 if (timeout !== false) {
71 clearTimeout(parseInt(timeout));
72 }
73
74 timeout = setTimeout(suggest, options.delay);
75 prevLength = $input.val().length;
76 }
77 }
78
79 function suggest() {
80 var q = $.trim($input.val()), items;
81
82 if (q.length >= options.minchars) {
83 var cached = checkCache(q);
84
85 if (cached) {
86 displayItems(cached['items']);
87 } else {
88 $.get(options.source, {q: q}, function(response) {
89 $results.hide();
90 items = parseResponse(response, q);
91 displayItems(items);
92 addToCache(q, items, response.length);
93 });
94 }
95 } else {
96 $results.hide();
97 }
98 }
99
100 function checkCache(q) {
101 for (var i = 0; i < cache.length; i++) {
102 if (cache[i]['q'] === q) {
103 cache.unshift(cache.splice(i, 1)[0]);
104 return cache[0];
105 }
106 }
107
108 return false;
109 }
110
111 function addToCache(q, items, size) {
112 var cached;
113 while (cache.length && (cacheSize + size > options.maxCacheSize)) {
114 cached = cache.pop();
115 cacheSize -= cached['size'];
116 }
117
118 cache.push({
119 q: q,
120 size: size,
121 items: items
122 });
123
124 cacheSize += size;
125 }
126
127 function displayItems(items) {
128 if (!items) {
129 return;
130 }
131
132 if (!items.length) {
133 $results.hide();
134 return;
135 }
136
137 resetPosition(); // when the form moves after the page has loaded
138
139 var html = '';
140
141 for (var i = 0; i < items.length; i++) {
142 var data = $(items[i]).data();
143 var elementSelector = 'input[value="' + data['dgType'] + '|' + data['dgId'] + '"]';
144
145 if ($(elementSelector, $list).length <= 0) {
146 html += '<li>' + items[i] + '</li>';
147 }
148 }
149
150 $results.html(html).show();
151
152 $results
153 .children('li')
154 .mouseover(function() {
155 $results.children('li').removeClass(options.selectClass);
156 $(this).addClass(options.selectClass);
157 })
158 .click(function(e) {
159 e.preventDefault();
160 e.stopPropagation();
161 selectCurrentResult();
162 });
163 }
164
165 function parseResponse(response, q) {
166 var items = [];
167 var results = JSON.parse(response);
168
169 // parse returned data for non-empty items
170 for (var i = 0; i < results.length; i++) {
171 var result = results[i];
172
173 if (result) {
174 var element = '<span data-dg-id="' + result.id + '" data-dg-type="' + result.type + '" >';
175 element += result.name.replace(
176 new RegExp(q, 'ig'),
177 function(q) {
178 return '<span class="' + options.matchClass + '" >' + q + '</span>';
179 }
180 );
181 element += '</span>';
182
183 items[items.length] = element;
184 }
185 }
186
187 return items;
188 }
189
190 function getCurrentResult() {
191 if (!$results.is(':visible')) {
192 return false;
193 }
194
195 var $currentResult = $results.children('li.' + options.selectClass);
196 return (!$currentResult.length) ? false : $currentResult;
197 }
198
199 function getDatetimeInput(formName, id, type) {
200 var $label = $('<label>').attr({
201 "for": formName + '-' + 'id' + '-' + type
202 }).html(type);
203
204 var $input = $('<input>').attr({
205 "type": 'datetime-local',
206 "id": formName + '-' + 'id' + '-' + type,
207 "name": formName + '[' + id + '][' + type + ']'
208 });
209
210 return $('<div>').append($label).append($input);
211 }
212
213 function selectCurrentResult() {
214 var $currentResult = getCurrentResult();
215
216 if ($currentResult) {
217 $currentResult = $('span:first-child', $currentResult);
218
219 var formName = 'uam_dynamic_user_groups';
220 var dgType = $currentResult.data('dg-type');
221 var dgId = $currentResult.data('dg-id');
222 var id = dgType + '|' + dgId;
223 var elementId = 'uam_user_groups-' + id;
224
225 var $elementInput = $('<input>').attr({
226 "id": elementId,
227 "type": 'checkbox',
228 "value": id,
229 "name": formName + '[' + id + '][id]',
230 "checked": "checked"
231 });
232
233 var $elementLabel = $('<label>').attr({
234 "for": elementId,
235 "class": 'selectit'
236 }).html($currentResult.html().replace(/(<([^>]+)>)/ig, ''));
237
238 var $dateButton = $('<span>').attr({
239 "class": 'uam_group_date'
240 }).html('Setup time based group assignment');
241
242 var $dateContainer = $('<div>').attr({
243 "class": 'uam_group_date_form'
244 });
245
246 $dateContainer.append(getDatetimeInput(formName, id, 'fromDate'))
247 .append(getDatetimeInput(formName, id, 'toDate'));
248
249 var $element = $('<li>')
250 .append($elementInput)
251 .append('\n')
252 .append($elementLabel)
253 .append($dateButton)
254 .append($dateContainer);
255
256 $list.append($element);
257
258 $results.hide();
259 $input.trigger('change');
260 $input.val('');
261
262 if (options.onSelect) {
263 options.onSelect.apply($input[0]);
264 }
265 }
266 }
267
268 function nextResult() {
269 var $currentResult = getCurrentResult();
270
271 if ($currentResult) {
272 $currentResult.removeClass(options.selectClass)
273 .next()
274 .addClass(options.selectClass);
275 } else {
276 $results.children('li:first-child').addClass(options.selectClass);
277 }
278
279 }
280
281 function prevResult() {
282 var $currentResult = getCurrentResult();
283
284 if ($currentResult) {
285 $currentResult
286 .removeClass(options.selectClass)
287 .prev()
288 .addClass(options.selectClass);
289 } else {
290 $results.children('li:last-child').addClass(options.selectClass);
291 }
292 }
293 };
294
295 $.fn.uamGroupSuggest = function(source, options) {
296 if (!source) {
297 return;
298 }
299
300 options = options || {};
301 options.source = source;
302 options.delay = options.delay || 100;
303 options.listClass = options.listClass || '.uam_group_selection';
304 options.resultsClass = options.resultsClass || 'ac_results';
305 options.selectClass = options.selectClass || 'ac_over';
306 options.matchClass = options.matchClass || 'ac_match';
307 options.minchars = options.minchars || 2;
308 options.onSelect = options.onSelect || false;
309 options.maxCacheSize = options.maxCacheSize || 65536;
310
311 this.each(function() {
312 $.uamGroupSuggest(this, options);
313 });
314
315 return this;
316 };
317 })(jQuery);