");
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, "" + c + ">")
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