first commit

This commit is contained in:
Christian Lawson-Perfect 2025-03-21 15:03:42 +00:00
commit fc7f3d13b3
11 changed files with 868 additions and 0 deletions

0
.make.lock Normal file
View file

Binary file not shown.

View file

@ -0,0 +1,7 @@
@font-face {
font-family: 'Atkinson Hyperlegible';
font-style: normal;
font-display: swap;
font-weight: 200 800;
src: url(AtkinsonHyperlegibleNextVF-Variable.woff2) format('woff2-variations');
}

73
chirun-logo.svg Normal file
View file

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="233.53189mm"
height="83.500763mm"
viewBox="0 0 233.53189 83.500763"
version="1.1"
id="svg1"
xml:space="preserve"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
sodipodi:docname="chirun-logo.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="0.86278062"
inkscape:cx="451.44732"
inkscape:cy="199.35543"
inkscape:window-width="1862"
inkscape:window-height="1016"
inkscape:window-x="58"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" /><defs
id="defs1"><filter
style="color-interpolation-filters:sRGB"
inkscape:label="Drop Shadow"
id="filter19"
x="-0.010520231"
y="-0.030729536"
width="1.0236705"
height="1.0691415"><feFlood
result="flood"
in="SourceGraphic"
flood-opacity="0.498039"
flood-color="rgb(0,0,0)"
id="feFlood18" /><feGaussianBlur
result="blur"
in="SourceGraphic"
stdDeviation="1.000000"
id="feGaussianBlur18" /><feOffset
result="offset"
in="blur"
dx="0.600000"
dy="0.600000"
id="feOffset18" /><feComposite
result="comp1"
operator="in"
in="flood"
in2="offset"
id="feComposite18" /><feComposite
result="comp2"
operator="over"
in="SourceGraphic"
in2="comp1"
id="feComposite19" /></filter></defs><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-6.160854,-70.07281)"><path
style="fill:#324d5d;fill-opacity:1;filter:url(#filter19)"
d="m 140.54894,150.50976 c -2.97113,-0.14986 -5.14707,-0.83748 -6.64876,-2.10107 -1.27883,-1.07606 -2.3977,-3.46549 -3.11082,-6.64334 -0.37174,-1.6566 -0.37306,-1.72738 -0.44026,-23.63258 l -0.0674,-21.970995 h 5.59929 5.59929 l 0.0184,17.737665 c 0.0101,9.75572 0.0675,19.37597 0.12759,21.37833 0.10345,3.44808 0.1325,3.69036 0.54918,4.57994 0.40248,0.85925 0.53025,0.97979 1.49965,1.41483 1.69282,0.75969 3.52431,0.99721 6.94921,0.90122 3.43404,-0.0962 4.83591,-0.39282 7.05873,-1.49329 2.44921,-1.21255 4.5328,-3.52487 5.35851,-5.94676 0.36115,-1.0593 0.36322,-1.15811 0.4151,-19.81827 l 0.0521,-18.753665 h 5.58043 5.58043 v 26.587715 26.58771 l -5.37633,-0.0447 -5.37634,-0.0447 -0.0474,-2.159 c -0.0261,-1.18745 -0.1171,-2.159 -0.20231,-2.159 -0.0852,0 -1.32118,0.59698 -2.74661,1.32662 -3.49287,1.78792 -7.85599,3.1977 -10.80435,3.49103 -0.60537,0.0602 -1.97697,0.25109 -3.048,0.42413 -2.51592,0.4065 -3.82199,0.47425 -6.51934,0.33821 z m -80.348661,-0.77094 c -5.219705,-0.57687 -8.558685,-2.14828 -10.7581,-5.06305 -0.816987,-1.08271 -2.759911,-4.87184 -3.646771,-7.112 -1.513304,-3.82252 -4.012526,-11.41046 -5.491433,-16.67264 -0.794788,-2.82797 -0.237975,-3.08544 -5.188416,2.39909 -2.378393,2.63499 -6.484171,7.11499 -9.12395,9.95555 -2.63978,2.84057 -6.526871,7.06967 -8.637981,9.398 -4.382963,4.83395 -5.114586,5.5478 -5.977929,5.83273 -1.14658,0.37841 -2.4620117,-0.43014 -2.7370437,-1.68235 -0.264767,-1.20548 -0.863252,-0.50343 17.5822197,-20.62466 6.441639,-7.02685 11.763323,-12.86401 11.825964,-12.97145 0.142698,-0.24476 -0.839791,-4.10775 -2.308733,-9.07759 C 30.69123,87.045485 26.042053,77.623105 22.319213,76.924695 c -2.207571,-0.41414 -4.139579,0.9825 -5.657144,4.08951 -0.470884,0.96408 -0.96318,1.84169 -1.093991,1.95025 -0.349833,0.29034 -2.247218,0.39569 -3.077918,0.1709 -0.435649,-0.11789 -0.829398,-0.36165 -0.996752,-0.61707 -0.261258,-0.39873 -0.25054,-0.5024 0.192855,-1.86545 0.617247,-1.8975 1.405175,-3.07389 3.183879,-4.75358 2.746974,-2.59406 4.377253,-3.2919 7.960838,-3.40763 3.938494,-0.12719 6.733468,0.38371 9.513966,1.73909 2.957927,1.44187 4.284135,2.93025 6.339219,7.1144 2.294877,4.67236 5.243636,12.87286 6.880497,19.134665 0.438219,1.6764 0.820483,3.07583 0.849476,3.10985 0.198331,0.23267 2.722511,-2.44221 12.602141,-13.354515 12.194187,-13.46879 14.76312,-16.15553 15.692501,-16.41215 1.302067,-0.35951 2.472634,0.26746 2.693064,1.44245 0.176194,0.9392 -0.425474,1.95671 -2.593736,4.38637 -3.249308,3.64103 -11.170061,12.3794 -17.655829,19.47834 -9.258041,10.133315 -9.144,10.004555 -9.144,10.324125 0,0.2877 1.462878,5.69954 2.311564,8.55152 3.807534,12.79509 8.216712,22.87348 11.399162,26.05593 0.445058,0.44506 1.07798,0.93675 1.406493,1.09264 2.021468,0.95925 4.758511,-0.63259 6.142706,-3.57254 0.338892,-0.71978 0.733564,-1.55322 0.87705,-1.85209 0.217561,-0.45316 0.384454,-0.56193 1.005018,-0.65499 0.409274,-0.0614 1.210389,-0.0779 1.780257,-0.0366 1.381284,0.0999 1.742477,0.49943 1.610316,1.78119 -0.303686,2.94526 -4.390079,7.23924 -8.131681,8.54476 -0.837621,0.29226 -1.496499,0.37186 -3.330218,0.40232 -1.2573,0.0209 -2.5527,0.008 -2.878667,-0.0275 z M 89.494946,122.40844 V 95.484445 h 5.077092 5.077093 l 0.04524,4.21033 0.04524,4.210325 2.031999,-1.85312 c 5.08248,-4.635055 10.04016,-6.867165 15.95967,-7.185555 l 2.07433,-0.11158 v 4.9368 4.936805 l -0.80433,6.8e-4 c -2.36744,0.002 -6.4377,1.10667 -8.8878,2.41214 -4.72326,2.51665 -7.89492,6.44802 -9.22741,11.43765 l -0.4389,1.64352 -0.0588,13.716 c -0.0324,7.5438 -0.10178,14.11605 -0.1543,14.605 l -0.0955,0.889 h -5.321809 -5.321815 z m 102.785334,0 V 95.484445 h 5.16466 c 2.84057,0 5.17634,0.019 5.19059,0.0423 0.0143,0.0233 0.0714,1.50556 0.127,3.29395 l 0.10108,3.251615 1.43933,-1.19973 c 2.79223,-2.327425 5.51838,-3.904915 8.41009,-4.866515 2.16708,-0.72064 3.71898,-0.98765 6.49125,-1.11683 7.91923,-0.36902 13.25514,2.50724 15.74446,8.486885 1.42732,3.42856 1.51672,4.95746 1.64519,28.13396 l 0.0988,17.82233 h -5.61155 -5.61155 l -0.014,-15.79033 c -0.008,-8.68469 -0.0653,-17.43528 -0.12799,-19.44577 l -0.11396,-3.65544 -0.71827,-1.44953 c -1.72576,-3.48272 -4.89716,-4.96996 -10.32961,-4.8441 -2.48332,0.0575 -2.50395,0.0613 -3.82309,0.69113 -2.94334,1.4054 -5.28231,4.78603 -6.11837,8.84316 -0.79097,3.83838 -0.84396,5.23446 -0.79243,20.87655 l 0.0487,14.77433 h -5.60013 -5.60012 z"
id="path3" /></g></svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
chirun.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 KiB

BIN
clp-2023-blurred.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

BIN
clp-2023.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 KiB

139
index.html Normal file
View file

@ -0,0 +1,139 @@
<!doctype html>
<html lang="en">
<head>
<title>Accessibility of teaching and assessment material in maths, stats and physics</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css" id="theme">
<script type="module" src="script.js"></script>
</head>
<body>
<header>
<h1>Accessibility of teaching and assessment material in maths, stats and physics</h1>
<p>
Christian Lawson-Perfect
<br>
Digital Learning Unit, School of Mathematics, Statistics and Physics
</p>
<img alt="Christian Lawson-Perfect" src="clp-2023-blurred.jpg" class="portrait">
</header>
<main>
<section class="plain" style="--col: 1">
<p>
Read this poster online:
<a class="qr" href="."></a>
</p>
</section>
<section style="--col: 2 / span 2; " id="context">
<h1>Context</h1>
<p>Maths, Stats and Physics has around 900 undergraduate students and around 100 taught modules.</p>
<p>In MSP, over 13% of students have an SSP, compared to 6% in Engineering and 7% in Computing. Many students without SSPs would benefit from accessibility improvements.</p>
<p><strong>Maths is different:</strong> typesetting mathematical notation is hard, and typesetting maths in accessible formats is even harder.</p>
<p>Lecturers typically prepare material in LaTeX or write by hand in lectures.</p>
</section>
<section style="--col: span 2; " id="chirun">
<h1><a href="https://chirun.org.uk" target="_blank"><img src="chirun-logo.svg" alt="Chirun" style="height: 1.5em"></a></h1>
<p>Chirun is a tool to produce accessible course material from LaTeX or Markdown source, developed here.</p>
<figure>
<img src="chirun.png" alt="Chirun">
<figcaption><a class="qr" href="https://chirun.org.uk/demo">chirun.org.uk/demo</a></figcaption>
</figure>
</section>
<section style="--col: span 2; " id="the_beginning">
<h1>The beginning</h1>
<p>We introduced Chirun in 2017 to support an incoming student with long list of accessibility requirements.</p>
<p>To speed things up, we paid students to type up existing handwritten notes in LaTeX.</p>
<p><strong>Aim:</strong> improve accessibility for all teaching, not just this student. Provide a consistent level of accessibility that enables almost all students to access their material without adjustments.</p>
</section>
<section style="--col: span 2;align-self: end;" data-cols="2" id="the_carrot">
<h1>🥕 The carrot</h1>
<p>I talked at the school's all-staff meetings about how students struggle with existing material and how to use our tools to produce accessible content.</p>
<p>We offered support to anyone who wanted it: we'd take their material and make it accessible.</p>
</section>
<section style="--col: span 6;background: none;border: none;margin: -2em 0;" class="print-only">
<svg class="squiggle" viewBox="-2 -7 545 19">
<path d="M 130 10 c 0 -5 5 -5 5 -5 l 130 0 c 5 0 5 -5 5 -5 l 0 -5 l 0 5 c 0 5 5 5 5 5 l 130 0 c 5 0 5 5 5 5"></path>
</svg>
</section>
<section style="--col: span 3;align-self: normal;" id="some_lecturers_take">
<h1>😇 <small>(some)</small> Lecturers take accessibility very seriously</h1>
<p>Many lecturers responded positively and gave us material to run through Chirun.</p>
<p>A handful of lecturers understood the brief and produced accessible material on their own. Thanks!</p>
<p>Some used their own tools, such as Bookdown.</p>
<p>After a year, some modules had <strong>all</strong> material available in accessible formats.</p>
</section>
<section style="--col: span 3" id="some_lecturers_don">
<h1>😠 <small>(some)</small> Lecturers <em>don't</em> take accessibility seriously</h1>
<p>After two years, take-up was very low: less than 25% of modules were acceptable.</p>
<p>Common complaints:</p>
<dl class="quotes">
<dt>Why should I do all that for one student?</dt>
<dd>Every student deserves to learn!</dd>
<dt>Is this student even any good?</dt>
<dd>Doesn't matter!</dd>
<dt>I'm overworked and don't have time to do this.</dt>
<dd>So let us help!</dd>
<dt>I don't know what to do.</dt>
<dd>Let us show you!</dd>
</dl>
</section>
<section style="--col: span 6;background: none;border: none;margin: -2em 0;" class="print-only">
<svg class="squiggle" width="100%" viewBox="-2 -2 545 19">
<path d="M 130 0 c 0 5 5 5 5 5 l 130 0 c 5 0 5 5 5 5 l 0 5 l 0 -5 c 0 -5 5 -5 5 -5 l 130 0 c 5 0 5 -5 5 -5"></path>
</svg>
</section>
<section style="--col: 3 / span 2;align-self: start;" id="the_stick">
<h1>🧹 The stick</h1>
<p>Using my Canvas admin role, I audited every module twice a semester.</p>
<p>I passed findings on to the director of education and directors of discipline, who talked directly to lecturers.</p>
<p>I emailed individual lecturers offering to take the job off their hands if they'd send me their material.</p>
</section>
<section style="--col: span 2" id="this_mainly_worked">
<h1>✔️ This mainly worked!</h1>
<p>Now, <strong>more than two thirds</strong> of modules have all material available in accessible formats.</p>
<p>Many physicists use PowerPoint and I can only offer them advice. 🤷🏻</p>
<p>We've moved on to looking at other aspects of accessibility: in-person delivery, communication, lecture recordings, …</p>
</section>
<section style="--col: span 3" id="future_work">
<h1>What you can do</h1>
<ul>
<li>
<p>Use Chirun to make your material accessible: it's available as an external tool in Canvas.
<a class="qr" href="https://chirun.org.uk">chirun.org.uk</a>
</p>
</li>
<li>
<p>Read our guidance on accessible teaching: <a class="qr" href="https://www.mas.ncl.ac.uk/accessible-teaching/">www.mas.ncl.ac.uk/accessible-teaching</a></p>
</li>
</ul>
</section>
<section style="--col: span 3;align-self: end;" id="thanks">
<h1>Talk to us</h1>
<dl>
<dt>Website</dt>
<dd><a class="qr" href="https://www.ncl.ac.uk/maths-physics/engagement/digital-learning/">ncl.ac.uk/maths-physics/engagement/digital-learning</a></dd>
<dt>Email</dt>
<dd><a href="mailto:msp.digital.learning@ncl.ac.uk">msp.digital.learning@ncl.ac.uk</a></dd>
</dl>
</section>
</main>
</body>
</html>

392
qrcode.js Normal file
View file

@ -0,0 +1,392 @@
/**
* @fileoverview
* - Using the 'QRCode for Javascript library'
* - Fixed dataset of 'QRCode for Javascript library' for support full-spec.
* - this library has no dependencies.
*
* @author davidshimjs
* @see <a href="http://www.d-project.com/" target="_blank">http://www.d-project.com/</a>
* @see <a href="http://jeromeetienne.github.com/jquery-qrcode/" target="_blank">http://jeromeetienne.github.com/jquery-qrcode/</a>
*/
var QRCode;
(function () {
//---------------------------------------------------------------------
// QRCode for JavaScript
//
// Copyright (c) 2009 Kazuhiko Arase
//
// URL: http://www.d-project.com/
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license.php
//
// The word "QR Code" is registered trademark of
// DENSO WAVE INCORPORATED
// http://www.denso-wave.com/qrcode/faqpatent-e.html
//
//---------------------------------------------------------------------
function QR8bitByte(data) {
this.mode = QRMode.MODE_8BIT_BYTE;
this.data = data;
this.parsedData = [];
// Added to support UTF-8 Characters
for (var i = 0, l = this.data.length; i < l; i++) {
var byteArray = [];
var code = this.data.charCodeAt(i);
if (code > 0x10000) {
byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18);
byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12);
byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6);
byteArray[3] = 0x80 | (code & 0x3F);
} else if (code > 0x800) {
byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12);
byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6);
byteArray[2] = 0x80 | (code & 0x3F);
} else if (code > 0x80) {
byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6);
byteArray[1] = 0x80 | (code & 0x3F);
} else {
byteArray[0] = code;
}
this.parsedData.push(byteArray);
}
this.parsedData = Array.prototype.concat.apply([], this.parsedData);
if (this.parsedData.length != this.data.length) {
this.parsedData.unshift(191);
this.parsedData.unshift(187);
this.parsedData.unshift(239);
}
}
QR8bitByte.prototype = {
getLength: function (buffer) {
return this.parsedData.length;
},
write: function (buffer) {
for (var i = 0, l = this.parsedData.length; i < l; i++) {
buffer.put(this.parsedData[i], 8);
}
}
};
function QRCodeModel(typeNumber, errorCorrectLevel) {
this.typeNumber = typeNumber;
this.errorCorrectLevel = errorCorrectLevel;
this.modules = null;
this.moduleCount = 0;
this.dataCache = null;
this.dataList = [];
}
QRCodeModel.prototype={addData:function(data){var newData=new QR8bitByte(data);this.dataList.push(newData);this.dataCache=null;},isDark:function(row,col){if(row<0||this.moduleCount<=row||col<0||this.moduleCount<=col){throw new Error(row+","+col);}
return this.modules[row][col];},getModuleCount:function(){return this.moduleCount;},make:function(){this.makeImpl(false,this.getBestMaskPattern());},makeImpl:function(test,maskPattern){this.moduleCount=this.typeNumber*4+17;this.modules=new Array(this.moduleCount);for(var row=0;row<this.moduleCount;row++){this.modules[row]=new Array(this.moduleCount);for(var col=0;col<this.moduleCount;col++){this.modules[row][col]=null;}}
this.setupPositionProbePattern(0,0);this.setupPositionProbePattern(this.moduleCount-7,0);this.setupPositionProbePattern(0,this.moduleCount-7);this.setupPositionAdjustPattern();this.setupTimingPattern();this.setupTypeInfo(test,maskPattern);if(this.typeNumber>=7){this.setupTypeNumber(test);}
if(this.dataCache==null){this.dataCache=QRCodeModel.createData(this.typeNumber,this.errorCorrectLevel,this.dataList);}
this.mapData(this.dataCache,maskPattern);},setupPositionProbePattern:function(row,col){for(var r=-1;r<=7;r++){if(row+r<=-1||this.moduleCount<=row+r)continue;for(var c=-1;c<=7;c++){if(col+c<=-1||this.moduleCount<=col+c)continue;if((0<=r&&r<=6&&(c==0||c==6))||(0<=c&&c<=6&&(r==0||r==6))||(2<=r&&r<=4&&2<=c&&c<=4)){this.modules[row+r][col+c]=true;}else{this.modules[row+r][col+c]=false;}}}},getBestMaskPattern:function(){var minLostPoint=0;var pattern=0;for(var i=0;i<8;i++){this.makeImpl(true,i);var lostPoint=QRUtil.getLostPoint(this);if(i==0||minLostPoint>lostPoint){minLostPoint=lostPoint;pattern=i;}}
return pattern;},createMovieClip:function(target_mc,instance_name,depth){var qr_mc=target_mc.createEmptyMovieClip(instance_name,depth);var cs=1;this.make();for(var row=0;row<this.modules.length;row++){var y=row*cs;for(var col=0;col<this.modules[row].length;col++){var x=col*cs;var dark=this.modules[row][col];if(dark){qr_mc.beginFill(0,100);qr_mc.moveTo(x,y);qr_mc.lineTo(x+cs,y);qr_mc.lineTo(x+cs,y+cs);qr_mc.lineTo(x,y+cs);qr_mc.endFill();}}}
return qr_mc;},setupTimingPattern:function(){for(var r=8;r<this.moduleCount-8;r++){if(this.modules[r][6]!=null){continue;}
this.modules[r][6]=(r%2==0);}
for(var c=8;c<this.moduleCount-8;c++){if(this.modules[6][c]!=null){continue;}
this.modules[6][c]=(c%2==0);}},setupPositionAdjustPattern:function(){var pos=QRUtil.getPatternPosition(this.typeNumber);for(var i=0;i<pos.length;i++){for(var j=0;j<pos.length;j++){var row=pos[i];var col=pos[j];if(this.modules[row][col]!=null){continue;}
for(var r=-2;r<=2;r++){for(var c=-2;c<=2;c++){if(r==-2||r==2||c==-2||c==2||(r==0&&c==0)){this.modules[row+r][col+c]=true;}else{this.modules[row+r][col+c]=false;}}}}}},setupTypeNumber:function(test){var bits=QRUtil.getBCHTypeNumber(this.typeNumber);for(var i=0;i<18;i++){var mod=(!test&&((bits>>i)&1)==1);this.modules[Math.floor(i/3)][i%3+this.moduleCount-8-3]=mod;}
for(var i=0;i<18;i++){var mod=(!test&&((bits>>i)&1)==1);this.modules[i%3+this.moduleCount-8-3][Math.floor(i/3)]=mod;}},setupTypeInfo:function(test,maskPattern){var data=(this.errorCorrectLevel<<3)|maskPattern;var bits=QRUtil.getBCHTypeInfo(data);for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<6){this.modules[i][8]=mod;}else if(i<8){this.modules[i+1][8]=mod;}else{this.modules[this.moduleCount-15+i][8]=mod;}}
for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<8){this.modules[8][this.moduleCount-i-1]=mod;}else if(i<9){this.modules[8][15-i-1+1]=mod;}else{this.modules[8][15-i-1]=mod;}}
this.modules[this.moduleCount-8][8]=(!test);},mapData:function(data,maskPattern){var inc=-1;var row=this.moduleCount-1;var bitIndex=7;var byteIndex=0;for(var col=this.moduleCount-1;col>0;col-=2){if(col==6)col--;while(true){for(var c=0;c<2;c++){if(this.modules[row][col-c]==null){var dark=false;if(byteIndex<data.length){dark=(((data[byteIndex]>>>bitIndex)&1)==1);}
var mask=QRUtil.getMask(maskPattern,row,col-c);if(mask){dark=!dark;}
this.modules[row][col-c]=dark;bitIndex--;if(bitIndex==-1){byteIndex++;bitIndex=7;}}}
row+=inc;if(row<0||this.moduleCount<=row){row-=inc;inc=-inc;break;}}}}};QRCodeModel.PAD0=0xEC;QRCodeModel.PAD1=0x11;QRCodeModel.createData=function(typeNumber,errorCorrectLevel,dataList){var rsBlocks=QRRSBlock.getRSBlocks(typeNumber,errorCorrectLevel);var buffer=new QRBitBuffer();for(var i=0;i<dataList.length;i++){var data=dataList[i];buffer.put(data.mode,4);buffer.put(data.getLength(),QRUtil.getLengthInBits(data.mode,typeNumber));data.write(buffer);}
var totalDataCount=0;for(var i=0;i<rsBlocks.length;i++){totalDataCount+=rsBlocks[i].dataCount;}
if(buffer.getLengthInBits()>totalDataCount*8){throw new Error("code length overflow. ("
+buffer.getLengthInBits()
+">"
+totalDataCount*8
+")");}
if(buffer.getLengthInBits()+4<=totalDataCount*8){buffer.put(0,4);}
while(buffer.getLengthInBits()%8!=0){buffer.putBit(false);}
while(true){if(buffer.getLengthInBits()>=totalDataCount*8){break;}
buffer.put(QRCodeModel.PAD0,8);if(buffer.getLengthInBits()>=totalDataCount*8){break;}
buffer.put(QRCodeModel.PAD1,8);}
return QRCodeModel.createBytes(buffer,rsBlocks);};QRCodeModel.createBytes=function(buffer,rsBlocks){var offset=0;var maxDcCount=0;var maxEcCount=0;var dcdata=new Array(rsBlocks.length);var ecdata=new Array(rsBlocks.length);for(var r=0;r<rsBlocks.length;r++){var dcCount=rsBlocks[r].dataCount;var ecCount=rsBlocks[r].totalCount-dcCount;maxDcCount=Math.max(maxDcCount,dcCount);maxEcCount=Math.max(maxEcCount,ecCount);dcdata[r]=new Array(dcCount);for(var i=0;i<dcdata[r].length;i++){dcdata[r][i]=0xff&buffer.buffer[i+offset];}
offset+=dcCount;var rsPoly=QRUtil.getErrorCorrectPolynomial(ecCount);var rawPoly=new QRPolynomial(dcdata[r],rsPoly.getLength()-1);var modPoly=rawPoly.mod(rsPoly);ecdata[r]=new Array(rsPoly.getLength()-1);for(var i=0;i<ecdata[r].length;i++){var modIndex=i+modPoly.getLength()-ecdata[r].length;ecdata[r][i]=(modIndex>=0)?modPoly.get(modIndex):0;}}
var totalCodeCount=0;for(var i=0;i<rsBlocks.length;i++){totalCodeCount+=rsBlocks[i].totalCount;}
var data=new Array(totalCodeCount);var index=0;for(var i=0;i<maxDcCount;i++){for(var r=0;r<rsBlocks.length;r++){if(i<dcdata[r].length){data[index++]=dcdata[r][i];}}}
for(var i=0;i<maxEcCount;i++){for(var r=0;r<rsBlocks.length;r++){if(i<ecdata[r].length){data[index++]=ecdata[r][i];}}}
return data;};var QRMode={MODE_NUMBER:1<<0,MODE_ALPHA_NUM:1<<1,MODE_8BIT_BYTE:1<<2,MODE_KANJI:1<<3};var QRErrorCorrectLevel={L:1,M:0,Q:3,H:2};var QRMaskPattern={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7};var QRUtil={PATTERN_POSITION_TABLE:[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],G15:(1<<10)|(1<<8)|(1<<5)|(1<<4)|(1<<2)|(1<<1)|(1<<0),G18:(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<5)|(1<<2)|(1<<0),G15_MASK:(1<<14)|(1<<12)|(1<<10)|(1<<4)|(1<<1),getBCHTypeInfo:function(data){var d=data<<10;while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)>=0){d^=(QRUtil.G15<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)));}
return((data<<10)|d)^QRUtil.G15_MASK;},getBCHTypeNumber:function(data){var d=data<<12;while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)>=0){d^=(QRUtil.G18<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)));}
return(data<<12)|d;},getBCHDigit:function(data){var digit=0;while(data!=0){digit++;data>>>=1;}
return digit;},getPatternPosition:function(typeNumber){return QRUtil.PATTERN_POSITION_TABLE[typeNumber-1];},getMask:function(maskPattern,i,j){switch(maskPattern){case QRMaskPattern.PATTERN000:return(i+j)%2==0;case QRMaskPattern.PATTERN001:return i%2==0;case QRMaskPattern.PATTERN010:return j%3==0;case QRMaskPattern.PATTERN011:return(i+j)%3==0;case QRMaskPattern.PATTERN100:return(Math.floor(i/2)+Math.floor(j/3))%2==0;case QRMaskPattern.PATTERN101:return(i*j)%2+(i*j)%3==0;case QRMaskPattern.PATTERN110:return((i*j)%2+(i*j)%3)%2==0;case QRMaskPattern.PATTERN111:return((i*j)%3+(i+j)%2)%2==0;default:throw new Error("bad maskPattern:"+maskPattern);}},getErrorCorrectPolynomial:function(errorCorrectLength){var a=new QRPolynomial([1],0);for(var i=0;i<errorCorrectLength;i++){a=a.multiply(new QRPolynomial([1,QRMath.gexp(i)],0));}
return a;},getLengthInBits:function(mode,type){if(1<=type&&type<10){switch(mode){case QRMode.MODE_NUMBER:return 10;case QRMode.MODE_ALPHA_NUM:return 9;case QRMode.MODE_8BIT_BYTE:return 8;case QRMode.MODE_KANJI:return 8;default:throw new Error("mode:"+mode);}}else if(type<27){switch(mode){case QRMode.MODE_NUMBER:return 12;case QRMode.MODE_ALPHA_NUM:return 11;case QRMode.MODE_8BIT_BYTE:return 16;case QRMode.MODE_KANJI:return 10;default:throw new Error("mode:"+mode);}}else if(type<41){switch(mode){case QRMode.MODE_NUMBER:return 14;case QRMode.MODE_ALPHA_NUM:return 13;case QRMode.MODE_8BIT_BYTE:return 16;case QRMode.MODE_KANJI:return 12;default:throw new Error("mode:"+mode);}}else{throw new Error("type:"+type);}},getLostPoint:function(qrCode){var moduleCount=qrCode.getModuleCount();var lostPoint=0;for(var row=0;row<moduleCount;row++){for(var col=0;col<moduleCount;col++){var sameCount=0;var dark=qrCode.isDark(row,col);for(var r=-1;r<=1;r++){if(row+r<0||moduleCount<=row+r){continue;}
for(var c=-1;c<=1;c++){if(col+c<0||moduleCount<=col+c){continue;}
if(r==0&&c==0){continue;}
if(dark==qrCode.isDark(row+r,col+c)){sameCount++;}}}
if(sameCount>5){lostPoint+=(3+sameCount-5);}}}
for(var row=0;row<moduleCount-1;row++){for(var col=0;col<moduleCount-1;col++){var count=0;if(qrCode.isDark(row,col))count++;if(qrCode.isDark(row+1,col))count++;if(qrCode.isDark(row,col+1))count++;if(qrCode.isDark(row+1,col+1))count++;if(count==0||count==4){lostPoint+=3;}}}
for(var row=0;row<moduleCount;row++){for(var col=0;col<moduleCount-6;col++){if(qrCode.isDark(row,col)&&!qrCode.isDark(row,col+1)&&qrCode.isDark(row,col+2)&&qrCode.isDark(row,col+3)&&qrCode.isDark(row,col+4)&&!qrCode.isDark(row,col+5)&&qrCode.isDark(row,col+6)){lostPoint+=40;}}}
for(var col=0;col<moduleCount;col++){for(var row=0;row<moduleCount-6;row++){if(qrCode.isDark(row,col)&&!qrCode.isDark(row+1,col)&&qrCode.isDark(row+2,col)&&qrCode.isDark(row+3,col)&&qrCode.isDark(row+4,col)&&!qrCode.isDark(row+5,col)&&qrCode.isDark(row+6,col)){lostPoint+=40;}}}
var darkCount=0;for(var col=0;col<moduleCount;col++){for(var row=0;row<moduleCount;row++){if(qrCode.isDark(row,col)){darkCount++;}}}
var ratio=Math.abs(100*darkCount/moduleCount/moduleCount-50)/5;lostPoint+=ratio*10;return lostPoint;}};var QRMath={glog:function(n){if(n<1){throw new Error("glog("+n+")");}
return QRMath.LOG_TABLE[n];},gexp:function(n){while(n<0){n+=255;}
while(n>=256){n-=255;}
return QRMath.EXP_TABLE[n];},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)};for(var i=0;i<8;i++){QRMath.EXP_TABLE[i]=1<<i;}
for(var i=8;i<256;i++){QRMath.EXP_TABLE[i]=QRMath.EXP_TABLE[i-4]^QRMath.EXP_TABLE[i-5]^QRMath.EXP_TABLE[i-6]^QRMath.EXP_TABLE[i-8];}
for(var i=0;i<255;i++){QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]]=i;}
function QRPolynomial(num,shift){if(num.length==undefined){throw new Error(num.length+"/"+shift);}
var offset=0;while(offset<num.length&&num[offset]==0){offset++;}
this.num=new Array(num.length-offset+shift);for(var i=0;i<num.length-offset;i++){this.num[i]=num[i+offset];}}
QRPolynomial.prototype={get:function(index){return this.num[index];},getLength:function(){return this.num.length;},multiply:function(e){var num=new Array(this.getLength()+e.getLength()-1);for(var i=0;i<this.getLength();i++){for(var j=0;j<e.getLength();j++){num[i+j]^=QRMath.gexp(QRMath.glog(this.get(i))+QRMath.glog(e.get(j)));}}
return new QRPolynomial(num,0);},mod:function(e){if(this.getLength()-e.getLength()<0){return this;}
var ratio=QRMath.glog(this.get(0))-QRMath.glog(e.get(0));var num=new Array(this.getLength());for(var i=0;i<this.getLength();i++){num[i]=this.get(i);}
for(var i=0;i<e.getLength();i++){num[i]^=QRMath.gexp(QRMath.glog(e.get(i))+ratio);}
return new QRPolynomial(num,0).mod(e);}};function QRRSBlock(totalCount,dataCount){this.totalCount=totalCount;this.dataCount=dataCount;}
QRRSBlock.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]];QRRSBlock.getRSBlocks=function(typeNumber,errorCorrectLevel){var rsBlock=QRRSBlock.getRsBlockTable(typeNumber,errorCorrectLevel);if(rsBlock==undefined){throw new Error("bad rs block @ typeNumber:"+typeNumber+"/errorCorrectLevel:"+errorCorrectLevel);}
var length=rsBlock.length/3;var list=[];for(var i=0;i<length;i++){var count=rsBlock[i*3+0];var totalCount=rsBlock[i*3+1];var dataCount=rsBlock[i*3+2];for(var j=0;j<count;j++){list.push(new QRRSBlock(totalCount,dataCount));}}
return list;};QRRSBlock.getRsBlockTable=function(typeNumber,errorCorrectLevel){switch(errorCorrectLevel){case QRErrorCorrectLevel.L:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+0];case QRErrorCorrectLevel.M:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+1];case QRErrorCorrectLevel.Q:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+2];case QRErrorCorrectLevel.H:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+3];default:return undefined;}};function QRBitBuffer(){this.buffer=[];this.length=0;}
QRBitBuffer.prototype={get:function(index){var bufIndex=Math.floor(index/8);return((this.buffer[bufIndex]>>>(7-index%8))&1)==1;},put:function(num,length){for(var i=0;i<length;i++){this.putBit(((num>>>(length-i-1))&1)==1);}},getLengthInBits:function(){return this.length;},putBit:function(bit){var bufIndex=Math.floor(this.length/8);if(this.buffer.length<=bufIndex){this.buffer.push(0);}
if(bit){this.buffer[bufIndex]|=(0x80>>>(this.length%8));}
this.length++;}};var QRCodeLimitLength=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]];
function _isSupportCanvas() {
return typeof CanvasRenderingContext2D != "undefined";
}
// android 2.x doesn't support Data-URI spec
function _getAndroid() {
var android = false;
var sAgent = navigator.userAgent;
if (/android/i.test(sAgent)) { // android
android = true;
var aMat = sAgent.toString().match(/android ([0-9]\.[0-9])/i);
if (aMat && aMat[1]) {
android = parseFloat(aMat[1]);
}
}
return android;
}
var svgDrawer = (function() {
var Drawing = function (el, htOption) {
this._el = el;
this._htOption = htOption;
};
Drawing.prototype.draw = function (oQRCode) {
var _htOption = this._htOption;
var _el = this._el;
var nCount = oQRCode.getModuleCount();
var nWidth = Math.floor(_htOption.width / nCount);
var nHeight = Math.floor(_htOption.height / nCount);
this.clear();
function makeSVG(tag, attrs) {
var el = document.createElementNS('http://www.w3.org/2000/svg', tag);
Object.entries(attrs).forEach(([k,v]) => {
el.setAttribute(k,v);
})
return el;
}
const margin = 2;
var svg = makeSVG("svg" , {'viewBox': `${-margin} ${-margin} ${nCount+2*margin} ${nCount+2*margin}`, 'width': '100%', 'height': '100%', 'fill': _htOption.colorLight});
svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
_el.appendChild(svg);
svg.appendChild(makeSVG("rect", {class: 'bg', width: nCount + 2*margin, height: nCount + 2*margin, x: -margin, y: -margin, "fill": _htOption.colorLight,}));
const data = oQRCode.dataList.map(d=>d.data).join('');
let i = 0;
for (var row = 0; row < nCount; row++) {
for (var col = 0; col < nCount; col++) {
const isDark = oQRCode.isDark(row, col);
if (isDark) {
var child = makeSVG("rect", {x: col, y: row, fill: _htOption.colorDark, width: 1, height: 1});
svg.appendChild(child);
}
if(i < data.length && (row >= 7 && row < nCount-7 || col >= 7 && col < nCount-7 || row >= 7 && col >= 7)) {
var child = makeSVG("text",{"x": String(col+0.5), "y": String(row+0.5), "font-size": "1", stroke: "none", 'font-weight': 'light', 'font-family': 'monospace', 'fill': 'gray', 'dominant-baseline': 'middle', 'text-anchor': 'middle'});
child.textContent = data[i];
i += 1;
svg.appendChild(child);
}
}
}
};
Drawing.prototype.clear = function () {
while (this._el.hasChildNodes())
this._el.removeChild(this._el.lastChild);
};
return Drawing;
})();
var useSVG = true;
// Drawing in DOM by using Table tag
var Drawing = svgDrawer;
/**
* Get the type by string length
*
* @private
* @param {String} sText
* @param {Number} nCorrectLevel
* @return {Number} type
*/
function _getTypeNumber(sText, nCorrectLevel) {
var nType = 1;
var length = _getUTF8Length(sText);
for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) {
var nLimit = 0;
switch (nCorrectLevel) {
case QRErrorCorrectLevel.L :
nLimit = QRCodeLimitLength[i][0];
break;
case QRErrorCorrectLevel.M :
nLimit = QRCodeLimitLength[i][1];
break;
case QRErrorCorrectLevel.Q :
nLimit = QRCodeLimitLength[i][2];
break;
case QRErrorCorrectLevel.H :
nLimit = QRCodeLimitLength[i][3];
break;
}
if (length <= nLimit) {
break;
} else {
nType++;
}
}
if (nType > QRCodeLimitLength.length) {
throw new Error("Too long data");
}
return nType;
}
function _getUTF8Length(sText) {
var replacedText = encodeURI(sText).toString().replace(/\%[0-9a-fA-F]{2}/g, 'a');
return replacedText.length + (replacedText.length != sText ? 3 : 0);
}
/**
* @class QRCode
* @constructor
* @example
* new QRCode(document.getElementById("test"), "http://jindo.dev.naver.com/collie");
*
* @example
* var oQRCode = new QRCode("test", {
* text : "http://naver.com",
* width : 128,
* height : 128
* });
*
* oQRCode.clear(); // Clear the QRCode.
* oQRCode.makeCode("http://map.naver.com"); // Re-create the QRCode.
*
* @param {HTMLElement|String} el target element or 'id' attribute of element.
* @param {Object|String} vOption
* @param {String} vOption.text QRCode link data
* @param {Number} [vOption.width=256]
* @param {Number} [vOption.height=256]
* @param {String} [vOption.colorDark="#000000"]
* @param {String} [vOption.colorLight="#ffffff"]
* @param {QRCode.CorrectLevel} [vOption.correctLevel=QRCode.CorrectLevel.H] [L|M|Q|H]
*/
QRCode = function (el, vOption) {
this._htOption = {
width : 256,
height : 256,
typeNumber : 4,
colorDark : "#000000",
colorLight : "#ffffff",
correctLevel : QRErrorCorrectLevel.H
};
if (typeof vOption === 'string') {
vOption = {
text : vOption
};
}
// Overwrites options
if (vOption) {
for (var i in vOption) {
this._htOption[i] = vOption[i];
}
}
if (typeof el == "string") {
el = document.getElementById(el);
}
if (this._htOption.useSVG) {
Drawing = svgDrawer;
}
this._android = _getAndroid();
this._el = el;
this._oQRCode = null;
this._oDrawing = new Drawing(this._el, this._htOption);
if (this._htOption.text) {
this.makeCode(this._htOption.text);
}
};
/**
* Make the QRCode
*
* @param {String} sText link data
*/
QRCode.prototype.makeCode = function (sText) {
this._oQRCode = new QRCodeModel(_getTypeNumber(sText, this._htOption.correctLevel), this._htOption.correctLevel);
this._oQRCode.addData(sText);
this._oQRCode.make();
this._el.title = sText;
this._oDrawing.draw(this._oQRCode);
this.makeImage();
};
/**
* Make the Image from Canvas element
* - It occurs automatically
* - Android below 3 doesn't support Data-URI spec.
*
* @private
*/
QRCode.prototype.makeImage = function () {
if (typeof this._oDrawing.makeImage == "function" && (!this._android || this._android >= 3)) {
this._oDrawing.makeImage();
}
};
/**
* Clear the QRCode
*/
QRCode.prototype.clear = function () {
this._oDrawing.clear();
};
/**
* @name QRCode.CorrectLevel
*/
QRCode.CorrectLevel = QRErrorCorrectLevel;
})();
export default QRCode;

19
script.js Normal file
View file

@ -0,0 +1,19 @@
import QRCode from './qrcode.js';
function add_qr_code(a) {
const div = document.createElement('div');
div.classList.add('qrcode');
const qrcode = new QRCode(div, {
width: 512,
height: 512
});
qrcode.makeCode(a.href);
a.append(div);
}
console.log('hey');
for(let a of document.querySelectorAll('a.qr')) {
console.log(a);
add_qr_code(a);
}

238
style.css Normal file
View file

@ -0,0 +1,238 @@
@import "atkinson-hyperlegible.css";
:root {
--spacing: 1em;
--bg-lum: 1;
--bg-chroma: 30%;
--bg-hue: 240;
font-size: 18pt;
color-scheme: light dark;
}
body {
font-family: 'Atkinson Hyperlegible';
line-height: 1.5;
width: 594mm;
height: 841mm;
margin: 0;
padding: 2cm;
--shrink: 100%;
transform: translate(calc(-50% + 0.5 * var(--shrink)),calc(-50% + 0.5 * var(--shrink))) scale(var(--shrink));
display: grid;
grid-template-rows: auto 1fr auto;
align-items: center;
}
header {
text-align: center;
font-size: 1.2rem;
display: grid;
grid-template:
"title title title title"
". name portrait ."
/ 1fr auto auto 1fr
;
gap: 1em;
justify-content: center;
& h1 {
grid-area: title;
}
& p {
grid-area: name;
}
& .portrait {
height: 5em;
border-radius: 50%;
align-self: center;
grid-area: portrait;
border: 0.2em solid #d9c181;
box-sizing: border-box;
}
}
h1, h2 {
margin: 0;
}
main {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 1em 2em;
align-items: center;
&:has(:nth-child(6)) { --num-slides: 6;}
&:has(:nth-child(7)) { --num-slides: 7;}
&:has(:nth-child(8)) { --num-slides: 8;}
&:has(:nth-child(9)) { --num-slides: 9;}
&:has(:nth-child(10)) { --num-slides: 10;}
&:has(:nth-child(11)) { --num-slides: 11;}
&:has(:nth-child(12)) { --num-slides: 12;}
&:has(:nth-child(13)) { --num-slides: 13;}
& :nth-child(1) { --index: 1;}
& :nth-child(2) { --index: 2;}
& :nth-child(3) { --index: 3;}
& :nth-child(4) { --index: 4;}
& :nth-child(5) { --index: 5;}
& :nth-child(6) { --index: 6;}
& :nth-child(7) { --index: 7;}
& :nth-child(8) { --index: 8;}
& :nth-child(9) { --index: 9;}
& :nth-child(10) { --index: 10;}
& :nth-child(11) { --index: 11;}
& :nth-child(12) { --index: 12;}
& :nth-child(13) { --index: 13;}
& section {
--slide-number: calc(var(--index) / var(--num-slides));
border-radius: 0.5em;
--bg-hue: calc(var(--slide-number) * 360);
background-color: oklch(var(--bg-lum) var(--bg-chroma) var(--bg-hue));
border: 0.2em solid;
border-color: color-mix(in oklch, oklch(var(--bg-lum) var(--bg-chroma) var(--bg-hue)), black 20%);
padding: 1em;
--col: span 1;
grid-column: var(--col);
&.plain {
text-align: center;
background: none;
border: none;
align-self: start;
padding: 0;
& p {
margin-top: 0;
}
& .qrcode {
width: 4cm;
margin: 1em;
}
}
}
}
dl.quotes {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.25em;
& dt {
&::before {content: '“';}
&::after {content: '”';}
justify-self: end;
text-align: end;
}
& dd {
font-style: italic;
}
}
@media print {
* {
text-wrap: balance;
}
a {
text-decoration: none;
color: inherit;
display: flex;
align-items: center;
justify-content: center;
gap: 1em;
font-weight: 250;
}
}
img {
width: 100%;
}
figure {
margin: 0;
}
a {
}
.qrcode {
width: 3cm;
& .bg {
fill: none;
}
}
.squiggle {
fill: none;
stroke: color-mix(in oklch, oklch(var(--bg-lum) var(--bg-chroma) var(--bg-hue)), black 30%);
stroke-width: 0.05em;
stroke-linejoin: round;
}
@media screen {
:root {
font-size: 18px;
}
.print-only {
display: none;
}
body {
width: revert;
height: revert;
margin: 0;
padding: 0.25rem;
}
header {
font-size: 1rem;
margin-bottom: 2rem;
}
main {
grid-template-columns: 1fr;
justify-items: center;
& section {
grid-column: 1;
&.plain {
display: none;
}
}
}
.qrcode {
display: none;
}
dl.quotes {
grid-template-columns: 1fr;
& dt {
text-align: start;
justify-self: start;
}
& dd {
text-align: end;
}
}
}