Skip to content

Instantly share code, notes, and snippets.

@Kyuuhachi
Created April 4, 2017 18:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kyuuhachi/3c96e14f4fddd8adff0e85027b6c0a8b to your computer and use it in GitHub Desktop.
Save Kyuuhachi/3c96e14f4fddd8adff0e85027b6c0a8b to your computer and use it in GitHub Desktop.
An userscript for cleaning up SchoolSoft's schedule's print view
// ==UserScript==
// @name Schedule
// @namespace c98
// @include https://sms7.schoolsoft.se/nti/jsp/student/right_student_schedule_print.jsp?*
// @version 1
// @grant none
// ==/UserScript==
print=alert;
(function() {
// {{{ Libs
$ = jQuery = window.$ || window.jQuery || window._jQuery;
// {{{ randomColor
;(function(root, factory) {
// Support AMD
if (typeof define === 'function' && define.amd) {
define([], factory);
// Support CommonJS
} else if (typeof exports === 'object') {
var randomColor = factory();
// Support NodeJS & Component, which allow module.exports to be a function
if (typeof module === 'object' && module && module.exports) {
exports = module.exports = randomColor;
}
// Support CommonJS 1.1.1 spec
exports.randomColor = randomColor;
// Support vanilla script loading
} else {
root.randomColor = factory();
}
}(this, function() {
// Seed to get repeatable colors
var seed = null;
// Shared color dictionary
var colorDictionary = {};
// Populate the color dictionary
loadColorBounds();
var randomColor = function (options) {
options = options || {};
// Check if there is a seed and ensure it's an
// integer. Otherwise, reset the seed value.
if (options.seed !== undefined && options.seed !== null && options.seed === parseInt(options.seed, 10)) {
seed = options.seed;
// A string was passed as a seed
} else if (typeof options.seed === 'string') {
seed = stringToInteger(options.seed);
// Something was passed as a seed but it wasn't an integer or string
} else if (options.seed !== undefined && options.seed !== null) {
throw new TypeError('The seed value must be an integer or string');
// No seed, reset the value outside.
} else {
seed = null;
}
var H,S,B;
// Check if we need to generate multiple colors
if (options.count !== null && options.count !== undefined) {
var totalColors = options.count,
colors = [];
options.count = null;
while (totalColors > colors.length) {
// Since we're generating multiple colors,
// incremement the seed. Otherwise we'd just
// generate the same color each time...
if (seed && options.seed) options.seed += 1;
colors.push(randomColor(options));
}
options.count = totalColors;
return colors;
}
// First we pick a hue (H)
H = pickHue(options);
// Then use H to determine saturation (S)
S = pickSaturation(H, options);
// Then use S and H to determine brightness (B).
B = pickBrightness(H, S, options);
// Then we return the HSB color in the desired format
return setFormat([H,S,B], options);
};
function pickHue (options) {
var hueRange = getHueRange(options.hue),
hue = randomWithin(hueRange);
// Instead of storing red as two seperate ranges,
// we group them, using negative numbers
if (hue < 0) {hue = 360 + hue;}
return hue;
}
function pickSaturation (hue, options) {
if (options.luminosity === 'random') {
return randomWithin([0,100]);
}
if (options.hue === 'monochrome') {
return 0;
}
var saturationRange = getSaturationRange(hue);
var sMin = saturationRange[0],
sMax = saturationRange[1];
switch (options.luminosity) {
case 'bright':
sMin = 55;
break;
case 'dark':
sMin = sMax - 10;
break;
case 'light':
sMax = 55;
break;
}
return randomWithin([sMin, sMax]);
}
function pickBrightness (H, S, options) {
var bMin = getMinimumBrightness(H, S),
bMax = 100;
switch (options.luminosity) {
case 'dark':
bMax = bMin + 20;
break;
case 'light':
bMin = (bMax + bMin)/2;
break;
case 'random':
bMin = 0;
bMax = 100;
break;
}
return randomWithin([bMin, bMax]);
}
function setFormat (hsv, options) {
switch (options.format) {
case 'hsvArray':
return hsv;
case 'hslArray':
return HSVtoHSL(hsv);
case 'hsl':
var hsl = HSVtoHSL(hsv);
return 'hsl('+hsl[0]+', '+hsl[1]+'%, '+hsl[2]+'%)';
case 'hsla':
var hslColor = HSVtoHSL(hsv);
return 'hsla('+hslColor[0]+', '+hslColor[1]+'%, '+hslColor[2]+'%, ' + Math.random() + ')';
case 'rgbArray':
return HSVtoRGB(hsv);
case 'rgb':
var rgb = HSVtoRGB(hsv);
return 'rgb(' + rgb.join(', ') + ')';
case 'rgba':
var rgbColor = HSVtoRGB(hsv);
return 'rgba(' + rgbColor.join(', ') + ', ' + Math.random() + ')';
default:
return HSVtoHex(hsv);
}
}
function getMinimumBrightness(H, S) {
var lowerBounds = getColorInfo(H).lowerBounds;
for (var i = 0; i < lowerBounds.length - 1; i++) {
var s1 = lowerBounds[i][0],
v1 = lowerBounds[i][1];
var s2 = lowerBounds[i+1][0],
v2 = lowerBounds[i+1][1];
if (S >= s1 && S <= s2) {
var m = (v2 - v1)/(s2 - s1),
b = v1 - m*s1;
return m*S + b;
}
}
return 0;
}
function getHueRange (colorInput) {
if (typeof parseInt(colorInput) === 'number') {
var number = parseInt(colorInput);
if (number < 360 && number > 0) {
return [number, number];
}
}
if (typeof colorInput === 'string') {
if (colorDictionary[colorInput]) {
var color = colorDictionary[colorInput];
if (color.hueRange) {return color.hueRange;}
}
}
return [0,360];
}
function getSaturationRange (hue) {
return getColorInfo(hue).saturationRange;
}
function getColorInfo (hue) {
// Maps red colors to make picking hue easier
if (hue >= 334 && hue <= 360) {
hue-= 360;
}
for (var colorName in colorDictionary) {
var color = colorDictionary[colorName];
if (color.hueRange &&
hue >= color.hueRange[0] &&
hue <= color.hueRange[1]) {
return colorDictionary[colorName];
}
} return 'Color not found';
}
function randomWithin (range) {
if (seed === null) {
return Math.floor(range[0] + Math.random()*(range[1] + 1 - range[0]));
} else {
//Seeded random algorithm from http://indiegamr.com/generate-repeatable-random-numbers-in-js/
var max = range[1] || 1;
var min = range[0] || 0;
seed = (seed * 9301 + 49297) % 233280;
var rnd = seed / 233280.0;
return Math.floor(min + rnd * (max - min));
}
}
function HSVtoHex (hsv){
var rgb = HSVtoRGB(hsv);
function componentToHex(c) {
var hex = c.toString(16);
return hex.length == 1 ? '0' + hex : hex;
}
var hex = '#' + componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]);
return hex;
}
function defineColor (name, hueRange, lowerBounds) {
var sMin = lowerBounds[0][0],
sMax = lowerBounds[lowerBounds.length - 1][0],
bMin = lowerBounds[lowerBounds.length - 1][1],
bMax = lowerBounds[0][1];
colorDictionary[name] = {
hueRange: hueRange,
lowerBounds: lowerBounds,
saturationRange: [sMin, sMax],
brightnessRange: [bMin, bMax]
};
}
function loadColorBounds () {
defineColor(
'monochrome',
null,
[[0,0],[100,0]]
);
defineColor(
'red',
[-26,18],
[[20,100],[30,92],[40,89],[50,85],[60,78],[70,70],[80,60],[90,55],[100,50]]
);
defineColor(
'orange',
[19,46],
[[20,100],[30,93],[40,88],[50,86],[60,85],[70,70],[100,70]]
);
defineColor(
'yellow',
[47,62],
[[25,100],[40,94],[50,89],[60,86],[70,84],[80,82],[90,80],[100,75]]
);
defineColor(
'green',
[63,178],
[[30,100],[40,90],[50,85],[60,81],[70,74],[80,64],[90,50],[100,40]]
);
defineColor(
'blue',
[179, 257],
[[20,100],[30,86],[40,80],[50,74],[60,60],[70,52],[80,44],[90,39],[100,35]]
);
defineColor(
'purple',
[258, 282],
[[20,100],[30,87],[40,79],[50,70],[60,65],[70,59],[80,52],[90,45],[100,42]]
);
defineColor(
'pink',
[283, 334],
[[20,100],[30,90],[40,86],[60,84],[80,80],[90,75],[100,73]]
);
}
function HSVtoRGB (hsv) {
// this doesn't work for the values of 0 and 360
// here's the hacky fix
var h = hsv[0];
if (h === 0) {h = 1;}
if (h === 360) {h = 359;}
// Rebase the h,s,v values
h = h/360;
var s = hsv[1]/100,
v = hsv[2]/100;
var h_i = Math.floor(h*6),
f = h * 6 - h_i,
p = v * (1 - s),
q = v * (1 - f*s),
t = v * (1 - (1 - f)*s),
r = 256,
g = 256,
b = 256;
switch(h_i) {
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5: r = v; g = p; b = q; break;
}
var result = [Math.floor(r*255), Math.floor(g*255), Math.floor(b*255)];
return result;
}
function HSVtoHSL (hsv) {
var h = hsv[0],
s = hsv[1]/100,
v = hsv[2]/100,
k = (2-s)*v;
return [
h,
Math.round(s*v / (k<1 ? k : 2-k) * 10000) / 100,
k/2 * 100
];
}
function stringToInteger (string) {
var total = 0
for (var i = 0; i !== string.length; i++) {
if (total >= Number.MAX_SAFE_INTEGER) break;
total += string.charCodeAt(i)
}
return total
}
return randomColor;
}));
// }}}
// {{{ getTable
(function($, undefined) {
'use strict';
var APP_NAME = 'getTable',
tables = []; // array of reference table
function parseTable(jq, index) {
var table = {rows: [], cols: [], cells: []},
iTable = typeof index === 'number' ? index : tables.length,
iColMax = -1, skip = {}, // {N<iRow>: {N<iCol>: B}}
elmTable = jq.get(0).nodeName.toLowerCase() === 'table' ? jq.get(0) :
(function() {
var elm = jq.closest('table');
return elm.length ? elm.get(0) : undefined;
})();
if (!elmTable) { return; }
table.elm = elmTable;
$(elmTable).data(APP_NAME, 'table:' + iTable);
function getRow(index) {
var i;
if (!table.rows[index]) {
for (i = 0; i <= index; i++)
{ table.rows[i] = table.rows[i] || {cells: [], table: table}; }
}
return table.rows[index];
}
function getCol(index) {
var i;
if (!table.cols[index]) {
for (i = 0; i <= index; i++)
{ table.cols[i] = table.cols[i] || {cells: [], table: table}; }
}
return table.cols[index];
}
$.each(elmTable.rows, function(iRow, elmRow) {
var row, col, cell, iCol, iCell = 0, elmCell, exRows, exCols, i, j;
$(elmRow).data(APP_NAME, 'table:' + iTable + ',row:' + iRow);
(function() {
var colsLen = 0;
$.each(elmRow.cells, function(i, cell) { colsLen += +cell.colSpan || 1; });
if (colsLen - 1 > iColMax) { iColMax = colsLen - 1; }
})();
for (iCol = 0; iCol <= iColMax; iCol++) {
if (skip[iRow] && skip[iRow][iCol]) { continue; }
if (elmCell = elmRow.cells[iCell++]) {
$(elmCell).data(APP_NAME, 'table:' + iTable + ',cell:' + table.cells.length);
cell = {elm: elmCell, rows: [], cols: [], table: table, iRow: iRow, iCol: iCol};
// extending via colspan="0", colgroup and rowspan="0" isn't supported.
// http://dev.w3.org/html5/spec/single-page.html#attr-tdth-colspan
exRows = (+elmCell.rowSpan || 1) - 1;
exCols = (+elmCell.colSpan || 1) - 1;
for (i = 0; i <= exRows; i++) {
row = getRow(iRow + i);
cell.rows.push(row);
row.cells.push(cell);
}
for (i = 0; i <= exCols; i++) {
col = getCol(iCol + i);
cell.cols.push(col);
col.cells.push(cell);
}
for (i = 1; i <= exRows; i++) {
skip[iRow + i] = skip[iRow + i] || {};
for (j = 0; j <= exCols; j++) { skip[iRow + i][iCol + j] = true; }
}
iCol += exCols;
table.cells.push(cell);
}
}
});
// cross line cells
$.each(table.cells, function(i, cell) {
var xCells = [cell];
$.each(cell.rows.concat(cell.cols),
function(i, rowCol) { uniqueConcat(xCells, rowCol.cells); });
cell.xCells = xCells;
});
$.each(table.rows,
function(i, row) { row.cells.sort(function(a, b) { return a.iCol - b.iCol; }); });
$.each(table.cols,
function(i, col) { col.cells.sort(function(a, b) { return a.iRow - b.iRow; }); });
tables[iTable] = table;
return table;
}
function uniqueConcat(arrBase, arrNew) {
$.each(arrNew, function(i, elm) {
if ($.inArray(elm, arrBase) < 0) { arrBase.push(elm); }
});
}
// {table: N, row: N, cell: N}
function parseIndex(jq) {
var index = {}, indexText = jq.data(APP_NAME) || '',
re = /\b(\w+):(\d+)/g, matches;
while ((matches = re.exec(indexText)) !== null) {
index[matches[1]] = +matches[2];
}
return index;
}
function getParse(jq, force) {
var iTable = parseIndex(jq).table;
return force || typeof iTable !== 'number' || !tables[iTable] ?
parseTable(jq, iTable) : tables[iTable];
}
function isTable(tagName) { return tagName === 'table'; }
function isRow(tagName) { return tagName === 'tr'; }
function isCell(tagName) { return tagName === 'td' || tagName === 'th'; }
function isSection(tagName) { return tagName === 'thead' || tagName === 'tfoot' || tagName === 'tbody'; }
function isAny(tagName)
{ return isTable(tagName) || isRow(tagName) || isCell(tagName) || isSection(tagName); }
// Array of cell objects -> Array of elements
function cells2Elms(cells) { return $.map(cells, function(cell) { return cell.elm; }); }
// Array of cell objects -> jQuery object
function cells2Jq(cells) { return $(cells2Elms(cells)); }
function selectCells(jq) {
var elms = [];
jq.each(function() {
var that = $(this), tagName = that.get(0).nodeName.toLowerCase(), table;
if (isTable(tagName) && (table = getParse(that))) {
uniqueConcat(elms, cells2Elms(table.cells));
} else if (isRow(tagName) && (table = getParse(that))) {
uniqueConcat(elms, cells2Elms(table.rows[parseIndex(that).row].cells));
} else if (isCell(tagName) && (table = getParse(that))) {
uniqueConcat(elms, [table.cells[parseIndex(that).cell].elm]); // same as that.get(0)
} else if (isSection(tagName) && (table = getParse(that))) {
$.each(that.get(0).rows, function(i, elmRow) {
uniqueConcat(elms, cells2Elms(table.rows[parseIndex($(elmRow)).row].cells));
});
}
});
return $(elms.length ? elms : null);
}
function selectXCells(jq) {
var elms = [];
jq.each(function() {
var that = $(this), tagName = that.get(0).nodeName.toLowerCase(), table;
if (isCell(tagName) && (table = getParse(that))) {
uniqueConcat(elms, cells2Elms(table.cells[parseIndex(that).cell].xCells));
}
});
return $(elms.length ? elms : null);
}
function selectRows(jq) {
return $.map(selectRowsArray(jq), function(row) { return cells2Jq(row.cells); });
}
function selectRowsCells(jq) {
var elms = [];
$.each(selectRowsArray(jq),
function(i, row) { uniqueConcat(elms, cells2Elms(row.cells)); });
return $(elms.length ? elms : null);
}
function selectRowsArray(jq) {
var rows = [];
jq.each(function() {
var that = $(this), tagName = that.get(0).nodeName.toLowerCase(), table;
if (isTable(tagName) && (table = getParse(that))) {
uniqueConcat(rows, table.rows);
} else if (isRow(tagName) && (table = getParse(that))) {
uniqueConcat(rows, [table.rows[parseIndex(that).row]]);
} else if (isCell(tagName) && (table = getParse(that))) {
uniqueConcat(rows, table.cells[parseIndex(that).cell].rows);
} else if (isSection(tagName) && (table = getParse(that))) {
uniqueConcat(rows, $.map(that.get(0).rows, function(elmRow)
{ return table.rows[parseIndex($(elmRow)).row]; }));
}
});
return rows;
}
function selectCols(jq) {
return $.map(selectColsArray(jq), function(col) { return cells2Jq(col.cells); });
}
function selectColsCells(jq) {
var elms = [];
$.each(selectColsArray(jq),
function(i, col) { uniqueConcat(elms, cells2Elms(col.cells)); });
return $(elms.length ? elms : null);
}
function selectColsArray(jq) {
var cols = [];
jq.each(function() {
var that = $(this), tagName = that.get(0).nodeName.toLowerCase(), table;
if ((isTable(tagName) || isRow(tagName) || isSection(tagName)) &&
(table = getParse(that))) {
uniqueConcat(cols, table.cols);
} else if (isCell(tagName) && (table = getParse(that))) {
uniqueConcat(cols, table.cells[parseIndex(that).cell].cols);
}
});
return cols;
}
function selectTable(jq) {
var elms = [];
jq.each(function() {
var that = $(this), tagName = that.get(0).nodeName.toLowerCase(), table;
if (isAny(tagName) && (table = getParse(that))) {
uniqueConcat(elms, [table.elm]); // same as that.get(0)
}
});
return $(elms.length ? elms : null);
}
function reParse(jq) {
return jq.each(function() {
var that = $(this), tagName = that.get(0).nodeName.toLowerCase();
if (isAny(tagName)) { getParse(that, true); }
});
}
$.fn[APP_NAME] = function(action) {
return (
action === 'cells' ? selectCells(this) :
action === 'xCells' ? selectXCells(this) :
action === 'rows' ? selectRows(this) :
action === 'rowsCells' ? selectRowsCells(this) :
action === 'cols' ? selectCols(this) :
action === 'colsCells' ? selectColsCells(this) :
action === 'table' ? selectTable(this) :
reParse(this));
};
})(jQuery);
// }}}
// {{{ sprintf
/* globals window, exports, define */
(function(window) {
'use strict'
var re = {
not_string: /[^s]/,
not_bool: /[^t]/,
not_type: /[^T]/,
not_primitive: /[^v]/,
number: /[diefg]/,
numeric_arg: /bcdiefguxX/,
json: /[j]/,
not_json: /[^j]/,
text: /^[^\x25]+/,
modulo: /^\x25{2}/,
placeholder: /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijostTuvxX])/,
key: /^([a-z_][a-z_\d]*)/i,
key_access: /^\.([a-z_][a-z_\d]*)/i,
index_access: /^\[(\d+)\]/,
sign: /^[\+\-]/
}
function sprintf() {
var key = arguments[0], cache = sprintf.cache
if (!(cache[key] && cache.hasOwnProperty(key))) {
cache[key] = sprintf.parse(key)
}
return sprintf.format.call(null, cache[key], arguments)
}
sprintf.format = function(parse_tree, argv) {
var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length, is_positive = true, sign = ''
for (i = 0; i < tree_length; i++) {
node_type = get_type(parse_tree[i])
if (node_type === 'string') {
output[output.length] = parse_tree[i]
}
else if (node_type === 'array') {
match = parse_tree[i] // convenience purposes only
if (match[2]) { // keyword argument
arg = argv[cursor]
for (k = 0; k < match[2].length; k++) {
if (!arg.hasOwnProperty(match[2][k])) {
throw new Error(sprintf('[sprintf] property "%s" does not exist', match[2][k]))
}
arg = arg[match[2][k]]
}
}
else if (match[1]) { // positional argument (explicit)
arg = argv[match[1]]
}
else { // positional argument (implicit)
arg = argv[cursor++]
}
if (re.not_type.test(match[8]) && re.not_primitive.test(match[8]) && get_type(arg) == 'function') {
arg = arg()
}
if (re.numeric_arg.test(match[8]) && (get_type(arg) != 'number' && isNaN(arg))) {
throw new TypeError(sprintf("[sprintf] expecting number but found %s", get_type(arg)))
}
if (re.number.test(match[8])) {
is_positive = arg >= 0
}
switch (match[8]) {
case 'b':
arg = parseInt(arg, 10).toString(2)
break
case 'c':
arg = String.fromCharCode(parseInt(arg, 10))
break
case 'd':
case 'i':
arg = parseInt(arg, 10)
break
case 'j':
arg = JSON.stringify(arg, null, match[6] ? parseInt(match[6]) : 0)
break
case 'e':
arg = match[7] ? parseFloat(arg).toExponential(match[7]) : parseFloat(arg).toExponential()
break
case 'f':
arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg)
break
case 'g':
arg = match[7] ? parseFloat(arg).toPrecision(match[7]) : parseFloat(arg)
break
case 'o':
arg = arg.toString(8)
break
case 's':
arg = String(arg)
arg = (match[7] ? arg.substring(0, match[7]) : arg)
break
case 't':
arg = String(!!arg)
arg = (match[7] ? arg.substring(0, match[7]) : arg)
break
case 'T':
arg = get_type(arg)
arg = (match[7] ? arg.substring(0, match[7]) : arg)
break
case 'u':
arg = parseInt(arg, 10) >>> 0
break
case 'v':
arg = arg.valueOf()
arg = (match[7] ? arg.substring(0, match[7]) : arg)
break
case 'x':
arg = parseInt(arg, 10).toString(16)
break
case 'X':
arg = parseInt(arg, 10).toString(16).toUpperCase()
break
}
if (re.json.test(match[8])) {
output[output.length] = arg
}
else {
if (re.number.test(match[8]) && (!is_positive || match[3])) {
sign = is_positive ? '+' : '-'
arg = arg.toString().replace(re.sign, '')
}
else {
sign = ''
}
pad_character = match[4] ? match[4] === '0' ? '0' : match[4].charAt(1) : ' '
pad_length = match[6] - (sign + arg).length
pad = match[6] ? (pad_length > 0 ? str_repeat(pad_character, pad_length) : '') : ''
output[output.length] = match[5] ? sign + arg + pad : (pad_character === '0' ? sign + pad + arg : pad + sign + arg)
}
}
}
return output.join('')
}
sprintf.cache = {}
sprintf.parse = function(fmt) {
var _fmt = fmt, match = [], parse_tree = [], arg_names = 0
while (_fmt) {
if ((match = re.text.exec(_fmt)) !== null) {
parse_tree[parse_tree.length] = match[0]
}
else if ((match = re.modulo.exec(_fmt)) !== null) {
parse_tree[parse_tree.length] = '%'
}
else if ((match = re.placeholder.exec(_fmt)) !== null) {
if (match[2]) {
arg_names |= 1
var field_list = [], replacement_field = match[2], field_match = []
if ((field_match = re.key.exec(replacement_field)) !== null) {
field_list[field_list.length] = field_match[1]
while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
if ((field_match = re.key_access.exec(replacement_field)) !== null) {
field_list[field_list.length] = field_match[1]
}
else if ((field_match = re.index_access.exec(replacement_field)) !== null) {
field_list[field_list.length] = field_match[1]
}
else {
throw new SyntaxError("[sprintf] failed to parse named argument key")
}
}
}
else {
throw new SyntaxError("[sprintf] failed to parse named argument key")
}
match[2] = field_list
}
else {
arg_names |= 2
}
if (arg_names === 3) {
throw new Error("[sprintf] mixing positional and named placeholders is not (yet) supported")
}
parse_tree[parse_tree.length] = match
}
else {
throw new SyntaxError("[sprintf] unexpected placeholder")
}
_fmt = _fmt.substring(match[0].length)
}
return parse_tree
}
var vsprintf = function(fmt, argv, _argv) {
_argv = (argv || []).slice(0)
_argv.splice(0, 0, fmt)
return sprintf.apply(null, _argv)
}
/**
* helpers
*/
function get_type(variable) {
if (typeof variable === 'number') {
return 'number'
}
else if (typeof variable === 'string') {
return 'string'
}
else {
return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase()
}
}
var preformattedPadding = {
'0': ['', '0', '00', '000', '0000', '00000', '000000', '0000000'],
' ': ['', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
'_': ['', '_', '__', '___', '____', '_____', '______', '_______'],
}
function str_repeat(input, multiplier) {
if (multiplier >= 0 && multiplier <= 7 && preformattedPadding[input]) {
return preformattedPadding[input][multiplier]
}
return Array(multiplier + 1).join(input)
}
/**
* export to either browser or node.js
*/
if (typeof exports !== 'undefined') {
exports.sprintf = sprintf
exports.vsprintf = vsprintf
}
else {
window.sprintf = sprintf
window.vsprintf = vsprintf
if (typeof define === 'function' && define.amd) {
define(function() {
return {
sprintf: sprintf,
vsprintf: vsprintf
}
})
}
}
})(typeof window === 'undefined' ? this : window);
// }}}
// }}}
var lessons = [[], [], [], [], []];
$("table.print > tbody > tr:first > *:gt(1)").each(function(day) { // All headers, except the first two
$(this).getTable("colsCells").filter(":gt(0):not(.printLight)").each(function() {
table = [];
$("> table.inline > tbody > tr", $(this)).each(function() {
table.push(row2 = []);
$("td", $(this)).each(function() {
row2.push($(this).text().trim());
});
});
var name, start, end, room, name2, teacher, term;
if(table[1].length == 1) {
name = table[0][0];
start = table[1][0];
end = table[2][0].substring(1);
room = table[3][0];
name2 = table[4][0];
} else {
name = table[0][0];
start = table[0][1];
end = table[1][1].substring(1);
room = table[1][0];
if(table.length > 2) name2 = table[2][0];
if(table.length > 3) teacher = table[3][0];
}
function ptime(stamp) {
var p = stamp.split(":");
return parseInt(p[0], 10) * 60 + parseInt(p[1], 10);
}
lessons[day].push({
"name": name,
"name2": (name2 || name).replace(/^IV-/, "").replace(/-.*$/, "").trim(),
"start": ptime(start),
"end": ptime(end),
"room": room,
"teacher": (teacher || "").toLowerCase(),
});
});
});
var start = 8*60, end = 17*60;
function percent(n) (n / (end - start) * 100) + "%"
function time(n) sprintf("%02d:%02d", Math.floor(n / 60), Math.floor(n % 60))
function schedule(dayName, lessons) {
var el = $()
for(l of lessons) {
var seed = 0;
for(n in l.name2) seed ^= l.name2.charCodeAt(n) << (8 * (n % 8));
el = el.add(
$("<div class=lesson>")
.css({
"top": percent(l["start"] - 8 * 60),
"height": percent(l["end"] - l["start"]),
"background-color": randomColor({ "luminosity": "light", "seed": seed & 0xFFFFFFFF })
})
.append($("<div class=content>")
.append($("<div>").text(l.name2))
.append($("<div>").text(time(l.start) + '-' + time(l.end)))
.append($("<div>").text(l.room))
.append($("<div>").text(l.teacher))
)
);
}
console.log(el)
return $("<div class='col sched'>")
.append($("<div class=head>").text(dayName))
.append($("<div class=col-cont>").append(el))
}
function ruler() {
var el = $();
var n = 30;
for(var i = start; i < end; i += n)
el = el.add($("<div class=ruler-item>").css("height", percent(n)).text(time(i)))
return $("<div class='col ruler-col'>")
.append($("<div class=head>").text($(".printLarge").text().trim().split(" ").pop()))
.append($("<div class=col-cont>").append(el))
}
var shadow = "0 0 1px 0px #0F0F0F"
var css = `
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
body {
display: flex;
flex-direction: row;
font: 10px sans-serif;
}
.head {
box-shadow: ${shadow} inset, ${shadow};
overflow: hidden;
background: white;
font-size: 150%;
padding: .25em;
height: 1em;
flex: 0 0 auto;
}
.col {
align-self: stretch;
display: flex;
flex-direction: column;
}
.col-cont {
box-shadow: ${shadow} inset;
overflow: hidden;
position: relative;
flex: 1 0 auto;
}
.sched {
flex: 1 0 auto;
text-align: center;
}
.sched > .col-cont {
background: #AFAFAF;
}
.lesson {
position: absolute;
width: 100%;
box-shadow: ${shadow} inset, ${shadow};
overflow: hidden;
display: flex;
flex-direction: row;
justify-content: center;
align-content: center;
align-items: center;
}
.ruler {
flex: 0 0 auto;
width: 8em;
}
.ruler > .col-cont {
}
.ruler-item {
box-shadow: ${shadow} inset, ${shadow};
overflow: hidden;
display: flex;
flex-direction: row;
justify-content: center;
align-content: center;
align-items: center;
}
`
$(":root").replaceWith(
$("<html>")
.append(
$("<head>")
.append($("<meta charset=utf-8>"))
.append($("<title>").text("Schedule"))
.append($("<style>").html(css))
)
.append(
$("<body>")
.append(ruler())
.append(schedule("Mon", lessons[0]))
.append(schedule("Tue", lessons[1]))
.append(schedule("Wed", lessons[2]))
.append(schedule("Thu", lessons[3]))
.append(schedule("Fri", lessons[4]))
)
);
})();
// vim: foldmethod=marker
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment