Skip to content

Commit

Permalink
Multiplication tables example
Browse files Browse the repository at this point in the history
  • Loading branch information
GrahamHannington committed Nov 17, 2024
1 parent 885c14c commit f833209
Show file tree
Hide file tree
Showing 7 changed files with 228 additions and 1 deletion.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,12 @@ Example image:

`center/contain+no-repeat+url(https://eoimages.gsfc.nasa.gov/images/imagerecords/57000/57723/globe_west_2048.jpg)`

### `backBackground`

Overrides `background` on even-numbered pages.

For allowed values, see `background`.

### `fadeIn`

Time in seconds to fade-in the next page.
Expand Down
6 changes: 5 additions & 1 deletion bigas.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,14 +268,18 @@ function loadExternalScript (src) {

function styleText (svgElement) {
const state = getState()
var background = null
if (state.googleFont) svgElement.style.fontFamily = state.googleFont
if (state.fontWeight) svgElement.style.fontWeight = state.fontWeight
if (state.fontStyle) svgElement.style.fontStyle = state.fontStyle
if (state.margin) svgElement.style.margin = state.margin
if (state.width) svgElement.style.width = state.width
if (state.height) svgElement.style.height = state.height
// Apply background to parent (container) element
if (state.background) svgElement.parentElement.style.background = state.background
if (state.background) background = state.background
// If the current page number is even, use backBackground, if it is set
if ((state.currentPage % 2 == 0) && state.backBackground) background = state.backBackground
if (background) svgElement.parentElement.style.background = background
// Apply text styles
for (const text of svgElement.children) {
if (state.textFill) text.style.fill = state.textFill
Expand Down
13 changes: 13 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@

- [Days of the week](https://grahamhannington.github.io/bigas?text=Monday//Tuesday//Wednesday//Thursday//Friday//Saturday//Sunday)

## [Multiplication tables](https://grahamhannington.github.io/bigas/examples/multiplication)

By default, this example lists multiplication tables from 1 to 12, and then shows the selected table as a set of flash cards, in pairs of "questions" and "answers".

Alternatively, you can specify a query string to go directly to a multiplication table.

Examples:

[`multiplicand=15&maxMultiplier=10`](https://grahamhannington.github.io/bigas/examples/multiplication/?multiplicand=15&maxMultiplier=10)


[`multiplicand=13&minMultiplier=-3&maxMultiplier=9`](https://grahamhannington.github.io/bigas/examples/multiplication/?multiplicand=13&minMultiplier=-3&maxMultiplier=9)

## [Burger](https://grahamhannington.github.io/bigas/examples/burger.html)

Web developers: this example uses the `formatSVGElementsByClassName()` function to format multiple SVG elements based on class name.
Expand Down
59 changes: 59 additions & 0 deletions examples/multiplication/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<!doctype html>
<html>
<head>
<title>Burger</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link href="../images/favicon.ico" rel="shortcut icon"/>
<script type="module">
import * as Multiplication from "./modules/multiplication.js"
Multiplication.init()
</script>
<style>
body {
background: black;
font-family: 'Arial Unicode', Arial, sans-serif;
margin: 1rem;
}

h1, div, p {
color: white;
}
h1, p {
margin: 0 0 1rem 0;
}

p {
margin-top: 1rem;
}

h1, .tables .table {
font-size: 2rem;
font-weight: normal;
}

.tables {
display: grid;
grid-template-columns: repeat(auto-fill,minmax(15em, 1fr));
gap: 1rem;
}

.tables .table {
padding: 1rem;
border: 0;
transition: border-color 0.5s;
border: 0.2rem solid transparent;
background: royalblue;
}

p a:hover {
text-decoration: underline;
}

.tables .table:hover {
border-color: white;
}
</style>
</head>
<body>
</body>
</html>
105 changes: 105 additions & 0 deletions examples/multiplication/modules/multiplication.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { getState, setState, getStateProperty, setStateProperty } from './state.js'
import { log } from '../../../modules/log.js'

const urlEncodedMultiplicationSign = '%26%23x00D7%3B'
const urlEncodedSpace = '+'
const urlEncodedNoBreakSpace = '%26%23xA0%3B'
const urlEncodedEqualsSign = '%26%23x003D%3B'
const urlEncodedEnDash = '%26%23x2013%3B'

const lineSeparator = '/'
const pageSeparator = '//'

function init () {
setStateFromURLParams ()
const state = getState()
if (state.multiplicand) {
showTableBigAs(state.multiplicand, state.minMultiplier, state.maxMultiplier)
} else {
showListofTables()
}
}

function showListofTables () {
const state = getState()
let heading = document.createElement("h1")
let tables = document.createElement("div")
tables.classList.add('tables')
for (let multiplicand = state.minMultiplicand; multiplicand <= state.maxMultiplicand; multiplicand++) {
let table = document.createElement("div")
table.dataset.multiplicand = multiplicand
table.dataset.minMultiplier = state.minMultiplier
table.dataset.maxMultiplier = state.maxMultiplier
table.classList.add('table')
table.textContent = multiplicand + ' \u{00D7} ' + state.minMultiplier + ' \u{2026} ' + state.maxMultiplier
table.addEventListener('click', (event) => {
showTableBigAs (table.dataset.multiplicand, table.dataset.minMultiplier, table.dataset.maxMultiplier)
})
tables.appendChild(table)
}
heading.textContent = state.appName
document.body.appendChild(heading)
document.body.appendChild(tables)
}

function showTableBigAs (multiplicand, minMultiplier, maxMultiplier) {
var problemText
var solutionText
var horizontalRule
var result
var queryString = 'background=royalblue&backBackground=darkgreen&textAlign=right&wordPerLineInPortrait=true&text='
for (let multiplier = minMultiplier; multiplier <= maxMultiplier; multiplier++) {
problemText = multiplicand + urlEncodedSpace + urlEncodedMultiplicationSign + urlEncodedNoBreakSpace + multiplier
// Build a horizontal rule from en dashes
horizontalRule = urlEncodedEnDash.repeat(multiplicand.toString().length + 2)
result = multiplicand * multiplier
solutionText = problemText + '[p:' + lineSeparator + horizontalRule + '][l:+' + urlEncodedEqualsSign + ']+' + result
queryString += problemText + pageSeparator + solutionText
if (multiplier < maxMultiplier) {
queryString += pageSeparator
}
}
window.location.href = '../../?' + queryString
}

// Set state properties from parameters in the URL query string
function setStateFromURLParams () {
const urlParams = new URLSearchParams(window.location.search)
const state = getState()
const newState = {}
// Iterate over URL parameters
for (const [key, value] of urlParams) {
// If the URL parameter name matches a state property, set the state property
if (Object.hasOwn(state, key)) {
// Coerce the URL parameter value (string or null) to the correct type, based on the type of the existing state property
switch (typeof state[key]) {
case 'boolean':
// If the state property is a Boolean, then just the parameter name (without a value) means true
switch (value.toLowerCase()) {
case '':
case 'true':
newState[key] = true
break
case 'false':
newState[key] = false
break
default:
log.warn('Bad value ignored for URL query string parameter: ' + key + '=' + value + '. Value must be true or false.\nTip: Specifying ' + key + ' (the parameter name by itself, with no trailing equal sign or value) has the same effect as ' + key + '=true.')
}
break
case 'string':
case 'object':
newState[key] = value
break
case 'number':
newState[key] = Number(value)
break
}
} else {
log.warn('Unrecognized parameter in URL query string: ' + key)
}
}
setState(newState)
}

export { init }
39 changes: 39 additions & 0 deletions examples/multiplication/modules/state.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Manage the state (application properties)

// Initialize the state
let state = {
appName: 'Multiplication tables',
multiplicand: null,
minMultiplicand: 1,
maxMultiplicand: 12,
minMultiplier: 1,
maxMultiplier: 12
}

// Return the state object
function getState () {
return state
}

// Return the state property
function getStateProperty(key) {
return state[key]
}


// Update the state
function setState (newState) {
// Append properties of the new state to the old state,
// potentially overwriting existing properties of the old state
state = { ...state, ...newState }
return state
}

// Update the state property
function setStateProperty (key, value) {
state[key] = value
}


// Export the getState and setState functions
export { getState, setState, getStateProperty, setStateProperty }
1 change: 1 addition & 0 deletions modules/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
let state = {
appName: 'Big As',
background: '#000000',
backBackground: null,
currentPage: 1,
fontStyle: 'normal',
googleFont: null,
Expand Down

0 comments on commit f833209

Please sign in to comment.