Innholdsblokker

Disse kommer i to versjoner:

  • Innholdsblokker som de ulike sidetypene kan bruke direkte. Disse har først og fremst en semantisk funksjon; de markerer hvilken funksjon innholdet i blokken har på siden.

  • Innholdsblokker som kun er støtteblokker for blokkene i forrige punkt, og som de ulike sidetypene ikke skal referere til direkte. Disse implementerer støtte for den ekstra funksjonaliteten vi ønsker at ArtikkelBlock skal ha, f.eks SVG-figurer, TeX-uttrykk og så videre. Alle andre blokktyper enn de nevnt i forrige punkt er av denne typen.

Blokktypene som er ment å kunne brukes utenfra ligger i modulen artikkel.blocks, og kan importeres rett fra den modulen. Se src/artikkel/blocks/__init__.py.

Støtteblokkene er ikke tilgjengelig via artikkel.blocks, men er tilgjengelig via relative importer. Se f.eks i src/artikkel/blocks/artikkel.py hvordan ArtikkelBlock importerer støtteblokkene via:

from .callout import CalloutBlock
from .comment import CommentBlock
from .index import IndexBlock
from .tex import TexBlock
from .tikz import TikzBlock
from .subpages import SubpagesBlock
from .svg import SvgBlock
from .shiny import ShinyBlock

ArtikkelBlock

Funksjon:

Brødtekst

Kode:

src/artikkel/blocks/artikkel.py

Template:

Ingen egen template (inkluderes i Artikkel via include_block)

Denne innholdsblokken brukes i hoveddelen (brødteksten) av en Artikkel.

Består av kun én blokktype, som gjentas en gang for hvert avsnitt på siden:

Dette er gjort for å kunne rendre hvert enkelt avsnitt inne i sitt eget <section>-element slik at vi har muligheten til å lage kollapsbare avsnitt i mobilversjonen, slik som f.eks Wikipedia har («trykk på h2-overskriften, så skjules avsnittet»). For å kunne få til dette må vi både ha et wrapper-element rundt alle blokkene som hører til samme avsnitt, og vi må ha kontroll på hvordan både <h2>-elementet og wrapper-elementet rendres.

En annen årsak er at vi ikke har kontroll over hvordan overskrifter inne i en RichTextBlock rendres, og at de pr. Wagtail 2.4 rendres uten id-attributt. Dette gjør det vanskelig å på et senere tidspunkt lage en blokktype som genererer innholdsfortegnelse på siden (liste over <a href="#id">...</a> uten å innføre en egen innholdsblokk da. Hvis publiseringssystemet da er fylt med mye innhold, vil det være veldig mye arbeid forbundet med å flytte overskriftene fra RichTextBlock til egne innholdsblokker. Denne innholdsblokken er altså opprettet for å være føre var, og ikke fordi vi på nåværende tidspunkt trenger å spesialbehandle overskrifter.

ArtikkelSectionBlock

Funksjon:

Avsnitt

Kode:

src/artikkel/blocks/artikkel.py

Template:

src/artikkel/templates/artikkel/artikkel_section_block.html

Denne innholdsblokken representerer et avsnitt, og består av en overskrift og en eller flere andre innholdsblokker av disse to hovedtypene:

Wagtails innebygde blokker:

  • Rik tekst (RichTextBlock)

  • Vedlegg (DocumentBlock)

Våre egendefinerte blokker (unntatt LeadBlock):

CalloutBlock

Funksjon:

Infoboks

Kode:

src/artikkel/blocks/callout.py

Template:

src/artikkel/templates/artikkel/callout_block.html

Infoboksen består av en overskrift + brødtekst, og kan styles i flere varianter:

  • Definition

  • Theorem

  • Proof

  • Information

  • Question

  • Warning

Forskjellen mellom de ulike bokstypene er fargen, om boksen i utgangspunktet er kollapset (brødteksten vises først når man klikker på overskriften), og om det legges til tekst foran tittelen.

For å oppfordre til riktig bruk av denne blokktypen, kan brødteksten kun inneholde:

  • En begrenset variant av RichTextBlock (vanlig tekst, uthevet tekst, nummererte og unummererte lister og lenker til interne/eksterne sider eller dokumenter).

  • TeX-kode (TexBlock).

  • Tikz-figurer (TikzBlock).

  • Forhåndsdefinert tekst (PredefinedTextBlock).

Mulighet for H2/H3/H4-overskrifter, video, bilder og kursiv tekst er altså fjernet, se bruken av RichTextBlock(features=[...]) i callout.py.

CodeBlock

Funksjon:

Listing av programkode

Kode:

src/artikkel/blocks/code.py

Template:

src/artikkel/templates/artikkel/code_block.html

Blokk for kodelistinger, med syntax highlighting og knapp for å kopiere kodeblokken til utklippstavlen.

Følgende språk støttes:

  • Julia

  • MATLAB

  • Octave

  • Python

  • R

Wagtail-admingrensesnittet er modifisert for å gi monospaced font også i redigeringsgrensesnittet for denne blokken, se Ekstra CSS.

CommentBlock

Funksjon:

Kommentar

Kode:

src/artikkel/blocks/comment.py

Template:

src/artikkel/templates/artikkel/comment_block.html

Gjør det mulig å legge inn en kommentar som kun vises i redigeringsmodus, og ikke rendres på siden.

IndexBlock

Funksjon:

Vise innholdsfortegnelse

Kode:

src/artikkel/blocks/index.py

Template:

src/artikkel/templates/artikkel/index_block.html src/artikkel/templates/artikkel/index_video_block.html (videooversikten) src/artikkel/templates/artikkel/index_other_block.html (beviser/eksempler/regneregler)

Denne innholdsblokken viser en innholdsfortegnelse over alle ressurser av en bestemt type som finnes i hierarkiet under den artikkelen man velger å vise innholdsfortegnelsen for.

Den kan brukes til å liste opp alle:

  • artikler

  • beviser

  • eksempler

  • regneregler

  • videoer

enten for hvert kapittel (for en valgt side på nivå 1) eller for nettstedet som helhet (hvis man velger startsiden).

Blokken prøver å være smart: En innholdsfortegnelse for et enkeltavsnitt skrives ut uten overskrift, mens en innholdsfortegnelse for hele nettstedet vises gruppert etter kapittel.

Formatteringen kan variere fra ressurstype til ressurstype, avhengig av om det kun listes opp lenker til andre artikler, eller om det også lenkes til videoer og nedlastbare PDF-filer:

Artiklene må være satt til riktig sidetype og sidetypen må være markert som eksempel/bevis/regneregel (se Page Type) for å bli listet opp på riktig sted.

Opplisting

Innhold

Artikler

(buggy!)

  • Liste med lenker til artikkel-undersidene i kapittelet (alt som ikke er bevis/eksempel)

  • Inkluderer per i dag innholdsfortegnelse- undersidene (det er ikke meningen)

Beviser

  • Liste med lenker til bevis-undersidene i kapittelet

Eksempler

  • Liste med lenker til eksempel-undersidene

  • Liste over relevante oppgaver i boka hvis oppgaven har videoløsning

Regneregler

  • Liste med lenker til regneregel-artiklene i kapittelet

Videoer

  • Introvideo for kapittelet

  • Liste over temavideoer i kapittelet

  • Liste over relevante oppgaver i boka hvis oppgaven har videoløsning

  • Videoløsning for eksamensoppgavene som er lenket opp fra kapittelet

Opplisting av hele eksamenssett støttes ikke av denne blokken.

JSXGraphBlock

Funksjon:

Embedding av JSXGraph-applikasjoner.

Kode:

src/artikkel/blocks/jsxgraph.py

Template:

src/artikkel/templates/artikkel/jsxgraph_block.html

En JSXGraph-boks består av feltene:

  • Figurtekst (caption)

  • Javascript-kode (applikasjonen selv)

  • Bredde og høyde (minimum 200x200, maksimum 800x600)

For å unngå kollisjon mellom variabelnavn på tvers av grafer (hvis det finnes to eller flere grafer på en og samme side), inkluderes javascript-koden i en closure/anonym funksjon. Denne funksjonen kalles umiddelbart etter at den er definert, og får to parametre:

  • board_id: HTML element-ID til canvasen JSXGraph rendrer applikasjonen i.

  • html_id: HTML element-ID til et lite område utenfor canvasen der applikasjonen kan tegne opp inputfelter eller annen output. Feltet er plassert under canvasen, mellom canvas og figurtekst.

Disse er tilgjengelige som forhåndsdefinerte variabler i JSXGraph-koden. board_id brukes typisk som argument til initBoard() ved initialisering av JSXGraph:

var board = JXG.JSXGraph.initBoard(board_id, { ... });

html_id brukes kun hvis applikasjonen har behov for å tegne opp input/output-felter utenfor selve JSXGraph-canvasen. Disse kan da tegnes opp ved å fylle elementet med ID html_id med ønsket HTML-kode.

document.getElementById(html_id).innerHTML += '...';

Eksempelet «Adding events» viser hvordan applikasjonen kan generere output. I dette eksempelet brukes hardkodet element-ID myOutput, her bør javascript-koden referere til variabelen html_id i stedet for å bruke tekststrengen 'myOutput'.

Eksempelet «Change Equation of a Graph» viser interaksjon mellom inputfelter og JSXGraph-applikasjonen. Siden Wagtail kjører JSXGraph-applikasjonen i sin egen closure, vil i utgangspunktet ikke callback-funksjonen doIt() som defineres i applikasjonen være tilgjengelig fra andre steder på nettsiden, og det vil ikke fungere å referere til den i <input>-elementene.

For å gjøre callback-funksjonen tilgjengelig i globalt skop må den i stedet defineres som en attributt på window-objektet:

// Ikke slik:
function doIt() {
    [...]
}

// Men slik:
window.doIt = function() {
    [...]
}

Ideelt sett bør heller ikke inpufeltenes element-ID hardkodes, men genereres ut fra html_id:

// Ikke slik:

document.getElementById(html_id).innerHTML += '<input type="text" id="eingabe" value="Math.sin(x)*Math.cos(x)">';
eval("function f(x){ return "+document.getElementById("eingabe").value+";}");

// Men slik:

input_id = html_id + '_input'

document.getElementById(html_id).innerHTML += '<input type="text" id="' + input_id + '" value="Math.sin(x)*Math.cos(x)">';
eval("function f(x){ return "+document.getElementById(input_id).value+";}");

og tilsvarende i callback-funksjonen og andre steder der getElementById() brukes. Da er man sikret mot navnekollisjoner hvis man har flere grafer på hver side.

I motsetning til andre figurtyper blir JSXGraph ikke vist i full bredde uten marg på små enheter. Hvis panorering er enablet i figuren, og figuren dekker hele den lille mobilskjermen, mister brukeren muligheten til å scrolle opp og ned på nettsiden, og blir stuck inne i figuren. Figuren må derfor ha en smal venstremarg slik at man kan nå tak i sidebakgrunnen for å scrolle forbi figuren. Av samme grunn er også høyden på figuren begrenset oppad til 600px, for å unngå at den dekker hele det synlige området på skjermen.

LeadBlock

Funksjon:

Ingress

Kode:

src/artikkel/blocks/artikkel.py

Template:

Ingen egen template (inkluderes i Artikkel via include_block)

Egen innholdsblokk for ingressen i en Artikkel. Består av:

  • Rik tekst (RichTextBlock)

Innholdet er begrenset til kun uthevet tekst, punktlister og lenker. Det er kun mulig å ha én RichTextBlock inne i en LeadBlock.

PictureBlock

Funksjon:

PNG-figurer og JPEG-bilder

Kode:

src/artikkel/blocks/picture.py

Template:

src/artikkel/templates/artikkel/picture_block.html

Blokk for bilde + påkrevd bildetekst.

PredefinedTextBlock

Funksjon:

Sette inn en blokk med forhåndsdefinert tekst

Kode:

src/artikkel/blocks/predefined_text.py

Template:

src/artikkel/templates/artikkel/predefined_text_block.html

Setter inn en forhåndsdefinert tekstblokk.

Forhåndsdefinerte tekstblokker må legges inn som Predefined Text-snippets.

ShinyBlock

Funksjon:

Embedding av Shiny-applikasjoner

Kode:

src/artikkel/blocks/shiny.py

Template:

src/artikkel/templates/artikkel/shiny_block.html

Applikasjonens URL + figurtekst må oppgis.

Applikasjonen blir embeddet i en <iframe>, og blokken forsøker å resize iframen automatisk slik at hele applikasjonen vises. For at dette skal fungere må Shiny-applikasjonen skrives på en bestemt måte. Se https://www.cultureofinsight.com/blog/2018/03/15/2018-03-15-responsive-iframes-for-shiny-apps/ for detaljert forklaring på hvordan resizingen fungerer. Kortversjonen er at ui-variabelen må inkludere et script helt først, og en HTML-tag til slutt:

ui <- fluidPage(
  tags$head(
    tags$script(src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/3.6.2/iframeResizer.contentWindow.min.js",
                type="text/javascript")
    ),

  # Resten av ui-elementene plasseres her ...

  HTML('<div data-iframe-height></div>')
)

I tillegg må også siden som inneholder iframen inkludere et script. Dette gjøres via base.html. (Scriptet inkluderes på alle sider, ikke bare de som embedder Shiny-applikasjoner.)

SubpagesBlock

Funksjon:

Vise artikkelens undersider

Kode:

src/artikkel/blocks/subpages.py

Template:

src/artikkel/templates/artikkel/subpages_block.html

Denne innholdsblokken lager en liste over artikkelens undersider. Kun de direkte undersidene vises, og ikke alle undersider rekursivt.

Det er også mulig å velge å vise undersidene til en annen artikkel.

Blokken skriver ut listen uten noen form for overskrift.

SvgBlock

Funksjon:

SVG-figurer

Kode:

src/artikkel/blocks/svg.py

Template:

src/artikkel/templates/artikkel/svg_block.html

Denne innholdsblokken implementerer støtte for SVG-figurer.

Wagtails bildemodell støtter kun PNG/JPG, så vi henter figuren fra et opplastet dokument.

Støtte for å endre størrelsen på figuren mangler.

TexBlock

Funksjon:

Støtte for «display mode» TeX

Kode:

src/artikkel/blocks/tex.py

Template:

src/artikkel/templates/artikkel/tex_block.html

Det er mulig å skrive matematikk inne i en RichTextBlock (både inline ved å bruke \( ... \), og i display mode ved å bruke \[ ... ])), men diplay mode-matematikk som skrives inn over flere linjer fungerer ikke så godt, siden RichTextBlock tolker hardt linjeskift som nytt avsnitt, og rendrer:

\[
    ...
\]

som:

<p>\[</p>
<p>...</p>
<p>\]</p>

som gjør at uttrykket ignoreres av Mathjax, siden det ikke forekommer i en og samme <p>.

En TexBlock er bare et flerlinjes inputfelt som rendres inne i et og samme avsnitt.

Blokken lar deg velge mellom vanlig display mode eller et align-environment. Bruk da & som kolonneseparator, som ellers i TeX. Eksempel:

a =& ~ \sin^2(x) + \cos^2(x) \\
  =& ~ 1

TikzBlock

Funksjon:

Inline Tikz-figurer

Kode:

src/artikkel/blocks/tikz.py

Template:

src/artikkel/templates/artikkel/tikz_block.html

Denne innholdsblokken lar deg skrive inn Tikz-kode direkte og få generert en SVG- eller PNG-figur on-the-fly.

Det er mulig å velge hvilken LaTeX-kompilator som skal brukes (pdflatex eller lualatex). For lualatex finnes det også en variant som kompilerer til PNG.

Det er anbefalt å bruke SVG slik at figuren blir skalerbar og ser bra ut på høyoppløste skjermer, men hvis figuren er veldig komplisert kan den resultere i en veldig stor SVG-fil som medfører at siden lastes tregt. I så fall kan PNG-kompilatoren brukes for å redusere figurstørrelsen. Dette er mest aktuelt når tikz-figuren inneholder veldig mange objekter (ekstremt finmasket grid, etc.).

PNG-figurene er ikke skalerbare, men PNG-kompilatoren forsøker å bøte på dette ved å kompilere figurene i dobbel oppløsning (@2x) og skalere dem ned til 50% ved visning, slik at figurene ikke ser altfor ille ut på høyoppløste skjermer.

Bildefilen caches via Djangos cache framework.

For å legge til nye kompilatorer må det defineres en ny subklasse av TikzCompiler, og klassen må dekoreres med @TikzCompiler.register(). For et hypotetisk eksempel acmetex:

@TikzCompiler.register('acmetex')
class TikzCompilerAcmetex(TikzCompiler):
    def compile(self, preamble, code):
        ...

I tillegg må kompilatoren gjøres tilgjengelig i nedtrekksmenyen i redigeringsgrensesnittet. Dette gjøres ved å utvide TikzBlock.compiler.

class TikzBlock(StructBlock):
    [...]
    compiler = ChoiceBlock(default='lualatex', choices=[
        ('lualatex', 'lualatex to SVG'),
        ('pdflatex', 'pdflatex to SVG'),
        ('acmetex', 'acmetex to SVG'),
    ])