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) {
40 'style="font-family: \'Lucida Console\', Monaco, monospace;" '+
41 'ng-model="content" '+
42 'size="{{content.length * 1.1}}" '+
43 'maxlength="{{max}}" '+
52 contextItemContainer: '@',
56 controller : ['$scope',
59 /* XXX Example, for testing. We'll get this from the tag-table services for realz
61 if (!$scope.contextItemContainer) {
62 $scope.contextItemContainer = "default_context";
63 $scope[$scope.contextItemContainer] = [
73 if ($scope.contextItemContainer)
74 $scope.item_container = $scope[$scope.contextItemContainer];
76 $scope.showContext = function (event) {
77 if ($scope.context_menu_element) {
78 console.log('Reshowing context menu...');
79 $($scope.context_menu_element).css({ display: 'block', top: event.pageY, left: event.pageX });
80 $('body').on('click.context_menu',function() {
81 $($scope.context_menu_element).css('display','none');
82 $('body').off('click.context_menu');
87 if (angular.isArray($scope.item_container)) { // we have a list of values or transforms
88 console.log('Showing context menu...');
91 '<ul class="dropdown-menu" role="menu">'+
92 '<eg-context-menu-item ng-repeat="item in item_container" item="item" content="content"/>'+
95 var tnode = angular.element(tmpl);
96 $document.find('body').append(tnode);
104 $scope.context_menu_element = tnode;
106 $timeout(function() {
107 var e = $compile(tnode)($scope);
111 $('body').on('click.context_menu',function() {
112 $(tnode).css('display','none');
113 $('body').off('click.context_menu');
124 link: function (scope, element, attrs) {
126 if (scope.onKeydown) element.bind('keydown', scope.onKeydown);
128 element.bind('change', function (e) { element.size = scope.max || parseInt(scope.content.length * 1.1) });
130 if (scope.contextItemContainer && angular.isArray(scope[scope.contextItemContainer]))
131 element.bind('contextmenu', scope.showContext);
136 .directive("egMarcEditSubfield", function () {
141 '<span class="marcsfcode"><label class="marcedit"'+
142 'for="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}s{{subfield[2]}}code" '+
143 '>‡</label><eg-marc-edit-editable '+
147 'subfield="subfield" '+
148 'content="subfield[0]" '+
150 'on-keydown="onKeydown" '+
151 'id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}s{{subfield[2]}}code" '+
153 '<span><eg-marc-edit-editable '+
155 'class="marcedit marcsfvalue" '+
157 'subfield="subfield" '+
158 'content="subfield[1]" '+
159 'on-keydown="onKeydown" '+
160 'id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}s{{subfield[2]}}value" '+
163 scope: { field: "=", subfield: "=", onKeydown: '=' },
168 .directive("egMarcEditInd", function () {
172 template: '<span><eg-marc-edit-editable '+
174 'class="marcedit marcind" '+
178 'on-keydown="onKeydown" '+
179 'id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}i{{indNumber}}"'+
181 scope: { ind : '=', field: '=', onKeydown: '=', indNumber: '@' },
186 .directive("egMarcEditTag", function () {
190 template: '<span><eg-marc-edit-editable '+
192 'class="marcedit marctag" '+
196 'on-keydown="onKeydown" '+
197 'id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}tag"'+
199 scope: { tag : '=', field: '=', onKeydown: '=' },
204 .directive("egMarcEditDatafield", function () {
209 '<span><eg-marc-edit-tag field="field" tag="field.tag" on-keydown="onKeydown"/></span>'+
210 '<span><eg-marc-edit-ind field="field" ind="field.ind1" on-keydown="onKeydown" ind-number="1"/></span>'+
211 '<span><eg-marc-edit-ind field="field" ind="field.ind2" on-keydown="onKeydown" ind-number="2"/></span>'+
212 '<span><eg-marc-edit-subfield ng-repeat="subfield in field.subfields" subfield="subfield" field="field" on-keydown="onKeydown"/></span>'+
214 scope: { field: "=", onKeydown: '=' }
218 .directive("egMarcEditControlfield", function () {
223 '<span><eg-marc-edit-tag field="field" tag="field.tag" on-keydown="onKeydown"/></span>'+
224 '<span><eg-marc-edit-editable '+
227 'class="marcedit marcdata" '+
228 'content="field.data" '+
229 'on-keydown="onKeydown" '+
230 'id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}data"'+
233 scope: { field: "=", onKeydown: '=' }
237 .directive("egMarcEditLeader", function () {
242 '<span><eg-marc-edit-editable '+
243 'class="marcedit marctag" '+
245 'on-keydown="onKeydown" '+
247 'disabled="disabled"'+
249 '<span><eg-marc-edit-editable '+
250 'class="marcedit marcdata" '+
252 'max="{{record.leader.length}}" '+
253 'content="record.leader" '+
254 'id="r{{record.subfield(\'901\',\'c\')[1]}}leaderdata" '+
255 'on-keydown="onKeydown"'+
258 controller : ['$scope',
259 function ( $scope ) {
263 scope: { record: "=", onKeydown: '=' }
267 /// TODO: fixed field editor and such
268 .directive("egMarcEditRecord", function () {
270 template: '<form ng-submit="saveRecord()">'+
271 '<div class="marcrecord">'+
272 '<div><eg-marc-edit-leader record="record" on-keydown="onKeydown"/></div>'+
273 '<div><eg-marc-edit-controlfield ng-repeat="field in controlfields" field="field" on-keydown="onKeydown"/></div>'+
274 '<div><eg-marc-edit-datafield ng-repeat="field in datafields" field="field" on-keydown="onKeydown"/></div>'+
276 '<button class="btn btn-default" type="submit">Save</button>'+
278 '<button class="btn btn-default" ng-click="seeBreaker()">Breaker</button>',
281 scope: { recordId : '=', maxUndo : '@' },
282 controller : ['$timeout','$scope','egCore',
283 function ( $timeout , $scope , egCore ) {
285 $scope.max_undo = $scope.maxUndo || 100;
286 $scope.record_undo_stack = [];
287 $scope.record_redo_stack = [];
288 $scope.in_undo = false;
289 $scope.in_redo = false;
290 $scope.record = new MARC.Record();
291 $scope.save_stack_depth = 0;
292 $scope.controlfields = [];
293 $scope.datafields = [];
295 $scope.onKeydown = function (event) {
296 var event_return = true;
298 if (event.which == 89 && event.ctrlKey) { // ctrl+y, redo
299 event_return = $scope.processRedo();
300 } else if (event.which == 90 && event.ctrlKey) { // ctrl+z, undo
301 event_return = $scope.processUndo();
302 } else { // Assumes only marc editor elements have IDs that can trigger this event handler.
303 $scope.current_event_target = $(event.target).attr('id');
304 if ($scope.current_event_target) {
305 $scope.current_event_target_cursor_pos =
306 event.target.selectionDirection=='backward' ?
307 event.target.selectionStart :
308 event.target.selectionEnd;
315 function setCaret() {
316 if ($scope.current_event_target) {
317 var element = $('#'+$scope.current_event_target).get(0);
319 element.setSelectionRange(
320 $scope.current_event_target_cursor_pos,
321 $scope.current_event_target_cursor_pos
323 $scope.current_event_target = null;
327 function loadRecord() {
328 return egCore.pcrud.retrieve(
329 'bre', $scope.recordId
330 ).then(function(rec) {
331 $scope.in_redo = true;
333 $scope.record = new MARC.Record({ marcxml : $scope.bre.marc() });
334 $scope.controlfields = $scope.record.fields.filter(function(f){ return f.isControlfield() });
335 $scope.datafields = $scope.record.fields.filter(function(f){ return !f.isControlfield() });
336 $scope.save_stack_depth = $scope.record_undo_stack.length;
340 $scope.$watch('record.toBreaker()', function (newVal, oldVal) {
341 if (!$scope.in_undo && !$scope.in_redo && oldVal != newVal) {
342 $scope.record_undo_stack.push({
344 target: $scope.current_event_target,
345 pos: $scope.current_event_target_cursor_pos
348 if ($scope.record_undo_stack.length != $scope.save_stack_depth) {
349 console.log('should get a listener... does not');
350 $('body').on('beforeunload', function(){
351 return 'There is unsaved data in this record.'
354 $('body').off('beforeunload');
358 if ($scope.record_undo_stack.length > $scope.max_undo)
359 $scope.record_undo_stack.shift();
361 console.log('undo stack is ' + $scope.record_undo_stack.length + ' deep');
362 $scope.in_redo = false;
363 $scope.in_undo = false;
366 $scope.processUndo = function () {
367 if ($scope.record_undo_stack.length) {
368 $scope.in_undo = true;
370 var undo_item = $scope.record_undo_stack.pop();
371 $scope.record_redo_stack.push(undo_item);
373 $scope.record = new MARC.Record({ marcbreaker : undo_item.breaker });
374 $scope.controlfields = $scope.record.fields.filter(function(f){ return f.isControlfield() });
375 $scope.datafields = $scope.record.fields.filter(function(f){ return !f.isControlfield() });
377 $scope.current_event_target = undo_item.target;
378 $scope.current_event_target_cursor_pos = undo_item.pos;
379 console.log('Undo targeting ' + $scope.current_event_target + ' position ' + $scope.current_event_target_cursor_pos);
381 $timeout(function(){$scope.$digest()}).then(setCaret);
388 $scope.processRedo = function () {
389 if ($scope.record_redo_stack.length) {
390 $scope.in_redo = true;
392 var redo_item = $scope.record_redo_stack.pop();
393 $scope.record_undo_stack.push(redo_item);
395 $scope.record = new MARC.Record({ marcbreaker : redo_item.breaker });
396 $scope.controlfields = $scope.record.fields.filter(function(f){ return f.isControlfield() });
397 $scope.datafields = $scope.record.fields.filter(function(f){ return !f.isControlfield() });
399 $scope.current_event_target = redo_item.target;
400 $scope.current_event_target_cursor_pos = redo_item.pos;
401 console.log('Redo targeting ' + $scope.current_event_target + ' position ' + $scope.current_event_target_cursor_pos);
403 $timeout(function(){$scope.$digest()}).then(setCaret);
410 $scope.saveRecord = function () {
411 $scope.bre.marc($scope.record.toXmlString());
412 return egCore.pcrud.update(
417 $scope.seeBreaker = function () {
418 alert($scope.record.toBreaker());
421 $scope.$watch('recordId',
422 function(newVal, oldVal) {
423 if (newVal && newVal !== oldVal) {