UNPKG

pip-webui

Version:

HTML5 UI for LOB applications

523 lines (439 loc) 20.9 kB
/** * @file Checklist edit control * @copyright Digital Living Software Corp. 2014-2016 * @todo * + Improve samples in sampler app * + Renamed to pip-checklist-edit and implement pip-checklist (pip-checklist-view) control */ /* global angular */ (function () { 'use strict'; var thisModule = angular.module("pipChecklistEdit", ['pipCore', 'pipComposite.Templates']); /** * ngDisabled: '&', * pipChanged: '=', * pipDraggable: '=', * pipOptions: '=', * pipScrollContainer: '@' */ thisModule.directive('pipChecklistEdit', function () { return { restrict: 'EA', replace: false, scope: { ngDisabled: '&', pipChanged: '=', pipDraggable: '=', pipOptions: '=', pipScrollContainer: '@' }, templateUrl: 'checklist_edit/checklist_edit.html', controller: 'pipChecklistEditController' } } ); thisModule.controller('pipChecklistEditController', function ($scope, $element, $attrs, $document,pipUtils, $rootScope) { $scope.selected = {}; $scope.selected.index = 0; $scope.selected.drag = $scope.pipDraggable; $scope.selected.dragInit = $scope.pipDraggable; $scope.selected.dragId = 0; $scope.selected.id = now(); $scope.selected.isChanged = false; generateList($scope.pipOptions); $scope.onTextareaKeyDown = onTextareaKeyDown; $scope.onAddItem = onAddItem; $scope.onChangeItem = onChangeItem; $scope.onClick = onClick; $scope.onTextAreaClick = onTextAreaClick; $scope.onDropComplete = onDropComplete; $scope.onDeleteItem = onDeleteItem; $scope.onChecked = onChecked; $scope.updateContents = updateContents; $scope.onItemFocus = onItemFocus; $scope.onMove = onMove; $scope.onStart = onStart; $scope.onStop = onStop; $scope.isDisabled = isDisabled; $scope.onDownDragg = onDownDragg; $scope.isSelectedItem = isSelectedItem; // Watch for options changes if (pipUtils.toBoolean($attrs.pipRebind)) { $scope.$watchCollection('pipOptions', function (newValue) { if (!$scope.selected.isChanged) { generateList($scope.pipOptions); } else { $scope.selected.isChanged = false; } }); } if (pipUtils.toBoolean($attrs.pipRebind)) { $scope.$watchCollection('pipDraggable', function (newValue) { $scope.pipDraggable = newValue; }); } $scope.onChecklistChange = _.debounce(onChecklistChange , 200); // Add class $element.addClass('pip-checklist-edit'); return; function getCaret(el) { if (el.selectionStart) { return el.selectionStart; } else if ($document.selection) { el.focus(); var r = $document.selection.createRange(); if (r == null) { return 0; } var re = el.createTextRange(), rc = re.duplicate(); re.moveToBookmark(r.getBookmark()); rc.setEndPoint('EndToStart', re); return rc.text.length; } return 0; } function isDisabled() { if ($scope.ngDisabled) { return $scope.ngDisabled(); } else { return false; } }; function onItemFocus(index) { if (isDisabled()) return; $scope.selected.index = index; }; function isSelectedItem(index) { var empty; try { empty = $scope.checklistContent[index].empty; } catch (err) { empty = true; } return $scope.selected.index == index && $scope.pipDraggable && !empty; }; function setSelectionRange(input, selectionStart, selectionEnd) { if (input.setSelectionRange) { input.focus(); input.setSelectionRange(selectionStart, selectionEnd); } else if (input.createTextRange) { var range = input.createTextRange(); range.collapse(true); range.moveEnd('character', selectionEnd); range.moveStart('character', selectionStart); range.select(); } } function setCaretToPos (input, pos) { setSelectionRange(input, pos, pos); } function onTextareaKeyDown($event, index, item) { if (isDisabled()) return; if ($scope.selected.index == -1) return; if ($event && $event.target) { // calculate caret position var posCaret = getCaret($event.target); // calculate textarea length if ($event.target.value !== undefined) var textareaLength = $event.target.value.length; } // delete empty item after backspace or del if ($scope.selected.index > 0 && item.text != '' && posCaret == 0 && $event.keyCode == 8 && !$event.ctrlKey && !$event.shiftKey) { if (!item.empty) { var position = $scope.checklistContent[$scope.selected.index - 1].text.length; $scope.checklistContent[$scope.selected.index - 1].text = $scope.checklistContent[$scope.selected.index - 1].text + item.text; $scope.selected.index -= 1; $scope.checklistContent.splice($scope.selected.index + 1, 1); $scope.onChecklistChange(); setFocus($scope.selected.index, position); } if ($event) $event.stopPropagation(); return false; } if (item.text == '' && ($event.keyCode == 8 || $event.keyCode == 46) && !$event.ctrlKey && !$event.shiftKey) { if (!item.empty) onDeleteItem(index, item); if ($event) $event.stopPropagation(); return false; } //press enter - create new item if (($event.keyCode == 13 || $event.keyCode == 45) && !$event.ctrlKey && !$event.shiftKey) { // insert if (posCaret !== undefined && posCaret == 0) { // add item before current item if ($scope.selected.index > 0) addItem('', $scope.selected.index - 1); else { $scope.selected.index = -1; addItem('', -1); } if ($event) $event.stopPropagation(); if ($event) $event.preventDefault(); return false; } if (textareaLength && posCaret && textareaLength == posCaret) { // add item after current item if (!item.empty) { addItem('', $scope.selected.index); } if ($event) $event.stopPropagation(); if ($event) $event.preventDefault(); return false; } if (textareaLength && posCaret && textareaLength > posCaret) { // divide current item if (!item.empty) { var valueCurrent, newItem; valueCurrent = item.text.substring(0, posCaret); newItem = item.text.substring(posCaret); item.text = valueCurrent; addItem(newItem, $scope.selected.index); setFocus($scope.selected.index, 0); } if ($event) $event.stopPropagation(); if ($event) $event.preventDefault(); return false; } if ($event) $event.preventDefault(); return false; } // move cursor up if ((posCaret === 0 || posCaret == textareaLength) && $scope.checklistContent.length > 1 && $event.keyCode == 38 && !$event.ctrlKey && !$event.shiftKey) { // insert if ($event) $event.stopPropagation(); if ($event) $event.preventDefault(); if (posCaret !== undefined && textareaLength !== undefined && posCaret == 0) { // move to new item if ($scope.selected.index == 0) { $scope.selected.index = $scope.checklistContent.length - 1; var position = $scope.checklistContent[$scope.selected.index].text.length; setFocus($scope.selected.index, position); } else { $scope.selected.index -= 1; var position = $scope.checklistContent[$scope.selected.index].text.length; setFocus($scope.selected.index, position); } } else { // move caret to text end setFocus($scope.selected.index, 0); } return false; } // move cursor down if ((posCaret === 0 || posCaret == textareaLength) && $scope.checklistContent.length > 1 && $event.keyCode == 40 && !$event.ctrlKey && !$event.shiftKey) { // insert if ($event) $event.stopPropagation(); if ($event) $event.preventDefault(); if (posCaret !== undefined && textareaLength !== undefined && posCaret == textareaLength) { // move to new item if ($scope.selected.index >= $scope.checklistContent.length - 1) { $scope.selected.index = 0; setFocus($scope.selected.index, 0); } else { $scope.selected.index += 1; setFocus($scope.selected.index, 0); } } else { // move caret to text end setFocus($scope.selected.index, textareaLength); } return false; } // delete item if (!item.empty && $event.keyCode == 46 && $event.ctrlKey && !$event.shiftKey) { if ($event) $event.stopPropagation(); if ($event) $event.preventDefault(); onDeleteItem(index, item); return false; } // check/uncheck item if ($event.keyCode == 32 && $event.ctrlKey && !$event.shiftKey) { if ($event) $event.stopPropagation(); if ($event) $event.preventDefault(); if (item) { item.checked = !item.checked $scope.onChecklistChange(); } return false; } } function onAddItem() { addItem('', $scope.selected.index - 1); }; function onChangeItem(index) { if (index > -1 && $scope.checklistContent[index] && $scope.checklistContent[index].empty) { if ($scope.checklistContent[index].empty) { $scope.checklistContent[index].empty = false; $scope.checklistContent.push(getNewItem('', true)); } } $scope.onChecklistChange(); }; function onClick($event, index) { if (isDisabled()) return; $scope.selected.index = index; // if ($event) $event.preventDefault(); }; function onTextAreaClick($event, index) { if (isDisabled()) return; $scope.selected.index = index; // if ($event) $event.stopPropagation(); }; function onDropComplete(placeIndex, obj, event, componentId) { if ($scope.selected.id != componentId) return; if (!$scope.selected.drag) return; var index = placeIndex; var tmpIndex = $scope.selected.index; var checklist = _.cloneDeep($scope.checklistContent); if (!(tmpIndex == 0 && placeIndex == 1)) { if (tmpIndex > index) { if (index > checklist.length - 1) index = checklist.length - 1; // move up for (var i = 0; i < tmpIndex - index; i++) { checklist[tmpIndex - i] = checklist[tmpIndex - i - 1]; } checklist[index] = obj; } if (tmpIndex < index) { index -= 1; //move down for (var i = 0; i < index - tmpIndex; i++) { checklist[tmpIndex + i] = checklist[tmpIndex + i + 1]; } checklist[index] = obj; } $scope.selected.index = index; } $scope.checklistContent = checklist; $scope.onChecklistChange(); }; function onMove() { setWidth(); $scope.isWidth = true; }; function onStop(id) { setTimeout(function () { $scope.selected.drag = $scope.selected.dragInit; $scope.selected.dragId = 0; $scope.$apply(); }, 50); if($scope.isWidth) { setWidth100(); $scope.isWidth = false; } }; function onStart(id) { $scope.selected.isChanged = true; if (id && id != $scope.selected.dragId) $scope.selected.drag = false; }; function onDownDragg(item) { if ($scope.pipDraggable && $scope.checklistContent.length > 2 && !item.empty) { $rootScope.$broadcast('onChecklistDrag'); $scope.selected.dragId = $scope.selected.id; } }; function onDeleteItem(index, item) { if ($scope.checklistContent.length == 1) { $scope.checklistContent[0].text = ''; $scope.checklistContent[0].checked = false; $scope.checklistContent[0].empty = true; $scope.selected.index = 0; } else { if (index >= 0 && index <= $scope.checklistContent.length) $scope.checklistContent.splice(index, 1); else return; } if ($scope.selected.index >= $scope.checklistContent.length) $scope.selected.index = $scope.checklistContent.length - 1; setFocus($scope.selected.index, 0); $scope.onChecklistChange(); }; function onChecked(item) { $scope.onChecklistChange(); }; function updateContents() { $scope.selected.isChanged = true; var content = [], i; for (i = 0; i < $scope.checklistContent.length; i++) { if ($scope.checklistContent[i] && !$scope.checklistContent[i].empty) content.push({ checked: $scope.checklistContent[i].checked, text: $scope.checklistContent[i].text }) } $scope.pipOptions = content; }; function onChecklistChange() { updateContents(); if ($scope.pipChanged) { $scope.pipChanged(); } }; function setFocus(index, toPos) { if (index > -1) { setTimeout(function () { var nextElement = angular.element('#check-item-text-' + $scope.selected.id + '-' + index); if (nextElement) { nextElement.focus(); if (toPos !== undefined && nextElement[0]) setCaretToPos(nextElement[0], toPos); } }, 50); } }; function addItem(text, index) { var newItem = getNewItem(text, false); if (index > -1) $scope.selected.index = index; if ($scope.checklistContent.length < 2) { $scope.checklistContent.unshift(newItem); } else { $scope.checklistContent.splice($scope.selected.index + 1, 0, newItem); } $scope.selected.index += 1; setFocus($scope.selected.index); $scope.onChecklistChange(); } function getNewItem(text, isEmpty) { return { checked: false, text: text || '', empty: isEmpty } }; function now(){ return +new Date; } function clearList() { $scope.selected.index = 0; $scope.checklistContent = []; // push empty item $scope.checklistContent.push(getNewItem('', true)); }; function generateList(content) { if (!content || content.length < 1) { clearList(); } else { $scope.checklistContent = []; _.each(content, function(item){ $scope.checklistContent.push(item); }); // push empty item $scope.checklistContent.push(getNewItem('', true)); } }; function setWidth100() { var element = angular.element('#check-item-' + + $scope.selected.id + '-' + $scope.selected.index); element.css( "width", 'none'); element.css( "max-width", 'none'); }; function setWidth() { if ($scope.isWidth) return; var elementEtalon = angular.element('#check-item-empty-' + $scope.selected.id); var value = elementEtalon.width(); var element = angular.element('#check-item-' + $scope.selected.id + '-' + $scope.selected.index); if (element) { element.css("width", value + 'px'); element.css("max-width", value + 'px'); } }; } ); })();