├── lib ├── browsercheck.js ├── date.format-min.js ├── DML_table-min.js ├── DML_sidemenue.js ├── date.format.js ├── DML_indexMenue.js ├── DML_jellyfish.js ├── DML_onlineEditor.js ├── DML_markdown.js ├── DML_table.js ├── DML-min.js ├── w3.css └── DML.js ├── README.md └── LICENSE /lib/browsercheck.js: -------------------------------------------------------------------------------- 1 | // Browser check for ES6 2 | function get_browser() { 3 | var ua=navigator.userAgent,tem,M=ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; 4 | if(/trident/i.test(M[1])){ 5 | tem=/\brv[ :]+(\d+)/g.exec(ua) || []; 6 | return {name:'IE',version:(tem[1]||'')}; 7 | } 8 | if(M[1]==='Chrome'){ 9 | tem=ua.match(/\bOPR|Edge\/(\d+)/) 10 | if(tem!=null) {return {name:'Opera', version:tem[1]};} 11 | } 12 | M=M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?']; 13 | if((tem=ua.match(/version\/(\d+)/i))!=null) {M.splice(1,1,tem[1]);} 14 | return { 15 | name: M[0], 16 | version: M[1] 17 | }; 18 | } 19 | 20 | 21 | try { 22 | sUsrAg = navigator.userAgent; 23 | new Function("(a = 0) => a"); 24 | } 25 | catch (err) { 26 | document.writeln("

Please update your Browser!

"); 27 | let b = get_browser(); 28 | document.writeln("- Current: "+b.name+", version "+b.version+"

"); 29 | document.writeln("
"); 30 | document.writeln("Full ECMAScript 6 (ES2015) support required
"); 31 | document.writeln("


"); 32 | } 33 | -------------------------------------------------------------------------------- /lib/date.format-min.js: -------------------------------------------------------------------------------- 1 | var dateFormat=function(){var t=/d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,e=/\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,a=/[^-+\dA-Z]/g,m=function(t,e){for(t=String(t),e=e||2;t.length99?Math.round(c/10):c),t:l<12?"a":"p",tt:l<12?"am":"pm",T:l<12?"A":"P",TT:l<12?"AM":"PM",Z:r?"UTC":(String(d).match(e)||[""]).pop().replace(a,""),o:(g>0?"-":"+")+m(100*Math.floor(Math.abs(g)/60)+Math.abs(g)%60,4),S:["th","st","nd","rd"][i%10>3?0:(i%100-i%10!=10)*i%10]};return n.replace(t,(function(t){return t in S?S[t]:t.slice(1,t.length-1)}))}}();dateFormat.masks={default:"ddd mmm dd yyyy HH:MM:ss",shortDate:"m/d/yy",mediumDate:"mmm d, yyyy",longDate:"mmmm d, yyyy",fullDate:"dddd, mmmm d, yyyy",shortTime:"h:MM TT",mediumTime:"h:MM:ss TT",longTime:"h:MM:ss TT Z",isoDate:"yyyy-mm-dd",isoTime:"HH:MM:ss",isoDateTime:"yyyy-mm-dd'T'HH:MM:ss",isoUtcDateTime:"UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"},dateFormat.i18n={dayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","January","February","March","April","May","June","July","August","September","October","November","December"]},Date.prototype.format=function(t,e){return dateFormat(this,t,e)}; -------------------------------------------------------------------------------- /lib/DML_table-min.js: -------------------------------------------------------------------------------- 1 | function table(e,t,l={}){return new _table(e,t,l)}class _table extends HTMLTableElement{constructor(e,t,l){super(),this._tabletimeout={},0==l?(this.showHead=!1,l={}):this.showHead=_init(l.showHead,!0),setOptions(this,l,{tableAttrib:"border: 1px solid black; ",headAttrib:"background-color: silver; ",bodyAttrib:"",cellAttrib:"",onCellClick:null,canSelect:!1,selectColor:"silver",invalidSelectColor:"#CC6060",invalidColor:"#FF8070",selectedRow:-1,selectedCol:-1}),this.rowSelect=_init(l.rowSelect,!0),this._rowid=l.rowid||[],this._rowvalue=l.rowvalue||[],this._rowvalid=l.rowvalid||[],this.onclick=e=>{if(e.srcElement.cellIndex<0)return;let t=e.srcElement.cellIndex,l=e.srcElement.parentElement.rowIndex;this.select(t,l)},this.doSelect=e=>{if(!this.canSelect)return;let t=e.target,l=t.parentElement.rowIndex,s=t.cellIndex;this.select(s,l)},setAttributes(this,this.tableAttrib),this.buildTable(e,t),l.head&&(this.head=l.head),l.body&&(this.body=l.body),this.select(this.selectedCol,this.selectedRow),l.onSelect&&(this.onSelect=l.onSelect),this.colorize(),appendBase(this)}getrowvalid(e){return arrayvalue(this._rowvalid,e,!0)}setrowvalid(e,t){this._rowvalid[e]=t,clearTimeout(this._tabletimeout),this._tabletimeout=setTimeout((()=>{this.colorize()}),10)}colorize(){for(let e in this.rows){let t=this.rows[e],l=this.getrowvalid(e);for(let e=0;e Aufbau 40 | 41 | // Callback Mouse leaves area 42 | this.base.onmouseleave = (e) => { 43 | let src = this.base.firstElementChild; 44 | do { 45 | if (Number(src.name) > 0) { 46 | src.style.display = "none"; 47 | } 48 | src = src.nextSibling; 49 | } while (src); 50 | }; 51 | 52 | // return this.base; 53 | 54 | } 55 | /*------------------------------------------------------ 56 | Menuebaum rekursiv erzeugen 57 | ------------------------------------------------------*/ 58 | _mkMenue(topics, level,_style) { 59 | Object.keys(topics).map(key => { // alle Topics durchgehen 60 | let s = "text-align: left;" 61 | + "padding: 5px; " 62 | + "width: 100%;" 63 | + "display: inline-block; " 64 | + "text-decoration: none;" 65 | 66 | // + "transition: opacity 0.3s;" 67 | + _style 68 | 69 | if (level > 0) { 70 | s += "margin-left: " + 10 * level + "px;"; 71 | s += "display: none;" 72 | } 73 | // else s += "z-index: 0;" 74 | let lnk; 75 | let href = topics[key] 76 | if (typeof (href) == "string") { 77 | if (href.includes("()")){ 78 | lnk = link(key, "javascript:"+href,s); // Aktiven functions-Link erzeugen 79 | } else 80 | lnk = link(key, href, s); // URL link erzeugen 81 | } else { 82 | lnk = link(key, "javascript:void(0);", s); // Element für Submenue 83 | this._mkMenue(href, level + 1,_style); // ---> Rekursion 84 | } 85 | lnk.name = level; 86 | 87 | /*------------------------------------------------------ 88 | Mouse enter Callback function 89 | ------------------------------------------------------*/ 90 | lnk.onmouseenter = (e) => { 91 | let src = e.srcElement; 92 | let level = Number(src.name); 93 | while (src.nextSibling) { 94 | let sib = src.nextSibling; 95 | let newLevel = Number(sib.name); 96 | if (newLevel <= level) return; 97 | if (newLevel == level + 1) { 98 | sib.style.display = "inline-block"; 99 | } 100 | src = sib; 101 | } 102 | } 103 | }) 104 | } 105 | 106 | 107 | } -------------------------------------------------------------------------------- /lib/date.format.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Date Format 1.2.3 3 | * (c) 2007-2009 Steven Levithan 4 | * MIT license 5 | * 6 | * Includes enhancements by Scott Trenda 7 | * and Kris Kowal 8 | * 9 | * Accepts a date, a mask, or a date and a mask. 10 | * Returns a formatted version of the given date. 11 | * The date defaults to the current date/time. 12 | * The mask defaults to dateFormat.masks.default. 13 | */ 14 | 15 | var dateFormat = function () { 16 | var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, 17 | timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, 18 | timezoneClip = /[^-+\dA-Z]/g, 19 | pad = function (val, len) { 20 | val = String(val); 21 | len = len || 2; 22 | while (val.length < len) val = "0" + val; 23 | return val; 24 | }; 25 | 26 | // Regexes and supporting functions are cached through closure 27 | return function (date, mask, utc) { 28 | var dF = dateFormat; 29 | 30 | // You can't provide utc if you skip other args (use the "UTC:" mask prefix) 31 | if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) { 32 | mask = date; 33 | date = undefined; 34 | } 35 | 36 | // Passing date through Date applies Date.parse, if necessary 37 | date = date ? new Date(date) : new Date; 38 | if (isNaN(date)) throw SyntaxError("invalid date"); 39 | 40 | mask = String(dF.masks[mask] || mask || dF.masks["default"]); 41 | 42 | // Allow setting the utc argument via the mask 43 | if (mask.slice(0, 4) == "UTC:") { 44 | mask = mask.slice(4); 45 | utc = true; 46 | } 47 | 48 | var _ = utc ? "getUTC" : "get", 49 | d = date[_ + "Date"](), 50 | D = date[_ + "Day"](), 51 | m = date[_ + "Month"](), 52 | y = date[_ + "FullYear"](), 53 | H = date[_ + "Hours"](), 54 | M = date[_ + "Minutes"](), 55 | s = date[_ + "Seconds"](), 56 | L = date[_ + "Milliseconds"](), 57 | o = utc ? 0 : date.getTimezoneOffset(), 58 | flags = { 59 | d: d, 60 | dd: pad(d), 61 | ddd: dF.i18n.dayNames[D], 62 | dddd: dF.i18n.dayNames[D + 7], 63 | m: m + 1, 64 | mm: pad(m + 1), 65 | mmm: dF.i18n.monthNames[m], 66 | mmmm: dF.i18n.monthNames[m + 12], 67 | yy: String(y).slice(2), 68 | yyyy: y, 69 | h: H % 12 || 12, 70 | hh: pad(H % 12 || 12), 71 | H: H, 72 | HH: pad(H), 73 | M: M, 74 | MM: pad(M), 75 | s: s, 76 | ss: pad(s), 77 | l: pad(L, 3), 78 | L: pad(L > 99 ? Math.round(L / 10) : L), 79 | t: H < 12 ? "a" : "p", 80 | tt: H < 12 ? "am" : "pm", 81 | T: H < 12 ? "A" : "P", 82 | TT: H < 12 ? "AM" : "PM", 83 | Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""), 84 | o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), 85 | S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10] 86 | }; 87 | 88 | return mask.replace(token, function ($0) { 89 | return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); 90 | }); 91 | }; 92 | }(); 93 | 94 | // Some common format strings 95 | dateFormat.masks = { 96 | "default": "ddd mmm dd yyyy HH:MM:ss", 97 | shortDate: "m/d/yy", 98 | mediumDate: "mmm d, yyyy", 99 | longDate: "mmmm d, yyyy", 100 | fullDate: "dddd, mmmm d, yyyy", 101 | shortTime: "h:MM TT", 102 | mediumTime: "h:MM:ss TT", 103 | longTime: "h:MM:ss TT Z", 104 | isoDate: "yyyy-mm-dd", 105 | isoTime: "HH:MM:ss", 106 | isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", 107 | isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" 108 | }; 109 | 110 | // Internationalization strings 111 | dateFormat.i18n = { 112 | dayNames: [ 113 | "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 114 | "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" 115 | ], 116 | monthNames: [ 117 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 118 | "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" 119 | ] 120 | }; 121 | 122 | // For convenience... 123 | Date.prototype.format = function (mask, utc) { 124 | return dateFormat(this, mask, utc); 125 | }; 126 | 127 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DML 2 | An Object Oriented Web Programming Framework 3 | 4 | DML is a new and radical approach to make web programming more efficient. Frameworks like VUE or REACT use Javascript to create dynamic content too, but need their own and very special ecosystem. This brings additional complexity to web design - and a long and steep learning curve. 5 | 6 | DML is different, it was designed to make web programming easier and more efficient. Why use different languages like HTML,CSS,JS,AJAX,JQUERY and PHP to solve 1 single task? 7 | 8 | The initial approach was simple, but was found to be amazingly useful: DML exposes (most) HTML-tags as Javascript functions. So, instead of creating a `

Headline

`-tag you can write `h1("Headline")` to create a DOM-object in Javascript now. What is the advantage, as the result will be identical? 9 | 10 | All DML-functions return a reference to the newly created object, that can directly be assigned to a JS-variable. In standard web sites - as html and JS are parsed by different systems - we need some ID´s to communicate between HTML and JS. The usual way is 11 | ``` 12 |

Headline

13 | 17 | ``` 18 | BUT (!!!) id´s are always! globally scoped, so encapsulation is simply not possible in web sites. With DML, things are different: you can write the same script as follows 19 | 20 | ``` 21 | 25 | ``` 26 | Sounds like a small advantage, but in fact, this is a huge step! DML brings Javascript closer to the DOM, which has a great impact: DOM-elements are created as part of Javascript object, so they can be fully encapsulated too. No need to create a virtual DOM, no need to use a shadow DOM. Pleas try out to see the advantages. DML-websites run smooth without unnecessary page refreshes even with very complex content. The DML-homepage was created only using DML! 27 | 28 | Don't be fooled by the apparent simplicity: DML provides a complete design platform to create web components and templates - just in a very different way you may be used to. This lib is made for OO-programmers rather than for web designers. Just add the DML-Library to your website and start HTML-Programming... And let the power of OO be with you! 29 | 30 | A minimal DML page will look like this: 31 | 32 | ``` 33 | 34 | 35 | 36 | 37 | 38 | title 39 | 40 | 41 | 42 | 43 | 44 | 48 | 49 | 50 | 51 | ``` 52 | 53 | 54 | ## DML in a nutshell 55 | 1. DML implements only a very small set of "generic" functions to let you use the HTML DOM API in a more "natural" way. Most HTML-tags are implemented as javascript functions: h1() creates a headline, p() create a paragraph and so on. 56 | 2. All DML-function return a reference to the DOM-element they just created. No need for ID´s, Classes and complicated Javascript functions to retrieve DOM references any more. 57 | 3. DOM references are returned as LOCAL variables, removing unwanted side effects and naming conflicts. DOM elements created inside a class are owned only by the instantiated object. True encapsulation can be realized. 58 | 4. Functions act as templates: Groups of DOM elements can be created by functions. As functions can use any kind of logic, functional templating is far more flexible than static templates. 59 | 5. Classes can be used to implement DOM objects AND event logic. Class objects can therefore generate very complex web objects, that are still completely encapsulated. This is the true basis for OO and to reuse web components. 60 | 6. The DML library is organized in multiple script libraries. The first - and always necessary - is DML.js. Functional units (like Menues, Table handlers etc.) are put together in separate units that usually contain only one class definition. General scripts should reside in the "lib"-folder, project specific scripts should be placed on the same level as your html-files. 61 | 7. Yes - it´s true: DML creates dynamic web pages by direct DOM manipulation, which is not search engine friendly (except with google, which can handle this). But this is not different from React or Vue. 62 | 63 | For more information see: https://efpage.de/DML/DML_homepage/ 64 | -------------------------------------------------------------------------------- /lib/DML_indexMenue.js: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------ 2 | Menue im aktuellen Kontext erzeugen 3 | Topics definiert die Struktur als JSON: 4 | DML_indexMenue 5 | 6 | Key ist der Text es Menue-Eintrages, Value der Link 7 | Wird eine Klammer mit angegeben, dann wird der link als Funktionsaufruf interpretiert. 8 | 9 | ------------------------------------------------------*/ 10 | function DML_indexMenue(parent, mainpage, topics, _style = "") { 11 | return new _sideMenue(parent, mainpage,topics, _style); 12 | } 13 | class _sideMenue { 14 | /*------------------------------------------------------ 15 | constructor: Menue rekursiv aufbauen 16 | das Menue wird in parent aufgebaut, 17 | Zielseite für scrolling is mainpage 18 | ------------------------------------------------------*/ 19 | constructor(parent, mainpage, topics, _style = "") { 20 | this.base = selectBase(div("")); // Invisible base area 21 | 22 | mainpage.onscroll = () => { 23 | for (let i in this.items) { 24 | let t = this.items[i].link.getBoundingClientRect().top 25 | if (t > screen.height / 3) { 26 | this.select(Math.max(0, i - 1)) 27 | return 28 | } 29 | } 30 | } 31 | 32 | 33 | 34 | this._mkMenue(parent, topics, _style); //--> Aufbau 35 | 36 | // Callback Mouse leaves area 37 | this.base.onmouseleave = (e) => { 38 | return 39 | let src = this.base.firstElementChild; 40 | do { 41 | if (src.level > 1) { 42 | src.style.display = "none"; 43 | } 44 | src = src.nextSibling; 45 | } while (src); 46 | }; 47 | 48 | unselectBase(); 49 | 50 | } 51 | /*------------------------------------------------------ 52 | Menuebaum erzeugen 53 | ------------------------------------------------------*/ 54 | _mkMenue(parent, topics, _style) { 55 | // alle Topics durchgehen 56 | selectBase(parent) 57 | this.items = []; 58 | for (let i in topics) { 59 | let item = topics[i] 60 | let s = "text-align: left;" 61 | + "display: block; " 62 | + "text-decoration: none;" 63 | + "overflow: hidden;" 64 | +"margin-left: " + 10 * item.level + "px;"; 65 | 66 | // + "transition: opacity 0.3s;" 67 | 68 | 69 | if (item.level > 1) { 70 | 71 | // s += "display: none;" 72 | 73 | } 74 | 75 | 76 | let lnk = span(item.text, _style); // URL link erzeugen 77 | lnk.classList.add("Level" + item.level); 78 | lnk.Level = item.level 79 | lnk.link = item.link; 80 | lnk.level = item.level; 81 | lnk.nr = i; 82 | setAttributes(lnk, s) 83 | this.items[i] = lnk // save internal list for requests 84 | 85 | /*------------------------------------------------------ 86 | Mouse enter Callback function 87 | ------------------------------------------------------*/ 88 | /* lnk.onmouseenter = (e) => { 89 | let src = e.srcElement; 90 | this.select(src.nr) 91 | } 92 | */ lnk.onclick = (e) => { 93 | e.srcElement.link.scrollIntoView({ behavior: "smooth" }); 94 | } 95 | } 96 | unselectBase() 97 | } 98 | /*------------------------------------------------------ 99 | find list index of target 100 | ------------------------------------------------------*/ 101 | findIndex(target) { 102 | for (let i in this.items) { 103 | if (this.items[i].link == target) 104 | return (i) 105 | } 106 | return (-1) 107 | } 108 | /*------------------------------------------------------ 109 | Select one item 110 | ------------------------------------------------------*/ 111 | select(nr) { 112 | // Reset all items 113 | let item 114 | for (let _i in this.items) { 115 | item = this.items[_i] 116 | item.style.backgroundColor = "" 117 | } 118 | // Mark item[nr] 119 | this.items[nr].style.backgroundColor = "rgba(0,0,0,0.5)" 120 | 121 | let level = this.items[nr].level; 122 | 123 | return 124 | //search previous main item 125 | let i = nr 126 | while ((i > 0) && (this.items[i].level > 1)) 127 | i--; 128 | // hide tree above 129 | /* for (let k = 0; k < i; k++) 130 | if (this.items[k].level > 1) { 131 | this.items[k].style.display = "none" 132 | this.items[k].style.opacity = 0; 133 | } 134 | */ // Make tree visible until nr 135 | for (; i < nr; i++) { 136 | this.items[i].style.display = "block" 137 | this.items[i].style.opacity = 1; 138 | } 139 | // Make next lower level visibe 140 | while (this.items[++i].level > level) { 141 | this.items[i].style.display = "block" 142 | this.items[i].style.opacity = 1; 143 | } 144 | while (this.items[++i].level == level) { 145 | this.items[i].style.display = "block" 146 | this.items[i].style.opacity = 1; 147 | } 148 | 149 | // Hide all after 150 | for (; i < this.items.length; i++) 151 | if (this.items[i].level > 1) { 152 | this.items[i].style.display = "none" 153 | this.items[i].style.opacity = 0; 154 | } 155 | 156 | } 157 | 158 | 159 | } -------------------------------------------------------------------------------- /lib/DML_jellyfish.js: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | DMLjellyfish-Menue: An innovative round menue 3 | Needs index array 4 | [ 5 | {"color": ,"text": , "link": } 6 | ... 7 | ] 8 | Title is center menue, same format 9 | ****************************************************************************************/ 10 | let mouseX = 0, mouseY = 0 11 | window.onmousemove = (e) => { 12 | mouseX = e.clientX; 13 | mouseY = e.clientY; 14 | } 15 | function ifcol(col) { 16 | if (col) 17 | return "background-color: " + col + ";" 18 | else 19 | return "" 20 | } 21 | 22 | /**************************************************************************************** 23 | Moving Buton 24 | ****************************************************************************************/ 25 | 26 | 27 | /*------------------------------------------------------ 28 | Create a moving round button 29 | You can bring force to the button, it will return 30 | to the initial position 31 | ------------------------------------------------------*/ 32 | function movingButton(s, x, y, diameter, attr) { return new _movingButton(s, x, y, diameter, attr) } 33 | class _movingButton { 34 | constructor(s, x, y, diameter, attr) { 35 | this.offset = diameter / 2 36 | this.p0 = { x: x, y: y } // Startpunkt 37 | this.d = { x: 0, y: 0 } // Auslenkung 38 | this.u = { x: 0, y: 0 } // Geschwindigkeit 39 | this.f = { x: 0, y: 0 } // Kraft 40 | this.button = rbutton(s, x, y, diameter, attr) 41 | 42 | } 43 | 44 | repaint() { 45 | 46 | // let f0 = {x: trunc(this.d.x*100), y: trunc(this.d.y*100)} 47 | // this.button.textContent = JSON.stringify(f0) 48 | this.u.x = this.u.x * 0.999 + (this.f.x / 100) - this.d.x / 1000; 49 | this.u.y = this.u.y * 0.999 + (this.f.y / 100) - this.d.y / 1000; 50 | this.d.x += this.u.x / 30; 51 | this.d.y += this.u.y / 30; 52 | this.button.style.transform = "translate(" + px(this.d.x - this.offset) + "," + px(this.d.y - this.offset) + ")" 53 | this.f.x = this.f.x * 0.99 54 | this.f.y = this.f.y * 0.99 55 | } 56 | // bring force to the button 57 | force(fx, fy) { 58 | this.f.x = fx; 59 | this.f.y = fy 60 | } 61 | // Momentanposition 62 | p() { 63 | return { x: this.p0.x + this.d.x, y: this.p0.y + this.d.y } 64 | } 65 | delta(mouseX, mouseY) { 66 | let ret = {}; 67 | let rect = this.button.getBoundingClientRect() 68 | ret.x = mouseX - (rect.left + rect.width / 2) 69 | ret.y = mouseY - (rect.top + rect.height / 2) 70 | ret.dist = Math.sqrt(ret.x * ret.x + ret.y * ret.y) 71 | return ret 72 | } 73 | 74 | } 75 | 76 | 77 | 78 | /**************************************************************************************** 79 | Jellyfish - Menue 80 | ****************************************************************************************/ 81 | 82 | function DMLjellyfish(title, width, height, props, cbattrib, btattrib, baseattrib) { return new _jellyfish(title, width, height, props, cbattrib, btattrib, baseattrib) } 83 | class _jellyfish { 84 | constructor(title, width, height, props, cbattrib = "", btattrib = "", baseattrib = "") { 85 | let x, y; 86 | this.props = props 87 | this.button = [] 88 | this.center = { x: trunc(width / 2), y: trunc(height / 2) } 89 | this.base = selectBase(div("", "width: " + width + "px; height: " + height + "px;" + _center)) 90 | setAttributes(this.base, baseattrib) 91 | this.canvas = canvas2D({ "width": width, "height": height }) 92 | this.canvas.ctx.lineWidth = 3 93 | this.centerbutton = movingButton(title.text, this.center.x, this.center.y, height / 3.5, cbattrib + "border: solid 3px; " + ifcol(title.color)) 94 | this.centerbutton.button.classList.add("DMLjellyfish") 95 | this.centerbutton.button.classList.add("center") 96 | this.centerbutton.button.onclick = () => window.open(this.button[i].link) 97 | for (let i in props) { 98 | let phi = i / props.length * 2 * Math.PI 99 | x = this.center.x + Math.sin(phi) * width / 3 100 | y = this.center.y - Math.cos(phi) * height / 3 101 | this.canvas.line(this.center.x, this.center.y, x, y) 102 | this.button[i] = movingButton(props[i].text, x, y, height / 4, btattrib + "border: solid 3px;") 103 | this.button[i].button.classList.add("DMLjellyfish") 104 | this.button[i].button.link = props[i].link 105 | this.button[i].button.classList.add("jelly") 106 | this.button[i].button.center = { "x": x, "y:": y } 107 | if (props[i].color) 108 | this.button[i].button.style.backgroundColor = props[i].color 109 | this.button[i].button.onclick = () => window.open(this.button[i].button.link, "_self") 110 | } 111 | unselectBase(); 112 | 113 | setInterval(() => { 114 | 115 | this.mousePos(mouseX, mouseY) 116 | for (let i in this.props) { 117 | /* this (Math.random() > 0.99) { 118 | this.button[i].f.x += (Math.random() - 0.5) * 3 119 | this.button[i].f.y += (Math.random() - 0.5) * 3 120 | } 121 | */ this.repaint() 122 | } 123 | }, 20) 124 | 125 | 126 | return this 127 | } 128 | 129 | mousePos(mouseX, mouseY) { 130 | let delta; 131 | for (let i in this.props) { 132 | delta = this.button[i].delta(mouseX, mouseY) 133 | if (delta.dist < 150) 134 | this.button[i].force(delta.x / 50, delta.y / 50) 135 | else 136 | this.button[i].force(0, 0) 137 | } 138 | } 139 | 140 | repaint() { 141 | this.canvas.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); 142 | 143 | for (let i in this.props) { 144 | let p = this.button[i].p() 145 | this.canvas.line(this.center.x, this.center.y, p.x, p.y) 146 | this.button[i].repaint() 147 | 148 | } 149 | } 150 | 151 | } 152 | 153 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /lib/DML_onlineEditor.js: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Online-Editor (c) Eckehard Fiedler 3 | Show online code Editor plus Full page result including HTML 4 | ICE.oninput = debounce(function () { 5 | pw.update(ICE.textContent) 6 | }) 7 | ****************************************************************************************/ 8 | const codefraction = 70; 9 | function inputCodeEditor(srctxt, attrib) { return new _inputCodeEditor(srctxt, attrib) } 10 | class _inputCodeEditor { 11 | constructor(srctxt, attrib) { 12 | this.editor = pre(srctxt, { 13 | "rows": "10", 14 | "class": "prettyprint ", 15 | "contenteditable": "true", 16 | "style": "overflow: auto; margin: 0px; padding: 5px 8px; width: " + (codefraction) + "%; text-align: left;" 17 | }) 18 | setAttributes(this.editor, attrib) 19 | //this.editor.textContent = srctxt; 20 | return (this.editor) 21 | } 22 | refresh() { 23 | this.editor.textContent = this.editor.value 24 | } 25 | } 26 | 27 | /**************************************************************************************** 28 | PageWindow: iframe to show a full page body content 29 | ta.oninput = debounce(function () { 30 | pw.update(ta.textContent) 31 | }, 250) 32 | ****************************************************************************************/ 33 | function pageWindow(txt, attrib) { return new _pageWindow(txt, attrib); } 34 | class _pageWindow { 35 | constructor(txt, attrib) { 36 | this.base = selectBase(div("", "width: " + (100 - codefraction) + "%; ")) 37 | this.error = div("", _bgsilver + "padding-left: 5px;") 38 | this.myFrame = make("iframe", 39 | { 40 | "frameBorder": "0", 41 | "seamless": "true", 42 | // "class": "pageFrame", 43 | "style": "width: 100%; height: 100%; text-align: center;" + _bgwhite 44 | }) 45 | this.doc = this.myFrame.contentDocument ? this.myFrame.contentDocument : this.myFrame.contentWindow.document; 46 | setAttributes(this.myFrame, attrib) 47 | let script = create("script", { "src": "..\\lib\\DML.js" }); 48 | this.doc.head.appendChild(script) 49 | script.onload = () => { this.update(txt) } 50 | window.onerror = (e) => { this.error.textContent = e; } 51 | this.doc.onerror = (e) => { this.error.textContent = e; } 52 | 53 | this.doc.onchange = () => { 54 | alert("doc") 55 | } 56 | this.myFrame.onchange = () => { 57 | alert("frame") 58 | } 59 | 60 | unselectBase() 61 | } 62 | update(txt) { 63 | let sp = DMLgetSP(); // get stack pointer 64 | 65 | this.txt = txt 66 | this.error.textContent = "" 67 | this.doc.open() 68 | this.doc.write("") 75 | this.doc.write(txt) 76 | this.doc.close() 77 | 78 | if (sp != DMLgetSP()) { 79 | alert("Stack mismacth in function pageWindow: " + DMLgetSP() + " <> " + sp) 80 | while (DMLgetSP() > sp) unselectBase(); 81 | } 82 | 83 | } 84 | } 85 | 86 | /**************************************************************************************** 87 | codeWindow: Show result of code (DML only) 88 | ****************************************************************************************/ 89 | function codeWindow(txt, attrib) { return new _codeWindow(txt, attrib); } 90 | class _codeWindow { 91 | constructor(txt, attrib) { 92 | this.base = selectBase(div("", "width: " + (100 - codefraction) + "%;" + _bgwhite)) // outer div 93 | this.error = div("", _bgsilver + "padding-left: 5px;") 94 | this.innerdiv = div("", "overflow: auto; margin: 0px; padding: 8px 8px; text-align: center;")//white-space: nowrap;") 95 | setAttributes(this.base, attrib) 96 | if (this.base.style.textAlign) 97 | this.innerdiv.style.textAlign = this.base.style.textAlign // Copy text alignment from outer box 98 | window.onerror = (e) => { 99 | // this.error.textContent = e; 100 | } 101 | this.update(txt) 102 | unselectBase() 103 | return this 104 | } 105 | update(txt) { 106 | this.error.textContent = "" 107 | this.innerdiv.innerHTML = "" 108 | selectBase(this.innerdiv) // Open current base 109 | try { 110 | let sp = DMLgetSP(); // get stack pointer 111 | 112 | eval(txt) 113 | 114 | if (sp != DMLgetSP()) { 115 | alert("Stack mismacth in function codeWindow: " + DMLgetSP() + " <> " + sp) 116 | while (DMLgetSP() > sp) unselectBase(); 117 | } 118 | 119 | } catch (e) { 120 | var err = e.constructor('Error in Evaled Script: ' + e.message); 121 | // +3 because `err` has the line number of the `eval` line plus two. 122 | // err.lineNumber = e.lineNumber - err.lineNumber + 3; 123 | this.error.textContent = e.message; 124 | throw err; 125 | } 126 | unselectBase() 127 | } 128 | } 129 | 130 | /*======================================================== 131 | Combined Editor/View 132 | 60% Code, 40& Result 133 | ========================================================*/ 134 | function pageEditor(srctxt, baseattr, cwattrib) { new _pageEditor(srctxt, baseattr, cwattrib) } 135 | class _pageEditor { 136 | constructor(srctxt, baseattr, cwattrib) { 137 | this.base = selectBase(div("", "display: flex")) 138 | setAttributes(this.base, baseattr) 139 | this.ice = inputCodeEditor(srctxt) 140 | this.cw = pageWindow(srctxt, cwattrib) 141 | this.ice.oninput = debounce(() => { 142 | let SP = DMLgetSP() 143 | this.cw.update(this.ice.textContent) 144 | if (SP != DMLgetSP()) 145 | alert("Stack misalignment in PageEditor: " + srctxt) 146 | }, 250) 147 | unselectBase() 148 | this.ice.onfocus = () => { 149 | window.onerror = (e) => { 150 | this.cw.error.textContent = e.message; 151 | } 152 | } 153 | this.ice.onblur = () => { 154 | window.removeEventListener("error", window); 155 | 156 | } 157 | } 158 | } 159 | 160 | 161 | function codeEditor(srctxt, baseattr, cwattrib) { new _codeEditor(srctxt, baseattr, cwattrib) } 162 | class _codeEditor { 163 | constructor(srctxt, baseattr, cwattrib) { 164 | this.base = selectBase(div("", "display: flex;")) 165 | 166 | setAttributes(this.base, baseattr) 167 | this.ice = inputCodeEditor(srctxt) 168 | this.cw = codeWindow(srctxt, cwattrib) 169 | this.ice.oninput = debounce(() => { 170 | let SP = DMLgetSP() 171 | this.cw.update(this.ice.textContent) 172 | if (SP != DMLgetSP()) 173 | alert("Stack misalignment in CodeEditor: " + srctxt) 174 | 175 | }, 250) 176 | this.ice.onfocus = () => { 177 | window.onerror = (e) => { 178 | this.cw.error.textContent = e.message; 179 | } 180 | } 181 | this.ice.onblur = () => { 182 | window.removeEventListener("error", window); 183 | 184 | } 185 | unselectBase() 186 | } 187 | } 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /lib/DML_markdown.js: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Markdwon by Dr. Ecki 3 | Spezialversion für meine Bedürfnisse 4 | 5 | # h1 6 | ## h2 7 | ### h3 8 | %%% Programmtext %%% 9 | &col &col &end Spaltenabschnitt 50% 10 | ¢er &end Zentrierter Abschnitt 11 | !IMG:name,(left|center|right),height px,offset x px, offset y px 12 | Erzeugt einen Index aus h1 und h2 mit 13 | [ 14 | {"level": level, "text":hp, "link":ref} 15 | ] 16 | ****************************************************************************************/ 17 | 18 | /*------------------------------------------------------ 19 | check if tag at start, than call function for the contents, 20 | return true or false 21 | ------------------------------------------------------*/ 22 | function mkHeadline(s, tag, f, index) { 23 | if (s.startsWith(tag)) { 24 | if (f) { 25 | let hp, level = tag.length; // headline-part oft content 26 | let content = s.slice(tag.length).trim() // trim tag and whitespaces 27 | if (content.includes("|")) { 28 | let tmp = content.split("|") // if line contains |, second is for index 29 | content = tmp[0] 30 | hp = tmp[1] 31 | } else 32 | hp = content; 33 | 34 | let ref = f("") 35 | ref.innerHTML = toHTML(content) 36 | if ((level < 4) && (hp)) 37 | if (Array.isArray(index)) 38 | index.push({ "level": level, "text": hp, "link": ref }) 39 | } 40 | return true 41 | } 42 | return false 43 | } 44 | 45 | /*------------------------------------------------------ 46 | Substitute DMLmarkdown b[]b, i[]i und u[]u 47 | ------------------------------------------------------*/ 48 | function toHTML(s) { 49 | let ar = ["b", "u", "i"] 50 | let tag1, tag2, flag 51 | for (i in ar) { 52 | c = ar[i] 53 | tag1 = c + "\\[" 54 | tag2 = "\\]" + c 55 | let r1 = new RegExp(tag1, 'g') 56 | let r2 = new RegExp(tag2, 'g') 57 | s = s.replace(r1, "<" + c + ">").replace(r2, "") 58 | } 59 | 60 | if (s.includes("%%%")) { 61 | let out = s.split("%%%") 62 | for (let i = 1; i < out.length; i += 2) 63 | out[i] = "
" + out[i] + "
" 64 | s = out.join("") 65 | } 66 | return s 67 | } 68 | 69 | /*------------------------------------------------------ 70 | Simple DMLmarkdown-style function call 71 | inp is a string, 72 | out is div 73 | headline is an array of menue entries 74 | ------------------------------------------------------*/ 75 | function DML_markdown(inp, out, index) { 76 | let output, iscol = false, attr, attr2; 77 | 78 | 79 | // *********** Funktonen **************** 80 | 81 | // subfunction Read Block til End 82 | /* function getblock(s) { 83 | let ret = s; 84 | while (true) { 85 | if (++n >= output.length) break // ------> 86 | s = getline() 87 | it (!t) break // ------> 88 | if (t.startsWith('&')) break // ------> 89 | ret += "\n" + s 90 | } 91 | n--; // jump back to allow evaluation of last line 92 | return ret 93 | } 94 | */ 95 | // get line n -> s: line, global t = s.trim() 96 | function getline() { 97 | if (n >= output.lenght) 98 | return "" 99 | return output[n++] 100 | } 101 | 102 | // Get first line and read until end or delimiter without trim() 103 | function getuntil(line, delimiter) { 104 | let ret = "" 105 | // Remove first line if empty 106 | if (line.trim() == "") 107 | line = getline().replace(/\t/g, " ") 108 | 109 | while (true) { 110 | if (line.includes(delimiter)) { 111 | while (line.includes(delimiter)) 112 | line = line.replace(delimiter, '') 113 | ret += line; 114 | return ret // ------> 115 | } else 116 | ret += line + "\n" 117 | if (n >= output.length) 118 | return ret // ------>; 119 | line = getline().replace(/\t/g, " ") 120 | } 121 | } 122 | 123 | // unselectBase if iscol was set 124 | function setcol() { 125 | if (iscol) 126 | unselectBase() 127 | iscol = true; 128 | } 129 | 130 | // *********** Programm **************** 131 | 132 | while (out.firstChild) out.removeChild(out.firstChild); 133 | //out.innerHTML = ""; // Clear output 134 | selectBase(out) 135 | 136 | // remove double linefeed, split source lines 137 | output = inp.replace(/(\r\n|\n|\r)/gm, "\n").split("\n") 138 | let n = 0, s, t; 139 | let buffer = "" 140 | const _br = "border-radius: 0px 10px 10px 0px;" 141 | while (n < output.length) { 142 | s = getline().replace(/\t/g, " ") // Line in s 143 | t = s.trim() 144 | 145 | if (mkHeadline(s, '######', h6, index)) continue 146 | if (mkHeadline(s, '#####', h5, index)) continue 147 | if (mkHeadline(s, '####', h4, index)) continue 148 | if (mkHeadline(s, '###', h3, index)) continue 149 | if (mkHeadline(s, '##', h2, index)) continue 150 | if (mkHeadline(s, '#', h1, index)) continue 151 | if (t == "---") { hr(); continue } 152 | if (t == "<") { br(); continue } // additional line break // ------> 153 | 154 | // Gray box heading 155 | if (s.startsWith('!!!')) { 156 | idiv(toHTML(s.slice(3).trim()), "padding: 2px 5px; margin-top: 25px; background-color: #ddd;"+_border+_bold); continue } 157 | 158 | 159 | // List ul 160 | if (s.startsWith('- ')) { 161 | let ar = [toHTML(s.slice(2).trim())] // Remember first line 162 | while (n < output.lenght - 1) { 163 | if (output[n].startsWith('- ')) { 164 | s = getline(); 165 | ar.push(toHTML(s.splice(2).trim())) 166 | } else break 167 | } 168 | ul(ar); continue 169 | } 170 | 171 | // 2-Colum side by side 172 | if (t.startsWith('&col')) { 173 | setcol() 174 | selectBase(div("", "display : inline-flex; width: 50%; padding: 0px 4px;")); continue 175 | } 176 | if (t.startsWith('¢er')) { 177 | setcol() 178 | selectBase(div("", "text-align: center")); continue 179 | } 180 | if (t.startsWith('&end')) { 181 | unselectBase(); 182 | iscol = false; continue 183 | } 184 | 185 | // Place images, Parameter left/center/right, Scale, Positon dx,dy 186 | if (t.startsWith('!IMG:')) { 187 | let params = s.slice(5).split(","); // remove tag and get arguments 188 | attr2 = attr = "" 189 | if (params.length > 1) { 190 | if (params[1] == "center") attr2 = "text-align: center;" 191 | if (params[1] == "right") attr2 = "text-align: right;" 192 | } 193 | if (params.length > 2) // Scale 194 | if (params[2]) 195 | attr += "height:" + params[2] + ";" 196 | if (params.length > 4) { 197 | attr += "position: relative; left: " + params[3] + "; top: " + params[4] + ";" 198 | div(image(params[0], attr), attr2 + ' height: 0px; ') 199 | } 200 | else 201 | div(image(params[0], attr), attr2) 202 | continue 203 | } 204 | 205 | // Call js function 206 | if (t.startsWith('!CALL:')) { 207 | let params = s.slice(6).split(","); // remove tag and get arguments 208 | attr = "" 209 | if (params.length > 1) { 210 | if (params[1] == "center") attr = "text-align: center;" 211 | if (params[1] == "right") attr = "text-align: right;" 212 | } 213 | selectBase(div("", attr)) 214 | window[params[0]](); 215 | unselectBase(); continue 216 | } 217 | 218 | if (t == '!BEGIN:') { // Gather lines in buffer 219 | buffer = "" 220 | while (n < output.length) { 221 | s = getline().replace(/\t/g, " ") // Line in s 222 | t = s.trim() 223 | if (t.startsWith("!")) break 224 | if (buffer == "") 225 | buffer = s 226 | else 227 | buffer += "\n" + s 228 | } 229 | } 230 | 231 | // Format block with css 232 | if (t.startsWith('!FORMAT:')) { 233 | p("", s.slice(8)).innerHTML = toHTML(buffer) // print paragraph 234 | continue 235 | } 236 | 237 | // Format Block bigger 238 | if (t.startsWith('!BIG:')) { 239 | p("", "font-size: 120%; font-weight: 500;").innerHTML = toHTML(buffer) 240 | continue; 241 | } 242 | 243 | 244 | // Evaluate code block 245 | if (t.startsWith('!EVAL:')) { 246 | eval(buffer) 247 | continue; 248 | } 249 | 250 | 251 | if (t.startsWith('!CODE_EDITOR:')) { 252 | let param = s.slice(13); // remove tag and get arguments 253 | let attr = ""; 254 | if (param.trim()) { 255 | if (param == "left") attr = "text-align: left;" 256 | if (param == "right") attr = "text-align: right;" 257 | } 258 | codeEditor(buffer, "width: 100%; max-height: 700px; overflow: auto; " + _br + _bigshadow, "background-color: #ffd;" + _br + _border+attr); 259 | continue; 260 | } 261 | 262 | if (t.startsWith('!PAGE_EDITOR:')) { 263 | pageEditor(buffer, "width: 100%;" + _br + _bigshadow, "background-color: #ffd;" + _br + _border); 264 | continue; 265 | } 266 | 267 | if (t.startsWith('!CODE:')) { 268 | pre(buffer, { "class": "prettyprint ", "style": "overflow: auto; padding: 2px 5px; width: 100%; margin:0 auto;" + _shadow }) 269 | continue; 270 | } 271 | 272 | // Program text 273 | if (s.startsWith('%%%')) { 274 | s = getuntil(s.slice(3), '%%%') 275 | let el = pre(s, { "class": "prettyprint ", "style": "overflow: auto; padding: 2px 5px; width: 100%; max-height: 350px; margin:0 auto;" + _shadow }) 276 | // el.innerHTML = PR.prettyPrintOne(s) 277 | continue 278 | } 279 | // Program text light 280 | if (s.startsWith('$$$')) { 281 | s = getuntil(s.slice(3), '$$$') 282 | let el = pre(s, { 283 | "class": " ", "style": "overflow: auto; padding: 4px 10px; width: 100%; margin:0 auto; background-color: #FFC;" 284 | + _bold + _border + _radius + _shadow 285 | }) 286 | // el.innerHTML = PR.prettyPrintOne(s) 287 | continue 288 | } 289 | // Program text transparent 290 | if (s.startsWith('???')) { 291 | s = getuntil(s.slice(3), '???') 292 | let el = pre(s, { "class": " ", "style": "overflow: auto; width: 100%; margin:0 auto; " + _bold }) 293 | // el.innerHTML = PR.prettyPrintOne(s) 294 | continue 295 | } 296 | 297 | // Kommentare 298 | if (s.startsWith('///')) { 299 | s = getuntil(s.slice(3), '///') 300 | continue 301 | } 302 | 303 | // Paragraph 304 | if (t) { 305 | p().innerHTML = toHTML(s) 306 | } 307 | 308 | 309 | } 310 | unselectBase() 311 | PR.prettyPrint() 312 | } -------------------------------------------------------------------------------- /lib/DML_table.js: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | DML-Table with extended fuctions 3 | (c) 30.5.2021 4 | 5 | DML_table: extends the standard HTML tables 6 | can be used in HTML as 7 | 8 | Create Table of fixed size mx,my. 9 | If showHead==false, table head is not created 10 | supports a rowId, that contains a value for each row. 11 | 12 | Cell or row hover with CSS only 13 | 14 | properties 15 | read values 16 | table.rowCount 17 | table.colCount 18 | table.selectedRowid 19 | table.selectedRowvalue 20 | table.selectedCellvalue() 21 | Set or read values 22 | table.head = [...] 23 | table.body = [[.],[.],[.]], if only one column [...] 24 | table.rowid = [] 25 | table.rowValue = [] 26 | 27 | 28 | functions 29 | table.cell(x,y): full cell access 30 | table.colStyle(1, "width: 150px; color: green; ") 31 | table.colStyle(["width: 20px","width: 120px","width: 55px; background-color: green;"]) 32 | table.put(mx, my, head, body): rebuild 33 | buildTable(mx, my, showHead, attrib, headAttrib) 34 | setrowvalid(row,status) // set status for a row. Internal array : _rowvalid 35 | getrowvalid(row) 36 | 37 | options: 38 | head || [] // set header data [...] 39 | body || [] // set body data [[.],[.],[.]], if only one column [...] 40 | tableAttrib = {} or "" // Whole table attributes 41 | headAttrib = {} or "" // header line attributes 42 | bodyAttrib = {} or "" // TBody attributes for body 0 43 | cellAttrib = {} or "" // TD-Attribute 44 | showHead = true 45 | onClick || null // Events 46 | onSelect || null 47 | canSelect || false 48 | rowSelect || true 49 | selectColor || "silver" 50 | invalidSelectColor: "#CC6060", 51 | invalidColor: "#FF8070", 52 | selectedRow || -1 53 | selectedCol || -1 54 | rowid || []; // Optional row Id 55 | rowvalue || []; // Optional content of a row 56 | 57 | ****************************************************************************************/ 58 | 59 | 60 | function table(mx, my, options = {}) { return new _table(mx, my, options) } 61 | class _table extends HTMLTableElement { 62 | constructor(mx, my, options) { 63 | super() // Create table element 64 | this._tabletimeout = {} 65 | 66 | 67 | if (options == false) { 68 | this.showHead = false 69 | options = {} 70 | } else { 71 | this.showHead = _init(options.showHead, true) // Tablehead 72 | } 73 | setOptions(this, options, { 74 | tableAttrib: "border: 1px solid black; ", 75 | headAttrib: "background-color: silver; ", 76 | bodyAttrib: "", 77 | cellAttrib: "", 78 | onCellClick: null, 79 | canSelect: false, 80 | selectColor: "silver", 81 | invalidSelectColor: "#CC6060", 82 | invalidColor: "#FF8070", 83 | selectedRow: -1, 84 | selectedCol: -1 85 | }) 86 | this.rowSelect = _init(options.rowSelect, true) 87 | this._rowid = options.rowid || []; // Optional row array 88 | this._rowvalue = options.rowvalue || []; // Optional content of a array 89 | this._rowvalid = options.rowvalid || []; // Flag to make indicate row is valid array 90 | 91 | // Variablen 92 | 93 | // Select-Funktion 94 | this.onclick = (e) => { 95 | if (e.srcElement.cellIndex<0) return; 96 | let col = e.srcElement.cellIndex; 97 | let row = e.srcElement.parentElement.rowIndex; 98 | this.select(col, row) 99 | } 100 | 101 | // this.doSelect = (e) => { 102 | this.doSelect = (e) => { 103 | if (!this.canSelect) return 104 | let el = e.target 105 | let row = el.parentElement.rowIndex 106 | let col = el.cellIndex 107 | this.select(col, row) 108 | } 109 | 110 | // Create table 111 | setAttributes(this, this.tableAttrib) 112 | this.buildTable(mx, my) 113 | 114 | // set content 115 | if (options.head) this.head = options.head 116 | if (options.body) this.body = options.body 117 | 118 | // Select before setting onSelect 119 | this.select(this.selectedCol, this.selectedRow) 120 | if (options.onSelect) // wait til end to set 121 | this.onSelect = options.onSelect; 122 | this.colorize(); 123 | // autobind(this) 124 | appendBase(this) 125 | } // end table() 126 | 127 | /*------------------------------------------------------ 128 | set complete rwoId as array ar 129 | ------------------------------------------------------*/ 130 | getrowvalid(i) { 131 | return arrayvalue(this._rowvalid, i, true); // Optional row Id 132 | } 133 | 134 | setrowvalid(i, value) { 135 | this._rowvalid[i] = value 136 | clearTimeout(this._tabletimeout) 137 | this._tabletimeout = setTimeout(() => { 138 | this.colorize(); 139 | }, 10); 140 | } 141 | 142 | /*------------------------------------------------------ 143 | Set colors according to selectedRow and getrowvalid 144 | ------------------------------------------------------*/ 145 | colorize() { 146 | //this.rows 147 | //let rows = el.parentElement.parentElement.childNodes 148 | 149 | for (let r in this.rows) { 150 | let ri = this.rows[r] 151 | let valid = this.getrowvalid(r) // check, if row is valid 152 | for (let i = 0; i < ri.childElementCount; i++) { 153 | if ((ri.rowIndex === this.selectedRow) && (this.rowSelect || i == this.selectedCol)) { 154 | // ri.cells[i].style.border = "solid 3px gray" 155 | if (valid) 156 | ri.cells[i].style.backgroundColor = this.selectColor 157 | else 158 | ri.cells[i].style.backgroundColor = this.invalidSelectColor 159 | 160 | } 161 | else { 162 | //ri.cells[i].style.border = null 163 | if (valid) 164 | ri.cells[i].style.backgroundColor = null 165 | else 166 | ri.cells[i].style.backgroundColor = this.invalidColor 167 | } 168 | } 169 | } 170 | } 171 | 172 | /*------------------------------------------------------ 173 | 174 | ------------------------------------------------------*/ 175 | buildTable(mx, my) { 176 | let x, y, th, tb, td 177 | 178 | this.innerHTML = "" // delete Table 179 | if (this.showHead) { 180 | th = createAt(this, "THEAD"); 181 | for (x = 0; x < mx; x++) 182 | createAt(th, "th", this.headAttrib).innerHTML = " " 183 | } 184 | 185 | tb = createAt(this, "TBODY", this.bodyAttrib) 186 | for (y = 0; y < my; y++) { 187 | let tr = createAt(tb, "TR") 188 | for (x = 0; x < mx; x++) { 189 | td = createAt(tr, "TD", this.cellAttrib) 190 | td.innerHTML = " " 191 | td.onclick = this.onCellClick 192 | } 193 | } 194 | } 195 | 196 | 197 | put(mx, my, head, body) { 198 | this.buildTable(mx, my); 199 | if (head) this.head = head 200 | if (body) this.body = body 201 | } 202 | 203 | /*------------------------------------------------------ 204 | return cell reference 205 | ------------------------------------------------------*/ 206 | cell(x, y) { 207 | let r = this.rows[y] 208 | return r.cells[x] 209 | } 210 | /*------------------------------------------------------ 211 | set style for column 212 | ------------------------------------------------------*/ 213 | colStyle(c, w, includeHead = false) { 214 | if (Array.isArray(c)) { 215 | let n = Math.min(c.length, this.colCnt) 216 | for (let k = 0; k < n; k++) { 217 | let w2 = c[k] 218 | for (let i = 0; i < this.rows.length; i++) { 219 | this.rows[i].childNodes[k].style.cssText = w2 220 | } 221 | if (includeHead) 222 | this.head[k].style.cssText = w2 223 | } 224 | } else { 225 | for (let i = 0; i < this.rows.length; i++) { 226 | this.rows[i].childNodes[c].style.cssText = w 227 | } 228 | if (includeHead) 229 | if (this.tHead) 230 | this.tHead.childNodes[c].style.cssText += w 231 | } 232 | } 233 | /*------------------------------------------------------ 234 | Select one gol 235 | ------------------------------------------------------*/ 236 | select(col, row) { 237 | this.selectedRow = row 238 | this.selectedCol = col 239 | 240 | 241 | this.colorize() 242 | 243 | if (this.onSelect) 244 | this.onSelect(col, row, this) 245 | } 246 | /*------------------------------------------------------ 247 | Kurzform für Zeilen selektieren. Erfordert rowSelect=true 248 | ------------------------------------------------------*/ 249 | selectRow(row) { 250 | this.select(0, row) 251 | } 252 | /*======================================================== 253 | properties 254 | ========================================================*/ 255 | get rowCount() { 256 | if (this.rows) 257 | return this.rows.length 258 | return 0 259 | } 260 | 261 | 262 | get colCount() { 263 | if (this.rows.length == 0) 264 | return 0 265 | return this.rows[0].childElementCount 266 | } 267 | 268 | 269 | /*------------------------------------------------------ 270 | head 271 | ------------------------------------------------------*/ 272 | get head() { 273 | let ret = [] 274 | for (let i in this.tHead.childNodes) { 275 | let n = this.tHead.childNodes[i] 276 | ret.push(n.innerHTML) 277 | } 278 | return ret 279 | } 280 | set head(ar) { 281 | if (this.showHead) { 282 | this.tHead.innerHTML = "" 283 | for (let i in ar) 284 | createAt(this.tHead, "th", this.headAttrib).innerHTML = ar[i] 285 | } 286 | } 287 | 288 | /*------------------------------------------------------ 289 | cells: Get or set 2d-Array 290 | ------------------------------------------------------*/ 291 | 292 | get body() { 293 | let r, ret = [] 294 | for (let y = 0; y < this.rowCount; y++) { 295 | r = [] 296 | let n = Array.from(this.rows[y].childNodes) 297 | for (let i in n) { 298 | let x = n[i] 299 | r.push(x.innerHTML) 300 | } 301 | ret.push(r) 302 | } 303 | return ret 304 | } 305 | set body(ar) { 306 | if (1 == this.colCount) { 307 | for (let y = 0; y < ar.length; y++) { 308 | if (y < this.rowCount) 309 | this.cell(0, y).innerHTML = ar[y] 310 | } 311 | } else { 312 | for (let y = 0; y < Math.min(ar.length, this.rowCount); y++) { 313 | for (let x = 0; x < Math.min(ar[y].length, this.colCount); x++) { 314 | this.cell(x, y).innerHTML = ar[y][x] 315 | } 316 | } 317 | } 318 | } 319 | 320 | /*------------------------------------------------------ 321 | set complete rwoId as array ar, 322 | get rowid array referene 323 | get selectedrowid als value 324 | ------------------------------------------------------*/ 325 | 326 | get rowid() { 327 | return this._rowid; // Optional row Id 328 | } 329 | set rowid(ar) { 330 | this._rowid = ar 331 | } 332 | 333 | 334 | /*------------------------------------------------------ 335 | selectedRowid 336 | ------------------------------------------------------*/ 337 | get selectedRowid() { 338 | if (this.selectedRow < 0) 339 | return "" 340 | return this._rowid[this.selectedRow] 341 | } 342 | 343 | /*------------------------------------------------------ 344 | set complete rwoId as array ar 345 | ------------------------------------------------------*/ 346 | 347 | get rowvalue() { 348 | return this._rowvalue; // Optional row Id 349 | } 350 | set rowvalue(ar) { 351 | this._rowvalue = ar 352 | } 353 | 354 | 355 | /*------------------------------------------------------ 356 | selectedRowvalue 357 | ------------------------------------------------------*/ 358 | get selectedRowvalue() { 359 | return this._rowvalue[this.selectedRow] 360 | } 361 | 362 | 363 | /*------------------------------------------------------ 364 | selectedCellvalue 365 | ------------------------------------------------------*/ 366 | get selectedCellvalue() { 367 | if ((this.selectedCol < 0) || (this.selectedRow < 0)) { 368 | return "" 369 | } 370 | let c = this.cell(this.selectedCol, this.selectedRow) 371 | return c.textContent 372 | } 373 | 374 | 375 | /*------------------------------------------------------ 376 | selectedCell 377 | ------------------------------------------------------*/ 378 | 379 | get selectedCell() { 380 | return this.cell(this.selectedCol, this.selectedRow) 381 | } 382 | } 383 | customElements.define('dml-table', _table, { extends: "table" }) -------------------------------------------------------------------------------- /lib/DML-min.js: -------------------------------------------------------------------------------- 1 | var _base,_baseStack=[],_block=!1,_onresizeElements=[];const svgref="http://www.w3.org/2000/svg",PI2=2*Math.PI,_style="style",_bold="font-weight: bold;",_italic="font-style: italic;",_fs="font-size: ",_bigtext="font-size: 130%;",_bg="background-color: ",_bgred="background-color: red;",_bgred2="background-color: #f50;",_bgy="background-color: #ffc;",_bggreen="background-color: #695;",_bgblue="background-color: blue;",_bgorange="background-color: #fc0;",_bgsilver="background-color: silver;",_bgyellow="background-color: #ffffee;",_bgwhite="background-color: white;",_bgblack="background-color: black;",_bgtrans="background-color: rgba(0,0,0,0.05);",_bgwtrans="background-color: rgba(255,255,255,0.5);",_red="color: red;",_blue="color: blue;",_navy="color: navy;",_white="color: white;",_yellow="color: yellow;",_center="text-align: center;",_right="text-align: right;",_top="vertical-align: top;",_bottom="vertical-align: bottom;",_middle="vertical-align: middle;",_flexmiddle="display: flex; align-items: center;",_blur="filter: blur(2px);",_shadow="box-shadow: 3px 3px 4px gray;",_bigshadow="box-shadow: 6px 6px 8px gray;",_smallShadow="box-shadow: 2px 2px 3px gray;",_txtShadow="text-shadow: 5px 6px 4px rgba(0,0,0,0.44);",_bigTxtShadow="text-shadow: 8px 13px 5px rgba(0,0,0,0.44);",_border="border: thin solid silver;",_noborder="border: 0px;",_radius="border-radius: 8px;",_miniRadius="border-radius: 5px;",_padding="padding: 2px;",_tpadding="padding: 1px 5px 1px 5px;",_bigPadding="padding: 10px;",_smallMargin="margin: 2px;",_margin="margin: 5px;",_marginLeft="margin-left: 5px;",_marginRight="margin-right: 5px;",_bigMarginLeft="margin-left: 10px;",_bigMarginRight="margin-right: 10px;",_inShadow="-webkit-box-shadow: inset 5px 5px 3px -2px rgba(0,0,0,0.64);-moz-box-shadow: inset 5px 5px 3px -2px rgba(0,0,0,0.64);box-shadow: inset 5px 5px 3px -2px rgba(0,0,0,0.64);",_box=_bgwhite+_border+_shadow,_ybox=_border+_shadow+_bg+"#ffc;",_bodyFlex="display: flex; flex-flow: row nowrap; justify-content: space-between;",_sideFlex="flex-shrink: 0.5;",_columnFlex="flex-grow: 0; display: flex; flex-flow: row nowrap;",_flex="display: flex;",_flexSpaceAround="display: flex; justify-content: space-around;",_flexSpaceBetween="display: flex; justify-content: space-around;",_sticky="position: -webkit-sticky; position: sticky; top: 0px;",_btnstyle="width: 100px; height: 24px; display: inline-flex; align-items: center; justify-content: center; margin: 8px;",_flybox="position: fixed;padding: 6px;box-shadow: 5px 5px 6px silver;border-radius: 8px;background-color: #ffffff;border: thin solid gray;left: 50%;top: 50%;transform: translate(-50%, -50%);";let _language=0;const de=0,en=1,fr=2;let languages=["de","en","fr"];function getLanguage(t){t.toLowerCase(t).substr(1,2);for(let e in languages)if(t.toLowerCase(t)==languages[e])return _language=e}function L(t,e,n){return Array.isArray(t)?t[_language]:1==_language&&e?e:2==_language&&n?n:t}function autobind(t){let e=Object.getPrototypeOf(t),n=Object.getOwnPropertyNames(e);for(let i of n){"function"==typeof e[i]&&"constructor"!==i&&(t[i]=e[i].bind(t))}}function call(t,...e){if(t instanceof Function)return t(...e)}function _import(t,e){"string"==typeof t&&(t=[t]);let n=t.length;for(i in t){let r=extractFilename(t[i]).replace(".","_");if(void 0===window[r]){window[r]=r;let s=document.createElement("script");s.src=t[i],s.onload=()=>{0==--n&&e&&e()},document.head.appendChild(s)}else if(e)return void e()}} 2 | /*! 3 | loadCSS: load a CSS file asynchronously. 4 | [c]2014 @scottjehl, Filament Group, Inc. 5 | Licensed MIT 6 | */function loadCSS(t,e,n){"use strict";var i=window.document.createElement("link"),r=e||window.document.getElementsByTagName("script")[0];i.rel="stylesheet",i.href=t,i.media="only x",r.parentNode.insertBefore(i,r),setTimeout((function(){i.media=n||"all"}))}function style(t,e){let n={};return e?("object"==typeof t?(n=t,n.style=e):("object"==typeof e&&(n=e),n.style=t),n):(n.style=t,n)}function extract(t,e,n){let i,r=[],s=!1;if(n&&(s=Array.isArray(n)),"object"==typeof e){if(Object.keys(e).length>0){let o=Object.keys(e),a=Object.values(e),l=!0;return t.forEach((function(t){l=!0;for(let e=0;e"+pretty(t)+""}function round(t,e=0){return m=Math.pow(10,e),Math.round(t*m)/m}function trunc(t){return Math.trunc(t)}function floor(t){return Math.floor(t)}function abs(t){return Math.abs(t)}function exp10(t){return Math.pow(10,t)}function log10(t){return Math.log10(t)}function inRange(t,e,n){return!(tn)}function constrain(t,e,n){return tn?n:t}function min(t,e){return Math.min(t,e)}function max(t,e){return Math.max(t,e)}function getMin(t,e){return e=Number(e),t?Math.min(t,e):e}function getMax(t,e){return e=Number(e),t?Math.max(t,e):e}function p(t,e){return{x:t,y:e}}function px(t){return"string"==typeof t?t:Math.round(t)+"px"}function getpx(t){return"string"==typeof t?(t=t.replace("px","").trim(),Number(t)):t}function arrayvalue(t,e,n){return void 0===t[e]?n:t[e]}function smooth(t){return t<0?0:t>1?1:t*t*(3-t-t)}function smooth2(t){return t<0?0:t>1?1:t<.5?2*t*t:1-2*(t=1-t)*t}function extractFilename(t){return t.includes("\\")?t.substring(t.lastIndexOf("\\")+1):t.substring(t.lastIndexOf("/")+1)}function debounce(t,e,n){var i;return function(){var r=this,s=arguments,o=function(){i=null,n||t.apply(r,s)},a=n&&!i;clearTimeout(i),i=setTimeout(o,e),a&&t.apply(r,s)}}function isTouchDevice(){return"ontouchstart"in window||navigator.maxTouchPoints>0||navigator.msMaxTouchPoints>0}function isMobileDevice(){return navigator.userAgent.indexOf("Mobile")>0}function _init(t,e){return void 0===t?e:t}function setOptions(t,e,n){let i=Object.keys(n);for(let r in i){let s=i[r];void 0!==e[s]?t[s]=e[s]:t[s]=n[s]}}function dragElement(t,e=!0){let n,i,r,s,o=!1,a=0,l=0;if(!e)return t.removeEventListener("touchstart",c),void t.removeEventListener("mousedown",c);function c(e){e=e||window.event,t==e.target&&(e.offsetY>25||("touchstart"===e.type?(r=e.touches[0].clientX-a,s=e.touches[0].clientY-l):(r=e.clientX-a,s=e.clientY-l),o=!0,document.addEventListener("touchend",u,!1),document.addEventListener("touchmove",h,!1),document.addEventListener("mouseup",u,!1),document.addEventListener("mousemove",h,!1),document.body.style.cursor="move"))}function u(t){r=n,s=i,o=!1,document.removeEventListener("touchend",u,!1),document.removeEventListener("touchmove",h,!1),document.removeEventListener("mouseup",u,!1),document.removeEventListener("mousemove",h,!1),document.body.style.cursor="default"}function h(e){o&&(e.preventDefault(),"touchmove"===e.type?(n=e.touches[0].clientX-r,i=e.touches[0].clientY-s):(n=e.clientX-r,i=e.clientY-s),a=n,l=i,function(t,e,n){n.style.transform="translate3d("+t+"px, "+e+"px, 0)"}(n,i,t))}return t.addEventListener("touchstart",c,!1),t.addEventListener("mousedown",c,!1),this}function selectBase(t){return _baseStack.push(_base),_baseStack.length>100&&(alert("DML error: _baseStackOverflow in bushBase()"),_baseStack=[]),_base="string"==typeof t?document.getElementById(t):t}function sb(t){selectBase(t)}function getBase(){return _base}function DMLgetSP(){return _baseStack.length}function DMLsetSP(t,e="DMLsetSP"){if(t>_baseStack.length)alert("Error in "+e+", Stack pointer below desired SP");else for(;_baseStack.length>t;)_base=_baseStack.pop();return _baseStack.length}function DMLchkSP(t=0,e="Missing unselectBase()"){return DMLgetSP()!=t&&alert("DML error: _baseStack size mismatch - "+e+", before: "+t+", after: "+DMLgetSP()),_baseStack.length}function checkSP(t,e){let n=DMLgetSP(),i=t();return DMLchkSP(n,e),i}function unselectBase(t=1,e=-1,n="unselectBase"){for(let i=0;i=0&&DMLgetSP()!=e&&alert("DML error: _baseStack size mismatch - "+n+", before: "+e+", after: "+DMLgetSP())}return _baseStack.length}function chk_node(t){if("string"==typeof t){let e=create("span");return e.innerHTML=t,e}return t}function textNode(t){return document.createTextNode(t)}function setAttributes(t,e){return"string"==typeof e&&(e={style:e}),"object"==typeof e&&Object.keys(e).forEach((function(n){let i=e[n];if("style"!=n)t.setAttribute(n,i);else{i.split(";").forEach((function(e){if(e){let n=e.split(":");if(2==n.length){let e=n[0].trim(),i=n[1].trim();t.style.setProperty(e,i)}}}))}})),t}function createAt(t,e,n){let i=document.createElement(e);return setAttributes(i,n),t.appendChild(i),i}function create(t,e,n){let i=document.createElement(t);return n&&("string"==typeof n?i.innerHTML=n:i.appendChild(n)),e&&setAttributes(i,e),i}function appendBase(t){let e=chk_node(t);if(_base)_base.appendChild(e);else{if(!document.body)return;document.body.appendChild(e)}return e}function _appendBase(t){return _base?_base.appendChild(t):document.body.append(t),t}function make(t,e,n){return appendBase(create(t,e,n))}function addProps(t,e,n){n.forEach((function(n){if("string"==typeof n)t.add(create(e,{},n));else if("object"==typeof n){let i=create(e,n,Object.values(n)[0]);t.add(i)}else t.add(create(e,{},JSON.stringify(n)))}))}function putProps(t,e,n){t.innerHTML="",addProps(t,e,n)}function appendChilds(t,e,n){"object"!=typeof t&&alert("Error in appendChilds: First Parameter should be object");for(let i in n){let r=n[i];t.appendChild(create(e,{},r))}}function elementById(t){return document.getElementById(t)}function br(t){let e,n=t||1;for(let t=0;t{r.remove(),n&&n()},unselectBase(3),dragElement(r),DMLchkSP(i,"msgBox"),s}function askBox(t,e,n,i){let r=DMLgetSP(),s=sidiv("","text-align: center;"+_flybox+"width: 250px");setAttributes(s,e);let o=sdiv(t);return selectBase(s),button("Yes",_btnstyle).onclick=()=>{s.remove(),n instanceof Function&&n()},button("No",_btnstyle).onclick=()=>{s.remove(),i instanceof Function&&i()},unselectBase(3),dragElement(s),DMLchkSP(r,"msgBox"),o}function canvas2D(t){return new _canvas2D(t)}class _canvas2D{constructor(t){t?t.hasOwnProperty("visible")||(t.visible=!0):t={visible:!0},t.visible?this.canvas=make("canvas",t):this.canvas=create("canvas",t),this.ctx=this.canvas.getContext("2d"),this.points=[],this.shadow=0}get width(){return this.canvas.width}set width(t){this.canvas.width=t}get height(){return this.canvas.height}set height(t){this.canvas.height=t}beginPath(){this.ctx.beginPath()}stroke(){this.ctx.stroke()}clear(){this.ctx.clearRect(0,0,this.width,this.height)}setLineType(t=1,e="black",n=[]){"number"==typeof n&&(n=[n]),this.ctx.lineWidth=t,this.ctx.strokeStyle=e,this.ctx.setLineDash(n)}setFillStyle(t="white"){this.ctx.fillStyle=t}set shadow(t=0){this._shadow=t,t?(this.ctx.shadowBlur=1.3*t,this.ctx.shadowColor="rgba(0,0,0,0.5)",this.ctx.shadowOffsetX=t,this.ctx.shadowOffsetY=t):this.ctx.shadowColor="transparent"}get shadow(){return this._shadow}line(t,e,n,i){this.ctx.beginPath(),this.ctx.moveTo(t,e),this.ctx.lineTo(n,i),this.ctx.stroke()}_line(t,e,n,i){this.ctx.moveTo(t,e),this.ctx.lineTo(n,i)}rect(t,e,n,i,r={}){setOptions(this,r,{fill:!1,center:!1,angle:0}),this.ctx.beginPath(),0!=this.angle?(this.ctx.save(),this.ctx.translate(t,e),this.ctx.rotate(this.angle*Math.PI/180),this.center?this.ctx.rect(-n/2,-i/2,n,i):this.ctx.rect(0,0,n,i),this.ctx.restore()):this.center?this.ctx.rect(t-n/2,e-i/2,n,i):this.ctx.rect(t,e,n,i),this.fill&&this.ctx.fill(),this.ctx.stroke()}_rect(t,e,n,i,r={}){setOptions(this,r,{fill:!1,center:!1,angle:0}),0!=this.angle?(this.ctx.save(),this.ctx.translate(t,e),this.ctx.rotate(this.angle*Math.PI/180),this.center?this.ctx.rect(-n/2,-i/2,n,i):this.ctx.rect(0,0,n,i),this.ctx.restore()):this.center?this.ctx.rect(t-n/2,e-i/2,n,i):this.ctx.rect(t,e,n,i),this.fill&&this.ctx.fill()}circle(t,e,n,i={}){setOptions(this,i,{fill:!1}),this.ctx.beginPath(),this.ctx.arc(t,e,n/2,0,PI2),this.fill&&this.ctx.fill(),this.ctx.stroke()}_circle(t,e,n,i={}){this.fill=i.fill||!1,this.ctx.moveTo(t,e),this.ctx.arc(t,e,n/2,0,PI2),this.fill&&this.ctx.fill()}clrPoints(){this.points=[]}addPoint(t,e){this.points.push({x:t,y:e})}polyline(t,e={}){this.fill=e.fill||!1,this.ctx.beginPath(),this._polyline(t),this.fill&&this.ctx.fill(),this.ctx.stroke()}_polyline(t){let e;if(e=t||this.points,e.length>0){this.ctx.moveTo(e[0].x,e[0].y);for(let t=1;t{e.setAttributeNS(null,n,t[n])})),appendBase(e),e}function svg_line(t){let e=document.createElementNS("http://www.w3.org/2000/svg","line");return Object.keys(t).forEach((n=>{e.setAttributeNS(null,n,t[n])})),appendBase(e),e}function ul(t,e){let n=make("ul",e);return n.items=t,n}function ol(t,e){let n=make("ol",e);return n.items=t,n}function fieldset(t,e={}){setOptions(this,e,{legendAttrib:"",fieldsetAttrib:""});let n=make("fieldset",fieldsetAttrib);return n.textAlign="left",t=t.replace(/ /g," "),n.appendChild(create("legend",legendAttrib,t)),n}function radio(t,e,n,i,r){let s,o,a=[];for(s=0;s{Array.isArray(t)||(t=[t]);const n=await Promise.all(t);if(1==n.length){let t=n[0];e(t.result,t.par1,t.par2,t.par3)}else if(Array.isArray(e))for(let t in n){let i=n[t];e(i.result,i.par1,i.par2,i.par3)}else e(n)}))}function httpGet(t,e,n,i){let r={error:function(){},response:function(){}};return fetch(t,{method:"GET",headers:{"Content-type":"application/json;charset=UTF-8"}}).then((t=>{if(!t.ok)throw"function"==typeof r.error&&r.error("File not found",t),new Error(t.statusText);return t.json()})).then((t=>{"function"==typeof r.response&&r.response(t,e,n,i)})),r}function httpGet2(t,e,n,i){let r={error:function(){},response:function(){}},s=new XMLHttpRequest;return s.onreadystatechange=function(){if(4==this.readyState&&200==this.status){if("function"==typeof r.response)try{let t=JSON.parse(s.responseText);r.response(t,e,n,i)}catch(t){r.response(s.responseText,e,n,i)}}else r.error("ReadyState == "+this.readyState)},s.open("GET",t,!0),s.setRequestHeader("Accept","application/json"),s.send(),r}function sqliteGetTableNames(t,e,n,i){let r={response:function(){}};return httpGet(t+'?q=SELECT name FROM sqlite_master WHERE type = "table"').response=function(t){let s=extract(t,{},"name");"function"==typeof r.response&&r.response(s,e,n,i)},r}function sqliteGetKeys(t,e,n,i,r){let s={response:function(){}};return httpGet(t+"?q=select * from "+e+" LIMIT 1").response=function(t){let e=Object.keys(t[0]);"function"==typeof s.response&&s.response(e,n,i,r)},s}function sqliteGetTable(t,e,n,i,r,s){let o="",a={response:function(){}};if(n&&Object.keys(n).length>0){let t=Object.keys(n);o=" where ";for(let e=0;e0&&(o+=" and "),o+=t[e]+'="'+n[t[e]]+'"'}return httpGet(t+"?q=select * from "+e+o).response=function(t){"function"==typeof a.response&&a.response(t,e,i,r,s)},a}function slider(t={}){let e=selectBase(idiv("",t.baseattrib)),n=getpx(e.style.height),i=getpx(e.style.width),r=div("","width: 0px; height: 0px;"),s=make("input",t.sliderattrib);s.type="range",s.style.position="relative",s.base=e,setOptions(s,t,{vertical:!1,showRange:!1,rangeattrib:"",min:0,max:100,low:s.min,high:s.max,value:50}),s.offx=0,s.offy=0,s.vertical?(s.offy=6,setAttributes(s,{orient:"vertical",style:"-webkit-appearance: slider-vertical;left: 0px; top: 0px;"}),0!=i&&0!=n||(i=30,e.style.width=px(i),n=150,e.style.height=px(n))):(s.offx=6,""!=e.style.width&&""!=e.style.height||(i=150,e.style.width=px(i),n=30,e.style.height=px(n)),s.style.top="-1px"),s.style.width="100%",s.style.height="100%";let o=s.getBoundingClientRect();return s.rangewidth=o.width-2*s.offx,s.rangeheight=o.height-2*s.offy,s.range=create("div","position: relative;"+_bggreen),setAttributes(s.range,s.rangeattrib),unselectBase(),s.setRange=function(t,e){s.low=t,s.high=e,s.updateRange()},s.updateRange=function(){if(s.low=constrain(Number(s.low),Number(s.min),Number(s.max)),s.high=constrain(Number(s.high),Number(s.min),Number(s.max)),s.vertical){let t=s.rangeheight/(s.max-s.min);s.range.style.height=px(t*(s.high-s.low)),s.range.style.top=px(t*(s.max-s.high)+s.offy),s.range.style.left=px(s.offx),s.range.style.width=px(s.rangewidth)}else{let t=s.rangewidth/(s.max-s.min);s.range.style.width=px(t*(s.high-s.low)),s.range.style.left=px(t*s.low+s.offx),s.range.style.top=px(s.offy),s.range.style.height=px(s.rangeheight)}},s.updateRange(),s.showRange&&r.appendChild(s.range),s}function registerOnresize(t){_onresizeElements.push(t)}HTMLUListElement.prototype.add=function(t){t&&appendChilds(this,"li",t)},HTMLUListElement.prototype.put=function(t){this.clear(),t&&appendChilds(this,"li",t)},HTMLUListElement.prototype.clear=function(){this.items;this.innerHTML=""},Object.defineProperty(HTMLUListElement.prototype,"items",{get:function(){let t,e=[];for(let n=0;n{for(let t in _onresizeElements){let e=_onresizeElements[t];e.onresize&&e.onresize(e)}_oldOnResize&&_oldOnResize()}; -------------------------------------------------------------------------------- /lib/w3.css: -------------------------------------------------------------------------------- 1 | /* W3.CSS 4.13 June 2019 by Jan Egil and Borge Refsnes */ 2 | html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit} 3 | /* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */ 4 | html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0} 5 | article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item} 6 | audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline} 7 | audio:not([controls]){display:none;height:0}[hidden],template{display:none} 8 | a{background-color:transparent}a:active,a:hover{outline-width:0} 9 | abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted} 10 | b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000} 11 | small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} 12 | sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none} 13 | code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible} 14 | button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold} 15 | button,input{overflow:visible}button,select{text-transform:none} 16 | button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button} 17 | button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0} 18 | button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText} 19 | fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em} 20 | legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto} 21 | [type=checkbox],[type=radio]{padding:0} 22 | [type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto} 23 | [type=search]{-webkit-appearance:textfield;outline-offset:-2px} 24 | [type=search]::-webkit-search-decoration{-webkit-appearance:none} 25 | ::-webkit-file-upload-button{-webkit-appearance:button;font:inherit} 26 | /* End extract */ 27 | html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden} 28 | h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px}.w3-serif{font-family:serif} 29 | h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px} 30 | hr{border:0;border-top:1px solid #eee;margin:20px 0} 31 | .w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit} 32 | .w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc} 33 | .w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1} 34 | .w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1} 35 | .w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center} 36 | .w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top} 37 | .w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px} 38 | .w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap} 39 | .w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)} 40 | .w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} 41 | .w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none} 42 | .w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none} 43 | .w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%} 44 | .w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none} 45 | .w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block} 46 | .w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s} 47 | .w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%} 48 | .w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc} 49 | .w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer} 50 | .w3-dropdown-hover:hover .w3-dropdown-content{display:block} 51 | .w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000} 52 | .w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000} 53 | .w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1} 54 | .w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px} 55 | .w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto} 56 | .w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%} 57 | .w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%} 58 | .w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px} 59 | .w3-main,#main{transition:margin-left .4s} 60 | .w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)} 61 | .w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px} 62 | .w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto} 63 | .w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0} 64 | .w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left} 65 | .w3-bar .w3-button{white-space:normal} 66 | .w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0} 67 | .w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%} 68 | .w3-responsive{display:block;overflow-x:auto} 69 | .w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before, 70 | .w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both} 71 | .w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%} 72 | .w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%} 73 | .w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%} 74 | .w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%} 75 | @media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%} 76 | .w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%} 77 | .w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}} 78 | @media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%} 79 | .w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%} 80 | .w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}} 81 | .w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px} 82 | .w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px} 83 | .w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell} 84 | .w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom} 85 | .w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important} 86 | @media (max-width:1205px){.w3-auto{max-width:95%}} 87 | @media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px} 88 | .w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative} 89 | .w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center} 90 | .w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}} 91 | @media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}} 92 | @media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}} 93 | @media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}} 94 | @media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}} 95 | .w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0} 96 | .w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2} 97 | .w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0} 98 | .w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0} 99 | .w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)} 100 | .w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)} 101 | .w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)} 102 | .w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)} 103 | .w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)} 104 | .w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none} 105 | .w3-display-position{position:absolute} 106 | .w3-circle{border-radius:50%} 107 | .w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px} 108 | .w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px} 109 | .w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px} 110 | .w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px} 111 | .w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word} 112 | .w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%} 113 | .w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)} 114 | .w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)} 115 | .w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}} 116 | .w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}} 117 | .w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}} 118 | .w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}} 119 | .w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}} 120 | .w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}} 121 | .w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}} 122 | .w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}} 123 | .w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important} 124 | .w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1} 125 | .w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75} 126 | .w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)} 127 | .w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)} 128 | .w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)} 129 | .w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important} 130 | .w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important} 131 | .w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important} 132 | .w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important} 133 | .w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important} 134 | .w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important} 135 | .w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important} 136 | .w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important} 137 | .w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important} 138 | .w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important} 139 | .w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important} 140 | .w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important} 141 | .w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important} 142 | .w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important} 143 | .w3-padding-64{padding-top:64px!important;padding-bottom:64px!important} 144 | .w3-left{float:left!important}.w3-right{float:right!important} 145 | .w3-button:hover{color:#000!important;background-color:#ccc!important} 146 | .w3-transparent,.w3-hover-none:hover{background-color:transparent!important} 147 | .w3-hover-none:hover{box-shadow:none!important} 148 | /* Colors */ 149 | .w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important} 150 | .w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important} 151 | .w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important} 152 | .w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important} 153 | .w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important} 154 | .w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important} 155 | .w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important} 156 | .w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important} 157 | .w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important} 158 | .w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important} 159 | .w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important} 160 | .w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important} 161 | .w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important} 162 | .w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important} 163 | .w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important} 164 | .w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important} 165 | .w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important} 166 | .w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important} 167 | .w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important} 168 | .w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important} 169 | .w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important} 170 | .w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important} 171 | .w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important} 172 | .w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important} 173 | .w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important} 174 | .w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important} 175 | .w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important} 176 | .w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important} 177 | .w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important} 178 | .w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important} 179 | .w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important} 180 | .w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important} 181 | .w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important} 182 | .w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important} 183 | .w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important} 184 | .w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important} 185 | .w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important} 186 | .w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important} 187 | .w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important} 188 | .w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important} 189 | .w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important} 190 | .w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important} 191 | .w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important} 192 | .w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important} 193 | .w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important} 194 | .w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important} 195 | .w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important} 196 | .w3-text-red,.w3-hover-text-red:hover{color:#f44336!important} 197 | .w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important} 198 | .w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important} 199 | .w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important} 200 | .w3-text-white,.w3-hover-text-white:hover{color:#fff!important} 201 | .w3-text-black,.w3-hover-text-black:hover{color:#000!important} 202 | .w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important} 203 | .w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important} 204 | .w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important} 205 | .w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important} 206 | .w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important} 207 | .w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important} 208 | .w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important} 209 | .w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important} 210 | .w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important} 211 | .w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important} 212 | .w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important} 213 | .w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important} 214 | .w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important} 215 | .w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important} 216 | .w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important} 217 | .w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important} 218 | .w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important} 219 | .w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important} 220 | .w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important} 221 | .w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important} 222 | .w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important} 223 | .w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important} 224 | .w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important} 225 | .w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important} 226 | .w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important} 227 | .w3-border-black,.w3-hover-border-black:hover{border-color:#000!important} 228 | .w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important} 229 | .w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important} 230 | .w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important} 231 | .w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important} 232 | .w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important} -------------------------------------------------------------------------------- /lib/DML.js: -------------------------------------------------------------------------------- 1 | /* DML.js 2 | 3 | (C) 28/07/2021 Eckehard Fiedler 4 | 5 | Create dynamic Websites on the fly. 6 | 7 | Content can be created completely or as a combination with standard HTML-Elemtents. 8 | General page structure should be: 9 | 10 | 11 | 12 | title 13 | 14 | 15 | 16 | 17 | 18 | 19 | ... Your HTML-Content, referenced Element with ID: 20 |

My Header

21 | 22 | 32 | 33 | 34 | Object Creation 35 | =============== 36 | First, an html-Element can be selected as base element: 37 | 38 | selectBase(ID) (ID can be an element ID or en element reference) 39 | unselectBase() -> restor previous base point 40 | 41 | if no element was selected or se selection was remove with select(""), the document body is used, 42 | elements are appended to the end of the document. HTML Elements can be added by 43 | 44 | let c = appendBase(obj) 45 | 46 | New Objects can be created with: 47 | 48 | let c = create(typ,attr,content) Create element with contents (either text or other object) 49 | 50 | As most elements will be added to the document directly, there is a short form: 51 | 52 | let c = make(typ, attr ,content), that combines appendBase(create(...) 53 | 54 | 55 | Example: Create an h1-Object: 56 | ============================ 57 | 58 | make("h1","Hello World")) 59 | 60 | make/appendBase returns the object reference, so any DOM-Property can be set on the fly as 61 | 62 | make("h1","Hello World").style.color = "#aa0000" 63 | 64 | or: 65 | 66 | let c = make("h1","Hello World") 67 | c.style.color = "#aa0000" 68 | 69 | or 70 | let h = make("h1","Hello World") 71 | with (h.style) 72 | { color = "#A00000" 73 | border = "solid #006F00" 74 | backgroundColor = "#aaaaaa" 75 | width = "50%" 76 | borderRadius = "30px" 77 | textAlign = "center" 78 | } 79 | 80 | It´s easy to copy a comlete style set like this: 81 | 82 | v2.style.cssText = v1.style.cssText 83 | 84 | Some functions for list and table creation are provided, that create new or set already defined list/table elements 85 | from arrays. 86 | 87 | We also very proudly present the most simple AJAX-request: 88 | 89 | httpGet(url, par1...).response = function(s, par1...) { ...do something } 90 | 91 | As function(s) is called delayed, it may not be able to access dynamic elements (e.g. a loop counter). Therefore, 92 | parameters par1-par3 can be set to transfer state informations at the time, httpGet ist called. 93 | 94 | */ 95 | /* ---------------------------------------------------------------------------- 96 | global variables 97 | ---------------------------------------------------------------------------- */ 98 | 99 | var _base // Global element stores current insert position. If empty, elements are added at the end of document. 100 | var _baseStack = [] // Stack for storing _base positions 101 | var _block = false // global var for blocking loaders 102 | var _onresizeElements = [] // global list for onresize handlers 103 | 104 | /* ---------------------------------------------------------------------------- 105 | constants 106 | ---------------------------------------------------------------------------- */ 107 | 108 | const svgref = "http://www.w3.org/2000/svg"; 109 | const PI2 = 2 * Math.PI 110 | const _style = "style" 111 | const _bold = "font-weight: bold;" 112 | const _italic = "font-style: italic;" 113 | const _fs = "font-size: " 114 | const _bigtext = "font-size: 130%;" 115 | const _bg = "background-color: " 116 | const _bgred = "background-color: red;" 117 | const _bgred2 = "background-color: #f50;" 118 | const _bgy = "background-color: #ffc;" 119 | const _bggreen = "background-color: #695;" 120 | const _bgblue = "background-color: blue;" 121 | const _bgorange = "background-color: #fc0;" 122 | const _bgsilver = "background-color: silver;" 123 | const _bgyellow = "background-color: #ffffee;" 124 | const _bgwhite = "background-color: white;" 125 | const _bgblack = "background-color: black;" 126 | const _bgtrans = "background-color: rgba(0,0,0,0.05);" 127 | const _bgwtrans = "background-color: rgba(255,255,255,0.5);" 128 | const _red = "color: red;" 129 | const _blue = "color: blue;" 130 | const _navy = "color: navy;" 131 | const _white = "color: white;" 132 | const _yellow = "color: yellow;" 133 | 134 | const _center = "text-align: center;" 135 | const _right = "text-align: right;" 136 | const _top = "vertical-align: top;" 137 | const _bottom = "vertical-align: bottom;" 138 | const _middle = "vertical-align: middle;" 139 | const _flexmiddle = "display: flex; align-items: center;" 140 | const _blur = "filter: blur(2px);" 141 | const _shadow = "box-shadow: 3px 3px 4px gray;" 142 | const _bigshadow = "box-shadow: 6px 6px 8px gray;" 143 | const _smallShadow = "box-shadow: 2px 2px 3px gray;" 144 | const _txtShadow = "text-shadow: 5px 6px 4px rgba(0,0,0,0.44);" 145 | const _bigTxtShadow = "text-shadow: 8px 13px 5px rgba(0,0,0,0.44);" 146 | const _border = "border: thin solid silver;" 147 | const _noborder = "border: 0px;" 148 | const _radius = "border-radius: 8px;" 149 | const _miniRadius = "border-radius: 5px;" 150 | const _padding = "padding: 2px;" 151 | const _tpadding = "padding: 1px 5px 1px 5px;" 152 | const _bigPadding = "padding: 10px;" 153 | const _smallMargin = "margin: 2px;" 154 | const _margin = "margin: 5px;" 155 | const _marginLeft = "margin-left: 5px;" 156 | const _marginRight = "margin-right: 5px;" 157 | const _bigMarginLeft = "margin-left: 10px;" 158 | const _bigMarginRight = "margin-right: 10px;" 159 | const _inShadow = "-webkit-box-shadow: inset 5px 5px 3px -2px rgba(0,0,0,0.64);" + 160 | "-moz-box-shadow: inset 5px 5px 3px -2px rgba(0,0,0,0.64);" + 161 | "box-shadow: inset 5px 5px 3px -2px rgba(0,0,0,0.64);" 162 | // Combined styles 163 | const _box = _bgwhite + _border + _shadow 164 | const _ybox = _border + _shadow + _bg + "#ffc;" 165 | 166 | // Flex Layout definitions: At leas 3 columns without header 167 | const _bodyFlex = "display: flex; flex-flow: row nowrap; justify-content: space-between;" 168 | const _sideFlex = "flex-shrink: 0.5;" // side will shrink less 169 | const _columnFlex = "flex-grow: 0; display: flex; flex-flow: row nowrap;" 170 | const _flex = "display: flex;" 171 | const _flexSpaceAround = "display: flex; justify-content: space-around;" 172 | const _flexSpaceBetween = "display: flex; justify-content: space-around;" 173 | // Use width: calc(100% - 200px); for expandable element 174 | const _sticky = "position: -webkit-sticky; position: sticky; top: 0px;" 175 | const _btnstyle = "width: 100px; height: 24px;" + 176 | " display: inline-flex; align-items: center;" + 177 | " justify-content: center; margin: 8px;" 178 | const _flybox = "position: fixed;" + 179 | "padding: 6px;" + 180 | "box-shadow: 5px 5px 6px silver;" + 181 | "border-radius: 8px;" + 182 | "background-color: #ffffff;" + 183 | "border: thin solid gray;" + 184 | "left: 50%;" + 185 | "top: 50%;" + 186 | "transform: translate(-50%, -50%);" 187 | 188 | /**************************************************************************************** 189 | Spracheinstellung 190 | Voreinstellung ist Deutsch. Nach Aufruf von getLanguage(...) wird die Sprache umgestellt 191 | mit L(["de","en","fr"]) 192 | ****************************************************************************************/ 193 | let _language = 0 194 | const de = 0 195 | const en = 1 196 | const fr = 2 197 | 198 | let languages = ["de", "en", "fr"] 199 | 200 | // Get language number from string 201 | function getLanguage(s) { 202 | let s2 = s.toLowerCase(s).substr(1, 2) 203 | for (let i in languages) { 204 | if (s.toLowerCase(s) == languages[i]) 205 | return _language = i 206 | } 207 | } 208 | 209 | /*------------------------------------------------------ 210 | Deliver language specific string 211 | can be L(["de","en","fr"]) or 212 | L("de","en","fr") 213 | ------------------------------------------------------*/ 214 | function L(s, sen, sfr) { 215 | if (Array.isArray(s)) { 216 | return s[_language] 217 | } 218 | if (_language == 1) 219 | if (sen) return sen 220 | if (_language == 2) 221 | if (sfr) return sfr 222 | return s 223 | } 224 | 225 | /**************************************************************************************** 226 | Helper functions 227 | ****************************************************************************************/ 228 | 229 | /*------------------------------------------------------ 230 | automatically binds all methods to the class instance 231 | !!! important !!! 232 | 233 | // Fix autobind 234 | (function autobind(self, proto){ 235 | for(let key of Object.getOwnPropertyNames( proto )){ 236 | if(key !== 'constructor') self[key] = self[key].bind(self); 237 | } 238 | let parentProto = Object.getPrototypeOf(proto); 239 | if (parentProto !== Object.prototype){ 240 | autobind(self, parentProto); 241 | } 242 | })(this, this.constructor.prototype); 243 | 244 | ------------------------------------------------------*/ 245 | function autobind(instance) { 246 | let proto = Object.getPrototypeOf(instance); 247 | let propertyNames = Object.getOwnPropertyNames(proto); 248 | for (let name of propertyNames) { 249 | let value = proto[name]; 250 | if ((typeof value === 'function')) { 251 | if (name !== 'constructor') 252 | instance[name] = proto[name].bind(instance); 253 | } 254 | } 255 | } 256 | 257 | /*------------------------------------------------------ 258 | immediate call. Replaces (f())() 259 | can be used to check, if f is a function 260 | ------------------------------------------------------*/ 261 | function call(f, ...args) { 262 | if (f instanceof Function) 263 | return f(...args) 264 | } 265 | 266 | /*------------------------------------------------------ 267 | dynamic script import 268 | gets single moduleName or arra of Modulenames for dynamic import 269 | calls callback, after last module is loaded 270 | prevents double import by creating a semaphore variable from filename 271 | 272 | _import(["..\\lib\\DML_table.js","..."], callback) 273 | _import(["..\\lib\\DML_table.js","..."]).ready = () =>{ } 274 | 275 | ------------------------------------------------------*/ 276 | function _import(moduleNames, callback) { 277 | 278 | if (typeof (moduleNames) == 'string') 279 | moduleNames = [moduleNames] 280 | 281 | let count = moduleNames.length 282 | for (i in moduleNames) { 283 | let moduleName = moduleNames[i]; 284 | let varName = extractFilename(moduleName).replace('.', '_'); 285 | if (typeof (window[varName]) == 'undefined') { 286 | window[varName] = varName // define a semaphore 287 | let script = document.createElement('script'); 288 | script.src = moduleNames[i]; 289 | script.onload = () => { 290 | if (--count == 0) { 291 | if (callback) callback() 292 | } 293 | }; 294 | document.head.appendChild(script); //or something of the likes 295 | } else { // if one lib was defined, cancel import 296 | if (callback) { 297 | callback() 298 | return 299 | } 300 | 301 | } 302 | } 303 | } 304 | 305 | /*! 306 | loadCSS: load a CSS file asynchronously. 307 | [c]2014 @scottjehl, Filament Group, Inc. 308 | Licensed MIT 309 | */ 310 | function loadCSS(href, before, media) { 311 | "use strict"; 312 | // Arguments explained: 313 | // `href` is the URL for your CSS file. 314 | // `before` optionally defines the element we'll use as a reference for injecting our 315 | // By default, `before` uses the first