Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 'get' canvas functions to ranges #79

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/Manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,14 +164,15 @@ export class Manifest extends IIIFResource {
this._parseRanges(item, path + "/" + i, range);
} else if (
(item["@type"] && item["@type"].toLowerCase() === "sc:canvas") ||
(item["type"] && item["type"].toLowerCase() === "canvas")
(item["type"] && item["type"].toLowerCase() === "canvas") ||
(item["type"] && item["type"].toLowerCase() === "specificresource")
) {
// store the ids on the __jsonld object to be used by Range.getCanvasIds()
if (!range.canvases) {
range.canvases = [];
}

const id: string = item.id || item["@id"];
const id: string = item.id || item["@id"] || item["source"];

range.canvases.push(id);
}
Expand Down
176 changes: 172 additions & 4 deletions src/Range.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
Canvas,
Duration,
IManifestoOptions,
ManifestResource,
Expand All @@ -13,14 +14,15 @@ import {
} from "@iiif/vocabulary/dist-commonjs";

export class Range extends ManifestResource {
private _canvases: Canvas[] | null = null;
private _ranges: Range[] | null = null;
public canvases: string[] | null = null;
public items: ManifestResource[] = [];
public parentRange: Range | undefined;
public path: string;
public treeNode: TreeNode;

constructor(jsonld?: any, options?: IManifestoOptions) {
constructor(jsonld ? : any, options ? : IManifestoOptions) {
super(jsonld, options);
}

Expand All @@ -34,6 +36,172 @@ export class Range extends ManifestResource {
return [];
}

getTopRange(range) {
let parentRange = range.parentRange;
if (parentRange) {
this.getTopRange(parentRange);
}
return parentRange;
}

getTotalCanvases(): number {
return this.getCanvases().length;
}

getCanvases(): Canvas[] {
if (this._canvases) {
return this._canvases;
}

let manifestSequence = this.getTopRange(
this
).options.resource.getSequences()[0];
let manifestCanvases =
manifestSequence.__jsonld.canvases || manifestSequence.__jsonld.elements;

const canvasLength = this.canvases ? this.canvases.length : 0;
let canvasItems: (Canvas | null)[] = new Array(canvasLength).fill(null);

const rangeItems = this.__jsonld.items;

if (manifestCanvases && this.canvases) {
for (let i = 0; i < manifestCanvases.length; i++) {
let c = manifestCanvases[i];

const fragmentCanvas = rangeItems.filter(item => {
return item.source === c.id;
});

if (c.id in this.canvases) {
if (fragmentCanvas) {
const fragment = fragmentCanvas[0].selector.value;
const fragmentCanvasId = `${c.id}#${fragment}`;
c = this._updateFragmentIds(c, fragmentCanvasId);
}

const canvas: Canvas = new Canvas(c, this.options);
canvas.index = this.canvases.indexOf(c.id);
canvasItems.splice(canvas.index, 1, canvas);
}
}
} else if (manifestSequence.__jsonld && this.canvases) {
for (let i = 0; i < manifestSequence.__jsonld.length; i++) {
let c = manifestSequence.__jsonld[i];

const fragmentCanvas = rangeItems.filter(item => {
return item.source === c.id;
});

if (this.canvases.includes(c.id)) {
const cIndex = this.canvases.indexOf(c.id);
if (fragmentCanvas) {
const fragment = fragmentCanvas[0].selector.value;
const fragmentCanvasId = `${c.id}#${fragment}`;
c = this._updateFragmentIds(c, fragmentCanvasId);
}

const canvas: Canvas = new Canvas(c, this.options);
canvas.index = cIndex;

canvasItems.splice(canvas.index, 1, canvas);
}
}
}

this._canvases =
canvasItems.length > 0 ?
!canvasItems.includes(null) ?
< Canvas[] > canvasItems :
null :
null;

return this._canvases !== null ? this._canvases : [];
}

// update __jsonld canvas id's because that is used by other functions in
// the library when working with canvases
_updateFragmentIds(canvasJson: any, newCanvasId: string): any {
// update ids in annotations
const items = canvasJson.items || canvasJson.content;
const annotations = items.length && items[0].items ? items[0].items : [];

if (annotations && canvasJson.items) {
for (let i = 0; i < annotations.length; i++) {
canvasJson["id"] = newCanvasId;
// update target canvas Id in all canvas annotations
canvasJson.items[0].items[i]["target"] = newCanvasId;
}
} else if (annotations) {
for (let i = 0; i < annotations.length; i++) {
canvasJson["id"] = newCanvasId;
// update target canvas Id in all canvas annotations
// replace this with (something that looks at other contents)
canvasJson.content[0].items[i]["target"] = newCanvasId;
}
}

return canvasJson;
}

getCanvasByIndex(canvasIndex: number): any {
return this.getCanvases()[canvasIndex];
}

getCanvasById(id: string): Canvas | null {
for (let i = 0; i < this.getTotalCanvases(); i++) {
const canvas = this.getCanvasByIndex(i);

const canvasId: string = Utils.normaliseUrl(canvas.id);

if (Utils.normaliseUrl(id) === canvasId) {
return canvas;
}
}
return null;
}

// Alternative solution can be this
/* getTopLevelCanvases(): Canvas[] {
if(this._canvases){
return this._canvases;
}

if (this.items.length) {
let canvasItems: Canvas[] = [];
for (let i = 0; i < this.items.length; i++) {
if (this.items[i].isCanvas()) {
canvasItems.push(<Canvas>this.items[i]);
}
}
return this._canvases = canvasItems;
}

let items = this.__jsonld.items || this.__jsonld.elements;

if (items) {
for (let i = 0; i < items.length; i++) {
if (items[i].type.includes("Canvas")) {
const c = items[i];
const canvas: Canvas = new Canvas(c, this.options);
canvas.index = i;
this.items.push(canvas);
}
}
} else if (this.__jsonld) {
for (let i = 0; i < this.__jsonld.length; i++) {
if (items[i].type.includes("Canvas")) {
const c = this.__jsonld[i];
const canvas: Canvas = new Canvas(c, this.options);
canvas.index = i;
this.items.push(canvas);
}
}
}

return this._canvases = <Canvas[]>this.items;
}
*/

getDuration(): Duration | undefined {
// For this implementation, we want to catch SOME of the temporal cases - i.e. when there is a t=1,100
if (this.canvases && this.canvases.length) {
Expand Down Expand Up @@ -145,7 +313,7 @@ export class Range extends ManifestResource {
return this._ranges;
}

return (this._ranges = <Range[]>this.items.filter(m => m.isRange()));
return (this._ranges = < Range[] > this.items.filter(m => m.isRange()));
}

getBehavior(): Behavior | null {
Expand Down Expand Up @@ -203,7 +371,7 @@ export class Range extends ManifestResource {
}

private _parseTreeNode(node: TreeNode, range: Range): void {
node.label = <string>range.getLabel().getValue(this.options.locale);
node.label = < string > range.getLabel().getValue(this.options.locale);
node.data = range;
node.data.type = Utils.normaliseType(TreeNodeType.RANGE);
range.treeNode = node;
Expand All @@ -225,4 +393,4 @@ export class Range extends ManifestResource {
}
}
}
}
}
1 change: 0 additions & 1 deletion src/Sequence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export class Sequence extends ManifestResource {
}

let items = this.__jsonld.canvases || this.__jsonld.elements;

if (items) {
for (let i = 0; i < items.length; i++) {
const c = items[i];
Expand Down
61 changes: 61 additions & 0 deletions test/fixtures/pres3.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,67 @@
]
}
]
},
{
"id": "http://example.org/iiif/book1/canvas/1",
"type": "Canvas",
"label": {
"@none": [
"p. 1"
]
},
"height": 1000,
"width": 750,
"duration": 180.0,
"items": [
{
"id": "http://example.org/iiif/book1/canvas/1/annotationpage/0",
"type": "AnnotationPage",
"items": [
{
"id": "http://example.org/iiif/book1/canvas/1/annotation/0",
"type": "Annotation",
"motivation": "painting",
"body": {
"id": "http://example.org/iiif/book1/canvas/1/images/page1.jpg",
"type": "Image",
"format": "image/jpeg",
"label": {
"@none": [
"Page 1"
]
}
},
"target": "http://example.org/iiif/book1/canvas/1"
}
]
}
]
}
],
"structures": [
{
"id": "http://foo.test/1/range/root",
"type": "Range",
"behavior": "sequence",
"items": [
{
"type": "SpecificResource",
"source": "http://example.org/iiif/book1/canvas/0",
"selector": {
"type": "FragmentSelector",
"value": "xywh=0,0,750,300"
}
},
{
"type": "SpecificResource",
"source": "http://example.org/iiif/book1/canvas/1",
"selector": {
"type": "FragmentSelector",
"value": "xywh=0,0,750,300"
}
}
]
}
]
}
24 changes: 23 additions & 1 deletion test/tests/pres3.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ var should = require('chai').should();
var manifesto = require('../../dist-commonjs/');
var manifests = require('../fixtures/manifests');

var manifest, sequence, canvas, content, annotation, body;
var manifest, range, sequence, canvas, content, annotation, body;

describe('presentation 3', function() {

Expand All @@ -23,6 +23,11 @@ describe('presentation 3', function() {
expect(metadata[0].label[0].value).to.equal('Author');
});

it('has a range', function() {
range = manifest.getTopRanges()[0].getRanges()[0];
expect(range).to.exist;
});

it('has a sequence', function() {
sequence = manifest.getSequenceByIndex(0);
expect(sequence).to.exist;
Expand All @@ -31,6 +36,23 @@ describe('presentation 3', function() {
it('has a canvas', function() {
canvas = sequence.getCanvases()[0];
expect(canvas).to.exist;
var canvasById = sequence.getCanvasById('http://example.org/iiif/book1/canvas/0');
expect(canvasById).to.exist;
var getCanvasByIndex = sequence.getCanvasByIndex(0);
expect(getCanvasByIndex).to.exist;
});

it('range has a canvas', function() {
canvas = range.getCanvases()[0];
expect(canvas).to.exist;
/* B */
});

it('updates canvas Id if canvas is listed as a fragment in range', function() {
canvas = range.getCanvases()[1];
const hasFragment = canvas.id.includes('#xywh=')
expect(hasFragment).to.exist;
/* B */
});

it('has an annotation body', function() {
Expand Down