From: Cesar Velez Date: Mon, 4 Dec 2017 17:45:35 +0000 (-0500) Subject: LP#1691263: make webstaff MARC editor wrap long fields X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=11cbc1f0d5da66cd3af6355e23d3b7ae8f6842a1;p=evergreen%2Fpines.git LP#1691263: make webstaff MARC editor wrap long fields This patch makes the MARC editor wrap long fields (e.g., bibliographic 505 fields) so that they fit the width of the enclosing window or modal. The approach taken is replacing the text input elements with contenteditable divs, which in turn can be better styled. To test ------- [1] Apply the patch. [2] Locate a record with a long 505 field and open it in the MARC editor. Verify that the contents of the field wrap. [3] Verify that record editing and saving work as expected. Signed-off-by: Cesar Velez Signed-off-by: Galen Charlton Signed-off-by: Kathy Lussier --- diff --git a/Open-ILS/src/templates/staff/cat/share/t_marcedit_editable.tt2 b/Open-ILS/src/templates/staff/cat/share/t_marcedit_editable.tt2 new file mode 100644 index 0000000000..1e5888f000 --- /dev/null +++ b/Open-ILS/src/templates/staff/cat/share/t_marcedit_editable.tt2 @@ -0,0 +1,20 @@ + + + +
{{content}}
+
diff --git a/Open-ILS/web/js/ui/default/staff/cat/services/marcedit.js b/Open-ILS/web/js/ui/default/staff/cat/services/marcedit.js index 2430dc0847..4411098a68 100644 --- a/Open-ILS/web/js/ui/default/staff/cat/services/marcedit.js +++ b/Open-ILS/web/js/ui/default/staff/cat/services/marcedit.js @@ -44,18 +44,34 @@ angular.module('egMarcMod', ['egCoreMod', 'ui.bootstrap']) } }]) +.directive("contenteditable", function() { + return { + restrict: "A", + require: "ngModel", + link: function(scope,element,attrs,ngModel){ + + function read(){ + // save new text into model + var elhtml = element.text(); + ngModel.$setViewValue(elhtml); + } + + ngModel.$render = function(){ + element.text(ngModel.$viewValue || ""); + }; + + element.bind("blur.c_e keyup.c_e change.c_e", function(){ + scope.$apply(read); + }); + } + }; +}) + .directive("egMarcEditEditable", ['$timeout', '$compile', '$document', function ($timeout, $compile, $document) { return { restrict: 'E', replace: true, - template: '', + templateUrl: './cat/share/t_marcedit_editable', scope: { field: '=', onKeydown: '=', @@ -66,11 +82,12 @@ angular.module('egMarcMod', ['egCoreMod', 'ui.bootstrap']) max: '@', itype: '@', selectOnFocus: '=', - advanceFocusAfterInput: '=' + advanceFocusAfterInput: '=', + isDisabled: "=" }, controller : ['$scope', function ( $scope ) { - + $scope.isInputDisabled = $scope.isDisabled == 'disabled'; if ($scope.contextItemContainer && angular.isArray($scope.$parent[$scope.contextItemContainer])) $scope.item_container = $scope.$parent[$scope.contextItemContainer]; else if ($scope.contextItemGenerator) @@ -146,9 +163,24 @@ angular.module('egMarcMod', ['egCoreMod', 'ui.bootstrap']) if (Boolean(scope.selectOnFocus)) { element.addClass('noSelection'); - element.bind('focus', function () { element.select() }); + element.bind('focus', function (e) { + var el = $(e.target).children('input').first(); + if (el.select) { el.select(); } + }); } + element.children("div[contenteditable]").each(function() { + $(this).focus(function(e) { + var tNode = e.target.firstChild; + var range = document.createRange(); + range.setStart(tNode, 0); + range.setEnd(tNode, tNode.length); + var sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + }); + }); + function findCaretTarget(id, itype) { var tgt = null; if (itype == 'tag') { @@ -349,6 +381,7 @@ angular.module('egMarcMod', ['egCoreMod', 'ui.bootstrap']) '/>'+ ''+ '= new_sf) sf[2]++; - if (sf[2] == index_sf) sf[1] = event.target.value.substring(0,start) + event.target.value.substring(end); + if (sf[2] == index_sf) { + sf[1] = event.target.value ? + event.target.value.substring(0,start) + event.target.value.substring(end) : + element.text().substring(0, start); + } }); event.data.scope.field.subfields.splice( new_sf, @@ -914,7 +958,8 @@ angular.module('egMarcMod', ['egCoreMod', 'ui.bootstrap']) deleteDatafield(event); event_return = false; - } else if (event.which == 46 && event.shiftKey && $(event.target).hasClass('marcsf')) { // shift+del, remove subfield + } else if (event.which == 46 && event.shiftKey && ($(event.target).hasClass('marcsf') || $(event.target.parentNode).hasClass('marcsf'))) { + // shift+del, remove subfield var sf = event.data.scope.subfield[2] - 1; if (sf == -1) sf = 0; @@ -1047,7 +1092,7 @@ angular.module('egMarcMod', ['egCoreMod', 'ui.bootstrap']) event_return = false; } else { // Assumes only marc editor elements have IDs that can trigger this event handler. - $scope.current_event_target = $(event.target).attr('id'); + $scope.current_event_target = $(event.target).hasClass('focusable') ? $(event.target) : null;//.attr('id'); if ($scope.current_event_target) { $scope.current_event_target_cursor_pos = event.target.selectionDirection=='backward' ? @@ -1065,7 +1110,7 @@ angular.module('egMarcMod', ['egCoreMod', 'ui.bootstrap']) if (!$scope.current_event_target_cursor_pos_end) $scope.current_event_target_cursor_pos_end = $scope.current_event_target_cursor_pos - var element = $('#'+$scope.current_event_target).get(0); + var element = $('#'+$scope.current_event_target + " .focusable").get(0); if (element) { element.focus(); if (element.setSelectionRange) { @@ -1074,10 +1119,24 @@ angular.module('egMarcMod', ['egCoreMod', 'ui.bootstrap']) $scope.current_event_target_cursor_pos_end ); } - $scope.current_event_cursor_pos_end = null; - $scope.current_event_target = null; + } + $scope.current_event_cursor_pos_end = null; + $scope.current_event_target = null; + } + } + + function getCaretPosEditableDiv(editableDiv){ + var caretPos = 0, sel, range; + if (window.getSelection) { + sel = window.getSelection(); + if (sel.rangeCount) { + range = sel.getRangeAt(0); + if (range.commonAncestorContainer.parentNode == editableDiv[0]) { + caretPos = range.endOffset; + } } } + return caretPos; } function loadRecord() {