5 angular.module('egMarcMod', ['egCoreMod', 'ui.bootstrap'])
7 .directive("egContextMenuItem", ['$timeout',function ($timeout) {
11 template: '<li><a ng-click="setContent(item.value,item.action)">{{item.label}}</a></li>',
12 scope: { item: '=', content: '=' },
13 controller: ['$scope','$element',
14 function ($scope , $element) {
15 if (!$scope.item.label) $scope.item.label = $scope.item.value;
16 if ($scope.item.divider) {
17 $element.style.borderTop = 'solid 1px';
20 $scope.setContent = function (v, a) {
22 if (a) replace_with = a($scope,$element,$scope.item.value,$scope.$parent.$parent.content);
24 $scope.$parent.$parent.$apply(function(){
25 $scope.$parent.$parent.content = replace_with
28 $($element).parent().css({display: 'none'});
35 .directive("egMarcEditEditable", ['$timeout', '$compile', '$document', function ($timeout, $compile, $document) {
39 template: '<input style="font-family: \'Lucida Console\', Monaco, monospace;" ng-model="content" size="{{content.length * 1.1}}" maxlength="{{max}}" class="" type="text"/>',
45 contextItemContainer: '@',
50 controller : ['$scope',
53 /* XXX Example, for testing. We'll get this from the tag-table services for realz
55 if (!$scope.contextItemContainer) {
56 $scope.contextItemContainer = "default_context";
57 $scope[$scope.contextItemContainer] = [
67 if ($scope.contextItemContainer)
68 $scope.item_container = $scope[$scope.contextItemContainer];
70 $scope.showContext = function (event) {
71 if ($scope.context_menu_element) {
72 console.log('Reshowing context menu...');
73 $($scope.context_menu_element).css({ display: 'block', top: event.pageY, left: event.pageX });
74 $('body').on('click.context_menu',function() {
75 $($scope.context_menu_element).css('display','none');
76 $('body').off('click.context_menu');
81 if (angular.isArray($scope.item_container)) { // we have a list of values or transforms
82 console.log('Showing context menu...');
85 '<ul class="dropdown-menu" role="menu">'+
86 '<eg-context-menu-item ng-repeat="item in item_container" item="item" content="content"/>'+
89 var tnode = angular.element(tmpl);
90 $document.find('body').append(tnode);
98 $scope.context_menu_element = tnode;
100 $timeout(function() {
101 var e = $compile(tnode)($scope);
105 $('body').on('click.context_menu',function() {
106 $(tnode).css('display','none');
107 $('body').off('click.context_menu');
118 link: function (scope, element, attrs) {
120 if (scope.onKeydown) element.bind('keydown', scope.onKeydown);
122 element.bind('change', function (e) { element.size = scope.max || parseInt(scope.content.length * 1.1) });
124 if (scope.contextItemContainer && angular.isArray(scope[scope.contextItemContainer]))
125 element.bind('contextmenu', scope.showContext);
130 .directive("egMarcEditSubfield", function () {
135 '<span><eg-marc-edit-editable '+
137 'class="marcsfcode" '+
139 'subfield="subfield" '+
140 'content="subfield[0]" '+
142 'on-keydown="onKeydown" '+
143 'id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}s{{subfield[2]}}code" '+
145 '<span><eg-marc-edit-editable '+
147 'class="marcsfvalue" '+
149 'subfield="subfield" '+
150 'content="subfield[1]" '+
151 'on-keydown="onKeydown" '+
152 'id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}s{{subfield[2]}}value" '+
155 scope: { field: "=", subfield: "=", onKeydown: '=' },
160 .directive("egMarcEditInd", function () {
164 template: '<span><eg-marc-edit-editable itype="ind" field="field" content="ind" max="1" on-keydown="onKeydown" id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}i{{indNumber}}"/></span>',
165 scope: { ind : '=', field: '=', onKeydown: '=', indNumber: '@' },
170 .directive("egMarcEditTag", function () {
174 template: '<span><eg-marc-edit-editable itype="tag" field="field" content="tag" max="3" on-keydown="onKeydown" id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}tag"/></span>',
175 scope: { tag : '=', field: '=', onKeydown: '=' },
180 .directive("egMarcEditDatafield", function () {
185 '<span><eg-marc-edit-tag class="marctag" field="field" tag="field.tag" on-keydown="onKeydown"/></span>'+
186 '<span><eg-marc-edit-ind class="marcind" field="field" ind="field.ind1" on-keydown="onKeydown" ind-number="1"/></span>'+
187 '<span><eg-marc-edit-ind class="marcind" field="field" ind="field.ind2" on-keydown="onKeydown" ind-number="2"/></span>'+
188 '<span><eg-marc-edit-subfield ng-repeat="subfield in field.subfields" subfield="subfield" field="field" on-keydown="onKeydown"/></span>'+
190 scope: { field: "=", onKeydown: '=' }
194 .directive("egMarcEditControlfield", function () {
199 '<span><eg-marc-edit-tag class="marctag" field="field" tag="field.tag" on-keydown="onKeydown"/></span>'+
200 '<span><eg-marc-edit-editable itype="cfld" field="field" class="marcdata" content="field.data" on-keydown="onKeydown" id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}data"/></span>'+
202 scope: { field: "=", onKeydown: '=' }
206 .directive("egMarcEditLeader", function () {
211 '<span><eg-marc-edit-editable class="marctag" content="tag" on-keydown="onKeydown" id="leadertag" disabled="disabled"/></span>'+
212 '<span><eg-marc-edit-editable class="marcdata" itype="ldr" max="{{record.leader.length}}" content="record.leader" id="r{{record.subfield(\'901\',\'c\')[1]}}leaderdata" on-keydown="onKeydown"/></span>'+
214 controller : ['$scope',
215 function ( $scope ) {
219 scope: { record: "=", onKeydown: '=' }
223 /// TODO: fixed field editor and such
224 .directive("egMarcEditRecord", function () {
226 template: '<form ng-submit="saveRecord()">'+
227 '<div class="marcrecord">'+
228 '<div><eg-marc-edit-leader record="record" on-keydown="onKeydown"/></div>'+
229 '<div><eg-marc-edit-controlfield ng-repeat="field in controlfields" field="field" on-keydown="onKeydown"/></div>'+
230 '<div><eg-marc-edit-datafield ng-repeat="field in datafields" field="field" on-keydown="onKeydown"/></div>'+
232 '<button class="btn btn-default" type="submit">Save</button>'+
234 '<button class="btn btn-default" ng-click="seeBreaker()">Breaker</button>',
237 scope: { recordId : '=', maxUndo : '@' },
238 controller : ['$timeout','$scope','egCore',
239 function ( $timeout , $scope , egCore ) {
241 $scope.max_undo = $scope.maxUndo || 100;
242 $scope.record_undo_stack = [];
243 $scope.record_redo_stack = [];
244 $scope.in_undo = false;
245 $scope.in_redo = false;
246 $scope.record = new MARC.Record();
248 $scope.onKeydown = function (event) {
249 var event_return = true;
251 if (event.which == 89 && event.ctrlKey) { // ctrl+y, redo
252 event_return = $scope.processRedo();
253 } else if (event.which == 90 && event.ctrlKey) { // ctrl+z, undo
254 event_return = $scope.processUndo();
255 } else { // Assumes only marc editor elements have IDs that can trigger this event handler.
256 $scope.current_event_target = $(event.target).attr('id');
257 if ($scope.current_event_target) {
258 $scope.current_event_target_cursor_pos =
259 event.target.selectionDirection=='backward' ?
260 event.target.selectionStart :
261 event.target.selectionEnd;
268 function setCaret() {
269 if ($scope.current_event_target) {
270 var element = $('#'+$scope.current_event_target).get(0);
272 element.setSelectionRange(
273 $scope.current_event_target_cursor_pos,
274 $scope.current_event_target_cursor_pos
276 $scope.current_event_target = null;
280 function loadRecord() {
281 return egCore.pcrud.retrieve(
282 'bre', $scope.recordId
283 ).then(function(rec) {
284 $scope.in_redo = true;
286 $scope.record = new MARC.Record({ marcxml : $scope.bre.marc() });
287 $scope.controlfields = $scope.record.fields.filter(function(f){ return f.isControlfield() });
288 $scope.datafields = $scope.record.fields.filter(function(f){ return !f.isControlfield() });
292 $scope.$watch('record.toBreaker()', function (newVal, oldVal) {
293 if (!$scope.in_undo && !$scope.in_redo && oldVal != newVal) {
294 $scope.record_undo_stack.push({
296 target: $scope.current_event_target,
297 pos: $scope.current_event_target_cursor_pos
301 if ($scope.record_undo_stack.length > $scope.max_undo)
302 $scope.record_undo_stack.shift();
304 console.log('undo stack is ' + $scope.record_undo_stack.length + ' deep');
305 $scope.in_redo = false;
306 $scope.in_undo = false;
309 $scope.processUndo = function () {
310 if ($scope.record_undo_stack.length) {
311 $scope.in_undo = true;
313 var undo_item = $scope.record_undo_stack.pop();
314 $scope.record_redo_stack.push(undo_item);
316 $scope.record = new MARC.Record({ marcbreaker : undo_item.breaker });
317 $scope.controlfields = $scope.record.fields.filter(function(f){ return f.isControlfield() });
318 $scope.datafields = $scope.record.fields.filter(function(f){ return !f.isControlfield() });
320 $scope.current_event_target = undo_item.target;
321 $scope.current_event_target_cursor_pos = undo_item.pos;
322 console.log('Undo targeting ' + $scope.current_event_target + ' position ' + $scope.current_event_target_cursor_pos);
324 $timeout(function(){$scope.$digest()}).then(setCaret);
331 $scope.processRedo = function () {
332 if ($scope.record_redo_stack.length) {
333 $scope.in_redo = true;
335 var redo_item = $scope.record_redo_stack.pop();
336 $scope.record_undo_stack.push(redo_item);
338 $scope.record = new MARC.Record({ marcbreaker : redo_item.breaker });
339 $scope.controlfields = $scope.record.fields.filter(function(f){ return f.isControlfield() });
340 $scope.datafields = $scope.record.fields.filter(function(f){ return !f.isControlfield() });
342 $scope.current_event_target = redo_item.target;
343 $scope.current_event_target_cursor_pos = redo_item.pos;
344 console.log('Redo targeting ' + $scope.current_event_target + ' position ' + $scope.current_event_target_cursor_pos);
346 $timeout(function(){$scope.$digest()}).then(setCaret);
353 $scope.saveRecord = function () {
354 $scope.bre.marc($scope.record.toXmlString());
355 return egCore.pcrud.update(
360 $scope.seeBreaker = function () {
361 alert($scope.record.toBreaker());
364 $scope.$watch('recordId',
365 function(newVal, oldVal) {
366 if (newVal && newVal !== oldVal) {
373 $scope.controlfields = [];
374 $scope.datafields = [];