\n';r++}
- v+='| ';
+ v += ' | ';
if (i>=col && dy| (No Date) | (Today) | ';
+ v += ' '
+ + '| (No Date) | '
+ + '(Today) | ';
l.HidLayer.NullArea = pg_addarea(l.HidLayer, 1, 1+(r+1)*18, 100, 16, 'dt', 'dt_null', 3);
l.HidLayer.NullArea.DateVal = null;
l.HidLayer.NullArea.parentPaneId = l.myid;
@@ -451,7 +484,12 @@ function dt_inittime(l) {
// build the structure for the time
v = "";
- v += "\n";
+ v += ""
+ + " |  | "
+ + " |  | "
+ + " |  | "
+ + " (24h) | "
+ + " \n";
htr_write_content(l.TimeHidLayer, v);
htr_setvisibility(l.TimeHidLayer, 'inherit');
htr_setvisibility(l.TimeVisLayer, 'hidden');
@@ -866,11 +904,11 @@ function dt_create_pane(ml,bg,w,h,h2,name) {
h+=20;
}
str += " ";
- str += "  | ";
- str += "  | ";
- str += " | ";
- str += "  | ";
- str += "  | ";
+ str += "  | ";
+ str += "  | ";
+ str += " | ";
+ str += "  | ";
+ str += "  | ";
str += " ";
str += " ";
str += " | S | ";
@@ -893,6 +931,7 @@ function dt_create_pane(ml,bg,w,h,h2,name) {
pg_stackpopup(l,ml);
setClipHeight(l,h);
setClipWidth(l,w);
+ enableClippingCSS(l);
//l.HidLayer = new Layer(1024, l);
l.HidLayer = htr_new_layer(1024,l);
diff --git a/centrallix-os/sys/js/htdrv_dropdown.js b/centrallix-os/sys/js/htdrv_dropdown.js
index b3a23a8db..dd0a6aabc 100644
--- a/centrallix-os/sys/js/htdrv_dropdown.js
+++ b/centrallix-os/sys/js/htdrv_dropdown.js
@@ -1,4 +1,4 @@
-// Copyright (C) 1998-2001 LightSys Technology Services, Inc.
+// Copyright (C) 1998-2026 LightSys Technology Services, Inc.
//
// You may use these files and this library under the terms of the
// GNU Lesser General Public License, Version 2.1, contained in the
@@ -9,6 +9,18 @@
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
+
+// A resize observer to update dropdowns when they are resized.
+const dd_resize_observer = new ResizeObserver(e => e.forEach(({ target }) => {
+ // Ignore widgets that don't have a visible panelayer in need of updating.
+ if (htr_getvisibility(target.PaneLayer) !== 'inherit') return;
+
+ // Reopen the dropdown to rerender it.
+ dd_collapse(target);
+ dd_expand(target);
+}));
+
+
// Form manipulation
function dd_getvalue()
@@ -390,6 +402,9 @@ function dd_collapse(l)
//pg_resize_area(l.area,getClipWidth(l)+1,getClipHeight(l)+1, -1, -1);
htr_setvisibility(l.PaneLayer, 'hidden');
dd_current = null;
+
+ /** Remove the pane to avoid leaking DOM nodes. **/
+ dd_remove_pane(l);
}
}
@@ -407,7 +422,10 @@ function dd_expand(l)
l.Values.splice(0,0,nullitem);
}
if (l && !l.PaneLayer)
+ {
l.PaneLayer = dd_create_pane(l);
+ l.PaneLayer.style.cursor = 'pointer';
+ }
if (l && htr_getvisibility(l.PaneLayer) != 'inherit')
{
pg_stackpopup(l.PaneLayer, l);
@@ -775,6 +793,41 @@ function dd_create_pane(l)
return p;
}
+/** Quick and dirty function to remove panes without leaking DOM nodes. **/
+function dd_remove_pane(l)
+ {
+ if (!l || !l.PaneLayer) return;
+
+ const p = l.PaneLayer;
+
+ // Function for removing elements.
+ const remove_node = (n) => { if (n && n.parentNode) n.parentNode.removeChild(n); }
+
+ // Remove item DOM nodes if present.
+ if (l.Items && l.Items.length)
+ {
+ for (let i = 0; i < l.Items.length; i++)
+ {
+ remove_node(l.Items[i]);
+ l.Items[i] = null;
+ }
+ l.Items.length = 0;
+ l.Items = null;
+ }
+
+ // Remove scrollbar/thumb layers if present.
+ remove_node(p.ScrLayer);
+ remove_node(p.BarLayer);
+ remove_node(p.TmbLayer);
+
+ // Remove the pane root.
+ remove_node(p);
+
+ // Clear references.
+ p.ScrLayer = p.BarLayer = p.TmbLayer = p.Items = p.mainlayer = null;
+ l.PaneLayer = null;
+ }
+
/// REPLACE ITEMS IN DROPDOWN
function dd_add_items(l,ary)
@@ -1194,7 +1247,6 @@ function dd_init(param)
l.NumDisplay = param.numDisplay;
l.Mode = param.mode;
l.SQL = param.sql;
- l.popup_width = param.popup_width?param.popup_width:param.width;
l.VisLayer = param.c1;
l.HidLayer = param.c2;
htr_init_layer(l.VisLayer, l, 'ddtxt');
@@ -1244,7 +1296,6 @@ function dd_init(param)
l.getfocushandler = dd_getfocus;
l.bg = param.background;
l.hl = param.highlight;
- l.w = param.width; l.h = param.height;
l.fieldname = param.fieldname;
l.enabled = 'full';
if (l.Mode != 3)
@@ -1268,11 +1319,35 @@ function dd_init(param)
else if (imgs[i].src.substr(-13,5) == 'white')
imgs[i].upimg = true;
}
- l.area = pg_addarea(l, -1, -1, getClipWidth(l)+3,
- getClipHeight(l)+3, 'dd', 'dd', 3);
if (l.form) l.form.Register(l);
l.init_items = false;
+ // Setup getters for widths and heights.
+ const width_ratio = param.popup_width / param.width;
+ Object.defineProperties(l, {
+ w: {
+ get() { return getRelativeW(l); },
+ configurable: true,
+ enumerable: true,
+ },
+ h: {
+ get() { return getRelativeH(l); },
+ configurable: true,
+ enumerable: true,
+ },
+ popup_width: {
+ get() { return l.w * width_ratio; },
+ configurable: true,
+ enumerable: true,
+ },
+ });
+
+ // Setup the hover area.
+ l.area = pg_addarea(l, -1, -1, () => l.w + 3, () => l.h + 3, 'dd', 'dd', 3);
+
+ // Resize dropdown automatically.
+ dd_resize_observer.observe(l);
+
// Events
var ie = l.ifcProbeAdd(ifEvent);
ie.Add("MouseDown");
diff --git a/centrallix-os/sys/js/htdrv_editbox.js b/centrallix-os/sys/js/htdrv_editbox.js
index 160ce0bdf..d033138fa 100644
--- a/centrallix-os/sys/js/htdrv_editbox.js
+++ b/centrallix-os/sys/js/htdrv_editbox.js
@@ -1,4 +1,4 @@
-// Copyright (C) 1998-2004 LightSys Technology Services, Inc.
+// Copyright (C) 1998-2026 LightSys Technology Services, Inc.
//
// You may use these files and this library under the terms of the
// GNU Lesser General Public License, Version 2.1, contained in the
@@ -162,8 +162,10 @@ function eb_setdesc(txt)
({
"z-index":"-1",
"color":this.desc_fgcolor?this.desc_fgcolor:"#808080",
- "top":($(this).height() - $(this.DescLayer).height())/2 + "px",
+ "top":"0px",
"left":(this.input_width() + ((this.content || this.has_focus)?4:0) + 5) + "px",
+ "height":"100%",
+ "align-content":"center",
"visibility":"inherit",
"white-space":"nowrap",
});
@@ -699,10 +701,11 @@ function eb_init(param)
$(l.ContentLayer).prop('disabled', false);
}
l.isFormStatusWidget = false;
- if (cx__capabilities.CSSBox)
- pg_addarea(l, -1,-1,$(l).width()+3,$(l).height()+3, 'ebox', 'ebox', param.isReadOnly?0:3);
- else
- pg_addarea(l, -1,-1,$(l).width()+1,$(l).height()+1, 'ebox', 'ebox', param.isReadOnly?0:3);
+
+ // Add the hover area.
+ const area_adj = (cx__capabilities.CSSBox) ? 3 : 1;
+ pg_addarea(l, -1, -1, () => $(l).width() + area_adj, () => $(l).height() + area_adj, 'ebox', 'ebox', (param.isReadOnly) ? 0 : 3);
+
if (param.form)
l.form = wgtrGetNode(l, param.form);
else
diff --git a/centrallix-os/sys/js/htdrv_html.js b/centrallix-os/sys/js/htdrv_html.js
index b40264bec..91cf53a65 100644
--- a/centrallix-os/sys/js/htdrv_html.js
+++ b/centrallix-os/sys/js/htdrv_html.js
@@ -1,4 +1,4 @@
-// Copyright (C) 1998-2001 LightSys Technology Services, Inc.
+// Copyright (C) 1998-2026 LightSys Technology Services, Inc.
//
// You may use these files and this library under the terms of the
// GNU Lesser General Public License, Version 2.1, contained in the
@@ -240,7 +240,6 @@ function ht_init(param)
{
setClipHeight(l, getdocHeight(l));
}
- pg_set_style(l, 'height', getdocHeight(l));
if (param.width != -1)
{
setClipWidth(l, param.width);
@@ -250,7 +249,11 @@ function ht_init(param)
{
setClipWidth(l, getdocWidth(l));
}
- pg_set_style(l, 'width', getdocWidth(l));
+
+ /** Clipping breaks responsive pages and is not required in modern browsers. **/
+ disableClippingCSS(l);
+ disableClippingCSS(l2);
+
if (source.substr(0,5) == 'http:')
{
//pg_serialized_load(l, source, ht_reloaded);
@@ -289,6 +292,8 @@ function ht_init(param)
//l.watch('source', ht_sourcechanged);
pg_resize(l.parentLayer);
+ disableClippingCSS(l.parentLayer);
+
return l;
}
diff --git a/centrallix-os/sys/js/htdrv_image.js b/centrallix-os/sys/js/htdrv_image.js
index a4a608022..55e53c666 100644
--- a/centrallix-os/sys/js/htdrv_image.js
+++ b/centrallix-os/sys/js/htdrv_image.js
@@ -1,6 +1,6 @@
// htdrv_image.js
//
-// Copyright (C) 2004 LightSys Technology Services, Inc.
+// Copyright (C) 2004-2026 LightSys Technology Services, Inc.
//
// You may use these files and this library under the terms of the
// GNU Lesser General Public License, Version 2.1, contained in the
@@ -146,13 +146,27 @@ function im_set_scale(a, v)
function im_action_offset(aparam)
{
- im_set_x.call(this, "xoffset", aparam.X);
- im_set_y.call(this, "yoffset", aparam.Y);
+ const { X, Y } = aparam;
+
+ // Log warning.
+ console.warn('Offset action used: This breaks page responsiveness.');
+ console.log(`Action Info: X=${X} Y=${Y} Target=`, this);
+
+ // Update the offset values.
+ im_set_x.call(this, "xoffset", X);
+ im_set_y.call(this, "yoffset", Y);
}
function im_action_scale(aparam)
{
- im_set_scale.call(this, "scale", aparam.Scale);
+ const { Scale } = aparam;
+
+ // Log warning.
+ console.warn('Scale action used: This breaks page responsiveness.');
+ console.log(`Action Info: Scale=${Scale} Target=`, this);
+
+ // Update the scale value.
+ im_set_scale.call(this, "scale", Scale);
}
function im_init(l)
diff --git a/centrallix-os/sys/js/htdrv_imagebutton.js b/centrallix-os/sys/js/htdrv_imagebutton.js
index c3aae6b2a..a78a4f7bd 100644
--- a/centrallix-os/sys/js/htdrv_imagebutton.js
+++ b/centrallix-os/sys/js/htdrv_imagebutton.js
@@ -1,4 +1,4 @@
-// Copyright (C) 1998-2001 LightSys Technology Services, Inc.
+// Copyright (C) 1998-2026 LightSys Technology Services, Inc.
//
// You may use these files and this library under the terms of the
// GNU Lesser General Public License, Version 2.1, contained in the
@@ -211,6 +211,7 @@ function ib_init(param)
l.img.kind = 'ib';
l.cursrc = param.n;
setClipWidth(l, w);
+ disableClippingCSS(l);
l.trigger = ib_trigger;
diff --git a/centrallix-os/sys/js/htdrv_label.js b/centrallix-os/sys/js/htdrv_label.js
index a0226f1cb..6bd89dd92 100644
--- a/centrallix-os/sys/js/htdrv_label.js
+++ b/centrallix-os/sys/js/htdrv_label.js
@@ -1,4 +1,4 @@
-// Copyright (C) 1998-2001 LightSys Technology Services, Inc.
+// Copyright (C) 1998-2026 LightSys Technology Services, Inc.
//
// You may use these files and this library under the terms of the
// GNU Lesser General Public License, Version 2.1, contained in the
@@ -103,7 +103,6 @@ function lb_disable()
function lb_update()
{
var v = htutil_nlbr(htutil_encode(htutil_obscure(this.content), true));
- //var txt = this.stylestr + (v?v:"") + " ";
var txt = v?v:"";
$(this).find("span").html(txt).attr("style", htutil_getstyle(this, null, {}));
/*if (cx__capabilities.Dom0NS) // only serialize this for NS4
@@ -176,7 +175,6 @@ function lbl_init(l, wparam)
l.content = wparam.text;
l.orig_content = wparam.text;
l.fieldname = wparam.field;
- l.stylestr = wparam.style;
l.tooltip = wparam.tooltip;
l.tipid = null;
l.pointcolor = wparam.pfg;
diff --git a/centrallix-os/sys/js/htdrv_menu.js b/centrallix-os/sys/js/htdrv_menu.js
index f517e3948..96c2d58d4 100644
--- a/centrallix-os/sys/js/htdrv_menu.js
+++ b/centrallix-os/sys/js/htdrv_menu.js
@@ -1,4 +1,4 @@
-// Copyright (C) 1998-2001 LightSys Technology Services, Inc.
+// Copyright (C) 1998-2026 LightSys Technology Services, Inc.
//
// You may use these files and this library under the terms of the
// GNU Lesser General Public License, Version 2.1, contained in the
@@ -395,19 +395,21 @@ function mn_init(param)
menu.objname = param.name;
menu.cur_highlight = null;
+ // Set up sizing.
if (cx__capabilities.CSS2)
{
if (menu.scrollHeight == 0)
{
- pg_set_style(menu,'height',menu.childNodes[0].scrollHeight);
- pg_set_style(menu,'width',menu.childNodes[0].scrollWidth);
+ if (param.h === -1) pg_set_style(menu, 'height', menu.childNodes[0].scrollHeight);
+ if (param.w === -1) pg_set_style(menu, 'width', menu.childNodes[0].scrollWidth);
}
else
{
- pg_set_style(menu,'height',menu.scrollHeight);
- pg_set_style(menu,'width',menu.scrollWidth);
+ if (param.h === -1) pg_set_style(menu, 'height', menu.scrollHeight);
+ if (param.w === -1) pg_set_style(menu, 'width', menu.scrollWidth);
}
}
+ disableClippingCSS(menu);
menu.act_w = getClipWidth(menu.clayer);
menu.act_h = getClipHeight(menu.clayer);
if ($(menu).css('visibility') == 'hidden' && (!menu.__WgtrParent.style || $(menu.__WgtrParent).css('visibility') == 'inherit'))
diff --git a/centrallix-os/sys/js/htdrv_objcanvas.js b/centrallix-os/sys/js/htdrv_objcanvas.js
index aeaa1fd1a..4c19ce8ef 100644
--- a/centrallix-os/sys/js/htdrv_objcanvas.js
+++ b/centrallix-os/sys/js/htdrv_objcanvas.js
@@ -1,6 +1,6 @@
// sys/js/htdrv_objcanvas.js
//
-// Copyright (C) 2004 LightSys Technology Services, Inc.
+// Copyright (C) 2004-2026 LightSys Technology Services, Inc.
//
// You may use these files and this library under the terms of the
// GNU Lesser General Public License, Version 2.1, contained in the
@@ -113,6 +113,7 @@ function oc_add_osrc_object(o)
y = parseInt(y);
// make and position the layer
+ console.error("New layer created. This will probably break responsive design.");
var l = this.NewLayer();
htr_init_layer(l, this, 'oc');
l.osrc_oid = o.oid;
diff --git a/centrallix-os/sys/js/htdrv_osrc.js b/centrallix-os/sys/js/htdrv_osrc.js
index f256cd70e..7e3cdc89f 100644
--- a/centrallix-os/sys/js/htdrv_osrc.js
+++ b/centrallix-os/sys/js/htdrv_osrc.js
@@ -2330,8 +2330,6 @@ function osrc_open_query_startat()
else
this.querysize = this.replicasize;
this.query_ended = false;
- //this.LogStatus();
- //console.log('OSRC ' + this.__WgtrName + ': startat ' + this.startat + ', rowcount ' + this.querysize);
this.DoRequest('multiquery', '/', {ls__startat:this.startat, ls__autoclose_sr:1, ls__autofetch:1, ls__objmode:0, ls__notify:this.request_updates, ls__rowcount:this.querysize, ls__sql:this.query, ls__sqlparam:this.EncodeParams()}, osrc_get_qid_startat);
}
diff --git a/centrallix-os/sys/js/htdrv_page.js b/centrallix-os/sys/js/htdrv_page.js
index 1da3ba1e5..9b645b300 100755
--- a/centrallix-os/sys/js/htdrv_page.js
+++ b/centrallix-os/sys/js/htdrv_page.js
@@ -1,4 +1,4 @@
-// Copyright (C) 1998-2001 LightSys Technology Services, Inc.
+// Copyright (C) 1998-2026 LightSys Technology Services, Inc.
//
// You may use these files and this library under the terms of the
// GNU Lesser General Public License, Version 2.1, contained in the
@@ -51,6 +51,11 @@ function pg_scriptavailable(s)
}
+/** Resize handling for all types of area boxes (hover, select, data, etc). **/
+const pg_area_resize_handlers = {};
+window.addEventListener('resize', (e) => Object.values(pg_area_resize_handlers).forEach(f => f(e)));
+
+
//START SECTION: DOM/CSS helper functions -----------------------------------
/** returns an attribute of the element in pixels **/
@@ -728,88 +733,61 @@ function pg_isinlayer(outer,inner)
return false;
}
-/** Function to make four layers into a box //SETH: ?? what's a 'box'?
-* pl - a layer
-* x,y - x,y-cord
-* w,h - widht, height
-* s - ?
-* tl - top layer
-* bl - bottom layer
-* rl - right layer
-* ll - left layer
-* c1 - color1, for tl and ll
-* c2 - color2, for bl and rl
-* z - zIndex
-**/
-function pg_mkbox(pl, x,y,w,h, s, tl,bl,rl,ll, c1,c2, z)
- {
+/*** Helper function for pg_init_box() to initialize a side of a box.
+ ***
+ *** @param layer The target layer (aka. dom node) for the side of the box.
+ *** @param parent_layer The target layer for which the box has been created.
+ *** @param x The x for this side of the box.
+ *** @param y The y for this side of the box.
+ *** @param w The width for this side of the box.
+ *** @param h The height for this side of the box.
+ *** @param color The color of this side of the box.
+ *** @param z The z-index for this side of the box.
+ ***/
+function pg_init_box_side(layer, parent_layer, x, y, w, h, color, z)
+ {
+ resizeTo(layer, w, h);
+ setClipWidth(layer, w);
+ setClipHeight(layer, h);
+ moveAbove(layer, parent_layer);
+ $(layer).offset({ left:x, top:y });
+ htr_setbgcolor(layer, color);
+ htr_setzindex(layer, z);
+ htr_setvisibility(layer, 'inherit');
- htr_setvisibility(tl, 'hidden');
- htr_setvisibility(bl, 'hidden');
- htr_setvisibility(rl, 'hidden');
- htr_setvisibility(ll, 'hidden');
- //abc();
- if (cx__capabilities.Dom0NS || cx__capabilities.Dom1HTML)
-/* {
- tl.bgColor = c1;
- ll.bgColor = c1;
- bl.bgColor = c2;
- rl.bgColor = c2;
- }
- else if (cx__capabilities.Dom1HTML) */
- {
- htr_setbgcolor(tl,c1);
- htr_setbgcolor(ll,c1);
- htr_setbgcolor(bl,c2);
- htr_setbgcolor(rl,c2);
- }
- //alert("x, y --" + x + " " + y);
-
- resizeTo(tl,w,1);
- setClipWidth(tl,w);
- setClipHeight(tl,1);
- //if (cx__capabilities.Dom1HTML && pl)
- // pl.parentLayer.appendChild(tl);
- moveAbove(tl,pl);
- //moveToAbsolute(tl,x,y);
- $(tl).offset({left:x, top:y});
- htr_setzindex(tl,z);
-
- resizeTo(bl,w+s-1,1);
- setClipWidth(bl,w+s-1);
- setClipHeight(bl,1);
- //if (cx__capabilities.Dom1HTML && pl)
- // pl.parentLayer.appendChild(bl);
- moveAbove(bl,pl);
- //moveToAbsolute(bl,x,y+h-s+1);
- $(bl).offset({left:x, top:y+h-s+1});
- htr_setzindex(bl,z);
-
- resizeTo(ll,1,h);
- setClipHeight(ll,h);
- setClipWidth(ll,1);
- //if (cx__capabilities.Dom1HTML && pl)
- // pl.parentLayer.appendChild(ll);
- moveAbove(ll,pl);
- //moveToAbsolute(ll,x,y);
- $(ll).offset({left:x, top:y});
- htr_setzindex(ll,z);
-
- resizeTo(rl,1,h+1);
- setClipHeight(rl,h+1);
- setClipWidth(rl,1);
- //if (cx__capabilities.Dom1HTML && pl)
- // pl.parentLayer.appendChild(rl);
- moveAbove(rl,pl);
- //moveToAbsolute(rl,x+w-s+1,y);
- $(rl).offset({left:x+w-s+1, top:y});
- htr_setzindex(rl,z);
+ return;
+ }
+
+/*** Initialize the four layers (dom nodes) of a box UI element. These are
+ *** commonly used when a user hovers over or selects certain UI elements,
+ *** such as dropdown widgets.
+ ***
+ *** @param parent_layer The target layer for which the box has been created.
+ *** @param x The x coordinate of the top left corner of the box (in px).
+ *** @param y The y coordinate of the top left corner of the box (in px).
+ *** @param w The width of the box (in px).
+ *** @param h The height of the box (in px).
+ *** @param s The thickness of the box (in px)? Maybe?
+ *** @param top_layer The layer to be the line across the top of the box.
+ *** @param bottom_layer The layer to be the line across the bottom of the box.
+ *** @param right_layer The layer to be the line across the right side of the box.
+ *** @param left_layer The layer to be the line across the left side of the box.
+ *** @param color1 The "lit" color of the box (used for the top and left lines).
+ *** @param color2 The "unlit" color of the box (used for the bottom and right lines).
+ *** @param z The z-index for the sides of the box.
+ ***/
+function pg_init_box({
+ parent_layer,
+ x, y, w, h, s,
+ top_layer, bottom_layer, right_layer, left_layer,
+ color1, color2, z
+})
+ {
+ pg_init_box_side(top_layer, parent_layer, x, y, w, 1, color1, z);
+ pg_init_box_side(bottom_layer, parent_layer, x, y+h-s+1, w+s-1, 1, color2, z);
+ pg_init_box_side(right_layer, parent_layer, x+w-s+1, y, 1, h+1, color2, z);
+ pg_init_box_side(left_layer, parent_layer, x, y, 1, h, color1, z);
- htr_setvisibility(tl, 'inherit');
- htr_setvisibility(bl, 'inherit');
- htr_setvisibility(rl, 'inherit');
- htr_setvisibility(ll, 'inherit');
- //alert(rl.style.cssText);
return;
}
@@ -839,17 +817,62 @@ function pg_hidebox(tl,bl,rl,ll)
return;
}
-/** Function to make a new clickable "area" **INTERNAL** **/
-function pg_area(pl,x,y,w,h,cls,nm,f) //SETH: ?? what's an 'area'?
- {
- this.layer = pl;
- this.x = x;
- this.y = y;
- this.width = w;
- this.height = h;
- this.name = nm;
+/*** Internal constructor function to create a new clickable/hoverable "area".
+ *** This function has additional documentation in `HTFormInterface.md`.
+ ***
+ *** Note: Many functions specify (x,y) as (0,0), or as (-1,-1) if the focus
+ *** area should appear 1px outside the parent layer.
+ ***
+ *** Note: The x, y, w, and h params can all be specified as either a single
+ *** value or a function. The latter is useful because areas are redawn
+ *** when the page resizes, so a function can provide an updated value
+ *** for the new layout.
+ ***
+ *** @param parent The associated parent layer for which this area is rendered.
+ *** This object should implement the `keyhandler()`, `getfocushandler()`,
+ *** and `losefocushandler()`, as described in `HTFormInterface.md`.
+ *** @param x The x coordinate of the area, relative to the parent layer.
+ *** @param y The y coordinate of the area, relative to the parent layer.
+ *** @param width The width of the area.
+ *** @param height The height of the area.
+ *** @param cls A mostly unused value for the "context" of an area, used for
+ *** the callback functions described in `HTFormatInterface.md`. (As for how
+ *** "context" can be abbreviated to `cls`, your guess is as good as mine.)
+ *** @param name The name of the area, also used for callback functions.
+ *** @param f A bitmask representing zero or more of the following flags:
+ *** 1: Allow the area to receive keyboard focus.
+ *** 2: Allow the area to receive data focus.
+ ***/
+function pg_area(parent, x, y, width, height, cls, name, f)
+ {
+ // Function to handle params that might be functions.
+ const handle_param = (name, value) => {
+ if (typeof(value) === 'function')
+ {
+ // Set a base value and define a getter that calls the provided function.
+ this[name] = value();
+ Object.defineProperty(this, name, {
+ get() { return value.call(this); },
+ configurable: true,
+ enumerable: true
+ });
+ }
+
+ // If just a value is provided, simply set that.
+ else this[name] = value;
+ }
+
+ // Handle each parameter for the class.
+ this.layer = parent;
+ handle_param('x', x);
+ handle_param('y', y);
+ handle_param('width', width);
+ handle_param('height', height);
+ this.name = name;
this.cls = cls;
this.flags = f;
+
+ // Return the newly instantiated object.
return this;
}
@@ -924,9 +947,12 @@ function pg_resize_area(a,w,h,xo,yo)
}
}
-/** Function to add a new area to the arealist **/
+/*** Function to add a new area to the area list.
+ *** Note that x, y, w, & h can all be provided as
+ *** function for responsive resizing.
+ ***/
function pg_addarea(pl,x,y,w,h,cls,nm,f)
- {
+ {
var a = new pg_area(pl,x,y,w,h,cls,nm,f);
//pg_arealist.splice(0,0,a);
pg_arealist.push(a);
@@ -1354,6 +1380,8 @@ function pg_init(l,a,gs,ct) //SETH: ??
ia.Add("Launch", pg_launch);
ia.Add("Close", pg_close);
ia.Add("Alert", pg_alert);
+ ia.Add("Log", pg_log);
+ ia.Add("ReloadPage", pg_reload_page);
// Events
var ie = window.ifcProbeAdd(ifEvent);
@@ -1435,6 +1463,16 @@ function pg_alert(aparam)
alert(aparam.Message);
}
+function pg_log({ Message })
+ {
+ console.log(Message);
+ }
+
+function pg_reload_page()
+ {
+ window.location.reload();
+ }
+
function pg_reveal_cb(e)
{
if (e.eventName == 'ObscureOK')
@@ -1917,7 +1955,9 @@ function pg_findfocusarea(l, xo, yo)
function pg_setmousefocus(l, xo, yo)
{
- var a = pg_findfocusarea(l, xo, yo);
+ if (!l) return false;
+
+ const a = pg_findfocusarea(l, xo, yo);
if (a && a != pg_curarea)
{
pg_curarea = a;
@@ -1925,26 +1965,55 @@ function pg_setmousefocus(l, xo, yo)
{
if (!pg_curarea.layer.getmousefocushandler || pg_curarea.layer.getmousefocushandler(xo, yo, a.layer, a.cls, a.name, a))
{
- // wants mouse focus
- var offs = $(pg_curarea.layer).offset();
- //var x = getPageX(pg_curarea.layer)+pg_curarea.x;
- //var y = getPageY(pg_curarea.layer)+pg_curarea.y;
- var x = offs.left+pg_curarea.x;
- var y = offs.top+pg_curarea.y;
-
- var w = pg_curarea.width;
- var h = pg_curarea.height;
- if (cx__capabilities.Dom0NS)
- {
- pg_mkbox(l, x,y,w,h, 1, document.layers.pgtop,document.layers.pgbtm,document.layers.pgrgt,document.layers.pglft, page.mscolor1, page.mscolor2, document.layers.pgktop.zIndex-1);
- }
- else if (cx__capabilities.Dom1HTML)
+ // Create a function to handle all box updates with this focus.
+ const update_box = (area) =>
{
- pg_mkbox(l, x,y,w,h, 1, document.getElementById("pgtop"),document.getElementById("pgbtm"),document.getElementById("pgrgt"),document.getElementById("pglft"), page.mscolor1, page.mscolor2, htr_getzindex(document.getElementById("pgktop"))-1);
- }
+ // Compute layout data.
+ const offs = $(area.layer).offset();
+ const x = area.x + offs.left;
+ const y = area.y + offs.top;
+ const w = area.width;
+ const h = area.height;
+
+ if (cx__capabilities.Dom0NS)
+ {
+ pg_init_box({
+ parent_layer: l,
+ x, y, w, h, s: 1,
+ top_layer: document.layers.pgtop,
+ bottom_layer: document.layers.pgbtm,
+ right_layer: document.layers.pgrgt,
+ left_layer: document.layers.pglft,
+ color1: page.mscolor1,
+ color2: page.mscolor2,
+ z: document.layers.pgktop.zIndex - 1,
+ });
+ }
+ else if (cx__capabilities.Dom1HTML)
+ {
+ pg_init_box({
+ parent_layer: l,
+ x, y, w, h, s: 1,
+ top_layer: document.getElementById("pgtop"),
+ bottom_layer: document.getElementById("pgbtm"),
+ right_layer: document.getElementById("pgrgt"),
+ left_layer: document.getElementById("pglft"),
+ color1: page.mscolor1, color2: page.mscolor2,
+ z: htr_getzindex(document.getElementById("pgktop")) - 1,
+ });
+ }
+ };
+
+ // Initial update.
+ update_box(pg_curarea);
+
+ // Responsive updates.
+ const area = pg_curarea; // Save value so we can create a closure below.
+ pg_area_resize_handlers.mouse_focus = () => update_box(area);
}
}
}
+ if (!a) delete pg_area_resize_handlers.mouse_focus;
}
function pg_removekbdfocus(p)
@@ -1956,23 +2025,55 @@ function pg_removekbdfocus(p)
pg_curkbdarea = null;
if (cx__capabilities.Dom0NS)
{
- pg_mkbox(null,0,0,0,0, 1, document.layers.pgktop,document.layers.pgkbtm,document.layers.pgkrgt,document.layers.pgklft, page.kbcolor1, page.kbcolor2, document.layers.pgtop.zIndex+100);
+ pg_init_box({
+ parent_layer: null,
+ x: 0, y: 0, w: 0, h: 0, s: 1,
+ top_layer: document.layers.pgktop,
+ bottom_layer: document.layers.pgkbtm,
+ right_layer: document.layers.pgkrgt,
+ left_layer: document.layers.pgklft,
+ color1: page.kbcolor1, color2: page.kbcolor2,
+ z: document.layers.pgtop.zIndex + 100,
+ });
}
else if (cx__capabilities.Dom1HTML)
{
- pg_mkbox(null,0,0,0,0, 1, document.getElementById("pgktop"),document.getElementById("pgkbtm"),document.getElementById("pgkrgt"),document.getElementById("pgklft"), page.kbcolor1, page.kbcolor2, pg_get_style(document.getElementById("pgtop"), 'zIndex')+100);
+ pg_init_box({
+ parent_layer: null,
+ x: 0, y: 0, w: 0, h: 0, s: 1,
+ top_layer: document.getElementById("pgktop"),
+ bottom_layer: document.getElementById("pgkbtm"),
+ right_layer: document.getElementById("pgkrgt"),
+ left_layer: document.getElementById("pgklft"),
+ color1: page.kbcolor1, color2: page.kbcolor2,
+ z: pg_get_style(document.getElementById("pgtop"), 'zIndex') + 100,
+ });
}
}
+
+ // Clear resize handling.
+ delete pg_area_resize_handlers.mouse_focus;
+ delete pg_area_resize_handlers.data_focus;
+ delete pg_area_resize_handlers.kbd_focus;
+
return true;
}
function pg_setdatafocus(a)
{
+ if (!a) return false;
+
var x = getPageX(a.layer)+a.x;
var y = getPageY(a.layer)+a.y;
var w = a.width;
var h = a.height;
var l = a.layer;
+
+ // Setup resize handling.
+ pg_area_resize_handlers.data_focus = () => {
+ // Recall function to update values.
+ pg_setdatafocus(a);
+ };
// hide old data focus box
if (l.pg_dttop != null)
@@ -2015,16 +2116,36 @@ function pg_setdatafocus(a)
// draw new data focus box
if (cx__capabilities.Dom0NS)
{
- pg_mkbox(l,x-1,y-1,w+2,h+2, 1, l.pg_dttop,l.pg_dtbtm,l.pg_dtrgt,l.pg_dtlft, page.dtcolor1, page.dtcolor2, document.layers.pgtop.zIndex+100);
+ pg_init_box({
+ parent_layer: l,
+ x: x - 1, y: y - 1, w: w + 2, h: h + 2, s: 1,
+ top_layer: l.pg_dttop,
+ bottom_layer: l.pg_dtbtm,
+ right_layer: l.pg_dtrgt,
+ left_layer: l.pg_dtlft,
+ color1: page.dtcolor1, color2: page.dtcolor2,
+ z: document.layers.pgtop.zIndex + 100,
+ });
}
else if (cx__capabilities.Dom1HTML)
{
- pg_mkbox(l,x-1,y-1,w+2,h+2, 1, l.pg_dttop,l.pg_dtbtm,l.pg_dtrgt,l.pg_dtlft, page.dtcolor1, page.dtcolor2, pg_get_style(document.getElementById("pgtop"),'zIndex')+100);
+ pg_init_box({
+ parent_layer: l,
+ x: x - 1, y: y - 1, w: w + 2, h: h + 2, s: 1,
+ top_layer: l.pg_dttop,
+ bottom_layer: l.pg_dtbtm,
+ right_layer: l.pg_dtrgt,
+ left_layer: l.pg_dtlft,
+ color1: page.dtcolor1, color2: page.dtcolor2,
+ z: pg_get_style(document.getElementById("pgtop"),'zIndex') + 100,
+ });
}
}
function pg_setkbdfocus(l, a, xo, yo)
{
+ if (!l) return false;
+
var from_kbd = false;
if (xo == null && yo == null)
{
@@ -2056,23 +2177,27 @@ function pg_setkbdfocus(l, a, xo, yo)
pg_curkbdarea = a;
pg_curkbdlayer = l;
+ // Setup resize handling.
+ pg_area_resize_handlers.kbd_focus = () => {
+ // Recall function to update values.
+ pg_setkbdfocus(l, a, xo, yo);
+ };
+
if (pg_curkbdlayer && pg_curkbdlayer.getfocushandler)
{
v=pg_curkbdlayer.getfocushandler(xo,yo,a.layer,a.cls,a.name,a,from_kbd);
if (v & 1)
{
- // mk box for kbd focus
- //if (prevArea != a)
- // {
- // if (cx__capabilities.Dom0NS)
- // {
- // pg_mkbox(l ,x,y,w,h, 1, document.layers.pgktop,document.layers.pgkbtm,document.layers.pgkrgt,document.layers.pgklft, page.kbcolor1, page.kbcolor2, document.layers.pgtop.zIndex+100);
- // }
- // else if (cx__capabilities.Dom1HTML)
- // {
- pg_mkbox(l ,x,y,w,h, 1, document.getElementById("pgktop"),document.getElementById("pgkbtm"),document.getElementById("pgkrgt"),document.getElementById("pgklft"), page.kbcolor1, page.kbcolor2, htr_getzindex(document.getElementById("pgtop"))+100);
- // }
- // }
+ pg_init_box({
+ parent_layer: l,
+ x, y, w, h, s: 1,
+ top_layer: document.getElementById("pgktop"),
+ bottom_layer: document.getElementById("pgkbtm"),
+ right_layer: document.getElementById("pgkrgt"),
+ left_layer: document.getElementById("pgklft"),
+ color1: page.kbcolor1, color2: page.kbcolor2,
+ z: htr_getzindex(document.getElementById("pgtop")) + 100,
+ });
}
if (v & 2)
{
@@ -3028,9 +3153,12 @@ function pg_check_resize(l)
{
if (wgtrGetServerProperty(l, "height") != $(l).height())
{
- if (wgtrGetParent(l).childresize)
+ const parent = wgtrGetParent(l);
+ if (parent.childresize)
{
- var geom = wgtrGetParent(l).childresize(l, wgtrGetServerProperty(l, "width"), wgtrGetServerProperty(l, "height"), $(l).width(), $(l).height());
+ const width = wgtrGetServerProperty(l, "width");
+ const height = wgtrGetServerProperty(l, "height");
+ const geom = parent.childresize(l, width, height, $(l).width(), $(l).height());
if (geom)
{
wgtrSetServerProperty(l, "height", geom.height);
diff --git a/centrallix-os/sys/js/htdrv_page_moz.js b/centrallix-os/sys/js/htdrv_page_moz.js
deleted file mode 100644
index bf84f15e8..000000000
--- a/centrallix-os/sys/js/htdrv_page_moz.js
+++ /dev/null
@@ -1,268 +0,0 @@
-// Copyright (C) 1998-2001 LightSys Technology Services, Inc.
-//
-// You may use these files and this library under the terms of the
-// GNU Lesser General Public License, Version 2.1, contained in the
-// included file "COPYING" or http://www.gnu.org/licenses/lgpl.txt.
-//
-// This program 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 Lesser General Public License for more details.
-
-
-function pg_ping_init(param)
- {
- var l = param.layer;
- var i = param.i;
- l.tid=setInterval(pg_ping_send,i,l);
- }
-
-
-function pg_ping_recieve()
- {
- this.removeEventListener('load',pg_ping_recieve,false);
- if(this.contentDocument.getElementsByTagName('a')[0].target!=='OK')
- {
- clearInterval(this.tid);
- confirm('you have been disconnected from the server');
- }
- }
-
-
-function pg_ping_send(p)
- {
- if(p.addEventListener)
- p.addEventListener('load',pg_ping_recieve,false);
- //else
- // p.onload=pg_ping_recieve;
- p.src='/INTERNAL/ping';
- }
-
-/** Function to set modal mode to a layer. **/
-function pg_setmodal(l)
- {
- pg_modallayer = l;
- }
-
-/** Function to find out whether image or layer is in a layer **/
-function pg_isinlayer(outer,inner)
- {
- if (inner == outer) return true;
- if(!outer) return true;
- if(!inner) return false;
- var i = 0;
- var olist = outer.getElementsByTagName('iframe');
- for(i=0;i maxheight)
- maxheight = cl.y + cl.clip.height;
- if ((cl.visibility == 'show' || cl.visibility == 'inherit') && cl.x + cl.clip.width > maxwidth)
- maxwidth = cl.x + cl.clip.width;
- }
- if (l.maxheight && maxheight > l.maxheight) maxheight = l.maxheight;
- if (l.minheight && maxheight < l.minheight) maxheight = l.minheight;
- if (l!=window) l.clip.height = maxheight;
- else l.document.height = maxheight;
- if (l.maxwidth && maxwidth > l.maxwidth) maxwidth = l.maxwidth;
- if (l.minwidth && maxwidth < l.minwidth) maxwidth = l.minwidth;
- if (l!=window) l.clip.width = maxwidth;
- else l.document.width = maxwidth;
- }
-
-/** Add a universal "is visible" function that handles inherited visibility. **/
-function pg_isvisible(l)
- {
- if (l.visibility == 'show') return 1;
- else if (l.visibility == 'hidden') return 0;
- else if (l == window || l.parentLayer == null) return 1;
- else return pg_isvisible(l.parentLayer);
- }
-
-/** Cursor flash **/
-function pg_togglecursor()
- {
- if (pg_curkbdlayer != null && pg_curkbdlayer.cursorlayer != null)
- {
- if (pg_curkbdlayer.cursorlayer.visibility != 'inherit')
- pg_curkbdlayer.cursorlayer.visibility = 'inherit';
- else
- pg_curkbdlayer.cursorlayer.visibility = 'hidden';
- }
- setTimeout(pg_togglecursor,333);
- }
-
-
-
-/** Keyboard input handling **/
-function pg_addkey(s,e,mod,modmask,mlayer,klayer,tgt,action,aparam)
- {
- kd = new Object();
- kd.startcode = s;
- kd.endcode = e;
- kd.mod = mod;
- kd.modmask = modmask;
- kd.mouselayer = mlayer;
- kd.kbdlayer = klayer;
- kd.target_obj = tgt;
- kd.fnname = 'Action' + action;
- kd.aparam = aparam;
- pg_keylist.splice(0,0,kd);
- pg_keylist.sort(pg_cmpkey);
- return kd;
- }
-
-
-function pg_cmpkey(k1,k2)
- {
- return (k1.endcode-k1.startcode) - (k2.endcode-k2.startcode);
- }
-
-function pg_removekey(kd)
- {
- for(i=0;i= pg_keylist[i].startcode && k <= pg_keylist[i].endcode && (pg_keylist[i].kbdlayer == null || pg_keylist[i].kbdlayer == pg_curkbdlayer) && (pg_keylist[i].mouselayer == null || pg_keylist[i].mouselayer == pg_curlayer) && (m & pg_keylist[i].modmask) == pg_keylist[i].mod)
- {
- pg_keylist[i].aparam.KeyCode = k;
- pg_keylist[i].target_obj[pg_keylist[i].fnname](pg_keylist[i].aparam);
- return false;
- }
- }
- return false;
- }
-
-
-// Load indication
-if (window.pg_scripts) pg_scripts['htdrv_page_moz.js'] = true;
diff --git a/centrallix-os/sys/js/htdrv_pane.js b/centrallix-os/sys/js/htdrv_pane.js
index dfdb597ad..7e9ce94fb 100644
--- a/centrallix-os/sys/js/htdrv_pane.js
+++ b/centrallix-os/sys/js/htdrv_pane.js
@@ -1,4 +1,4 @@
-// Copyright (C) 1998-2001 LightSys Technology Services, Inc.
+// Copyright (C) 1998-2026 LightSys Technology Services, Inc.
//
// You may use these files and this library under the terms of the
// GNU Lesser General Public License, Version 2.1, contained in the
@@ -79,16 +79,21 @@ function pn_setbackground(aparam)
function pn_action_resize(aparam)
{
- var w = aparam.Width?aparam.Width:pg_get_style(this, 'width');
- var h = aparam.Height?aparam.Height:pg_get_style(this, 'height');
+ const { Width, Height } = aparam;
+
+ // Log warning.
+ console.warn('Resize action used: This breaks page responsiveness.');
+ console.log(`Action Info: Width=${Width} Height=${Height} Target=`, this);
+
+ // Resize the pane.
+ const w = Width ?? pg_get_style(this, 'width');
+ const h = Height ?? pg_get_style(this, 'height');
resizeTo(this, w, h);
}
function pn_action_point(aparam)
{
- var divs = htutil_point(this, aparam.X, aparam.Y, aparam.AtWidget, aparam.BorderColor, aparam.FillColor, this.point1, this.point2);
- this.point1 = divs.p1;
- this.point2 = divs.p2;
+ htr_action_point(this, aparam);
}
function pn_init(param)
diff --git a/centrallix-os/sys/js/htdrv_radiobutton.js b/centrallix-os/sys/js/htdrv_radiobutton.js
index 5b106deb9..e019c09d2 100644
--- a/centrallix-os/sys/js/htdrv_radiobutton.js
+++ b/centrallix-os/sys/js/htdrv_radiobutton.js
@@ -1,4 +1,4 @@
-// Copyright (C) 1998-2001 LightSys Technology Services, Inc.
+// Copyright (C) 1998-2026 LightSys Technology Services, Inc.
//
// You may use these files and this library under the terms of the
// GNU Lesser General Public License, Version 2.1, contained in the
@@ -37,7 +37,6 @@ function rb_setvalue(v) {
}
}
this.clearvalue();
- //alert('Warning: "'+v+'" is not in the radio button list.');
}
function rb_cb_getvalue(p) {
@@ -104,12 +103,8 @@ function add_radiobutton(optionPane, param) {
var rb = wgtrGetParent(optionPane);
rb.rbCount++;
optionPane.valueIndex = rb.rbCount;
- /*optionPane.kind = 'radiobutton';
- optionPane.document.layer = optionPane;*/
htr_init_layer(optionPane, rb, 'radiobutton');
- //optionPane.mainlayer = rb;
optionPane.optionPane = optionPane;
- optionPane.isSelected = param.selected;
optionPane.valueStr = param.valuestr;
optionPane.labelStr = param.labelstr;
@@ -151,8 +146,14 @@ function add_radiobutton(optionPane, param) {
htr_setvisibility(optionPane.unsetPane, 'inherit');
}
- optionPane.yOffset = getRelativeY(optionPane)+getRelativeY(rb.coverPane)+getRelativeY(rb.borderPane);
- pg_addarea(rb, getRelativeX(optionPane), optionPane.yOffset, getClipWidth(optionPane), pg_parah+4, optionPane, 'rb', 3);
+ const yOffset = getRelativeY(rb.coverPane) + getRelativeY(rb.borderPane) - 1;
+ optionPane.area = pg_addarea(rb,
+ () => getRelativeX(optionPane) + 2,
+ () => getRelativeY(optionPane) + yOffset,
+ () => getRelativeW(optionPane) + 2,
+ () => getRelativeH(optionPane) + 3,
+ optionPane, 'rb', 3
+ );
}
function rb_getfocus(xo,yo,l,c,n,a,from_kbd)
@@ -347,8 +348,6 @@ function rb_changemode(){
for (var i=0;i e.forEach(({ target }) => {
+ target.UpdateThumb();
+}));
+
+
+function sp_init({ layer: pane, area_name, thumb_name })
{
- var l = param.layer;
- var alayer=null;
- var tlayer=null;
- var ml;
- var img;
- var i;
- if(cx__capabilities.Dom0NS)
- {
- var layers = pg_layers(l);
- for(i=0;i 100) aparam.Percent = 100;
- setRelativeY(this.area, -d*aparam.Percent/100);
+ const { bottom } = child.getBoundingClientRect();
+ if (bottom > maxBottom) maxBottom = bottom;
}
- else if (typeof aparam.Offset != 'undefined')
+ area.content_height = Math.max(0, Math.round(maxBottom - top));
+
+ /** Watch for changes in content height. **/
+ if (cx__capabilities.Dom0IE)
{
- if (aparam.Offset < 0) aparam.Offset = 0;
- else if (aparam.Offset > d) aparam.Offset = d;
- setRelativeY(this.area, -aparam.Offset);
+ area.runtimeStyle.clip.pane = pane;
+ // how to watch this in IE?
+ area.runtimeStyle.clip.onpropertychange = sp_WatchHeight;
}
- else if (typeof aparam.RangeStart != 'undefined' && typeof aparam.RangeEnd != 'undefined')
+ else
{
- var ny = -getRelativeY(this.area);
- if (ny + ch < aparam.RangeEnd) ny = aparam.RangeEnd - ch;
- if (ny > aparam.RangeStart) ny = aparam.RangeStart;
- if (ny < 0) ny = 0;
- if (ny > d) ny = d;
- setRelativeY(this.area, -ny);
+ area.clip.pane = pane;
+ area.clip.watch("height", sp_WatchHeight);
}
- this.UpdateThumb(h);
}
-function sp_WatchHeight(property, oldvalue, newvalue)
+/** ========== Getter functions ========== **/
+/** Functions to compute common values needed often in this code. **/
+
+/** @returns The height of content inside the scrollpane (even if not all of it is visible). **/
+function sp_get_content_height(area)
+ {
+ return area.content_height;
+ }
+
+/** @returns The height of visible area available to the scrollpane. **/
+function sp_get_available_height(pane)
+ {
+ return parseInt(getComputedStyle(pane).height);
+ }
+
+/** @returns The height of the content outside the available visible area of the scrollpane. **/
+function sp_get_nonvisible_height(pane)
+ {
+ return sp_get_content_height(pane.area) - sp_get_available_height(pane);
+ }
+
+/** @returns The height of visible area available to the scroll bar. **/
+function sp_get_scrollbar_height(pane)
+ {
+ /** The up and down buttons and thumb are each 18px. **/
+ return sp_get_available_height(pane) - (3*18);
+ }
+
+/** @returns The distance down that the scrollpane has been scrolled. **/
+function sp_get_scroll_dist(area)
+ {
+ return -getRelativeY(area);
+ }
+
+
+/*** Update the scrollpane to handle the height of its contained content
+ *** (aka. its child widgets) changing.
+ ***
+ *** @param property Unused
+ *** @param old_value The old height of the child content (unused).
+ *** @param new_value The new height of the child content.
+ ***/
+function sp_WatchHeight(property, old_value, new_value)
{
+ const { pane } = this;
+ const { area } = pane;
+
+ /** Handle legacy Internet Explorer behavior. **/
if (cx__capabilities.Dom0IE)
- {
- newvalue = htr_get_watch_newval(window.event);
- }
-
- // make sure region not offscreen now
- newvalue += getClipTop(this.pane.area);
- if (getRelativeY(this.pane.area) + newvalue < getClipHeight(this.pane)) setRelativeY(this.pane.area, getClipHeight(this.pane) - newvalue);
- if (newvalue < getClipHeight(this.pane)) setRelativeY(this.pane.area, 0);
- this.pane.UpdateThumb(newvalue);
- newvalue -= getClipTop(this.pane.area);
- this.bottom = this.top + newvalue; /* ns seems to unlink bottom = top + height if you modify clip obj */
- return newvalue;
+ new_value = htr_get_watch_newval(window.event);
+
+ /** Update the internal content height value. **/
+ area.content_height = new_value;
+
+ /** Get the available height of the visible area. **/
+ const available_height = sp_get_available_height(pane);
+
+ /** Scroll to the top if the content is now smaller than the visible area. **/
+ if (getRelativeY(area) + new_value < available_height)
+ setRelativeY(area, available_height - new_value);
+ if (new_value < available_height) setRelativeY(area, 0);
+
+ /** Update the scroll thumb. **/
+ pane.UpdateThumb();
+
+ return new_value;
}
-function sp_UpdateThumb(h)
+/** Called when the ScrollTo action is used. **/
+function sp_action_ScrollTo({ Percent, Offset, RangeStart, RangeEnd })
{
- /** 'this' is a spXpane **/
- if(!h)
- { /** if h is supplied, it is the soon-to-be clip.height of the spXarea **/
- h=getClipHeight(this.area)+getClipTop(this.area); // height of content
- }
- var d=h-getClipHeight(this); // height of non-visible content (max scrollable distance)
- var v=getClipHeight(this)-(3*18);
- if(d<=0)
- setRelativeY(this.thum, 18);
- else
- setRelativeY(this.thum, 18+v*(-getRelativeY(this.area)/d));
+ const pane = this;
+ const available = sp_get_available_height(pane);
+ const nonvisible_height = sp_get_nonvisible_height(pane); // Height of non-visible content.
+
+ /** Ignore the action if all content is visible. **/
+ if (nonvisible_height <= 0) return;
+
+ /** Calculate the new location to scroll to. **/
+ const new_scroll_height =
+ (Offset !== undefined) ? Offset :
+ (Percent !== undefined) ? Math.clamp(0, Percent / 100, 1) * nonvisible_height :
+ (RangeStart !== undefined && RangeEnd !== undefined) ?
+ Math.clamp(RangeEnd - available, sp_get_scroll_dist(pane.area), RangeStart) :
+ 0; /* Fallback default value. */
+
+ /** Scroll to the new location. **/
+ sp_scroll_to(pane, new_scroll_height);
}
-function do_mv()
+/** Recalculate and update the location of the scroll thumb. **/
+function sp_update_thumb()
{
+ const pane = this;
+ const { area, thumb } = pane;
- var ti=sp_target_img;
- /** not sure why, but it's getting called with a null sp_target_img sometimes... **/
- if(!ti)
+ /** Get the height of nonvisible content. **/
+ const nonvisible_height = sp_get_nonvisible_height(pane);
+
+ /** Handle the case where all content is visible. **/
+ if (nonvisible_height <= 0)
{
+ /** All we need to do is to move the scroll thumb to the top. **/
+ setRelativeY(thumb, 18);
return;
}
- var h=getClipHeight(ti.area)+getClipTop(ti.area); // height of content
- var d=h-getClipHeight(ti.pane); // height of non-visible content (max scrollable distance)
- var incr=sp_mv_incr;
- if(d<0)
- incr=0;
- if (ti.kind=='sp')
+
+ /** Calculate where the scroll thumb should be based on the scroll progress. **/
+ let scroll_dist = sp_get_scroll_dist(area);
+ if (scroll_dist > nonvisible_height)
{
- var scrolled = -getRelativeY(ti.area); // distance scrolled already
- if(incr > 0 && scrolled+incr>d)
- incr=d-scrolled;
+ /** Scroll down to fill the new space at the bottom of the scrollpane. **/
+ setRelativeY(area, -nonvisible_height);
+ scroll_dist = nonvisible_height;
+ }
+ const progress = scroll_dist / nonvisible_height;
+ const progress_scaled = 18 + sp_get_scrollbar_height(pane) * progress;
+
+ /** Set the scroll thumb to the calculated location. **/
+ setRelativeY(thumb, progress_scaled);
+ }
- /** if we've scrolled down less than we want to go up, go up the distance we went down **/
- if(incr < 0 && scrolled<-incr)
- incr=-scrolled;
+/*** Scroll the scrollpane to the specified `scroll_height`.
+ ***
+ *** @param pane The affected scrollpane DOM node.
+ *** @param scroll_height The new height, in pixels, that the content should
+ *** be scrolled to as a result of this scroll.
+ ***/
+function sp_scroll_to(pane, scroll_height)
+ {
+ /** Ignore undefined target pane. **/
+ if (!pane) return;
+
+ /** Don't scroll if there's no content to scroll. **/
+ const nonvisible_height = sp_get_nonvisible_height(pane);
+ if (nonvisible_height < 0) return;
+
+ /** Save the current scroll amount for later. **/
+ const scroll_height_old = sp_get_scroll_dist(pane.area);
+
+ /** Clamp the scroll height within the bounds of the scroll bar. **/
+ const scroll_height_new = Math.clamp(0, scroll_height, nonvisible_height);
+
+ /** Update the content. **/
+ setRelativeY(pane.area, -scroll_height_new);
+ pane.UpdateThumb();
+
+ /** Construct the param for the centrallix 'Scroll' event. **/
+ const percent_old = (scroll_height_old / nonvisible_height) * 100;
+ const percent_new = (scroll_height_new / nonvisible_height) * 100;
+ const param = { Percent: percent_new, Change: percent_new - percent_old };
+
+ /** Schedule the scroll event to allow the page to repaint first. **/
+ setTimeout(() => cn_activate(pane, 'Scroll', param), 0);
+ }
- /*var layers = pg_layers(ti.pane);
- for(var i=0;i getPageY(ti.pane)+18+v) new_y=getPageY(ti.pane)+18+v;
- if (new_y < getPageY(ti.pane)+18) new_y=getPageY(ti.pane)+18;
- setPageY(ti.thum,new_y);
- var h=getClipHeight(ti.area)+getClipTop(ti.area);
- var d=h-getClipHeight(ti.pane);
- if (d<0) d=0;
- var yincr = (((getRelativeY(ti.thum)-18)/v)*-d) - getRelativeY(ti.area);
- moveBy(ti.area, 0, yincr);
- return EVENT_HALT | EVENT_PREVENT_DEFAULT_ACTION;
- }
+ /** Trigger Centrallix events. **/
+ const pane = sp_get_pane(e);
+ if (pane) cn_activate(pane, 'MouseMove');
+
+ /** Monitor events on other DOM nodes to detect MouseOut. **/
+ if (!pane && sp_target_mainlayer)
+ {
+ /** Mouse out has occurred, ending the mouse over. **/
+ cn_activate(sp_target_mainlayer, 'MouseOut');
+ sp_target_mainlayer = undefined;
+ }
+
+ /** Check if a drag is in progress (aka. the drag target exists and is a scroll thumb). **/
+ const target_img = sp_drag_img;
+ if (target_img && target_img.kind === 'sp' && target_img.name === 't')
+ {
+ const { pane } = target_img;
+
+ /** Get drag_dist: the distance that the scroll bar should move. **/
+ const page_y = getPageY(target_img.thumb);
+ const drag_dist = e.pageY - page_y;
+
+ /** Scale drag_dist to the distance that the content should move. **/
+ const scrollbar_height = sp_get_scrollbar_height(pane);
+ const nonvisible_height = sp_get_nonvisible_height(pane);
+ const content_drag_dist = (drag_dist / scrollbar_height) * nonvisible_height;
+
+ /** Scroll the content by the required amount to reach the new mouse location. **/
+ sp_scroll(target_img.pane, content_drag_dist);
+
+ /** Event handled. **/
+ return EVENT_HALT | EVENT_PREVENT_DEFAULT_ACTION;
+ }
+
+ /** Continue the event. **/
return EVENT_CONTINUE | EVENT_ALLOW_DEFAULT_ACTION;
}
+/*** Handles mouse up events anywhere on the page.
+ ***
+ *** @param e The event that has occurred.
+ *** @returns An event result (see ht_render.js).
+ ***/
function sp_mouseup(e)
{
- if (sp_mv_timeout != null)
- {
- clearTimeout(sp_mv_timeout);
- sp_mv_timeout = null;
- sp_mv_incr = 0;
- }
- if (sp_target_img != null)
- {
- if (sp_target_img.name != 'b')
- pg_set(sp_target_img,'src',htutil_subst_last(sp_target_img.src,"b.gif"));
- sp_target_img = null;
- }
- if (e.kind == 'sp') cn_activate(e.mainlayer, 'MouseUp');
+ /** Trigger Centrallix events. **/
+ if (e.kind === 'sp')
+ {
+ const params = sp_get_event_params(e);
+ cn_activate(e.mainlayer, 'MouseUp', params);
+ if (sp_click_in_progress)
+ cn_activate(e.mainlayer, 'Click', params);
+ }
+
+ /** A click is no longer in progress. **/
+ sp_click_in_progress = false;
+
+ /** Check for an active drag. **/
+ if (sp_drag_img)
+ {
+ /** End the drag. **/
+ sp_drag_img = undefined;
+ }
+
+ /** Check for a pressed button. **/
+ if (sp_button_img)
+ {
+ /** Reset the pressed button. **/
+ pg_set(sp_button_img, 'src', htutil_subst_last(sp_button_img.src, "b.gif"));
+ sp_button_img = undefined;
+ }
+
+ /** Continue the event. **/
return EVENT_CONTINUE | EVENT_ALLOW_DEFAULT_ACTION;
}
+/*** Handles mouse over events anywhere on the page.
+ ***
+ *** @param e The event that has occurred.
+ *** @returns An event result (see ht_render.js).
+ ***/
function sp_mouseover(e)
{
- if (e.kind == 'sp')
- {
- if (!sp_cur_mainlayer)
- {
- cn_activate(e.mainlayer, 'MouseOver');
- sp_cur_mainlayer = e.mainlayer;
- }
- }
+ /** Check for mouse over on an sp element. **/
+ if (sp_target_mainlayer && e.kind === 'sp')
+ {
+ /** Begin a mouse over. **/
+ cn_activate(e.mainlayer, 'MouseOver');
+ sp_target_mainlayer = e.mainlayer;
+ }
+
+ /** Continue the event. **/
return EVENT_CONTINUE | EVENT_ALLOW_DEFAULT_ACTION;
}
-// Load indication
+/** Indicate loading is complete. **/
if (window.pg_scripts) pg_scripts['htdrv_scrollpane.js'] = true;
diff --git a/centrallix-os/sys/js/htdrv_tab.js b/centrallix-os/sys/js/htdrv_tab.js
index ebab8b6b6..f043853bc 100644
--- a/centrallix-os/sys/js/htdrv_tab.js
+++ b/centrallix-os/sys/js/htdrv_tab.js
@@ -1,4 +1,4 @@
-// Copyright (C) 1998-2004 LightSys Technology Services, Inc.
+// Copyright (C) 1998-2026 LightSys Technology Services, Inc.
//
// You may use these files and this library under the terms of the
// GNU Lesser General Public License, Version 2.1, contained in the
@@ -9,7 +9,6 @@
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-
// Sets the value of the current tab (but not the appearance), without
// triggering on-change events.
function tc_set_tab_unwatched()
@@ -27,189 +26,219 @@ function tc_set_tab_unwatched()
// Makes the given tab current.
function tc_makecurrent()
{
- var t;
- if (this.tabctl.tloc != 4 && htr_getzindex(this.tab) > htr_getzindex(this.tabctl)) return 0;
- for(var i=0;i htr_getzindex(t)) return 0;
+ for(let i = 0; i < tabs.length; i++)
{
- t = this.tabctl.tabs[i];
- if (t != this && (t.tabctl.tloc == 4 || htr_getzindex(t.tab) > htr_getzindex(this.tab)))
+ const cur = tabs[i];
+ if (cur !== this && (cur.tabctl.tloc === 'None' || htr_getzindex(cur.tab) > htr_getzindex(tab)))
{
- htr_setzindex(t, htr_getzindex(this.tabctl) - 1);
- htr_setvisibility(t, 'hidden');
- if (t.tabctl.tloc != 4)
+ htr_setzindex(cur, htr_getzindex(t) - 1);
+ htr_setvisibility(cur, 'hidden');
+ if (cur.tabctl.tloc !== 'None')
{
- htr_setzindex(t.tab, htr_getzindex(this.tabctl) - 1);
- t.tab.marker_image.src = '/sys/images/tab_lft3.gif';
- moveBy(t.tab, this.tabctl.xo, this.tabctl.yo);
- //setClipItem(t.tab, t.tabctl.cl, getClipItem(t.tab, t.tabctl.cl) + t.tabctl.ci);
- if (this.tabctl.inactive_bgColor) htr_setbgcolor(t.tab, this.tabctl.inactive_bgColor);
- if (this.tabctl.inactive_bgnd) htr_setbgimage(t.tab, this.tabctl.inactive_bgnd);
+ htr_setzindex(cur.tab, htr_getzindex(t) - 1);
+ cur.tab.marker_image.src = '/sys/images/tab_lft3.gif';
+ cur.tab.classList.remove('tab_selected');
+ if (t.inactive_bgColor) htr_setbgcolor(cur.tab, t.inactive_bgColor);
+ if (t.inactive_bgnd) htr_setbgimage(cur.tab, t.inactive_bgnd);
}
}
}
- htr_setzindex(this, htr_getzindex(this.tabctl) + 1);
+ htr_setzindex(this, htr_getzindex(t) + 1);
htr_setvisibility(this,'inherit');
- if (this.tabctl.tloc != 4)
+ if (tloc !== 'None')
{
- if (this.tabctl.main_bgColor) htr_setbgcolor(this.tab, this.tabctl.main_bgColor);
- if (this.tabctl.main_bgnd) htr_setbgimage(this.tab, this.tabctl.main_bgnd);
- htr_setzindex(this.tab, htr_getzindex(this.tabctl) + 1);
- this.tab.marker_image.src = '/sys/images/tab_lft2.gif';
- moveBy(this.tab, -this.tabctl.xo, -this.tabctl.yo);
- //setClipItem(this.tab, this.tabctl.cl, getClipItem(this.tab, this.tabctl.cl) - this.tabctl.ci);
+ if (t.main_bgColor) htr_setbgcolor(tab, t.main_bgColor);
+ if (t.main_bgnd) htr_setbgimage(tab, t.main_bgnd);
+ htr_setzindex(tab, htr_getzindex(t) + 1);
+ tab.marker_image.src = '/sys/images/tab_lft2.gif';
+ tab.classList.add('tab_selected');
}
this.setTabUnwatched();
- this.tabctl.ifcProbe(ifEvent).Activate("TabChanged", {Selected:this.tabctl.selected, SelectedIndex:this.tabctl.selected_index});
+
+ // Activate the Centrallix TabChanged event.
+ t.ifcProbe(ifEvent).Activate("TabChanged", {
+ Selected:t.selected,
+ SelectedIndex:t.selected_index,
+ });
}
-function tc_makenotcurrent(t)
+function tc_makenotcurrent(page)
{
- htr_setzindex(t,htr_getzindex(t.tabctl) - 1);
- htr_setvisibility(t,'hidden');
- if (t.tabctl.tloc != 4)
+ const { tabctl, tab } = page;
+
+ htr_setzindex(page, htr_getzindex(tabctl) - 1);
+ htr_setvisibility(page, 'hidden');
+
+ if (tabctl.tloc !== 'None')
{
- htr_setzindex(t.tab,htr_getzindex(t.tabctl) - 1);
- t.tab.marker_image.src = '/sys/images/tab_lft3.gif';
- moveBy(t.tab, t.tabctl.xo, t.tabctl.yo);
- //setClipItem(t.tab, t.tabctl.cl, getClipItem(t.tab, t.tabctl.cl) + t.tabctl.ci);
- if (t.tabctl.inactive_bgColor) htr_setbgcolor(t.tab, t.tabctl.inactive_bgColor);
- if (t.tabctl.inactive_bgnd) htr_setbgimage(t.tab, t.tabctl.inactive_bgnd);
+ htr_setzindex(page.tab,htr_getzindex(page.tabctl) - 1);
+ tab.marker_image.src = '/sys/images/tab_lft3.gif';
+ tab.classList.remove('tab_selected');
+ if (tabctl.inactive_bgColor) htr_setbgcolor(tab, tabctl.inactive_bgColor);
+ if (tabctl.inactive_bgnd) htr_setbgimage(tab, tabctl.inactive_bgnd);
}
}
-
-// Adds a new tab to the tab control
-function tc_addtab(l_tab, l_page, l, nm, type,fieldname)
+
+/*** Adds a new tab to the tab control. This function deals with whether or
+ *** not that tab is selected as LITTLE AS POSSIBLE since that piece of state
+ *** should be handled elsewhere with functions like tc_makenotcurrent() or
+ *** tc_makecurrent().
+ ***
+ *** @param param The object containing parameters for the function.
+ *** @param param.l_tab The tab to be added.
+ *** @param param.l_page The page to which the tab shall be added.
+ *** @param param.name The name of the tab.
+ *** @param param.type The type of the tab.
+ *** @param param.fieldname The fieldname of the tab.
+ ***/
+function tc_add_tab(param)
{
- var newx;
- var newy;
- if (!l_tab) l_tab = new Object();
- l_page.tabname = nm;
+ const { tab, page, name, type, fieldname } = param;
+ const tabctl = this, { tloc, tab_h, tab_spacing, tabs } = tabctl;
+ const l_tab = tab ?? {}, l_page = page;
+
+ let x, y;
+ l_page.tabname = name;
l_page.type = type;
l_page.fieldname = fieldname;
- l_page.tabindex = this.tabs.length+1;
- htr_init_layer(l_page,l,'tc_pn');
+ l_page.tabindex = tabs.length + 1;
+ htr_init_layer(l_page, tabctl, 'tc_pn');
ifc_init_widget(l_page);
- if (l.tloc != 4)
+
+ // Calculate the location and flexibility to render the tab.
+ if (tloc === 'None')
+ {
+ x = 0;
+ y = 0;
+ }
+ else
{
- htr_init_layer(l_tab,l,'tc');
- if (l.tloc == 0 || l.tloc == 1) // top or bottom
+ htr_init_layer(l_tab, tabctl, 'tc');
+
+ /** Calculate x coordinate. **/
+ if (tloc === 'Top' || tloc === 'Bottom')
{
- if (this.tabs.length > 0)
+ if (tabs.length > 0)
+ {
+ const previous_tab = tabs[tabs.length - 1].tab;
+ x = getRelativeX(previous_tab) + $(previous_tab).outerWidth() + tab_spacing;
+ }
+ else if (tabctl.tab_fl_x)
{
- //alert(htr_getphyswidth(this.tabs[this.tabs.length-1]));
- newx = getPageX(this.tabs[this.tabs.length-1].tab) + $(this.tabs[this.tabs.length-1].tab).outerWidth() + 1;
- if (htr_getvisibility(this.tabs[this.tabs.length-1]) == 'inherit') newx += l.xo;
+ // Copy tabctl.style.left to avoid small but noticeable inconsistencies.
+ setRelativeX(l_tab, tabctl.style.left);
}
else
- newx = getPageX(this);
+ {
+ // Math for inflexible tabs do not suffer from the inconsistencies handled above.
+ x = getRelativeX(tabctl);
+ }
}
- else if (l.tloc == 2) // left
- newx = getPageX(this)- htr_getviswidth(l_tab) + 0;
- else if (l.tloc == 3) // right
- newx = getPageX(this) + htr_getviswidth(this) + 1;
+ else if (tloc === 'Left')
+ x = getRelativeX(tabctl) - htr_getviswidth(l_tab);
+ else // Right
+ x = getRelativeX(tabctl); // Included in xtoffset (see below)
- if (l.tloc == 2 || l.tloc == 3) // left or right
+ /** Calculate y coordinate. **/
+ if (tloc === 'Left' || tloc === 'Right')
{
- if (this.tabs.length > 0)
+ if (tabs.length > 0)
{
- newy = getPageY(this.tabs[this.tabs.length-1].tab) + 26;
- if (htr_getvisibility(this.tabs[this.tabs.length-1]) == 'inherit') newy += l.yo;
+ const previous_tab = tabs[tabs.length - 1].tab;
+ y = getRelativeY(previous_tab) + tab_h + tab_spacing;
}
+ else if (tabctl.tab_fl_y)
+ /** Copy tabctl.style.top to avoid small but noticeable inconsistencies. **/
+ setRelativeY(l_tab, tabctl.style.top);
else
- newy = getPageY(this);
+ /** Math for inflexible tabs do not suffer from inconsistencies. * */
+ y = getRelativeY(tabctl);
}
- else if (l.tloc == 1) // bottom
- newy = getPageY(this)+ htr_getvisheight(this) + 1;
- else // top
- newy = getPageY(this) - 24;
-
- // Clipping
- switch(l.tloc)
+ else if (tloc === 'Bottom')
+ y = getRelativeY(tabctl); // Included in ytoffset (see below)
+ else // Top
+ y = getRelativeY(tabctl) - tab_h;
+
+ /** Apply the same tab offsets used on the server. **/
+ x += tabctl.xtoffset;
+ y += tabctl.ytoffset;
+
+ // Space out tab away from previous tab to account for borders.
+ if (tabs.length > 0)
{
- case 0: // top
- $(l_tab).css('clip', 'rect(-10px, ' + ($(l_tab).outerWidth()+10) + 'px, 25px, -10px)');
- break;
- case 1: // bottom
- $(l_tab).css('clip', 'rect(0px, ' + ($(l_tab).outerWidth()+10) + 'px, 35px, -10px)');
- break;
- case 2: // left
- $(l_tab).css('clip', 'rect(-10px, ' + ($(l_tab).outerWidth()) + 'px, 35px, -10px)');
- break;
- case 3: // right
- $(l_tab).css('clip', 'rect(-10px, ' + ($(l_tab).outerWidth()+10) + 'px, 35px, 0px)');
- break;
+ switch (tloc)
+ {
+ case 'Top': case 'Bottom': x += 2; break;
+ case 'Left': case 'Right': y += 2; break;
+ }
}
}
- else
- {
- newx = 0;
- newy = 0;
- }
- if (htr_getvisibility(l_page) != 'inherit')
- {
- if (l.tloc != 4)
- {
- newx += l.xo;
- newy += l.yo;
- //setClipItem(l_tab, l.cl, getClipItem(l_tab, l.cl) + l.ci);
- if (l.inactive_bgColor) htr_setbgcolor(l_tab, l.inactive_bgColor);
- else if (l.main_bgColor) htr_setbgcolor(l_tab, l.main_bgColor);
- if (l.inactive_bgnd) htr_setbgimage(l_tab, l.inactive_bgnd);
- else if (l.main_bgnd) htr_setbgimage(l_tab, l.main_bgnd);
- }
- }
- else
+ // Handle visibility.
+ if (htr_getvisibility(l_page) === 'inherit')
{
- htr_unwatch(l,"selected","tc_selection_changed");
- htr_unwatch(l,"selected_index","tc_selection_changed");
- l.selected = l_page.tabname;
- l.selected_index = l_page.tabindex;
- l.current_tab = l_page;
- l.init_tab = l_page;
- pg_addsched_fn(window,"pg_reveal_event",new Array(l_page,l_page,'Reveal'), 0);
- htr_watch(l,"selected", "tc_selection_changed");
- htr_watch(l,"selected_index", "tc_selection_changed");
- if (l.tloc != 4)
+ htr_unwatch(tabctl, "selected", "tc_selection_changed");
+ htr_unwatch(tabctl, "selected_index", "tc_selection_changed");
+ tabctl.selected = l_page.tabname;
+ tabctl.selected_index = l_page.tabindex;
+ tabctl.current_tab = l_page;
+ tabctl.init_tab = l_page;
+ pg_addsched_fn(window, "pg_reveal_event", [l_page, l_page, 'Reveal'], 0);
+ htr_watch(tabctl, "selected", "tc_selection_changed");
+ htr_watch(tabctl, "selected_index", "tc_selection_changed");
+ if (tloc !== 'None')
{
- if (l.main_bgColor) htr_setbgcolor(l_tab, l.main_bgColor);
- if (l.main_bgnd) htr_setbgimage(l_tab, l.main_bgnd);
+ if (tabctl.main_bgColor) htr_setbgcolor(l_tab, tabctl.main_bgColor);
+ if (tabctl.main_bgnd) htr_setbgimage(l_tab, tabctl.main_bgnd);
}
}
- if (l.tloc != 4)
+
+ // Handle images.
+ if (tloc !== 'None')
{
- var images = pg_images(l_tab);
- for(var i=0;i this.tabs.length) return o;
+ if (tabindex < 1 || tabindex > tabs.length) return o;
// okay to change tab.
- //this.tabs[tabindex-1].makeCurrent();
+ //tabs[tabindex-1].makeCurrent();
if (this.selchange_schedid)
pg_delsched(this.selchange_schedid);
- this.selchange_schedid = pg_addsched_fn(this,"ChangeSelection1", new Array(this.tabs[tabindex-1]), 0);
+ this.selchange_schedid = pg_addsched_fn(this, "ChangeSelection1", new Array(tabs[tabindex - 1]), 0);
return n;
}
-function tc_action_set_tab(aparam)
+function tc_action_set_tab({ Tab, TabIndex })
{
- if (aparam.Tab) this.selected = aparam.Tab;
- else if (aparam.TabIndex) this.selected_index = parseInt(aparam.TabIndex);
+ if (Tab) this.selected = Tab;
+ else if (TabIndex) this.selected_index = parseInt(TabIndex);
}
function tc_showcontainer()
@@ -263,13 +294,13 @@ function tc_showcontainer()
function tc_clear_tabs(tabs)
{
- for(var i=0;i   | "+vals[j]+" |  | |