Giter VIP home page Giter VIP logo

tify's Introduction

TIFY is a slim and mobile-friendly IIIF document viewer built with Vue.js. It supports IIIF Presentation API and Image API version 2 and 3.

Continue reading to learn how to integrate TIFY into your website or application and about its options and API, check out the website for usage examples, or have a look at the user guide.

Embedding TIFY

TIFY is available as an npm package:

npm install tify

Embed TIFY into your website in three easy steps:

  1. Include both the JavaScript and the stylesheet.

    • Either download TIFY and copy the contents of the dist directory to your server:

       <script src="tify.js?v0.31.0"></script>
       <link rel="stylesheet" href="tify.css?v0.31.0">

      To avoid issues with browser caching, add a query parameter with the current version, e.g. ?v0.31.0.

    • Or use jsDelivr:

       <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/tify.js"></script>
       <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tify.css">
    • Or import TIFY into your web application:

       import 'tify'
       import 'tify/dist/tify.css'
  2. Add an HTML block element with an id and set its height.

    <div id="tify" style="height: 640px"></div>
  3. Create a TIFY instance.

    <script>
    new Tify({
      container: '#tify',
      manifestUrl: 'https://example.org/iiif-manifest.json',
    })
    </script>

Many aspects of the theme can be modified with SCSS variables or CSS custom properties, allowing you to easily adapt TIFY’s appearance to your website. See the theme settings file for all available variables.

Upgrading

If you are are upgrading from any previous version, have a look at the upgrading guidelines.

Options

TIFY takes an options object as its only parameter. While optional, you usually want to set container and manifestUrl.

  • childManifestAutoloaded: boolean, default true

    If the manifest set by manifestUrl is a collection (@type is sc:Collection) and childManifestUrl is not set, automatically load the first manifest in the collection. This only works for collections with manifests on the first level; when the collection only contains other collections and childManifestUrl is not set, only the collection view is shown until the user selects a child manifest to load.

  • childManifestUrl: string or null (default)

    If the manifest set by manifestUrl is a collection (@type is sc:Collection), additionally load another IIIF manifest, whose @type must be sc:Manifest. Note that TIFY does not check if this additional manifest is actually part of the collection.

  • container: string or HTMLElement or null (default)

    The HTML element into which TIFY is mounted. If set to null, TIFY is not mounted at all until mount is called (see API).

  • fallbackLanguage: string, default 'en'

    The language to be used for strings from the IIIF manifest that are not available in the current language. If no value matches language or fallbackLanguage, the first available language is displayed.

  • filters: object, default {}

    Sets the initial image filters. Available properties are 'brightness', 'contrast' (both a floating-point number between 0.5 and 2) and 'saturation' (floating-point number between 0 and 3), all optional.

  • language: string, default 'en'

    The interface language, matching the translation filename without extension. See which translations are available or add your own.

  • manifestUrl: string or null (default)

    The URL of the IIIF manifest to load.

  • optionsResetOnPageChange: array of strings, default ['pan']

    Viewer options that are reset on page change. Allowed array values are 'filters', 'pan', 'rotation' and 'zoom'.

  • pageLabelFormat: string, default 'P : L'

    Defines how page labels are displayed in the page selector and in the thumbnails view. The placeholder P is replaced by the physical page number (consecutive numbers starting at 1) while L is replaced by the logical page label, which can be any string, defined by the manifest.

  • pages: array of 1-based integers or null (default)

    The page(s) to display initially. If null, the initial page is determined by the manifest’s startCanvas, and if that is not set either, the first page is displayed. Page numbers start at 1.

  • pan: object, default {}

    Sets the initial pan. The object has two optional properties x and y, both floating-point numbers. The higher the value, the more to the left respectively top the image is positioned. By default, the image is centered within the container.

  • translationsDirUrl: string or null (default)

    The URL of the directory where TIFY finds its translations, without trailing /. If not set, TIFY tries to determine this URL automatically from its <script> element, but this may not work depending on how TIFY is loaded.

  • urlQueryKey: string or null (default), only use characters A…Z a…z 0…9 - _

    If set, parameters are read from the URL query and any changes are reflected, using the key provided. This works with multiple concurrent instances, but each instance must use a unique key. Note that when urlQueryKey is set, all options defined by urlQueryParams can be overridden by changing the URL in the browser’s address bar.

  • urlQueryParams: array of strings, default ['childManifestUrl', 'filters', 'pages', 'pan', 'rotation', 'view', 'zoom']

    The parameter keys to be read from and stored in the URL query. Only has effect if urlQueryKey is set, in which case parameters read from the URL override options of the same name.

  • view: string, default ''

    The initially displayed view (panel); scan, fulltext, thumbnails, toc, info, help, or empty (same as scan). On large screens, the scan is always shown next to the selected view.

  • viewer: object

    An object with options for OpenSeadragon, TIFY’s image rendering component. See its documentation for all available options.

  • zoom: floating-point number, default null

    Sets the initial zoom level. The higher the number, the deeper the zoom. By default, zoom is set automatically so that the full image is visible.

An example with most available options set to non-default values:

new Tify({
  container: '#tify',
  language: 'de',
  manifestUrl: 'https://example.org/iiif-manifest.json',
  pageLabelFormat: 'P (L)',
  pages: [2, 3],
  pan: { x: .45, y: .6 },
  translationsDirUrl: '/translations/tify',
  urlQueryKey: 'tify',
  urlQueryParams: ['pages'],
  view: '',
  viewer: {
    immediateRender: false,
  },
  zoom: 1.2,
})

API

With the exception of mount and destroy, all API functions are only available after TIFY has been mounted and the manifest has been loaded. Then the ready promise is fulfilled. There is no API function to load a new manifest; just replace the instance.

Use the API like this:

const tify = new Tify({ manifestUrl: 'https://example.org/iiif-manifest.json' })

tify.mount('#tify')

tify.ready.then(() => {
  tify.setPage([1, 12, 13])
  tify.setView('thumbnails')
  tify.viewer.viewport.zoomTo(2)
})
  • destroy

    Destroys the current instance and removes event listeners. If you are using TIFY in an SPA, this should be called every time a page containing TIFY is unmounted to avoid memory leaks.

    No parameters.

  • mount

    Mounts TIFY.

    Parameters:

    • container: string or HTMLElement, required

      CSS selector pointing to a single HTML node or the node itself into which TIFY is mounted.

  • resetScan

    Resets the scan display options.

    Parameters:

    • includingFiltersAndRotation: boolean, default false

      By default, only pan and zoom are reset. If true, image filters and rotation are reset, too.

  • setPage

    Changes the active page or pages.

    Parameters:

    • pageOrPages: 1-based integer or array thereof (required)

      Provide a number to display a single page or an array of numbers to display multiple pages at once. If the number (or any of the numbers in the array) is smaller than 1 or greater than the number of pages in the document, the command is ignored.

    Returns an array of the current pages or false if pageOrPages is invalid.

  • setLanguage

    Changes the frontend language and loads the associated translation. This function returns a Promise.

    Parameters:

    • language: string, default 'en'

      The language to load. A JSON file containing the translations for this language must be present in public/translations. Untranslated strings are displayed in English.

  • setView

    Changes the active view (panel).

    Parameters:

    • name: string (required)

      The view’s name; 'export', 'fulltext', 'help', 'info', 'scan', 'thumbnails', 'toc', or an empty string (same as 'scan').

  • toggleDoublePage

    Switches from single to double page (“book view”) and vice versa.

    Parameters:

    • forced: boolean, default false

      Double page is forced on (true) or off (false).

  • toggleFullscreen

    Toggles fullscreen mode. For security reasons, most browsers require a user interaction to enter fullscreen mode; a button calling this function via onclick works, but trying to do so automatically does probably not.

    Parameters:

    • forced: boolean, default false

      Fullscreen is forced on (true) or off (false).

OpenSeadragon API

The viewer object exposes the full OpenSeadragon API. If you want to control the scan view programmatically, the methods of viewer.viewport are probably of interest.

Build Setup

You need to have Node.js v18.0 or above, npm (usually comes with Node.js) and git installed.

Install dependencies:

npm install

Run in development mode with hot reload and automatic linting:

npm run dev

Build for production with minification:

npm run build

The production build will be stored in dist.

Running Tests

Run unit tests: npm run test:unit

Run end-to-end tests:

  • Development build: npm run dev
  • Production build: npm run build && npm run test:e2e

Göttingen State and University Library

tify's People

Contributors

asajedi avatar atomotic avatar commandblock123 avatar dependabot[bot] avatar hrvoj3e avatar ipf avatar jameswchan avatar paulpestov avatar pierrz avatar smuehlh avatar t11r avatar wojtekarpinski avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tify's Issues

New option: Render toolbar

An option that enables/disables the toolbar at the top would be a nice addition.

When integrating TIFY in our application, we had to hide the toolbar by manually adjusting the minified CSS. Before that it looked like this:

unbenannt

Support viewingDirection property

Needed for the proper presentation (particularly the two-page view) of books written in right-to-left languages such as Arabic, Farsi, Urdu, Hebrew, etc.

Adjust About TIFY

About TIFY
TIFY is a slim and mobile-friendly IIIF document viewer.
Version xxxxx

Documentation
Source code
Report a bug

Link zu [Contributors]

Copyright (c) 2017-2020 Göttingen University - Göttingen State and
University Library
Licensed under GNU Affero General Public License v3.0

ready event?

Hey guys, great tool, I just deployed it on a server and it works great!

I was wondering if there is a way to get notified when the viewer is "ready". I found Tify.loading and the viewer seems to be ready once that is 0. However, something like Tify.addEventListener('ready', ...) would be nice.

Thanks again,
Moritz

Make TIFY happy again

In 2017, I created TIFY at the Göttingen State and University Library (@subugoe). TIFY got some attention from the IIIF community and is built upon by several projects. Among the upcoming Mirador 3, Universal Viewer and a few others, TIFY fills its own niche by offering some unique features, and can be a valuable tool for making image collections and related metadata publicly available.

However, since I left my job to found my own company, development has stalled. There has not been a release for over a year (which only @subugoe staff could do), most issues did not even get a reply, and TIFY remains almost invisible among over 200 repositories, most of which are stagnant or only used internally.

This makes TIFY, me, and possibly its users sad.

To increase visibility and to bundle related repositories, like an upcoming website and plugins, TIFY should be moved to its own GitHub organization, which I am hereby offering to maintain. Unlike another fork, this would keep all issues (and stars 😌) and redirect visitors to the new official repository. Issues would be taken care of, and I already have plans for further development. Of course, TIFY will always remain open source.

@subugoe and @doganzm (head of Software & Service Development), what do you say, 👍 or 👎?

The opinions of users, contributors (@ipf, @smuehlh, @pierrz, @JamesWChan, and @asajedi), and organizations who use TIFY (@nationalarchives and @ecds, among others) are also welcome.

Fix translations

With the current release, translations do not work anymore.
The filter trans is called, but the app.messages is empty.
The call to load the translation files succeeds.

Problem to display Ranges w/o canvases

Tify fails to display Ranges without a canvases property, for instance this the case for all the Manifests from Cambridge University (example: https://tify.sub.uni-goettingen.de/demo.html?manifest=https://cudl.lib.cam.ac.uk/iiif/MS-ADD-08640).

Tify throws the error "TypeError: "t.$root.canvases[(o.firstPage - 1)] is undefined"", which breaks both the "Info" and "Contents" panels.

According to Presentation API 2.1, the canvases property is optional on a Range.

Tify should probably ignore the Range without canvases (which is always the first one in the case of Cambridge Manifests). This is what Mirador does.
Or instead try to display that Range anyway, as UV does (even if the rendering is not completely satisfactory in the Index panel): http://universalviewer.io/uv.html?manifest=https://cudl.lib.cam.ac.uk/iiif/MS-ADD-08640

Problem getting tify to run in Vue 2.3 Single File Component

Hello,

I'm wondering what I am doing wrong? I keep getting the following errors:

vue-router.esm.js?fe87:16 [vue-router] Failed to resolve async component default: Error: TIFY container element not found
vue-router.esm.js?fe87:1832 Error: TIFY container element not found

Here's my code (excerpts):

Here is my Vue component using Tify (it's a single file component):

Template:
<template> <div> <div id="tify" style="position: relative; width: 800px; height: 600px;"></div> </div> </template>

Script:

  require ('../../../iiif/tify.js')
  require ('../../../iiif/tify.css')

  let tifyOptions = {
      container: '#tify',
      language: 'de',
      manifestUrl: 'https://rawgit.com/pdaengeli/9866a1a01be9a806d82bcfb7305eaee2/raw/ca81647167842403ee503a964288eb2805dd6e49/letter_16636_manifest.json'
    }

Anyone has an idea what I am getting wrong?

How to control Tify-related query strings in URL

Hello there,

is it possible to control wether/when Tify pushes its query data into the URL? The issue is that once Tify is loaded, it pushes its query string into the URL (which is generally nice to have). However, when closing a modal containing the tify div, this query then stays in the URL.

Page without tify query
http://localhost:8000/data/letter/letter_06010

Example with tify query (tify div on display)
http://localhost:8000/data/letter/letter_06010?tify={%22view%22:%22scan%22}

When tify-div is closed, the query stays
http://localhost:8000/data/letter/letter_06010?tify={%22panX%22:0.001,%22panY%22:0.001,%22view%22:%22scan%22,%22zoom%22:747.714}

Is this an error in our setup? Or is it an issue with the plugin itself?

Thank you very much for your help.


Vue version: 2.5.15
Vue Router version: 3.0.1
Tify version: 0.20.0

Show different IIIF manifest structures

For the NLH AHN project (Historical Newspapers) we need to show different structures. The IIIF Presentation API doesn't support this, but we could create specific manifests, which reflects a specific view, so that we can support navigation over different structure types.

  1. Page based: As usual via pages and logical Structural elements.
  2. Articles based: Via articles, whereby not whole pages, but the scans of the page excerpts of the articles are to be displayed. An article then consists of one scan or a sequence of scans, which can then be used to navigate (previous/next section, start of article (previous/next excerpt, beginning of article, previous/next article).

The first question is which component could help to solve this problem? Choose a structure from the hit-list and open it in TIFY with the specific manifest or switch from TIFY. In the latter case, how should TIFY know about the different structures?

Any ideas are welcome :)

Support startCanvas parameter for sequences.

Tify should set the first canvas in a sequence based on the startCanvas parameter. It's possible to set the URL parameter like this:
tify={"pages":[2]}

But this should not be necessary because we would have read the manifest to get the startCanvas value. So this should be handled by the viewer.

Build errors

Build failed with errors.

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: node build/build.js
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! /home/[username]/.npm/_logs/2020-03-27T09_44_16_946Z-debug.log

Tify doesn't load from `defer` `<script>` tags

Currently Tify using a quite shaky mechanism to figure out a base path:
https://github.com/tify-iiif-viewer/tify/blob/main/src/main.js#L60

This has an issue if the browser doesn't guarantee that a page has been completely loaded when the initialisation of Tify is triggered. This can be the defer attribute of a <script>tag.

The result of this issue can be that the language files can't be loaded since the guessed base path is empty.

Add configuration setting to be able to set this path manually.

Support IIIF Image API

See #63, there has to be an internal IIIF Image API implementation in order to work, it should be exposed to the user on demand.

How to use multiple Tify instances on one page?

Currently it seems to be impossible to use multiple instances of Tify on one page. Additionally there is either no API documentation or no real API at all. The goal should be something like:

var tify1 = new Tify({"manifest": "https://example.com/iiif/manifest.json", "container": "#viewer", "init": true})
  • Please take into consideration to foster reuse by thinking Tify as a widget, not as an application and design the initialisation accordingly.
  • Enhance the developer documentation to describe how this can archived.

IIIF Image API not supported

Currently the IIIF Image API isn't supported. If one passes a info.json file generated by iiif_static.py there is just an exception.
The fact that there is just an exception but no error message is another issue...

TypeError: Cannot read property '0' of undefined
    at Ue.canvases (tify.js:12)
    at Kr.get (tify.js:12)
    at Kr.evaluate (tify.js:12)
    at Ue.canvases (tify.js:7)
    at s.hasOtherContent (tify.js:12)
    at Kr.get (tify.js:12)
    at Kr.evaluate (tify.js:12)
    at s.hasOtherContent (tify.js:7)
    at s.i (tify.js:12)
    at s.t._render (tify.js:12)

Annotations with array of bodies don't load

When the JSON-LD serialisation of an (Open) annotation in an AnnotationList has an array of objects in the resource key, Tify ignores all of them.

This is a snippet of an annotation with an array of annotation bodies, which only has one entry:

"resource" : [ {
        "@type" : "dctypes:Text",
        "http://dev.llgc.org.uk/sas/full_text" : "<img src=\"../abnormalhieratic/wp-content/uploads/2018/10/2Dd.svg\" alt=\"\" width=\"55\" height=\"34\" />\nType: VerbTransliteration: DdTranslation: Has said",
        "format" : "text/html",
        "chars" : "<p><img src=\"../abnormalhieratic/wp-content/uploads/2018/10/2Dd.svg\" alt=\"\" width=\"55\" height=\"34\" /></p>\n<p>Type: Verb<br /><br />Transliteration: Dd<br /><br />Translation: Has said<br /><br /></p>"
        } ],

The FullText pane only looks for either a chars entry in the resource or an @id, the text is not loaded – without any error message. It would be great if the annotation were loaded.

Add support for collections

I was quite excited to discover tify as it seems much more mobile friendly than the other viewers I've seen so far! I would love to try it but the big blocker is support for iiif collections, is this a planned feature?

I'm trying to get https://iiifpres.bdrc.io/2.1.1/collection/wio:bdr:W22084 to work on the demo but it triggers a JS error:

TypeError: "this.manifest.sequences is undefined"

Ideally the display would be similar to mirador2:

http://library.bdrc.io/view/bdr:W22084

(lazy loading subcollections and manifests if they appear on screen)

Check manifest for type and improve error handling

If one passes an unsupported IIIF API endpoint or just some JSON encoded rubbish, there is no real error handling.
There is an example to trigger this in #62.
It's better to catch the exception and report possible causes to the user.

Switch to ESLint Standard

I hereby propose to switch the ESLint rules from Airbnb to Standard. Standard is more commonly used and does not require pesky semicolons.

Invalid URL params - Reload produces 400 Bad Request

When navigating pages in tify 0.23.0 (and before) the URL is feeded with tify params like this:
http://localhost:10000/view/162330?tify={%22panX%22:0.537,%22panY%22:0.91,%22view%22:%22scan%22,%22zoom%22:0.474}

When clicking reload in browser I get a 400 Bad Request error page.
Server message:
"Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986"

Seems to be the curly braces, as valid characters are:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=

Load new manifest

I have an application where the user can change manifests on the fly. Changing window.Tify.options.manifest and calling window.Tify.init() does nothing.

Is there a way to do this?

postinstall fails on Windows

The postinstall script in package.json fails on Windows due to the usage of the rm command:

C:\Users\Sebastian\Git\tify-app>npm i

> [email protected] postinstall C:\Users\Sebastian\Git\tify-app\node_modules\tify
> rm -rf openseadragon && git clone https://github.com/openseadragon/openseadragon.git && cd openseadragon && git checkout tags/v2.3.1

Der Befehl "rm" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.

Add more configuration options

  • Add option to disable the toolbar (#8, only makes sense along with an API that controlling everything in the toolbar)
  • Add option to disable storing parameters in the URL (#24)
  • Add option to set the initial view (#36)

Add view option?

Great project! Keep up the great work!

Would love to see an option (https://github.com/subugoe/tify#options) added where you can set the view on load. The user can still change it but it would be nice to set it on load vs. right now it loads by default with the Info view.

Maybe:

view (string, default:”info”): Controls what view is displayed. By default, TIFY displays the Info view. Possible values: pages ({"view":"thumbnails"}), info ({"view":"info"}), export ({"view":"export"}), help ({"view":"help"}), or “” ({"view":""}).

Thanks.

Currently I’m using this JavaScript as a work around:

function updateURL() {
			if (history.pushState) {
				  var newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?tify={"view":"thumbnails"}';
				  window.history.pushState({path:newurl},'',newurl);
			  }
		}

Licensing question

A quick search revealed several services based on TIFY that removed the help tab and do not provide a link to the source as required by the AGPL 3.0, one of which (Glagoljica.hr) is even linked on @subugoe's website. Does this mean TIFY can be used under another license which does not require a link to the source?

End-to-end tests not working

In the current main branch, E2E tests are no longer working. Each test fails with this error message:

"before each" hook: codeceptjs.before for "Change view via buttons @smoke":
     Can't connect to WebDriver.
Error: Failed to create session.
session not created: This version of ChromeDriver only supports Chrome version 83

If there are additional steps to run for E2E tests to work, please update the readme.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.