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><eg-marc-edit-editable '+
143 'class="marcsfcode" '+
145 'subfield="subfield" '+
146 'content="subfield[0]" '+
148 'on-keydown="onKeydown" '+
149 'id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}s{{subfield[2]}}code" '+
151 '<span><eg-marc-edit-editable '+
153 'class="marcsfvalue" '+
155 'subfield="subfield" '+
156 'content="subfield[1]" '+
157 'on-keydown="onKeydown" '+
158 'id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}s{{subfield[2]}}value" '+
161 scope: { field: "=", subfield: "=", onKeydown: '=' },
166 .directive("egMarcEditInd", function () {
170 template: '<span><eg-marc-edit-editable '+
175 'on-keydown="onKeydown" '+
176 'id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}i{{indNumber}}"'+
178 scope: { ind : '=', field: '=', onKeydown: '=', indNumber: '@' },
183 .directive("egMarcEditTag", function () {
187 template: '<span><eg-marc-edit-editable '+
192 'on-keydown="onKeydown" '+
193 'id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}tag"'+
195 scope: { tag : '=', field: '=', onKeydown: '=' },
200 .directive("egMarcEditDatafield", function () {
205 '<span><eg-marc-edit-tag class="marctag" field="field" tag="field.tag" on-keydown="onKeydown"/></span>'+
206 '<span><eg-marc-edit-ind class="marcind" field="field" ind="field.ind1" on-keydown="onKeydown" ind-number="1"/></span>'+
207 '<span><eg-marc-edit-ind class="marcind" field="field" ind="field.ind2" on-keydown="onKeydown" ind-number="2"/></span>'+
208 '<span><eg-marc-edit-subfield ng-repeat="subfield in field.subfields" subfield="subfield" field="field" on-keydown="onKeydown"/></span>'+
210 scope: { field: "=", onKeydown: '=' }
214 .directive("egMarcEditControlfield", function () {
219 '<span><eg-marc-edit-tag class="marctag" field="field" tag="field.tag" on-keydown="onKeydown"/></span>'+
220 '<span><eg-marc-edit-editable '+
224 'content="field.data" '+
225 'on-keydown="onKeydown" '+
226 'id="r{{field.record.subfield(\'901\',\'c\')[1]}}f{{field.position}}data"'+
229 scope: { field: "=", onKeydown: '=' }
233 .directive("egMarcEditLeader", function () {
238 '<span><eg-marc-edit-editable '+
241 'on-keydown="onKeydown" '+
243 'disabled="disabled"'+
245 '<span><eg-marc-edit-editable '+
248 'max="{{record.leader.length}}" '+
249 'content="record.leader" '+
250 'id="r{{record.subfield(\'901\',\'c\')[1]}}leaderdata" '+
251 'on-keydown="onKeydown"'+
254 controller : ['$scope',
255 function ( $scope ) {
259 scope: { record: "=", onKeydown: '=' }
263 /// TODO: fixed field editor and such
264 .directive("egMarcEditRecord", function () {
266 template: '<form ng-submit="saveRecord()">'+
267 '<div class="marcrecord">'+
268 '<div><eg-marc-edit-leader record="record" on-keydown="onKeydown"/></div>'+
269 '<div><eg-marc-edit-controlfield ng-repeat="field in controlfields" field="field" on-keydown="onKeydown"/></div>'+
270 '<div><eg-marc-edit-datafield ng-repeat="field in datafields" field="field" on-keydown="onKeydown"/></div>'+
272 '<button class="btn btn-default" type="submit">Save</button>'+
274 '<button class="btn btn-default" ng-click="seeBreaker()">Breaker</button>',
277 scope: { recordId : '=', maxUndo : '@' },
278 controller : ['$timeout','$scope','egCore',
279 function ( $timeout , $scope , egCore ) {
281 $scope.max_undo = $scope.maxUndo || 100;
282 $scope.record_undo_stack = [];
283 $scope.record_redo_stack = [];
284 $scope.in_undo = false;
285 $scope.in_redo = false;
286 $scope.record = new MARC.Record();
287 $scope.save_stack_depth = 0;
288 $scope.controlfields = [];
289 $scope.datafields = [];
291 $scope.onKeydown = function (event) {
292 var event_return = true;
294 if (event.which == 89 && event.ctrlKey) { // ctrl+y, redo
295 event_return = $scope.processRedo();
296 } else if (event.which == 90 && event.ctrlKey) { // ctrl+z, undo
297 event_return = $scope.processUndo();
298 } else { // Assumes only marc editor elements have IDs that can trigger this event handler.
299 $scope.current_event_target = $(event.target).attr('id');
300 if ($scope.current_event_target) {
301 $scope.current_event_target_cursor_pos =
302 event.target.selectionDirection=='backward' ?
303 event.target.selectionStart :
304 event.target.selectionEnd;
311 function setCaret() {
312 if ($scope.current_event_target) {
313 var element = $('#'+$scope.current_event_target).get(0);
315 element.setSelectionRange(
316 $scope.current_event_target_cursor_pos,
317 $scope.current_event_target_cursor_pos
319 $scope.current_event_target = null;
323 function loadRecord() {
324 return egCore.pcrud.retrieve(
325 'bre', $scope.recordId
326 ).then(function(rec) {
327 $scope.in_redo = true;
329 $scope.record = new MARC.Record({ marcxml : $scope.bre.marc() });
330 $scope.controlfields = $scope.record.fields.filter(function(f){ return f.isControlfield() });
331 $scope.datafields = $scope.record.fields.filter(function(f){ return !f.isControlfield() });
332 $scope.save_stack_depth = $scope.record_undo_stack.length;
336 $scope.$watch('record.toBreaker()', function (newVal, oldVal) {
337 if (!$scope.in_undo && !$scope.in_redo && oldVal != newVal) {
338 $scope.record_undo_stack.push({
340 target: $scope.current_event_target,
341 pos: $scope.current_event_target_cursor_pos
344 if ($scope.record_undo_stack.length != $scope.save_stack_depth) {
345 console.log('should get a listener... does not');
346 $('body').on('beforeunload', function(){
347 return 'There is unsaved data in this record.'
350 $('body').off('beforeunload');
354 if ($scope.record_undo_stack.length > $scope.max_undo)
355 $scope.record_undo_stack.shift();
357 console.log('undo stack is ' + $scope.record_undo_stack.length + ' deep');
358 $scope.in_redo = false;
359 $scope.in_undo = false;
362 $scope.processUndo = function () {
363 if ($scope.record_undo_stack.length) {
364 $scope.in_undo = true;
366 var undo_item = $scope.record_undo_stack.pop();
367 $scope.record_redo_stack.push(undo_item);
369 $scope.record = new MARC.Record({ marcbreaker : undo_item.breaker });
370 $scope.controlfields = $scope.record.fields.filter(function(f){ return f.isControlfield() });
371 $scope.datafields = $scope.record.fields.filter(function(f){ return !f.isControlfield() });
373 $scope.current_event_target = undo_item.target;
374 $scope.current_event_target_cursor_pos = undo_item.pos;
375 console.log('Undo targeting ' + $scope.current_event_target + ' position ' + $scope.current_event_target_cursor_pos);
377 $timeout(function(){$scope.$digest()}).then(setCaret);
384 $scope.processRedo = function () {
385 if ($scope.record_redo_stack.length) {
386 $scope.in_redo = true;
388 var redo_item = $scope.record_redo_stack.pop();
389 $scope.record_undo_stack.push(redo_item);
391 $scope.record = new MARC.Record({ marcbreaker : redo_item.breaker });
392 $scope.controlfields = $scope.record.fields.filter(function(f){ return f.isControlfield() });
393 $scope.datafields = $scope.record.fields.filter(function(f){ return !f.isControlfield() });
395 $scope.current_event_target = redo_item.target;
396 $scope.current_event_target_cursor_pos = redo_item.pos;
397 console.log('Redo targeting ' + $scope.current_event_target + ' position ' + $scope.current_event_target_cursor_pos);
399 $timeout(function(){$scope.$digest()}).then(setCaret);
406 $scope.saveRecord = function () {
407 $scope.bre.marc($scope.record.toXmlString());
408 return egCore.pcrud.update(
413 $scope.seeBreaker = function () {
414 alert($scope.record.toBreaker());
417 $scope.$watch('recordId',
418 function(newVal, oldVal) {
419 if (newVal && newVal !== oldVal) {