1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | (function ($) {
|
8 |
|
9 | $.extend(true, window, {
|
10 | "Slick": {
|
11 | "Editors": {
|
12 | "Text": TextEditor,
|
13 | "Integer": IntegerEditor,
|
14 | "Float": FloatEditor,
|
15 | "Date": DateEditor,
|
16 | "YesNoSelect": YesNoSelectEditor,
|
17 | "Checkbox": CheckboxEditor,
|
18 | "PercentComplete": PercentCompleteEditor,
|
19 | "LongText": LongTextEditor
|
20 | }
|
21 | }
|
22 | });
|
23 |
|
24 | function TextEditor(args) {
|
25 | var $input;
|
26 | var defaultValue;
|
27 | var scope = this;
|
28 |
|
29 | this.init = function () {
|
30 | var navOnLR = args.grid.getOptions().editorCellNavOnLRKeys;
|
31 | $input = $("<INPUT type=text class='editor-text' />")
|
32 | .appendTo(args.container)
|
33 | .on("keydown.nav", navOnLR ? handleKeydownLRNav : handleKeydownLRNoNav)
|
34 | .focus()
|
35 | .select();
|
36 | };
|
37 |
|
38 | this.destroy = function () {
|
39 | $input.remove();
|
40 | };
|
41 |
|
42 | this.focus = function () {
|
43 | $input.focus();
|
44 | };
|
45 |
|
46 | this.getValue = function () {
|
47 | return $input.val();
|
48 | };
|
49 |
|
50 | this.setValue = function (val) {
|
51 | $input.val(val);
|
52 | };
|
53 |
|
54 | this.loadValue = function (item) {
|
55 | defaultValue = item[args.column.field] || "";
|
56 | $input.val(defaultValue);
|
57 | $input[0].defaultValue = defaultValue;
|
58 | $input.select();
|
59 | };
|
60 |
|
61 | this.serializeValue = function () {
|
62 | return $input.val();
|
63 | };
|
64 |
|
65 | this.applyValue = function (item, state) {
|
66 | item[args.column.field] = state;
|
67 | };
|
68 |
|
69 | this.isValueChanged = function () {
|
70 | return (!($input.val() === "" && defaultValue == null)) && ($input.val() != defaultValue);
|
71 | };
|
72 |
|
73 | this.validate = function () {
|
74 | if (args.column.validator) {
|
75 | var validationResults = args.column.validator($input.val());
|
76 | if (!validationResults.valid) {
|
77 | return validationResults;
|
78 | }
|
79 | }
|
80 |
|
81 | return {
|
82 | valid: true,
|
83 | msg: null
|
84 | };
|
85 | };
|
86 |
|
87 | this.init();
|
88 | }
|
89 |
|
90 | function IntegerEditor(args) {
|
91 | var $input;
|
92 | var defaultValue;
|
93 | var scope = this;
|
94 |
|
95 | this.init = function () {
|
96 | var navOnLR = args.grid.getOptions().editorCellNavOnLRKeys;
|
97 | $input = $("<INPUT type=text class='editor-text' />")
|
98 | .appendTo(args.container)
|
99 | .on("keydown.nav", navOnLR ? handleKeydownLRNav : handleKeydownLRNoNav)
|
100 | .focus()
|
101 | .select();
|
102 | };
|
103 |
|
104 | this.destroy = function () {
|
105 | $input.remove();
|
106 | };
|
107 |
|
108 | this.focus = function () {
|
109 | $input.focus();
|
110 | };
|
111 |
|
112 | this.loadValue = function (item) {
|
113 | defaultValue = item[args.column.field];
|
114 | $input.val(defaultValue);
|
115 | $input[0].defaultValue = defaultValue;
|
116 | $input.select();
|
117 | };
|
118 |
|
119 | this.serializeValue = function () {
|
120 | return parseInt($input.val(), 10) || 0;
|
121 | };
|
122 |
|
123 | this.applyValue = function (item, state) {
|
124 | item[args.column.field] = state;
|
125 | };
|
126 |
|
127 | this.isValueChanged = function () {
|
128 | return (!($input.val() === "" && defaultValue == null)) && ($input.val() != defaultValue);
|
129 | };
|
130 |
|
131 | this.validate = function () {
|
132 | if (isNaN($input.val())) {
|
133 | return {
|
134 | valid: false,
|
135 | msg: "Please enter a valid integer"
|
136 | };
|
137 | }
|
138 |
|
139 | if (args.column.validator) {
|
140 | var validationResults = args.column.validator($input.val());
|
141 | if (!validationResults.valid) {
|
142 | return validationResults;
|
143 | }
|
144 | }
|
145 |
|
146 | return {
|
147 | valid: true,
|
148 | msg: null
|
149 | };
|
150 | };
|
151 |
|
152 | this.init();
|
153 | }
|
154 |
|
155 | function FloatEditor(args) {
|
156 | var $input;
|
157 | var defaultValue;
|
158 | var scope = this;
|
159 |
|
160 | this.init = function () {
|
161 | var navOnLR = args.grid.getOptions().editorCellNavOnLRKeys;
|
162 | $input = $("<INPUT type=text class='editor-text' />")
|
163 | .appendTo(args.container)
|
164 | .on("keydown.nav", navOnLR ? handleKeydownLRNav : handleKeydownLRNoNav)
|
165 | .focus()
|
166 | .select();
|
167 | };
|
168 |
|
169 | this.destroy = function () {
|
170 | $input.remove();
|
171 | };
|
172 |
|
173 | this.focus = function () {
|
174 | $input.focus();
|
175 | };
|
176 |
|
177 | function getDecimalPlaces() {
|
178 |
|
179 | var rtn = args.column.editorFixedDecimalPlaces;
|
180 | if (typeof rtn == 'undefined') {
|
181 | rtn = FloatEditor.DefaultDecimalPlaces;
|
182 | }
|
183 | return (!rtn && rtn!==0 ? null : rtn);
|
184 | }
|
185 |
|
186 | this.loadValue = function (item) {
|
187 | defaultValue = item[args.column.field];
|
188 |
|
189 | var decPlaces = getDecimalPlaces();
|
190 | if (decPlaces !== null
|
191 | && (defaultValue || defaultValue===0)
|
192 | && defaultValue.toFixed) {
|
193 | defaultValue = defaultValue.toFixed(decPlaces);
|
194 | }
|
195 |
|
196 | $input.val(defaultValue);
|
197 | $input[0].defaultValue = defaultValue;
|
198 | $input.select();
|
199 | };
|
200 |
|
201 | this.serializeValue = function () {
|
202 | var rtn = parseFloat($input.val());
|
203 | if (FloatEditor.AllowEmptyValue) {
|
204 | if (!rtn && rtn !==0) { rtn = ''; }
|
205 | } else {
|
206 | rtn = rtn || 0;
|
207 | }
|
208 |
|
209 | var decPlaces = getDecimalPlaces();
|
210 | if (decPlaces !== null
|
211 | && (rtn || rtn===0)
|
212 | && rtn.toFixed) {
|
213 | rtn = parseFloat(rtn.toFixed(decPlaces));
|
214 | }
|
215 |
|
216 | return rtn;
|
217 | };
|
218 |
|
219 | this.applyValue = function (item, state) {
|
220 | item[args.column.field] = state;
|
221 | };
|
222 |
|
223 | this.isValueChanged = function () {
|
224 | return (!($input.val() === "" && defaultValue == null)) && ($input.val() != defaultValue);
|
225 | };
|
226 |
|
227 | this.validate = function () {
|
228 | if (isNaN($input.val())) {
|
229 | return {
|
230 | valid: false,
|
231 | msg: "Please enter a valid number"
|
232 | };
|
233 | }
|
234 |
|
235 | if (args.column.validator) {
|
236 | var validationResults = args.column.validator($input.val());
|
237 | if (!validationResults.valid) {
|
238 | return validationResults;
|
239 | }
|
240 | }
|
241 |
|
242 | return {
|
243 | valid: true,
|
244 | msg: null
|
245 | };
|
246 | };
|
247 |
|
248 | this.init();
|
249 | }
|
250 |
|
251 | FloatEditor.DefaultDecimalPlaces = null;
|
252 | FloatEditor.AllowEmptyValue = false;
|
253 |
|
254 | function DateEditor(args) {
|
255 | var $input;
|
256 | var defaultValue;
|
257 | var scope = this;
|
258 | var calendarOpen = false;
|
259 |
|
260 | this.init = function () {
|
261 | $input = $("<INPUT type=text class='editor-text' />");
|
262 | $input.appendTo(args.container);
|
263 | $input.focus().select();
|
264 | $input.datepicker({
|
265 | showOn: "button",
|
266 | buttonImageOnly: true,
|
267 | beforeShow: function () {
|
268 | calendarOpen = true;
|
269 | },
|
270 | onClose: function () {
|
271 | calendarOpen = false;
|
272 | }
|
273 | });
|
274 | $input.width($input.width() - 18);
|
275 | };
|
276 |
|
277 | this.destroy = function () {
|
278 | $.datepicker.dpDiv.stop(true, true);
|
279 | $input.datepicker("hide");
|
280 | $input.datepicker("destroy");
|
281 | $input.remove();
|
282 | };
|
283 |
|
284 | this.show = function () {
|
285 | if (calendarOpen) {
|
286 | $.datepicker.dpDiv.stop(true, true).show();
|
287 | }
|
288 | };
|
289 |
|
290 | this.hide = function () {
|
291 | if (calendarOpen) {
|
292 | $.datepicker.dpDiv.stop(true, true).hide();
|
293 | }
|
294 | };
|
295 |
|
296 | this.position = function (position) {
|
297 | if (!calendarOpen) {
|
298 | return;
|
299 | }
|
300 | $.datepicker.dpDiv
|
301 | .css("top", position.top + 30)
|
302 | .css("left", position.left);
|
303 | };
|
304 |
|
305 | this.focus = function () {
|
306 | $input.focus();
|
307 | };
|
308 |
|
309 | this.loadValue = function (item) {
|
310 | defaultValue = item[args.column.field];
|
311 | $input.val(defaultValue);
|
312 | $input[0].defaultValue = defaultValue;
|
313 | $input.select();
|
314 | };
|
315 |
|
316 | this.serializeValue = function () {
|
317 | return $input.val();
|
318 | };
|
319 |
|
320 | this.applyValue = function (item, state) {
|
321 | item[args.column.field] = state;
|
322 | };
|
323 |
|
324 | this.isValueChanged = function () {
|
325 | return (!($input.val() === "" && defaultValue == null)) && ($input.val() != defaultValue);
|
326 | };
|
327 |
|
328 | this.validate = function () {
|
329 | if (args.column.validator) {
|
330 | var validationResults = args.column.validator($input.val());
|
331 | if (!validationResults.valid) {
|
332 | return validationResults;
|
333 | }
|
334 | }
|
335 |
|
336 | return {
|
337 | valid: true,
|
338 | msg: null
|
339 | };
|
340 | };
|
341 |
|
342 | this.init();
|
343 | }
|
344 |
|
345 | function YesNoSelectEditor(args) {
|
346 | var $select;
|
347 | var defaultValue;
|
348 | var scope = this;
|
349 |
|
350 | this.init = function () {
|
351 | $select = $("<SELECT tabIndex='0' class='editor-yesno'><OPTION value='yes'>Yes</OPTION><OPTION value='no'>No</OPTION></SELECT>");
|
352 | $select.appendTo(args.container);
|
353 | $select.focus();
|
354 | };
|
355 |
|
356 | this.destroy = function () {
|
357 | $select.remove();
|
358 | };
|
359 |
|
360 | this.focus = function () {
|
361 | $select.focus();
|
362 | };
|
363 |
|
364 | this.loadValue = function (item) {
|
365 | $select.val((defaultValue = item[args.column.field]) ? "yes" : "no");
|
366 | $select.select();
|
367 | };
|
368 |
|
369 | this.serializeValue = function () {
|
370 | return ($select.val() == "yes");
|
371 | };
|
372 |
|
373 | this.applyValue = function (item, state) {
|
374 | item[args.column.field] = state;
|
375 | };
|
376 |
|
377 | this.isValueChanged = function () {
|
378 | return ($select.val() != defaultValue);
|
379 | };
|
380 |
|
381 | this.validate = function () {
|
382 | return {
|
383 | valid: true,
|
384 | msg: null
|
385 | };
|
386 | };
|
387 |
|
388 | this.init();
|
389 | }
|
390 |
|
391 | function CheckboxEditor(args) {
|
392 | var $select;
|
393 | var defaultValue;
|
394 | var scope = this;
|
395 |
|
396 | this.init = function () {
|
397 | $select = $("<INPUT type=checkbox value='true' class='editor-checkbox' hideFocus>");
|
398 | $select.appendTo(args.container);
|
399 | $select.focus();
|
400 | };
|
401 |
|
402 | this.destroy = function () {
|
403 | $select.remove();
|
404 | };
|
405 |
|
406 | this.focus = function () {
|
407 | $select.focus();
|
408 | };
|
409 |
|
410 | this.loadValue = function (item) {
|
411 | defaultValue = !!item[args.column.field];
|
412 | if (defaultValue) {
|
413 | $select.prop('checked', true);
|
414 | } else {
|
415 | $select.prop('checked', false);
|
416 | }
|
417 | };
|
418 |
|
419 | this.preClick = function () {
|
420 | $select.prop('checked', !$select.prop('checked'));
|
421 | };
|
422 |
|
423 | this.serializeValue = function () {
|
424 | return $select.prop('checked');
|
425 | };
|
426 |
|
427 | this.applyValue = function (item, state) {
|
428 | item[args.column.field] = state;
|
429 | };
|
430 |
|
431 | this.isValueChanged = function () {
|
432 | return (this.serializeValue() !== defaultValue);
|
433 | };
|
434 |
|
435 | this.validate = function () {
|
436 | return {
|
437 | valid: true,
|
438 | msg: null
|
439 | };
|
440 | };
|
441 |
|
442 | this.init();
|
443 | }
|
444 |
|
445 | function PercentCompleteEditor(args) {
|
446 | var $input, $picker;
|
447 | var defaultValue;
|
448 | var scope = this;
|
449 |
|
450 | this.init = function () {
|
451 | $input = $("<INPUT type=text class='editor-percentcomplete' />");
|
452 | $input.width($(args.container).innerWidth() - 25);
|
453 | $input.appendTo(args.container);
|
454 |
|
455 | $picker = $("<div class='editor-percentcomplete-picker' />").appendTo(args.container);
|
456 | $picker.append("<div class='editor-percentcomplete-helper'><div class='editor-percentcomplete-wrapper'><div class='editor-percentcomplete-slider' /><div class='editor-percentcomplete-buttons' /></div></div>");
|
457 |
|
458 | $picker.find(".editor-percentcomplete-buttons").append("<button val=0>Not started</button><br/><button val=50>In Progress</button><br/><button val=100>Complete</button>");
|
459 |
|
460 | $input.focus().select();
|
461 |
|
462 | $picker.find(".editor-percentcomplete-slider").slider({
|
463 | orientation: "vertical",
|
464 | range: "min",
|
465 | value: defaultValue,
|
466 | slide: function (event, ui) {
|
467 | $input.val(ui.value);
|
468 | }
|
469 | });
|
470 |
|
471 | $picker.find(".editor-percentcomplete-buttons button").on("click", function (e) {
|
472 | $input.val($(this).attr("val"));
|
473 | $picker.find(".editor-percentcomplete-slider").slider("value", $(this).attr("val"));
|
474 | });
|
475 | };
|
476 |
|
477 | this.destroy = function () {
|
478 | $input.remove();
|
479 | $picker.remove();
|
480 | };
|
481 |
|
482 | this.focus = function () {
|
483 | $input.focus();
|
484 | };
|
485 |
|
486 | this.loadValue = function (item) {
|
487 | $input.val(defaultValue = item[args.column.field]);
|
488 | $input.select();
|
489 | };
|
490 |
|
491 | this.serializeValue = function () {
|
492 | return parseInt($input.val(), 10) || 0;
|
493 | };
|
494 |
|
495 | this.applyValue = function (item, state) {
|
496 | item[args.column.field] = state;
|
497 | };
|
498 |
|
499 | this.isValueChanged = function () {
|
500 | return (!($input.val() === "" && defaultValue == null)) && ((parseInt($input.val(), 10) || 0) != defaultValue);
|
501 | };
|
502 |
|
503 | this.validate = function () {
|
504 | if (isNaN(parseInt($input.val(), 10))) {
|
505 | return {
|
506 | valid: false,
|
507 | msg: "Please enter a valid positive number"
|
508 | };
|
509 | }
|
510 |
|
511 | return {
|
512 | valid: true,
|
513 | msg: null
|
514 | };
|
515 | };
|
516 |
|
517 | this.init();
|
518 | }
|
519 |
|
520 | |
521 |
|
522 |
|
523 |
|
524 |
|
525 | function LongTextEditor(args) {
|
526 | var $input, $wrapper;
|
527 | var defaultValue;
|
528 | var scope = this;
|
529 |
|
530 | this.init = function () {
|
531 | var $container = $("body");
|
532 | var navOnLR = args.grid.getOptions().editorCellNavOnLRKeys;
|
533 |
|
534 | $wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>")
|
535 | .appendTo($container);
|
536 |
|
537 | $input = $("<TEXTAREA hidefocus rows=5 style='background:white;width:250px;height:80px;border:0;outline:0'>")
|
538 | .appendTo($wrapper);
|
539 |
|
540 | $("<DIV style='text-align:right'><BUTTON>Save</BUTTON><BUTTON>Cancel</BUTTON></DIV>")
|
541 | .appendTo($wrapper);
|
542 |
|
543 | $wrapper.find("button:first").on("click", this.save);
|
544 | $wrapper.find("button:last").on("click", this.cancel);
|
545 | $input.on("keydown", this.handleKeyDown);
|
546 |
|
547 | scope.position(args.position);
|
548 | $input.focus().select();
|
549 | };
|
550 |
|
551 | this.handleKeyDown = function (e) {
|
552 | if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) {
|
553 | scope.save();
|
554 | } else if (e.which == $.ui.keyCode.ESCAPE) {
|
555 | e.preventDefault();
|
556 | scope.cancel();
|
557 | } else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
|
558 | e.preventDefault();
|
559 | args.grid.navigatePrev();
|
560 | } else if (e.which == $.ui.keyCode.TAB) {
|
561 | e.preventDefault();
|
562 | args.grid.navigateNext();
|
563 | } else if (e.which == $.ui.keyCode.LEFT || e.which == $.ui.keyCode.RIGHT) {
|
564 | if (args.grid.getOptions().editorCellNavOnLRKeys) {
|
565 | var cursorPosition = this.selectionStart;
|
566 | var textLength = this.value.length;
|
567 | if (e.keyCode === $.ui.keyCode.LEFT && cursorPosition === 0) {
|
568 | args.grid.navigatePrev();
|
569 | }
|
570 | if (e.keyCode === $.ui.keyCode.RIGHT && cursorPosition >= textLength-1) {
|
571 | args.grid.navigateNext();
|
572 | }
|
573 | }
|
574 | }
|
575 | };
|
576 |
|
577 | this.save = function () {
|
578 | args.commitChanges();
|
579 | };
|
580 |
|
581 | this.cancel = function () {
|
582 | $input.val(defaultValue);
|
583 | args.cancelChanges();
|
584 | };
|
585 |
|
586 | this.hide = function () {
|
587 | $wrapper.hide();
|
588 | };
|
589 |
|
590 | this.show = function () {
|
591 | $wrapper.show();
|
592 | };
|
593 |
|
594 | this.position = function (position) {
|
595 | $wrapper
|
596 | .css("top", position.top - 5)
|
597 | .css("left", position.left - 5);
|
598 | };
|
599 |
|
600 | this.destroy = function () {
|
601 | $wrapper.remove();
|
602 | };
|
603 |
|
604 | this.focus = function () {
|
605 | $input.focus();
|
606 | };
|
607 |
|
608 | this.loadValue = function (item) {
|
609 | $input.val(defaultValue = item[args.column.field]);
|
610 | $input.select();
|
611 | };
|
612 |
|
613 | this.serializeValue = function () {
|
614 | return $input.val();
|
615 | };
|
616 |
|
617 | this.applyValue = function (item, state) {
|
618 | item[args.column.field] = state;
|
619 | };
|
620 |
|
621 | this.isValueChanged = function () {
|
622 | return (!($input.val() === "" && defaultValue == null)) && ($input.val() != defaultValue);
|
623 | };
|
624 |
|
625 | this.validate = function () {
|
626 | if (args.column.validator) {
|
627 | var validationResults = args.column.validator($input.val());
|
628 | if (!validationResults.valid) {
|
629 | return validationResults;
|
630 | }
|
631 | }
|
632 |
|
633 | return {
|
634 | valid: true,
|
635 | msg: null
|
636 | };
|
637 | };
|
638 |
|
639 | this.init();
|
640 | }
|
641 |
|
642 | |
643 |
|
644 |
|
645 |
|
646 |
|
647 | function handleKeydownLRNav(e) {
|
648 | var cursorPosition = this.selectionStart;
|
649 | var textLength = this.value.length;
|
650 | if ((e.keyCode === $.ui.keyCode.LEFT && cursorPosition > 0) ||
|
651 | e.keyCode === $.ui.keyCode.RIGHT && cursorPosition < textLength-1) {
|
652 | e.stopImmediatePropagation();
|
653 | }
|
654 | }
|
655 |
|
656 | function handleKeydownLRNoNav(e) {
|
657 | if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
|
658 | e.stopImmediatePropagation();
|
659 | }
|
660 | }
|
661 |
|
662 | })(jQuery);
|