diff --git a/js/src/annotations/annotationTooltip.js b/js/src/annotations/annotationTooltip.js index 19b1c469e9..94903797b1 100644 --- a/js/src/annotations/annotationTooltip.js +++ b/js/src/annotations/annotationTooltip.js @@ -153,19 +153,19 @@ event: false }, events: { - show: function(event, api) { + shown: function(event, api) { if (params.onTooltipShown) { params.onTooltipShown(event, api); } }, hidden: function(event, api) { if (params.onTooltipHidden) { params.onTooltipHidden(event, api); } + _this.removeAllEvents(api, params); }, visible: function (event, api) { - _this.removeAllEvents(api, params); _this.addViewerEvents(api, params); }, move: function (event, api) { - _this.removeAllEvents(api, params); - _this.addViewerEvents(api, params); + // _this.removeAllEvents(api, params); + // _this.addViewerEvents(api, params); } } }); @@ -232,6 +232,8 @@ _this.addEditorEvents(api, viewerParams); } else { _this.eventEmitter.publish('annotationInEditMode.' + _this.windowId,[oaAnno]); + api.destroy(); + jQuery(api.tooltip).remove(); } _this.eventEmitter.publish('SET_ANNOTATION_EDITING.' + _this.windowId, { diff --git a/js/src/annotations/osd-region-draw-tool.js b/js/src/annotations/osd-region-draw-tool.js index 64755502a5..de1d38db43 100644 --- a/js/src/annotations/osd-region-draw-tool.js +++ b/js/src/annotations/osd-region-draw-tool.js @@ -76,37 +76,38 @@ } }, - render: function() { + render: function () { + + if(this.parent.mode !== $.AnnotationsLayer.DISPLAY_ANNOTATIONS){ + return ; + } this.svgOverlay.restoreEditedShapes(); this.svgOverlay.paperScope.activate(); this.svgOverlay.paperScope.project.clear(); var _this = this; _this.annotationsToShapesMap = {}; - var deferreds = jQuery.map(this.list, function(annotation) { - var deferred = jQuery.Deferred(), - shapeArray; + + for (var i = 0; i < this.list.length; i++) { + var shapeArray; + var annotation = this.list[i]; if (annotation.on && typeof annotation.on === 'object') { if (!annotation.on.selector) { - return deferred; + continue; } else if (annotation.on.selector.value.indexOf(' 0) { _this.annotationsList.pop(); @@ -229,6 +231,21 @@ this.bottomPanelVisibility(this.bottomPanelVisible); } this.sidePanelVisibility(this.sidePanelVisible, '0s'); + + this.events.push(this.eventEmitter.subscribe('windowRemoved',function(event,id){ + if(_this.id === id){ + _this.destroy(); + } + })); + }, + + destroy:function(){ + var _this = this; + this.events.forEach(function(event){ + _this.eventEmitter.unsubscribe(event.name,event.handler); + }); + + this.element.remove(); }, update: function(options) { @@ -266,15 +283,15 @@ } }); - _this.eventEmitter.subscribe('HIDE_REMOVE_OBJECT.' + _this.id, function(event) { + _this.events.push(_this.eventEmitter.subscribe('HIDE_REMOVE_OBJECT.' + _this.id, function(event) { _this.element.find('.remove-object-option').hide(); - }); + })); - _this.eventEmitter.subscribe('SHOW_REMOVE_OBJECT.' + _this.id, function(event) { + _this.events.push(this.eventEmitter.subscribe('SHOW_REMOVE_OBJECT.' + _this.id, function(event) { _this.element.find('.remove-object-option').show(); - }); + })); - _this.eventEmitter.subscribe('sidePanelStateUpdated.' + this.id, function(event, state) { + _this.events.push(_this.eventEmitter.subscribe('sidePanelStateUpdated.' + this.id, function(event, state) { if (state.open) { _this.element.find('.mirador-icon-toc').addClass('selected'); _this.element.find('.view-container').removeClass('maximised'); @@ -282,57 +299,57 @@ _this.element.find('.mirador-icon-toc').removeClass('selected'); _this.element.find('.view-container').addClass('maximised'); } - }); + })); // TODO: temporary logic to minimize side panel if only tab is toc and toc is empty - _this.eventEmitter.subscribe('sidePanelVisibilityByTab.' + this.id, function(event, visible) { + _this.events.push(_this.eventEmitter.subscribe('sidePanelVisibilityByTab.' + this.id, function(event, visible) { _this.sidePanelVisibility(visible, '0s'); - }); + })); - _this.eventEmitter.subscribe('SET_CURRENT_CANVAS_ID.' + this.id, function(event, canvasID) { + _this.events.push(_this.eventEmitter.subscribe('SET_CURRENT_CANVAS_ID.' + this.id, function(event, canvasID) { _this.setCurrentCanvasID(canvasID); - }); + })); - _this.eventEmitter.subscribe('REMOVE_CLASS.' + this.id, function(event, className) { + _this.events.push(_this.eventEmitter.subscribe('REMOVE_CLASS.' + this.id, function(event, className) { _this.element.find('.view-container').removeClass(className); - }); + })); - _this.eventEmitter.subscribe('ADD_CLASS.' + this.id, function(event, className) { + _this.events.push(_this.eventEmitter.subscribe('ADD_CLASS.' + this.id, function(event, className) { _this.element.find('.view-container').addClass(className); - }); + })); - _this.eventEmitter.subscribe('UPDATE_FOCUS_IMAGES.' + this.id, function(event, images) { + _this.events.push(_this.eventEmitter.subscribe('UPDATE_FOCUS_IMAGES.' + this.id, function(event, images) { _this.updateFocusImages(images.array); - }); + })); - _this.eventEmitter.subscribe('HIDE_ICON_TOC.' + this.id, function(event) { + _this.events.push(_this.eventEmitter.subscribe('HIDE_ICON_TOC.' + this.id, function(event) { _this.element.find('.mirador-icon-toc').hide(); - }); + })); - _this.eventEmitter.subscribe('SHOW_ICON_TOC.' + this.id, function(event) { + _this.events.push(_this.eventEmitter.subscribe('SHOW_ICON_TOC.' + this.id, function(event) { _this.element.find('.mirador-icon-toc').show(); - }); + })); - _this.eventEmitter.subscribe('SET_BOTTOM_PANEL_VISIBILITY.' + this.id, function(event, visibility) { + _this.events.push(_this.eventEmitter.subscribe('SET_BOTTOM_PANEL_VISIBILITY.' + this.id, function(event, visibility) { if (typeof visibility !== 'undefined' && visibility !== null) { _this.bottomPanelVisibility(visibility); } else { _this.bottomPanelVisibility(_this.bottomPanelVisible); } - }); + })); - _this.eventEmitter.subscribe('TOGGLE_BOTTOM_PANEL_VISIBILITY.' + this.id, function(event) { + _this.events.push(_this.eventEmitter.subscribe('TOGGLE_BOTTOM_PANEL_VISIBILITY.' + this.id, function(event) { var visible = !_this.bottomPanelVisible; _this.bottomPanelVisibility(visible); - }); + })); - _this.eventEmitter.subscribe('DISABLE_WINDOW_FULLSCREEN', function(event) { + _this.events.push(_this.eventEmitter.subscribe('DISABLE_WINDOW_FULLSCREEN', function(event) { _this.element.find('.mirador-osd-fullscreen').hide(); - }); + })); - _this.eventEmitter.subscribe('ENABLE_WINDOW_FULLSCREEN', function(event) { + _this.events.push(_this.eventEmitter.subscribe('ENABLE_WINDOW_FULLSCREEN', function(event) { _this.element.find('.mirador-osd-fullscreen').show(); - }); + })); }, bindEvents: function() { @@ -385,10 +402,10 @@ _this.eventEmitter.subscribe('annotationUpdated.'+_this.id, function(event, oaAnno) { //first function is success callback, second is error callback - _this.endpoint.update(oaAnno, function() { + _this.endpoint.update(oaAnno, function(data) { jQuery.each(_this.annotationsList, function(index, value) { - if (value['@id'] === oaAnno['@id']) { - _this.annotationsList[index] = oaAnno; + if (value['@id'] === data['@id']) { + _this.annotationsList[index] = data; return false; } }); @@ -806,7 +823,7 @@ _this.endpoint.set('dfd', dfd); } else { options.dfd = dfd; - options.windowID = _this.id; + options.windowIDwindowID = _this.id; options.imagesList = _this.imagesList; options.eventEmitter = _this.eventEmitter; _this.endpoint = new $[module](options); diff --git a/locales/fr/translation.json b/locales/fr/translation.json index a87aa43a25..4fab836ebb 100644 --- a/locales/fr/translation.json +++ b/locales/fr/translation.json @@ -1,8 +1,8 @@ { "addItem": "Ajouter un objet", "addNewObject": "Ajouter un objet à partir de son URL", - "addSlotAbove": "Ajouter une fenêtre en dessous", - "addSlotBelow": "Ajouter une fenêtre au-dessus", + "addSlotAbove": "Ajouter une fenêtre au-dessus", + "addSlotBelow": "Ajouter une fenêtre en dessous", "addSlotLeft": "Ajouter une fenêtre à gauche", "addSlotRight": "Ajouter une fenêtre à droite", "addTagsHere": "Ajouter des mots-clés", diff --git a/spec/annotations/event-emitter.stub.js b/spec/event-emitter.stub.js similarity index 100% rename from spec/annotations/event-emitter.stub.js rename to spec/event-emitter.stub.js diff --git a/spec/utils/jsonLd.test.js b/spec/utils/jsonLd.test.js index 90aee401ff..bd4348c5a8 100644 --- a/spec/utils/jsonLd.test.js +++ b/spec/utils/jsonLd.test.js @@ -41,5 +41,51 @@ describe('JsonLd', function () { expect(Mirador.JsonLd.getTextValue(sample, 'en')).toEqual("Super waahoo"); expect(Mirador.JsonLd.getTextValue(sample)).toEqual("Super waahoo"); }); + + it('should return all values when no value has a langue associated', function() { + var sample = ['First value', + 'Second value']; + expect(Mirador.JsonLd.getTextValue(sample)).toEqual('First value
Second value'); + }); + + it('should return all values that best match the language preference', function() { + var sample = [ + 'This is a value without a language.', + {'@value': "This is an American value.", + '@language': "en-US"}, + {'@value': "This ia a British value.", + '@language': "en-UK"}, + 'This is another value without a language.', + {'@value': "C'est une valeur française.", + '@language': "fr"}]; + window.navigator.languages = ['en-US', 'en'] + expect(Mirador.JsonLd.getTextValue(sample)).toEqual("This is an American value."); + }); + + it('should pick a language if all values have a language but none match the preference', function() { + var sample = [ + {'@value': "This is an American value.", + '@language': "en-US"}, + {'@value': "This is another American value.", + '@language': "en-US"}, + {'@value': "C'est une valeur française.", + '@language': "fr"}]; + window.navigator.languages = ['de-DE', 'de']; + expect(Mirador.JsonLd.getTextValue(sample)) + .toEqual('This is an American value.
' + + 'This is another American value.'); + }); + + it('should return all values without an associated language if some have one, but none match the preference', function() { + var sample = [ + {'@value': "C'est une valeur française.", + '@language': "fr"}, + 'This is a value without a language.', + 'This is another value without a language.']; + window.navigator.languages = ['en-US', 'en']; + expect(Mirador.JsonLd.getTextValue(sample)) + .toEqual('This is a value without a language.
' + + 'This is another value without a language.'); + }) }); }); diff --git a/spec/widgets/sidePanel.test.js b/spec/widgets/sidePanel.test.js index 1f463c82f8..0dbaa19f06 100644 --- a/spec/widgets/sidePanel.test.js +++ b/spec/widgets/sidePanel.test.js @@ -1,16 +1,46 @@ describe('SidePanel', function() { + + function createSidePanel(sidePanelOptions) { + sidePanelOptions = sidePanelOptions || {}; + + var eventEmitter = new Mirador.EventEmitter(); + var state = new Mirador.SaveController(jQuery.extend( + true, {}, Mirador.DEFAULT_SETTINGS, {eventEmitter: eventEmitter} + )); + var fixture = getJSONFixture('BNF-condorcet-florus-dispersus-manifest.json'); + var manifest = new Mirador.Manifest(fixture['@id'], 'IIIF', fixture); + var canvasID = manifest.getCanvases()[0]['@id']; + var appendTo = jQuery('
'); + + var config = jQuery.extend(true, { + windowId: '380c9e54-7561-4010-a99f-f132f5dc13fd', + state: state, + eventEmitter: eventEmitter, + appendTo: appendTo, + manifest: manifest, + canvasID: canvasID, + layersTabAvailable: false, + tocTabAvailable: false, + annotationsTabAvailable: false, + hasStructures: false + }, sidePanelOptions); + + return new Mirador.SidePanel(config); + } beforeEach(function() { - + jasmine.getJSONFixtures().fixturesPath = 'spec/fixtures'; + this.sidePanel = createSidePanel(); }); afterEach(function() { }); - xdescribe('Initialization', function() { + describe('Initialization', function() { it('should initialize', function() { - + expect(this.sidePanel instanceof Mirador.SidePanel).toBeTruthy(); + expect(this.sidePanel.appendTo).toBeTruthy(); }); }); @@ -34,8 +64,10 @@ describe('SidePanel', function() { }); - xdescribe('render', function() { - + describe('render', function() { + it('should render on initialization', function() { + expect(this.sidePanel.appendTo.html()).toBeTruthy(); + }); }); xdescribe('toggle', function() { diff --git a/spec/workspaces/slot.test.js b/spec/workspaces/slot.test.js index baae4f8e74..0755b4c100 100644 --- a/spec/workspaces/slot.test.js +++ b/spec/workspaces/slot.test.js @@ -2,17 +2,13 @@ describe('Slot', function () { beforeEach(function () { var windowElement = jQuery('
'); this.appendTo = jQuery('
').append(windowElement); - this.eventEmitter = new Mirador.EventEmitter(); + this.eventEmitter = new MockEventEmitter(new Mirador.EventEmitter()); var mockWindow = { id: 'MOCK_WINDOW_1', element: windowElement }; - var windowConfig = { - state: new Mirador.SaveController(jQuery.extend(true, {}, Mirador.DEFAULT_SETTINGS, {eventEmitter:this.eventEmitter})) - }; - this.slot = new Mirador.Slot({ window: mockWindow, eventEmitter: this.eventEmitter @@ -20,13 +16,23 @@ describe('Slot', function () { }); describe('listenForActions', function () { - it('should respond to windowRemoved', function () { - var window = this.slot.window; - expect(this.appendTo.find('#MOCK_WINDOW_1').length).toBe(1); - expect(window.element.attr('id')).toEqual('MOCK_WINDOW_1'); - this.eventEmitter.publish('windowRemoved', 'MOCK_WINDOW_1'); + it('should respond to slotRemoved event', function () { + spyOn(this.slot, 'clearSlot'); + this.eventEmitter.publish('slotRemoved', { + slotID: this.slot.slotID + }); + expect(this.slot.clearSlot).toHaveBeenCalled(); + }); + }); + + describe('destroyEvents', function () { + it('should unsubscribe from all eventEmitter subscriptions', function () { + this.slot.window = {}; + this.slot.clearSlot(); + for(var key in this.slot.eventEmitter.events){ + expect(this.slot.eventEmitter.events[key]).toBe(0); + } expect(this.slot.window).toBe(undefined); - expect(this.appendTo.find('#MOCK_WINDOW_1').length).toBe(0); }); }); diff --git a/spec/workspaces/window.test.js b/spec/workspaces/window.test.js index 198ce95b57..f742a94760 100644 --- a/spec/workspaces/window.test.js +++ b/spec/workspaces/window.test.js @@ -2,11 +2,12 @@ describe('Window', function() { describe('Basic Operation', function() { beforeEach(function() { this.eventEmitter = new Mirador.EventEmitter(); + this.mockedEventEmitter = new MockEventEmitter(this.eventEmitter); this.appendTo = jQuery('
'); Mirador.viewer = { // all of this global state should be // removed as soon as possible. - eventEmitter: this.eventEmitter, + eventEmitter: this.mockedEventEmitter, annotationEndpoints: [], workspace: { slots: [] @@ -90,9 +91,32 @@ describe('Window', function() { expect(bottomPanelCalls.count()).toBe(1); }); }); + + describe('Destroying', function () { + + it('should respond to windowRemoved', function () { + spyOn(this.window,'destroy'); + this.eventEmitter.publish('windowRemoved', this.window.id); + expect(this.window.destroy).toHaveBeenCalled(); + }); + + it('should unsubscribe from all events', function () { + this.window.destroy(); + for(var key in this.window.eventEmitter.events){ + expect(this.window.eventEmitter.events[key]).toBe(0); + } + }); + + it('should remove dom element',function(){ + this.window.destroy(); + expect(this.appendTo.find('.window').length).toBe(0); + }) + + }); + }); describe('Configuration', function() { }); -}) +});