npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@prokomssp/edoc-viewer

v10.213.2

Published

Client for viewing and posting forms.

Readme

Viewer.js

Et JavaScript-bibliotek som lar deg rendre skjemaer og innhold fra Skjema.no (inkludert lagrede/innsendte skjemaer og personvernerklæringer) på din egen nettside.

Hva gjør biblioteket?

  • Rendrer innhold og skjemaer dynamisk.
  • Tilbyr JavaScript-metoder for skreddersydde løsninger og dypere integrasjon.
  • Tillater styling via egne CSS-filer.

Hva må du gjøre selv? Siden Viewer.js ikke leverer ferdige nettsider, er du selv ansvarlig for HTML-strukturen, plassering av komponenten, samt håndtering av navigasjon og logikk (f.eks. hva som skjer etter at et skjema er sendt inn eller avbrutt).

For å ta i bruk løsningen må du derfor ha mulighet til å sette opp og manipulere HTML- og JavaScript-koden direkte på nettsiden der biblioteket skal brukes.

Installasjon

Viewer.js kan installeres via npm:

npm install @prokomssp/edoc-viewer

Viewer-filene vil da legge seg i node_modules/@prokomssp/edoc-viewer.

ES6-moduler

Dersom du bruker ES6-moduler, kan du importere viewer.js direkte. Det gjelder også css-filen for styling:

import viewer from '@prokomssp/edoc-viewer';
import '@prokomssp/edoc-viewer/viewer.min.css';

Script- og CSS-inkludering uten ES6-moduler

Du kan inkludere viewer.min.js nederst på HTML siden før body slutt tag.

    <body>
        ...
        <script src="viewer.min.js"></script>
    </body>

Legg også inn css-stilsettet for viewer.js i head taggen.

    <head>
        ...
        <link rel='stylesheet' href='viewer.min.css' type='text/css'  />
    </head>

Dersom du ikke ønsker å benytte samme stilsett som på skjema.no, kan du legge inn din egen css-fil i tillegg til, eller istedenfor Viewer.js sin egen css-fil.

    <head>
        ...
		<link rel='stylesheet' href='viewer.min.css' type='text/css'  />
        <link rel='stylesheet' href='custom.css' type='text/css'  />
    </head>

Opprett et tomt element der skjemaet skal rendres. Du bestemmer elementets id og oppgir denne i kall til viewer.init().

<body>
    <div id="skjema"></div>
</body>

Bruk av Viewer.js

Hvis du importerer Viewer.js som en ES6-modul, får du et viewer-object som gir tilgang til alle metodene i Viewer.js. I tillegg vil viewer-objektet være tilgjengelig globalt via window.viewer.

Hvis du bruker Viewer.js via script-tagger vil du måtte bruke det globale window.viewer-objektet for å få tilgang til metodene.

init()

Før du kan kjøre noen andre metoder, må du initialisere Viewer.js med viewer.init(). Dette gjøres typisk når DOM-en er ferdig lastet, for eksempel ved å lytte på DOMContentLoaded-hendelsen, eller foreksempel i en useEffect-hook om man bruker React.

document.addEventListener("DOMContentLoaded", () => {
    viewer.init({
        apiUrl : "<api url>",
        customerId: "<customer id>",
        hide : {
            title: false, 
            buttons: false, 
        }
    });
});

De andre metodene kan lenkes sammen med init-metoden:

viewer.init({...}).form({...});

Det vil likevel være mer naturlig å kjøre init-metoden når siden lastes, og deretter kalle de andre metodene separat når det er behov for det.

init options:

|Egenskap|Eksempel|Obligatorisk|Beskrivelse| |--------|--------|------------|-----------| |apiUrl |https://api.skjema.no|Ja|Url til API-et| |customerId|9998|Ja|Kunde-id| |hide.title|true|Nei|Oppgi true dersom det er ønskelig å skjule tittel| |hide.buttons|true|Nei|Oppgi true dersom det er ønskelig å skjule knappene for "avbryt", "lagre" og til "kontroll"|

Rendre-metoder

Rendre-metoden brukes for å vise ferdig-rendret innhold på skjermen. Metodene krever en HTML-container der innholdet skal vises.

form()

.form() brukes for å vise et skjema i den angitte HTML-containeren. Metoden krever at divId er spesifisert, som peker til elementet der skjemaet skal rendres. I tillegg kan man spesifisere formId, refId og previewId for å vise henholdsvis skjema, mellomlagret utkast og forhåndsvisning. Man kan også oppgi callback-funksjoner for ulike hendelser som avbryt, lagre og sende inn.

viewer.form({
	divId: "<id til div>",
	formId: "<id til skjema som skal vises eller funksjon som returnerer denne>",
	refId: "<id til mellomlagret utkast som skal vises eller funksjon som returnerer denne>",
	previewId: "<id til forhåndsvisning eller funksjon som returnerer denne>",
	onAborting: function(proceed) {},
	onAborted: function() {},
	onSaving: function(proceed) {},
	onSaved: function() {},
	onSubmitted: function() {}        
});
Angi skjema

viewer.js trenger én av følgende for å vise et skjema: formId, refId eller previewId.

  • formId benyttes når et nytt, tomt skjema skal vises. For å se hvilke formId-er som er tilgjengelig, kan du gjøre et kall til viewer.getForms() (beskrevet nedenfor).
  • refId benyttes når et mellomlagret utkast skal gjenopptas. For å se hvilke refId-er som er tilgjengelig, kan du gjøre et kall til viewer.getCases() (beskrevet nedenfor).
  • previewId vil bli sendt med når edoc-designer åpner URL for forhåndsvisning av skjema.

Det er vanlig at formId, refId eller previewId sendes med som querystring-parametre til HTML-siden. viewer.js har en utility-metode for uthenting av parameter fra querystring: viewer.util.getQuery(paramName). Eksempelet nedenfor henter parametre med navn "formId", "refId" og "previewId" fra querystring. Dersom parameteren ikke finnes, returnerer funksjonen null.

viewer.form({
	...
	formId: () => viewer.util.getQuery("formId"),
	refId: () => viewer.util.getQuery("refId"),
	previewId: () => viewer.util.getQuery("previewId")					
});

Verdien for formId, refId eller previewId kan alternativt "hardkodes" slik:

viewer.form({
	...
	formId: "701660",
});

Merk at viewer.js vil kaste en exception dersom mer enn én av formId, refId eller previewId er satt.

Event-handling

Når et skjema er startet, kan utfyller avbryte, lagre eller sende inn skjemaet. viewer.js tilbyr event-handlere som gjør det mulig å hooke seg på disse hendelsene.

Koden nedenfor viser et eksempel på hvordan disse event-handlerne kan implementeres.

viewer.form({
	...
	onAborting: (proceed) => proceed(),
	onAborted: () => window.location = "/",
	onSaved: (saveInfo) => {
		if(saveInfo.isAuthenticated) window.location = "/cases";
		else window.location = "/saveReceipt?refId=" + saveInfo.externalRefId;
	},
	onSubmitted: (receipt) => window.location = "/submitReceipt?refId=" + receipt.refId,
});
onAborting

onAborting blir kalt når utfyller trykker avbryt og før selve avbrytelsen blir utført. Det er valgfritt å registrere en eventhandler til dette eventet. Du kan bruke eventet til å vise en "vil du virkelig avbryte"-dialog. Dersom utfyller bekrefter avbryting, kaller du proceed() eller proceed(true). Dersom utfyller ikke ønsker å avbryte, kaller du proceed(false).

Eksempelet nedenfor tar utgangspunkt i at du har laget en funksjon showAbortDialog() som viser et bekreftelses-vindu. Avhengig av om utfyller klikker ja eller nei, kalles proceed() med true eller false.

viewer.form({
	...
	onAborting: (proceed) => {
		showAbortConfirmationDialog() //må implementeres av deg
			.on("click", "#yes", () => proceed(true))
			.on("click", "#no", () => proceed(false));            
	},
});
onAborted

onAborted blir kalt etter at avbrytelsen er fullført. Her har du eksempelvis mulighet for å laste en ny URL i nettleseren.

viewer.form({
	...
	onAborted: () => window.location = "/",
});
onSaved

onSaved blir kalt etter at en mellomlagring er fullført. Her har du eksempelvis mulighet for å laste en ny URL i nettleseren.

viewer.form({
	...
	onSaved: (saveInfo) => window.location = "/cases",
});
onSubmitted

onSubmitted blir kalt etter at en innsending er fullført. Her har du eksempelvis mulighet for å laste en ny URL i nettleseren. Funksjonen får et receipt-objekt. Dette objektet inneholder referanse id for innsendingen i receipt.refId. Dette kan du eksempelvis bruke for å laste en side som viser info om innsendelsen. Se avsnittet for getCaseInfo() nedenfor.

Eksempelet nedenfor laster en ny side med referanse id i querystring.

viewer.form({
	...
	onSubmitted: (receipt) => window.location = "/receipt?refId=" + receipt.refId;
});

renderReceipt()

Når et skjema sendes inn returneres et objekt med informasjon om innsendingen. Dette kan brukes til å lage en egen kvitteringsside. Alternativt kan du rendre Viewer.js sin egen kvitteringsside med denne metoden. renderReceipt tar et parameter som er et objekt med innstillinger (options).

viewer.renderReceipt({...});
Options

|Property|Eksempel|Obligatorisk|Beskrivelse|Default| |--------|--------|------------|---------|-------------| |selector |"#receiptContainer"|Ja|Selector for elementet som skal holde kvitteringen|Påkrevd| |refId|"VMBXUP"|Ja|Ref-id for innsendt skjema|Påkrevd| |button|{title: "Gå tilbake",onClick: () => location.href = '/'}|Nei|Et objekt som angir tittel og onClick-funksjon for knappen på kvitteringssiden|Knapp vises ikke om denne er udefinert|

Implementasjon

Kvitteringssiden brukes sammen med form.onSubmitted. Kvitteringssiden kan settes opp som en egen side, f.eksempel med url "/kvittering/:refid". OnSubmitted returnerer et objekt som inneholder en refId. Da kan man videresende brukeren i onSubmitted slik:

viewer.form({
	onSubmitted(receipt) {
		location.href = '/kvittering/' + receipt.refId;
	}
});

Man kan også bruke renderReceipt direkte i onSubmitted-metoden:

viewer.form({
	onSubmitted(receipt) {
		viewer.renderReceipt({
			selector: "#receiptContainer",
			refId: receipt.refId,
			
		})
	}
});

renderPrivacy()

Viewer.js har muligheten ti å rendre personvernerklæringen. Til det brukes renderPrivacy-metoden. Den tar to parametre: En selector for elementet den skal rendres til, og et objekt med innstillinger (options):

viewer.renderPrivacy("#privacyContainer", {...});
Options

|Property|Eksempel|Obligatorisk|Beskrivelse|Default| |--------|--------|------------|---------|-------------| |culture |"en"|Nei|Angir hvilken språk som skal vises|Språket som er valgt i Viewer.js| |privacy|"{ "Privacy_Title": "...", "Privacy_Ingress": "...", "Privacy_Body": "..." }"|Nei|Personvernerklæring som skal vises|Hentes fra api| |onClose|() => location.href = '/'|Nei|Funksjon som skal kjøre når lukkeknappen klikkes|Hvis udefinert vil lukkeknappen ikke vises.| |error|Error('Ikke funnet')|Nei|Error-object med eventuell feilmelding som skal vises|Udefinert|

Du kan også bruke metoden getPrivacy() for å hente personvernerklæringen som et objekt i stedet for å rendre den direkte.

renderFooter()

Du kan bruke Viewer.js sin egen footer. Den vil inneholde informasjon om Viewer og link til personvernerklæring og/eller tilgjengelighetserklæring. RenderFooter tar to parametre: En selector som angir hvilket element footeren skal rendres til, og et objekt med innstillinger (options).

viewer.renderFooter("#footerContainer", {...});
Options

|Property|Eksempel|Obligatorisk|Beskrivelse|Default| |--------|--------|------------|---------|-------------| |accessibilityStatement |"/tilgjengelighet"|Nei|Link til tilgjengelighetserklæring|Link vises ikke hvis denne er udefinert| |privacyLink|"/personvern"|Nei|Link til personvernerklæring|Link vises ikke om denne og "privacyClick" er udefinert| |privacyClick|() => location.href = '/privacy'|Nei|Funksjon som skal kjøre når personvern-linken klikkes|Link vises ikke om denne og "privacyLink" er udefinert| |className|footer|Nei|Egendefinert css-klasse|Udefinert|

renderMyCasesTo()

Metoden renderMyCasesTo brukes for å rendre en liste over brukerens lagrede og innsendte skjemaer til et spesifisert element i DOM. Metoden tar fire parametre:

  • root: HTMLElement der sakene skal rendres.
  • fullPath: Full sti til saken.
  • siteRoot (valgfritt): Rot-URL for nettstedet.
  • callback (valgfritt): Funksjon som kjøres etter at rendringen er fullfør
const root = document.getElementById("myCasesContainer");
const fullPath = "/full/path/to/case";
const siteRoot = "/";

viewer.renderMyCasesTo(
    root,
    fullPath,
    siteRoot,
    () => console.log("Render complete")
);
Options

|Property|Eksempel|Obligatorisk|Beskrivelse|Default| |--------|--------|------------|---------|-------------| |root|document.getElementById("myCasesContainer")|Ja|HTMLElement der sakene skal rendres|Udefinert| |fullPath|"/full/path/to/case"|Ja|Full sti til siden|Udefinert| |siteRoot|"/"|Nei|Rot-URL for nettstedet|"/"| |callback|() => console.log("Render complete")|Nei|Funksjon som kjøres etter at rendringen er fullført|Udefinert|

Du kan også bruke data-metoden getMyCases() for å hente en liste over brukerens lagrede og innsendte skjemaer uten å rendre dem i DOM.

Data-metoder

Data-metoder er metoder du kan bruke i JavaScript for å hente ut data som du så kan bruke i ditt eget grensesnitt eller logikk. Disse metodene rendrer ikke noe i brukergrensesnittet selv, men returnerer data som du kan bruke videre.

getCategories()

Metoden getCategories() brukes for å hente en liste over tilgjengelige skjemaer, delt inn i kategorier. Dette kan brukes for å bygge en kategorioversikt i brukergrensesnittet.

viewer.getCategories().then((categories) => {
    console.log(categories);
}).catch((error) => {
    console.log(error);
});

Metoden returnerer en array med kategorier, der hver kategori inneholder en array med tilhørende skjemaer (templates).

[
    {
        "caption": "Nye skjemaer",
        "code": "Nye skjemaer",
        "id": "e5d42a82-f182-4708-94ee-d18355060682",
        "templates": [
            {
                "name": "Enkelt skjema",
                "id": "fc752d86-c19c-46ad-9163-a6f43eb66395",
                "formId": "enk-skm"
            },
            {
                "name": "Søknad",
                "id": "9e2dce00-4722-4206-8f43-1eacb06b555",
                "formId": "sok"
            },
        ]
    },
    {
        "caption": "Andre skjemaer",
        "code": "Andre skjemaer",
        "id": "ff178e88-d296-4388-a755-63498f032e55",
        "templates": [
            {
                "name": "Basic",
                "id": "ad9b2209-2d65-4316-a419-be6d33bd999",
                "formId": "basic"
            },
        ]
    },
]

Om du heller vil ha en ren liste over alle tilgjengelige skjemaer uten kategorier, kan du bruke getForms()-metoden.

getCaseInfo() - uthenting av info for kvittering

Etter innsending av skjema er det vanlig å vise en side som viser skjemaets navn, tidspunkt for innsendelse og referanse id. Denne informasjonen hentes via kall til viewer.getCaseInfo(refId). refId får du fra onSubmitted()-eventet når skjemaet sendes inn.

Eksempelet nedenfor viser hvordan referanse id, skjemaets navn og tidspunkt for innsendelse hentes.

<div id="receipt"></div>
<script>
    document.addEventListener("DOMContentLoaded", () => {
        const refId = viewer.util.getQuery("refId");

        viewer.getCaseInfo(refId).then((info) => {
			document.getElementById("receipt").innerHTML = 
			`
				refId: ${info.refId} <br/>
				name: ${info.name} <br/>
				updatedOn: ${info.updatedOn} <br/>
			`;
		}).catch((error) => {
			console.log(error);
		});
    });
</script>

session()

viewer.js benytter HTML 5 sessionStorage for lagring av skjemadata under utfylling. .session() gjør det mulig å fortelle viewer.js etter hvor lang inaktivitet disse skal fjernes fra sessionStorage. .init() må kalles før .session().

viewer
    .init({...})
    .session({...})

session object:

Eksempelet nedenfor setter opp 20 minutter som inaktiv periode, med varsling 5 minutter før disse 20 minuttene nåes. onIdleTimeoutWarning() blir da kalt et gitt antall minutter før sesjonen utgår. Eventet gjør det mulig å vise en dialog der bruker kan forlenge eller avslutte sesjonen sin. Kall extendSession() dersom sesjonen skal forlenges, eller endSession() dersom sesjonen skal avsluttes. Det er valgfritt å registrere en handler på onIdleTimeoutWarning. Dersom 20 minutter med inaktivitet passerer, eller utfyller i onIdleTimeoutWarning velger å avslutte sesjonen, blir onIdleTimeout kalt.

viewer.session({
	idleTimeoutMinutes: 20,
	warningTimeoutMinutes: 5,
	onIdleTimeoutWarning: (extendSession, endSession, sessionOptions) => {
		showTimeoutWarning(sessionOptions.warningTimeoutMinutes) //må implementeres av deg
			.on("click", "#yes", extendSession)
			.on("click", "#no", endSession);
	},
	onIdleTimeout: () => document.location = "/timeout";
})

sessionOptions.warningTimeoutMinutes viser hvor mange minutter det er igjen til sesjonen avsluttes på det tidspunktet da funksjonen ble kalt. Dersom du skal lage en nedtellingsfunksjon, kan du ta utgangspunkt i denne verdien.

|Egenskap|Eksempel|Obligatorisk|Beskrivelse| |--------|--------|------------|-----------| |idleTimeoutMinutes |60|Nei, default er 20|Antall minutter med inaktivitet før skjemadata fjernes.| |warningTimeoutMinutes|5|Nei|Utfyller blir gitt en advarsel om at sesjonen vil tømmes dette antall minutter i forveien.|

Brukerhåndtering

Dersom utfyller ikke er pålogget, men gjør en handling i viewer.js som krever pålogging, vil edoc-api sende brukeren til en identity-provider for pålogging. Handlinger i viewer.js som krever pålogging er mellomlagring av utkast og gjenopptaking av utkast, samt oppstart av skjema der det er satt krav til sikkerhetsnivå.

Eksempelet nedenfor viser hvordan du kan få tak i informasjon om bruker som blir logget på av viewer.js:

viewer.session({
	...
	onAuthenticated: (getUser) => {
		getUser() //if you need to get the user's id, invoke getUser.
			.then((user) => {
				alert(`You are logged in as ${user.id}!`); //do something with user.id
			});
	}        
});

Dersom du eksplisitt ønsker å logge en bruker inn via edoc-api, kan du kalle viewer.logIn(). Du vil motta eventet som vist ovenfor etter at pålogging er fullført.

viewer.logIn();

For å logge bruker ut fra edoc-api, kaller du viewer.logOut().

viewer.logOut()
    .then(() => {
        alert("Your session has ended.");
        window.location = "/";            
    });

getForms()

viewer.getForms() returnerer tilgjengelige skjema for kunden. Eksempelet nedenfor viser hvordan skjema kan hentes og listes ut på en HTML-side.

<!DOCTYPE html>
<html>
	<body>
		<div id="forms"></div>
		<script>
			document.addEventListener("DOMContentLoaded", () => {
				setLoaderVisibility(true);

				viewer.getForms()
					.then(forms => {
						const createFormLink = (form) => {
							var fragment = document.createDocumentFragment();
							const formLink = document.createElement("a");
							formLink.setAttribute("href", `/form?formId=${form.formId}`);
							formLink.text = `${form.name}`;

							fragment.appendChild(formLink);
							const br = document.createElement("br");
							fragment.appendChild(br);
							return fragment;
						}

						const formsElement = document.getElementById("forms");

						if(forms) {
							forms.forEach((form) => {
								formsElement.appendChild(createFormLink(form));
							});
						} else {
							formsElement.appendChild(document.createTextNode("No forms"));
						}
					});
			});
		</script>    
	</body>
</html>

getCases() og deleteCase()

viewer.getCases() returnerer mellomlagrede utkast for en utfyller. Eksempelet nedenfor viser hvordan utkast kan hentes og listes ut på en HTML-side. Eksempelet viser også hvordan utkastene kan slettes via viewer.deleteCase().

<!DOCTYPE html>
<html>
<body>
	<div id="content">
        <h2>Saved cases</h1>
        <div id="savedCases"></div>

        <h2>Submitted cases</h1>
        <div id="submittedCases"></div>
    </div>
    <script>
        document.addEventListener("DOMContentLoaded", () => {
            viewer.init(...);

            const renderCases = () => 
                viewer.getCases().then(cases => {
                    document.getElementById("content").style.display = "block";

                    const createCaseLink = (c, isSaved) => {
                        var fragment = document.createElement("div");
                        fragment.setAttribute("id", c.refId);

                        const caseLink = document.createElement("a");
                        if(isSaved) {
                            caseLink.setAttribute("href", `form.html?refId=${c.refId}`);
                        }
                        caseLink.text = `${c.name}`;
                        fragment.appendChild(caseLink);

                        const deleteLink = document.createElement("a");
                        deleteLink.setAttribute("href", "#");
                        deleteLink.text = " delete";
                        deleteLink.onclick = function(event) {
                            viewer.deleteCase(c.refId)
                            .then(() => {
                                document.getElementById(c.refId).remove();
                            }).catch((error) => {
                                alert(JSON.stringify(error));
                            });
                        };
                        fragment.appendChild(deleteLink);

                        const br = document.createElement("br");
                        fragment.appendChild(br);

                        return fragment;
                    }

                    const savedCasesElement = document.getElementById("savedCases");
                    savedCasesElement.innerHTML = "";

                    if(cases.saved) {
                        cases.saved.forEach(function(c) {
                            savedCasesElement.appendChild(createCaseLink(c, true));
                        });
                    } else {
                        savedCasesElement.appendChild(document.createTextNode("No saved cases"));
                    }

                    const submittedCasesElement = document.getElementById("submittedCases");
                    submittedCasesElement.innerHTML = "";

                    if(cases.submitted) {
                        cases.submitted.forEach( (c) => {
                            submittedCasesElement.appendChild(createCaseLink(c, false));
                        });
                    } else {
                        submittedCasesElement.appendChild(document.createTextNode("No submitted cases"));
                    }
                });

            renderCases();
        });
    </script>
</body>
</html>

getPdf()

PDF for innsendte saker kan lastes ned via viewer.getPdf(refId). PDF-en genereres on the fly av edoc-api. Edoc-api sjekker at innlogget bruker har rettighet på saken det blir forsøkt lastet ned PDF for

getPrivacy()

Dette er en metode for å hente personvernerklæringen fra api-et. Selve innholdet i erklæringen kan styres fra skjema.no Admin. Metoden tar ett parameter: Språkkode. Denne angir hvilken oversettelse av personvernerklæringen som blir lastet ned. metoden kan brukes slik:

const privacy = await viewer.getPrivacy("nb");

Responsen er en json med tre properties:

{
	"Privacy_Title": "Privacy",
    "Privacy_Ingress": "This privacy declaration ...",
    "Privacy_Body": "<h2 class=\"edoc__privacy__h2\">About the enterprise</h2>\r\n<p>The <strong>data controller</strong> is ....</p>"
}

Progresjonsvisning og feilhåndtering

Alle viewer metoder som gjør et kall til edoc-api returnerer et Promise-objekt. Fra det tidspunktet metoden blir kalt, og til operasjonen er fullført, kan det være lurt å vise en progresjons-indikator. Eksempelet nedenfor viser hvordan det kan gjøres.

<!DOCTYPE html>
<html>
	<body>
		<style>
			.loader {
				border: 16px solid #f3f3f3; /* Light grey */
				border-top: 16px solid #3498db; /* Blue */
				border-radius: 50%;
				width: 120px;
				height: 120px;
				animation: spin 2s linear infinite;
			}

			@keyframes spin {
				0% { transform: rotate(0deg); }
				100% { transform: rotate(360deg); }
			}
		</style>

		<div id="viewer"></div>
		<div id="loader" class="loader"></div>
		<script src="viewer.min.js"></script>

		<script>
			function setLoaderVisibility (isVisible) {
				const loader = document.getElementById("loader");

				if(loader) {
					loader.style.display = isVisible ? "block" : "none";
				}
			};

			document.addEventListener("DOMContentLoaded", () => {
				setLoaderVisibility(true);
				
				viewer.init(...)
					.form(...)
					.then(() => {
						setLoaderVisibility(false);
					}).catch((error) => {
						alert(error);
					}).finally(() => {
						setLoaderVisibility(false);
					});
			});
		</script>
	</body>
</html>