/* This file is part of Bolixo. Bolixo is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Bolixo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Bolixo. If not, see . */ /* This file hold various test done to figure out how to use html and javascript */ // To learn and experiment with HTML #include #include #include #include #include #include #include #include "../instrument.h" extern "C" void tlmp_initmod() { translat_load ("bolixo"); } static void do_webtable(const WEBID &id, int nbrow, unsigned &cur) { glocal int nbrow = nbrow; (id,cur,0,5); sethead ("title1\ttitle2\ttitle3\ttitle4"); setrowstyle ("white","bgcolor=white"); setrowstyle ("white+current","bgcolor=lightblue"); setclickopt(true,"",""); for (int i=0; i } static void do_webtable(const WEBID &id, int nbrow) { unsigned cur = 0; do_webtable (id,nbrow,cur); } static void layout (int width, int toprep, int middlerep) { //DIV main; main.w(width).h(100).disp("table").print(); DIV main; main.w(width).disp("flex").flowcol().print(); if (0){ DIV tb; tb.w(100).h(100).disp("flex").flowrow().print(); DIV c1; c1.flex("0 1 auto").print(); /- allo c1.end(); DIV c2; c2.flex("0 1 auto").print(); /- comment ca va c2.end(); }else if (0){ DIV tb; tb.h(5).disp("table-row").flex("0 1 auto").print(); DIV c1; c1.disp("table-cell").print(); /- allo c1.end(); DIV c2; c2.disp("table-cell").print(); /- comment ca va c2.end(); } if (0){ DIV tb; tb.h(95).disp("table-row").flex("1 1 auto").print(); DIV c1; c1.disp("table-cell").print(); /- Une autre ligne c1.end(); DIV c2; c2.disp("table-cell").print(); DIV col; col.bg("red").disp("flex").flowcol().print(); } DIV to; to.bg("gray").disp("flex").flex("0 1 auto").print(); for (int i=0; iButton4Button5 /-
} to.end(); DIV mi; mi.bg("yellow").w(100).disp("flex").flex("1 1 auto").print(); static int level = 0; if (level == 0){ level++; DIV d; d.w(100).disp("flex").flowrow().print(); layout(50,1,10); layout(50,2,10); level--; }else{ DIV d; d.w(100).disp("flex").flowrow().print(); DIV dd; dd.w(30).flex("0 1 auto").print(); (WEBID("titi")); for (int i=0; i<20; i++) setrow("white",0,"a\tb\tc"); dd.end(); DIV ddd; ddd.flex("1 1 auto").print(); /- for (int i=0; i
field-%d\n",i); } /-
} mi.end(); DIV bo; bo.bg("pink").flex("0 1 auto").print(); /- toto bo.end(); //col.end(); /- }
/* This test was done to experiment with div inside div, to learn how it behave */ void test1() { tlmpweb_title ("This is the start of a long long journey"); * { box-sizing: border-box; } .flex-container { display: flex; background-color: DodgerBlue; height: 100%; } .flex-ccontainer > div { background-color: #f1f1f1; margin: 10px; padding: 20px; font-size: 30px; height: 100%; } section { display: -webkit-flex; display: flex; background-color:lightblue; } .div{ width:30%; } .box { display: flex; flex-flow: column; height: 100%; } .right{ background-color:red; height:100%; display: flex; flex-flow: column; } .top{ background-color:gray; flex: 0 1 auto; } .middle{ background-color:yellow; flex: 1 1 auto; } .bottom{ flex: 0 1 auto; background-color:pink; } ?> tlmpweb_body("white",NULL);
allo le monde bababa babababa abababba
?> layout(40,1,10); layout(40,2,10); /- } /* This is replicating the complete layout of bolixo */ void bolixo() { .tab { //margin-bottom: 100%; //position: absolute; //top: 0; //left: 0; //bottom: 0; //width: 10em; /* or whatever */ } ?> tlmpweb_body("white",NULL); DIV main("main"); main.dispflex().flowcol().w(100).h(100).print(); { // The title DIV b0("main0","main0"); b0.w(100).flexfixe().print(); DIV banner; banner.w(100).dispflex().flowrow().bg("lightgray").print(); // Put some items DIV it; it.flexfixe().content("Bolixo.org"); it.flexgrow().content("
Welcome
"); it.flexfixe().content("
AboutLogout
"); } WEBID table1("table1"); WEBID table2("table2"); { DIV body("main1"); body.flexgrow().w(100).bg("red").print(); DIV tabs("tabs"); tabs.w(100).dispflex().flowrow().bg("gray").align("stretch").print(); DIV t("tab","tab"); t.w(20).flexfixe().bg("yellow").print(); { do_webtable(table1,20); //DIV grow; grow.dispflex().flowcol().print(); //DIV b0; b0.bg("black").flexgrow().content("This is a test"); } t.w(40).flexfixe().bg("lightblue").print(); { DIV t; t.dispflex().flowcol().print(); DIV tab21("tab2","tab2"); tab21.bg("blue").flexfixe().print(); /-

THIS IS T2

tab21.end(); DIV tab22; tab22.flexgrow().print(); do_webtable(table2,20); } t.w(40).flexfixe().bg("pink").print(); /-

THIS IS T2

t.end(); /-
} main.end(); var t = document.getElementById('main0').clientHeight; var col = document.getElementById("t2"); var diff = window.innerHeight-t; var line = "title bar height = " + t + " screenh = " + window.innerHeight + " res= " + diff; col.innerHTML = line + "
" + line + "
" + line; document.getElementById("tab").style.height=diff; var tables = document.getElementsByClassName('webtable'); var i; var tablestr=''; var sep=''; for (i = 0; i < tables.length; i++) { var table = tables[i]; tablestr+=sep+table.id+','+table.offsetHeight+','+table.offsetWidth; sep=','; } var ttop = document.getElementById("table2-top"); var tt = 0; if (ttop != null) tt = ttop.clientHeight; t = document.getElementById('tab2').clientHeight; document.getElementById("t3").innerHTML = tablestr + " tab2=" + t + " top=" + tt; document.getElementById("table2").style.height=diff-t-tt; document.getElementById("table1").style.height=diff-document.getElementById("table1-top").clientHeight; ?> } /* Try to understand why a form creates some vertical spaces in a layout The trick was "margin-bottom:0;" */ void form_space() { tlmpweb_body("white",NULL); DIV d; d.h(100).dispflex().flowcol().print(); DIV sub; sub.h(10).bg("yellow").print(); /- 111111
{ DIV s; s.w(100).bg("blue").print(); // /-
/-
// /-
} // /- /- 22222
/- 33333
sub.h(30).bg("red").print(); ("test"); /- /-
allo /-
return true;
sub.h(60).bg("green").print(); /- End }
static W_SSTRING w_file("file"); static W_SSTRING w_name("name"); static W_UNSIGNED w_delay("delay"); static void fctanim() { static const char *waitid = "waitpopup"; const unsigned width = 100; const unsigned height = 40; { DIV a("popup","popup-id"); a.print(); DIV d("popup-content",waitid); d.print(); DIV dd; dd.dispflex().flowrow().print(); DIV left; left.flexfixe().margins(10,10).vmargins(5,0).print(); htmlprintf ("\n",width,height,width,height); unsigned w1 = width/5; unsigned w1_2 = w1/2; unsigned h1 = height/2; const unsigned ray = w1/4; for (unsigned i=0; i<5; i++){ htmlprintf ("\n" ,i,i*w1+w1_2,h1,ray,i==0 ? "blue" : "white"); } /- left.end(); #if 0 DIV right; right.print(); htmlout ( "\n" "\n" "\n" "\n" "\n" "\n"); #endif } htmlprintf ("\n",waitid); } /* Add some animation when a form is submit after a delay */ void journey_formanim() { if (w_delay.getval() > 0) sleep (w_delay.getval()); glocal string error; tlmpweb_body("white",NULL); //tlmpweb_setscripts(); htmlout ("\n" ); DIV d; d.h(100).dispflex().flowcol().print(); function showname () { var name = document.getElementById('fileInput'); alert('Selected file: ' + name.files.item(0).name); alert('Selected file: ' + name.files.item(0).size); alert('Selected file: ' + name.files.item(0).type); }; function getextra(){ window.setTimeout(showanimate,500); return ""; } ?> ("test"); /- /-
/- execution delay (seconds) field_string (w_delay,""); /- Upload a file field_file (w_file); /- Message htmlout (glocal.error); /- bool ret = false; if (strcmp(w_file.c_str(),"toto.txt")==0){ glocal.error = "toto.txt is not accepted"; }else if (strcmp(w_file.c_str(),"")!=0){ ret = true; }else{ glocal.error = "You must specify a file"; } return ret; if (strcmp(w_file.c_str(),"")!=0){ const char *tempname = tlmpweb_getfilename(w_file); tlmp_warning ("upload file temp=%s",tempname); }
fctanim(); /- End /-
Retry }
/* Simple test to see the new HTML 5 tags section and friends */ void newtags() { .page-wrap { display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */ display: -ms-flexbox; /* TWEENER - IE 10 */ display: -webkit-flex; /* NEW - Chrome */ display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */ } .main-content { width: 60%; } .main-nav, .main-sidebar { -webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */ -moz-box-flex: 1; /* OLD - Firefox 19- */ width: 20%; /* For old syntax, otherwise collapses. */ -webkit-flex: 1; /* Chrome */ -ms-flex: 1; /* IE 10 */ flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */ } .main-content { -webkit-box-ordinal-group: 2; /* OLD - iOS 6-, Safari 3.1-6 */ -moz-box-ordinal-group: 2; /* OLD - Firefox 19- */ -ms-flex-order: 2; /* TWEENER - IE 10 */ -webkit-order: 2; /* NEW - Chrome */ order: 2; /* NEW, Spec - Opera 12.1, Firefox 20+ */ } .main-nav { -webkit-box-ordinal-group: 1; -moz-box-ordinal-group: 1; -ms-flex-order: 1; -webkit-order: 1; order: 1; } .main-sidebar { -webkit-box-ordinal-group: 3; -moz-box-ordinal-group: 3; -ms-flex-order: 3; -webkit-order: 3; order: 3; } ?> tlmpweb_body("white",NULL);
Main content: first in source order
?> } void scrollbar() { tlmpweb_body("white",NULL); DIV d; d.dispflex().flowcol().print(); /-
/-
/- previous page next page /-
/-
/-
WEBID table("table"); do_webtable(table,100); /-
}
static void draw_tab (const char *pathid, unsigned width, unsigned height, const char *fill, bool close, const char *title, bool drawx, const char *href, const char *xref) { if (width == 0){ width = strlen(title)*9; if (drawx) width += 25; } htmlprintf ("\n",width,height); htmlprintf ("\n",href); htmlprintf ("\n"); htmlprintf ("\t%s\n",height-10,title); htmlout ("\n"); if (drawx){ unsigned x=width-20; unsigned y=height-10; static unsigned id=0; htmlprintf ("\n",xref,id,id); htmlprintf ("\n",id,x-3,y-11); htmlprintf ("\n",x,y-8,x,y); id++; htmlout ("\n"); } htmlout ("\n"); } #if 0 static void draw_tab (unsigned width, unsigned height, const char *fill, bool close, const char *title) { draw_tab (width,height,fill,close,title,false,"",""); } #endif void draw_left_arrow(bool visible, const char *xref) { htmlout ("\n"); if (visible){ static unsigned id=0; htmlprintf ("\n",xref,id,id); htmlprintf ("\n",id); id++; } const char *color = visible ? "black" : "white"; htmlprintf ("\n",color,color); if (visible) htmlout ("\n"); // Always put the underline htmlout ("\n"); htmlout ("\n"); } void draw_right_arrow(bool visible, const char *xref) { htmlout ("\n"); if (visible){ static unsigned id=0; htmlprintf ("\n",xref,id,id); htmlprintf ("\n",id); id++; } const char *color = visible ? "black" : "white"; htmlprintf ("\n",color,color); if (visible) htmlout ("\n"); // Always put the underline htmlout ("\n"); htmlout ("\n"); } // Draw nice tabs using SVG static void tabs (int nbrep, bool arrow_left, bool arrow_right) { DIV main; main.dispflex().w(100).flowcol().print(); DIV head; head.h(10).w(100).flexfixe().bg("lightgray").print(); /-

Title

head.end(); DIV body; body.w(100).flexfixe().print(); DIV tabs; tabs.dispflex().flowrow().print(); { DIV col; col.flexfixe().w(50).print(); DIV cols; cols.dispflex().flowrow().print(); { DIV col; col.flexfixe().print(); draw_left_arrow(arrow_left,""); } { DIV col; col.flexgrow().overflow("hidden").print(); static struct { const char *s; bool dox; } tb[]={{"Messages",false},{"Projects",true},{"Mails",true}}; DIV d; d.dispflex().flowrow().bg("none").overflow("hidden").print(); DIV c; int j=0; for (int i=0; i ?> #endif } { DIV col; col.flexfixe().print(); draw_right_arrow(arrow_right,""); } DIV end; end.flexfixe().print(); /- ? } { DIV col; col.flexfixe().w(50).bg("yellow").print(); } //line x1=0 y1=20 x2=1000 y2=20 style='stroke-width:4; stroke=black;'/> }
void tabs() { tlmpweb_body("white",NULL); function changefill(id,color){ var e = document.getElementById(id); console.log ("e " + e != null); e.setAttribute('fill', color); //e.currentTarget.setAttribute('fill', color); } ?> tabs (0,true,true); tabs (1,false,true); tabs (2,false,true); tabs (8,false,true); } static W_SSTRING table("webtable"); static W_UNSIGNED menu("menu"); static W_UNSIGNED line("line"); static W_UNSIGNED screenheight("screenheight"); static W_UNSIGNED screenwidth("screenwidth"); static W_SSTRING fontsize("fontsize"); void popup() { .dropbtn { background-color: #4CAF50; color: white; padding: 16px; font-size: 16px; border: none; cursor: pointer; } .show {display: block;} .active { background-color: lightgrey;} ?> #if 0 ?> #endif tlmpweb_setscripts(); tlmpweb_body("white",NULL); if (table.isset()) htmlprintf ("webtable=%s
\n",table.c_str()); if (menu.isset()) htmlprintf ("menu=%u
\n",menu.getval()); if (line.isset()) htmlprintf ("line=%u
\n",line.getval()); if (screenheight.isset()) htmlprintf ("screenheight=%u
\n",screenheight.getval()); if (screenwidth.isset()) htmlprintf ("screenwidth=%u
\n",screenwidth.getval()); if (fontsize.isset()) htmlprintf ("fontsize=%s
\n",fontsize.c_str()); Test dropdown ?> /-

Table tb1


/- for (int i=0; i<5; i++){ htmlprintf ("\n",i); for (int j=0; j<5; j++){ htmlprintf ("
hello world how are you today %d",j); } /- } /-
/-

Table tb2


/- for (int i=0; i<5; i++){ htmlprintf ("\n",i,i&1?"0,2,4":"0,101,3,5"); for (int j=0; j<5; j++){ htmlprintf ("
this is table tb2 %d",j); } /- } /-
}
void webtable_drowdown() { WEBID table1("table1"); WEBID table2("table2"); tlmpweb_setscripts(); tlmpweb_body("white",NULL); unsigned cur = 0; (table1,cur,0,5); setthparms ("align=left bgcolor=lightgray",""); setrowstyle ("white","bgcolor=white"); setrowstyle ("white+current","bgcolor=lightblue"); for (unsigned i=0; i<4; i++){ adddrop_opt (i,string_f("menu %u",i)); } sethead ("title1\ttitle2\ttitle3\ttitle4"); setclickopt (true,"",""); for (int i=0; i<5; i++){ resetdrop(); if (i&1){ setdrop_visibles({0,1,2}); } setrow("white",i,"aaaa\tbbbb\tcccc\tdddd"); } } void webtable_popup() { tlmpweb_setscripts(); .xpopup { display: inline-block; } .iipopup-content { display: none; position: absolute; background-color: #f1f1f1; box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); z-index: 1; } ?> tlmpweb_body("white",NULL); WEBID id ("id"); do_webtable(id, 5); { DIV a("popup"); a.print(); DIV d("popup-content","popup"); d.print(); DIV dd; dd.dispflex().flowrow().print(); DIV left; left.flexfixe().margins(10,10).vmargins(5,0).print(); if (0){ /- This is an error /-

/- Another error }else{ ("popup"); /- /-
New file name field_string (w_file,""); /-
return true;
} left.end(); DIV right; right.print(); \n"); ?> } var pop = document.getElementById("popup"); if (pop != null){ pop.style.left = 200; pop.style.top = 100; console.log ("show="+pop.classList.toggle("show")); } ?> } static void index_script(unsigned scrollid1, unsigned scrollid2) { // Script to make sure the webtabs tabs use the full height of the screen // Then it takes the webtables and grows them too. document.onreadystatechange = function () { var state = document.readyState; if (state == 'interactive') { fixsize(); } else if (state == 'complete') { } }; var diff = 0; function allDescendants (node,total) { //console.log ("Enter " + node.className + " " + node.id); if (node.className == "tabs"){ var bord=(node.offsetHeight-node.clientHeight); var style = node.currentStyle || window.getComputedStyle(node); var margins = parseInt(style.marginTop,10) + parseInt(style.marginBottom,10); var paddings = parseInt(style.paddingTop,10) + parseInt(style.paddingBottom,10); total += bord + margins + paddings; console.log ("border node.id=" + node.id + " total="+total+" bord="+bord); } for (var i = 0; i < node.childNodes.length; i++) { var child = node.childNodes[i]; if (child.id != null && (child.id == "tabs" || child.id == "tab_form" || child.id == "webtable-top")){ total += child.offsetHeight; if (child.id == "tab_form") total += 2; // Bug scrollbar ??? console.log ("child.id=" + child.id + " total="+total+" height="+child.offsetHeight); }else{ if (child.id != null && child.id == "vframe2h"){ var bord=(child.offsetWidth-child.clientWidth); total += bord; console.log ("border child.id=" + child.id + " total="+total+" border="+bord); }else if (child.className == "webtable" || child.id == "textgrow"){ console.log ("Set webtable "+child.id+" total="+total+" diff="+diff+" oldheight="+child.offsetHeight); child.style.height = diff - total; break; } total = allDescendants(child,total); } } return total; } function fixsize(){ var t = document.getElementById('head').offsetHeight; diff = window.innerHeight-t; document.getElementById('body').style.height = diff-1; document.getElementById('main').style.height = window.innerHeight-1; var tabs = document.getElementsByClassName("tabs"); for (var i=0; i webtable_setscroll(); ?> } static void journey_setscroll() { (); tlmpweb_setscripts(); tlmpweb_body("white",NULL); WEBID id1 ("id1"); WEBID id2 ("id2"); { DIV m("","main"); m.w(100).h(100).print(); DIV d("","head"); d.w(100).h(10).print(); /- Hello d.end(); unsigned cur1 = 10; unsigned cur2 = 20; d.id("body").w(100).dispflex().flowrow().print(); { DIV tab("tabs"); tab.flexfixe().w(40).bg("lightblue").margins(5,5).vmargins(5,5).border(1,"black").print(); do_webtable(id1, 100,cur1); } { DIV tab("tabs"); tab.flexfixe().w(60).bg("lightred").margins(5,5).vmargins(5,5).border(1,"black").print(); do_webtable(id2, 100,cur2); } } unsigned w,h,l,scroll_top1=100,scroll_top2=400; tlmpweb_gettablegeometry (id1,w,h,scroll_top1,l); tlmpweb_gettablegeometry (id2,w,h,scroll_top2,l); tlmp_error ("top %u %u\n",scroll_top1,scroll_top2); index_script(scroll_top1,scroll_top2); } void util_endscript(PARAM_STRING); static void journey_subtabs() { (); tlmpweb_setscripts(); tlmpweb_body("white",NULL); WEBID id1 ("id1"); WEBID id2 ("id2"); { DIV m("","main"); m.w(100).h(100).print(); DIV d("","head"); d.w(100).h(10).print(); /- Hello d.end(); d.cls("tabs").id("body").w(100).dispflex().flowrow().print(); DIV d1("subtabs","d1"); d1.w(50).vpaddings(10,10).bg("pink").print(); DIV d2("subtabs","d2"); d2.w(95).vpaddings(10,10).bg("white").print(); DIV d3("subtabs","d3"); d3.w(95).vpaddings(10,10).bg("pink").print(); } util_endscript(""); } /* When you click on a link, it jumps to a new tab. If you click with the middle mouse button, it opens in a new tab, but stay in the current one (like normal). */ static void journey_click() { (); tlmpweb_setscripts(); htmlout ( "\n" ); tlmpweb_body("white",NULL); const char *url = "http://test1.bolixo.org/talk1.jpg"; htmlprintf ("",url); htmlprintf ("\n",url); htmlout ("\n"); } static void test_displen (const char *s, const char *font) { unsigned len = tlmpweb_displaylen(s,1); unsigned fact=1; htmlprintf ("len=%u
\n",len); DIV d; d.id("box").border(1,"black").wpx(len*fact).hpx(tlmpweb_fontsize()*fact).print(); htmlprintf ("%s\n",fact,font,s); d.end(); /-
var el = document.getElementById('box'); var style = window.getComputedStyle(el, null).getPropertyValue('font-size'); var fontSize = parseFloat(style); var fstyle = window.getComputedStyle(el, null).getPropertyValue('font-style'); var type = window.getComputedStyle(el, null).getPropertyValue('font-name'); console.log ('fontSize='+fontSize+' type='+type+' style='+fstyle); ?> } struct WORDINFO{ const char *txt; unsigned len; // In pixel unsigned txtlen; // strlen(txt); WORDINFO(const char *_txt, unsigned _len){ txt = _txt; len = _len; txtlen = strlen(txt); } }; class PARAGRAPH{ vector tb; // Will contain the paragraph splitted into words. public: vector words; // The paragraph is decomposed into words vector> lines; // Then the words are put together in lines unsigned cursor_pos=0; // Cursor position inside the line in pixel vector line_cursors; // character cursor position in each line, produced by locate_cursor() vector line_homes; // character cursor (paragraph) position of the start of each line vector line_ends; // character cursor (paragraph) position of the end of each line public: PARAGRAPH(); PARAGRAPH(PARAM_STRING txt, unsigned width); void init(PARAM_STRING txt, unsigned width); void locate_cursor(unsigned para_cursor, unsigned &noline, unsigned &line_cursor); unsigned get_para_cursor (unsigned noline); unsigned get_para_home (unsigned noline); unsigned get_para_end (unsigned noline); unsigned get_line_cursor (unsigned noline); }; static float para_fontsize=1; static unsigned displaylen_call=0; static unsigned journey_displaylen (PARAM_STRING txt) { displaylen_call++; return tlmpweb_displaylen (txt.ptr,para_fontsize); } PARAGRAPH::PARAGRAPH() { } PARAGRAPH::PARAGRAPH(PARAM_STRING txt, unsigned width) { init (txt,width); } void PARAGRAPH::init(PARAM_STRING txt, unsigned width) { tb.clear(); words.clear(); lines.clear(); line_homes.clear(); line_ends.clear(); str_splitline (txt.ptr,' ',tb); for (auto &w:tb){ w.insert(w.begin(),' '); words.emplace_back(w.c_str(),journey_displaylen(w)); } unsigned offset = 0; unsigned wordnum = 1; while (wordnum < words.size()){ // We assemble a line made of words until its width is larger than the div width. auto &wo = words[offset]; if (wo.txt[0] == ' '){ // Remove the space for the first word wo.txtlen--; wo.txt++; wo.len = journey_displaylen(wo.txt); } unsigned linelen = wo.len; for (unsigned i=offset+1; i<=wordnum; i++) linelen += words[i].len; //htmlprintf ("linelen=%u width=%u lines.size()=%lu
\n",linelen,width,lines.size()); if (linelen < width){ wordnum++; }else{ vector line; for (unsigned i=offset; i line; for (unsigned i=offset; i para_cursor){ // Ok the cursor is in that word string tmp (w.txt,para_cursor-offset_cursor); //htmlprintf ("last word :%s:
\n",tmp.c_str()); cursor_pos += journey_displaylen(tmp); break; } cursor_pos += w.len; offset_cursor = next_offset; } } break; } para_cursor -= line_size; } // We know the cursor horizonl position in pixel: cursor_pos // Now we will find the corresponding cursor position in each lines of the paragraph. // This will be stored in line_offsets. This is the cursor position in character. line_cursors.clear(); for (auto &l:lines){ unsigned pixel_offset = 0; unsigned offset = 0; for (auto &w:l){ unsigned next_pixel_offset = pixel_offset + w.len; if (next_pixel_offset > cursor_pos){ // The cursor is located in that word. const char *s = w.txt; string tmp; unsigned target_pos = cursor_pos - pixel_offset; while (*s != '\0'){ tmp += *s++; #if 0 htmlprintf ("line=%lu tmp=:%s: offset=%u target_pos=%u dlen=%u
\n" ,line_cursors.size(),tmp.c_str(),offset,target_pos,journey_displaylen(tmp)); #endif if (journey_displaylen(tmp) > target_pos) break; offset++; } break; } pixel_offset = next_pixel_offset; offset += w.txtlen; } line_cursors.push_back(offset); } } unsigned PARAGRAPH::get_para_home (unsigned noline) { unsigned ret = 0; if (noline < line_cursors.size()){ return line_homes[noline]; } return ret; } unsigned PARAGRAPH::get_para_end (unsigned noline) { unsigned ret = 0; if (noline < line_cursors.size()){ return line_ends[noline]; } return ret; } unsigned PARAGRAPH::get_para_cursor (unsigned noline) { unsigned ret = 0; if (noline < line_cursors.size()){ return line_homes[noline] + line_cursors[noline]; } return ret; } unsigned PARAGRAPH::get_line_cursor (unsigned noline) { unsigned ret = 0; if (noline < line_cursors.size()) ret = line_cursors[noline]; return ret; } /* We display a text in a div having a specified width. It forms a paragraph. The cursor represents the offset in the text as if the text was displayed on a single line. We do two job here. We try to convert the linear cursor into a line number and of column number inside the line. Then we try to find the corresponding column number in each line of the paragraph. We display first the paragraph with the cursor shown as a |. Then we display the paragraph with | on each line. */ static void journey_paragraph(unsigned width, const char *txt, unsigned cursor) { DIV d; d.border(1,"black").wpx(width).print(); unsigned len = strlen(txt); if (len > cursor){ htmlprintf ("%*.*s%c%s",cursor,cursor,txt,txt[cursor],txt+cursor+1); }else{ htmlout (txt); for (unsigned w=cursor; w\n"); htmlprintf ("exec=%Lu.%06Lu noline=%u cursor_pos=%u dispplaylen=%u
\n",diff/1000000,diff%1000000,noline,para.cursor_pos,displaylen_call); //for (auto o:line_offsets) htmlprintf ("offset=%u ",o); htmlout ("
\n"); // We make the DIV larger so the browser paragraph formatting is not used. // We display the paragraph line by line as PARAGRAPH understands it. DIV dd; dd.border(1,"black").wpx(width+100).print(); for (unsigned i=0; i\n",offset,offset,pts,pts+offset); } dd.end(); DIV ddd; dd.border(1,"black").wpx(width).print(); unsigned cur = para.get_para_cursor(noline); htmlprintf("%*.*s%c%s
\n",cur,cur,txt,txt[cur],txt+cur+1); /-
} void util_defstyles(); /* See if tlmpweb_displaylen() is accurate */ static void journey_displaylen() { util_defstyles(); htmlprintf ("fontsize=%u
\n",tlmpweb_fontsize()); for (auto s:{ "Inbox", "hello", "Hello_World", "Jacques_Gelinas", "Jacques_Gelinas@alpha.bolixo.org", "Jacques_Gélinas", "Jacques_Gélinas@alpha.bolixo.org", "Jacques_éèôÉÀ", "Jacques_éèôÉÀ@alpha.bolixo.org", }){ test_displen(s,"Arial"); } for (auto f:{ "Times New Roman", "Times", "serif", "Arial", "Helvetica", "sans-serif", "Lucida Console", "Courier", "monospace" }){ htmlprintf ("%s
\n",f); test_displen("hello how are you today ? How was it yesterday ? hello how are you today ? how was it yesterday ? And now How do you feel ?",f); } if (!tlmpweb_is_repost()){ /- } #if 1 string txt1 = "hello how are you today ? How was it yesterday ?"; string txt; for (int i=0; i<4; i++) txt += txt1; for (auto cursor:{15,115}){ htmlprintf ("CURSOR=%d
\n",cursor); for (auto w:{400,500,600}){ journey_paragraph(w,txt.c_str(),cursor); } } #endif }
static void journey_keypress() {
Allo comment
?> }
/* Try to move something over an SVG */ static void journey_animation() { var todo = []; function fctanimate(x0,y0,x1,y1,nostep,steps,duration,fctend){ var txt = document.getElementById('txtanim'); console.log ('txt='+' nostep='+nostep+' steps='+steps); var stepx = (x1-x0)/steps; var stepy = (y1-y0)/steps; console.log ('stepx='+stepx+' stepy='+stepy); txt.setAttribute('x',x0+stepx*nostep); txt.setAttribute('y',y0+stepy*nostep); txt.style.fill='black'; txt.style.stroke='red'; nostep++; if (nostep < steps){ console.log ('timer='+duration/steps); window.setTimeout(function(){ fctanimate(x0,y0,x1,y1,nostep,steps,duration,fctend); },duration/steps); }else{ fctend(); // Remove the first todo entry todo.shift(); // and starts the next one if (todo.length > 0) todo[0](); } } var number=0; function addanim(event){ todo[todo.length] = function(){ var fctend = function(){ var circleid='wait'+(number % 5); var circle = document.getElementById(circleid); circle.style.fill = 'red'; } if ((number % 4) == 0){ fctanimate(0,0,600,600,0,100,2000,fctend); }else if ((number % 4) == 1){ fctanimate(0,600,600,0,0,100,2000,fctend); }else if ((number % 4) == 2){ fctanimate(600,600,0,0,0,100,2000,fctend); }else{ fctanimate(600,0,0,600,0,100,2000,fctend); } }; // We execute the function only if there is only one. // If there is more, it means there is currently one running. if (todo.length == 1) todo[0](); number++; } ?> unsigned width=600; unsigned height=600; htmlprintf ("\n" ,width,height,width,height); unsigned w1 = width/5; unsigned w1_2 = w1/2; unsigned h1 = height/2; const unsigned ray = w1/4; for (unsigned i=0; i<5; i++){ htmlprintf ("\n" ,i,i*w1+w1_2,h1,ray,i==0 ? "blue" : "white"); } /- XX /- } static void journey_chat() {

?> }
static W_SSTRING w_upload ("upload"); /* Customize the look of input type=file */ static void journey_filebutton() { util_defstyles(); #upload { opacity: 0; position: absolute; z-index: -1; } ?> htmlout( ".labbutton {\n" " background-color: DodgerBlue;\n" " border: none;\n" " border-radius: 1em;\n" " color: #fff;\n" " padding: .3em .8em;\n" " font-size: 100%;\n" " box-shadow: 2px 2px 2px rgba(0,0,0,0.2);\n" " text-decoration: none;\n" " width: auto;\n" "display: inline-block;\n" "vertical-align: middle;\n" "}\n" ".labbutton:hover {\n" " background-color: lightskyblue;\n" "}\n" //".labbutton:active {\n" //" background-color: lightskyblue;\n" //" transform: translateY(0.25em);\n" "}\n"); ?> #if 1 ?> #endif ("f"); #if 0 DIV ddd; ddd.w(100).dispflex().flowrow().border(1,"red").print(); //DIV dddd; dddd.flexfixe().border(1,"blue").print(); field_file_attach (w_upload); //dddd.end(); //dddd.style("margin-left","auto").flexfixe().border(1,"orange").print(); button_send (); #else DIV ddd; ddd.w(100).dispflex().flowrow().border(1,"red").print(); DIV dddd; dddd.flexfixe().border(1,"blue").print(); ?> dddd.end(); // DIV dd; dd.flexfixe().border(1,"blue").style("margin-left","auto").print(); button_send(); #endif return 0; } static void journey_forminforms() { util_defstyles(); /- You enter s to get to the sub-dialog. /-
/- You enter ok to end the sub-dialog /-

htmlprintf ("validate name=:%s: file=:%s:\n",w_name.c_str(),w_file.c_str()); /-

("f"); /- file field_string (w_file,""); glocal bool ret = true; tlmp_warning ("validate1 name=:%s:",w_name.c_str()); htmlprintf ("w_file = :%s:
\n",w_file.c_str()); return glocal.ret;
glocal bool fail = false; htmlprintf ("Process file=:%s:
\n",w_file.c_str()); if (strcmp(w_file.c_str(),"s")==0){ glocal.fail= true; ("f"); DIV d; d.bg("blue").print(); d.donotend(); /- /- name field_string (w_name,""); bool ret = false; tlmp_warning ("validate2 name=:%s:",w_name.c_str()); if (strcmp(w_name.c_str(),"ok")==0){ ret = true; }else{ /- You must enter ok } htmlprintf ("subform validate ret=%d
\n",ret); return ret;
htmlprintf ("name=:%s: file=:%s:\n",w_name.c_str(),w_file.c_str()); glocal.fail = false;
/-

} fail = glocal.fail; keepediting = true; /-

htmlprintf ("Restart\n",tlmpweb_curpage()); } /* Generate the javascript code to fetch a video segment from the server */ static void journey_generate_fetchsegment() { // ... (definition of the MediaSource and its SourceBuffers) /** * Fetch a video or an audio segment, and returns it as an ArrayBuffer, in a * Promise. * @param {string} url * @returns {Promise.} */ function fetchSegment(url, start, len) { //console.log ("avant range"); range="bytes=" + start.toString()+"-"+(start+len-1).toString(); //console.log(range); headers = {headers: { 'content-type': 'multipart/byteranges', 'range': range, }}; console.log (headers.headers); return fetch(url,headers) .then(function(response) { var ret = response.arrayBuffer(); console.log ("content-type="+response.headers.get('content-type')); console.log ("content-Encoding="+response.headers.get('content-encoding')); //for (let [key, value] of response.headers) { // console.log(`${key} = ${value}`); //} console.log ("return array="+ret); return ret; }).then(function(buffer){ console.log ("return buffer "+buffer); return buffer; }).catch(function(error){ console.error(error); }); } ?> } /* Generate a fetchsegment that simply create buffers using a local (server side) file */ static void journey_generate_jsfetch() { /- } /* Try to play a video using mediasource */ static void journey_videostream() { if (0){ journey_generate_fetchsegment(); }else{ journey_generate_jsfetch(); } Your browser does not support the video tag. ?> } static void journey_webcam() { video, img { max-width:100%; } alo

fin ?> } static void journey_webrtc() { video, img { max-width:100%; } alo

fin ?> } /* Display a grid holding video tags. This is a prototype for the video conférence. Each guest is displayed in his own video tag. Another video tag goes on top, or is hidden, showing the active guest */ static void journey_manyvideos() { alo

?> ///- for (int i=0; i<10; i++) printf ("

\n",i); }
static void journey_selectinput() {

?> } extern "C" void webmain() { tlmpweb_title ("This is the start of a long long journey"); //test1(); //bolixo(); //newtags(); //form_space(); //scrollbar(); //tabs(); //popup(); //webtable_dropdown(); //webtable_popup(); //journey_setscroll(); //journey_subtabs(); //journey_click(); //journey_formanim(); //journey_displaylen(); //journey_keypress(); //journey_animation(); //journey_chat(); //journey_filebutton(); //journey_forminforms(); //journey_videostream(); //journey_webcam(); //journey_webrtc(); //journey_manyvideos(); journey_selectinput(); }