Nambafa
Formula generator
Introduction
Html does not have great native support for displaying mathematical expressions. To be able to formulate simple equations with ease, I have written a light-weight JavaScript generator that can represent some basic expressions in the form of tables, which then can be displayed as regular html.
An example of usage - plus the full code of the generator - can be found below. :)
Example of usage
The below formula is made using the generator.
The formula was generated using the relatively simple code below.
f.beg() + f.inte( f.frac('sin'+f.sup('2')+'x','x'), 'x', '0', '∞' ) + ' = ' + f.frac('π','2') + f.end();
The generator code
The below code is the full code for the generator.
class TableFormulator{
/***********************************************************************************************************************
Description: Class to generate table representations of simple formulas (mathematical equations)
Made by: Kristian Stormark
Version: 0.9.8
Usage (example):
var f = new TableFormulator(); var p = document.getElementById('myparent');
p.innerHTML = f.beg() + f.frac('1','2π') + f.inte('sin(x)','x','a','b') + f.end();
************************************************************************************************************************/
constructor(opt={}) { // Fun: constructor
//-------------------------------------------------------------------------------------> DESCRIPTION
// Class constructor - does nothing except set id + adds styling rules to document // Note
//-------------------------------------------------------------------------------------> SET DEFAULTS
var setdef = function(o,p,v){if(!o.hasOwnProperty(p)){o[p]=v;} return opt;}; // Aux: upd w/def val if unset
opt = setdef( opt, 'id', 'tbf' ); // Def: id (upd for mult inst)
opt = setdef( opt, 'border', false ); // Def: no borders (add for qc)
opt = setdef( opt, 'color', this.el2pv(document.body,'color')); // Def: body font color
//-------------------------------------------------------------------------------------> SET OBJECT ID
this.id = opt.id; // Set obj id (for css classes)
//-------------------------------------------------------------------------------------> INSERT STYLE-SHEET
var sid = this.id + '_style'; // Id for style el
if (document.getElementById(sid) === null){ // If not style el exist
var c = opt.color; // Get color (for fractions)
var s = document.createElement('style'); s.type='text/css'; s.id=sid; // Create style el (+set type&id)
var obj = this; // ("Bind" this...)
var r = function(cstr,rstr,e=''){return obj.s2s(cstr)+e+'{' + rstr + '}';}; // Short-hand: rule generator
var bc = 'border-spacing:0;border-collapse:collapse;'; // Short-hand: border collapse
var str = '' + // Build rule string
r('itm','display:inline-table;margin:0 0.2em;' + bc) + // + In-line table w/margin
r('itn','display:inline-table;margin:0;' + bc) + // + In-line table w/no margin
r('sup','font-size:65%;margin:0 auto;padding:0 auto;height:0.6em;' ) + // + Sup-script (h=min-h)
r('sub','font-size:65%;margin:0 auto;padding:0 auto;height:0.6em;' ) + // + Sub-script (h=min-h)
r('grp','font-size:150%;display:inline-block;' ) + // + "Group" el, like int. sign
r('wrp','display:flex;justify-content:center;align-items:center;' ) + // + Wrapper (for v. centering)
r('wrp','padding:0 0.1em;',' td' ) + // + Wrapper (for v. centering)
r('lin','border-top:1px solid ' + c + ';margin:0;padding:0;' + bc) ; // + Line for fraction
if(opt.border){ str = str + obj.s2s('wrp') + ' td{border: 1px solid ' + c + ';}'; } // Opt: Add border
s.innerHTML = str; // Set style str
document.getElementsByTagName('head')[0].appendChild(s); // Add style to document
} // End: if
} // End: fun
//---------------------------------------------------------------------------------------> MINI-FUNCTIONS
el2pv (el,p) { return window.getComputedStyle(el, null).getPropertyValue(p); } // Aux: get el. p. value (comp.)
s2c (str) { return str==='' ? '' : ' class="' + this.id + '_' + str + '"'; } // Aux: string-to-class
s2s (str) { return '.' + this.id + '_' + str; } // Aux: string-to-selector
beg () { return ''; } // Equation begin
end () { return ''; } // Equation end
enc (str) { return this.beg() + str + this.end(); } // Aux: encapsulate
encif (str) { return str ==='' ? str : this.beg() + str + this.end(); } // Aux: encapsulate if not empty
tagger(t) { return (d,c='',a='') =>'<'+t+this.s2c(c)+' '+a+'>'+d+''+t+'>';} // Aux: tag generator (req. bind)
//---------------------------------------------------------------------------------------> INTEGRAL
inte (f, x, a=null, b=null,symb='∫'){ // Fun: return str
var g,tb,tr,td;g=(t)=>this.tagger(t).bind(this); tb=g('table');tr=g('tr');td=g('td'); // Gen: table,tr, td
var span = g('span'); // Gen: span
var s = f.includes('wrp') ? ' style="transform:scale(1.2,1.4);"' : ''; // Mod: scale if nested (once)
b = b === null ? '' : tr( td(b,'sup') + td('') + td('') ); // Row: upper lim
a = a === null ? '' : tr( td(a,'sub') + td('') + td('') ); // Row: lower lim
var i = tr( td(span(symb,'grp',s)) + td(this.enc(f)) + td('d'+x) ); // Row: ∫+integrand+dx
return tb ( b + i + a, 'itm' ); // Tbl: all rows
} // End: fun
//---------------------------------------------------------------------------------------> FRACTION
frac (a,b){ // Fun: return str
var g,tb,tr,td;g=(t)=>this.tagger(t).bind(this); tb=g('table');tr=g('tr');td=g('td'); // Gen: table,tr, td
return tb ( tr(td(this.enc(a))) + tr(td(''),'lin') + tr(td(this.enc(b))), 'itm' ); // Tbl: a-line-b
} // End: fun
//---------------------------------------------------------------------------------------> VERTICAL STACK
vert (arr){ // Fun: return str
var g,tb,tr,td;g=(t)=>this.tagger(t).bind(this); tb=g('table');tr=g('tr');td=g('td'); // Gen: table,tr, td
return tb ( arr.map(s=>tr(td(this.encif(s),'sup'))).join(''), 'itn' ); // Tbl: all rows
} // End: fun
//---------------------------------------------------------------------------------------> SUP/POW AND SUB/IND
sup (n){ return this.vert([n,'']); } pow(n){ return this.sup(n); } // Fun: return str
sub (i){ return this.vert(['',i]); } ind(n){ return this.sub(n); } // Fun: return str
} // End: class