diff --git a/AppSrc/BatteryStatusDemo.wo b/AppSrc/BatteryStatusDemo.wo
new file mode 100644
index 0000000..82da3c2
--- /dev/null
+++ b/AppSrc/BatteryStatusDemo.wo
@@ -0,0 +1,135 @@
+Use cWebView.pkg
+Use cWebPanel.pkg
+Use cWebLabel.pkg
+Use cWebHtmlBox.pkg
+Use cLogger.pkg
+
+Use cBatteryStatusAPI.pkg
+Use cWebCheckBox.pkg
+
+Object oBatteryStatusDemo is a cWebView
+ Set peWebViewStyle to wvsDrillDown
+ Set peViewType to vtUndefined
+ Set pbShowCaption to False
+
+ Set psCaption to "Battery Status Demo"
+
+ Set piMaxWidth to 1024
+ Set piColumnCount to 6
+ Set pbServerOnShow to True
+
+ Object oBatteryStatusAPI is a cBatteryStatusAPI
+ Procedure OnChargingChange Boolean bCharging
+ If (bCharging) Begin
+ Send Log of oLogger "Device is charging"
+ End
+ Else Begin
+ Send Log of oLogger "Device is not charging"
+ End
+ End_Procedure
+
+ Procedure OnLevelChange Number nLevel
+ Send Log of oLogger (SFormat("Battery level is %1%", nLevel * 100))
+ End_Procedure
+
+ Procedure OnChargingTimeChange Integer iRemainingSeconds
+ If (iRemainingSeconds > -1) Begin
+ Send Log of oLogger (SFormat("Time to fully charged is %1 seconds", iRemainingSeconds))
+ End
+ Else Begin
+ Send Log of oLogger "Not currently charging"
+ End
+ End_Procedure
+
+ Procedure OnDischargingTimeChange Integer iRemainingSeconds
+ If (iRemainingSeconds > -1) Begin
+ Send Log of oLogger (SFormat("Time to fully discharged is %1 seconds", iRemainingSeconds))
+ End
+ Else Begin
+ Send Log of oLogger "Not currently discharging"
+ End
+ End_Procedure
+ End_Object
+
+ Object oWebMainPanel is a cWebPanel
+ Set piColumnCount to 12
+ WebSetResponsive piColumnCount rmMobile to 6
+
+ Object oWebLabel is a cWebLabel
+ Set piColumnSpan to 0
+ Set psCaption to "Supported?"
+ End_Object
+
+ Object oWebHtmlBox is a cWebHtmlBox
+ Set piColumnSpan to 0
+ Set psHtml to '
'
+ End_Object
+
+ Object oWebLabel2 is a cWebLabel
+ Set psCaption to "The Battery Status API lets you receive events about changes in the battery status of the device. Note that the 'charging time' and 'discharging time' events do not seem to provide useful information."
+ Set piColumnSpan to 0
+ End_Object
+
+ Object oWebCheckbox1 is a cWebCheckbox
+ Set piColumnSpan to 3
+ Set psCaption to "Charging status"
+ Set pbServerOnChange to True
+
+ Procedure OnChange String sNewValue String sOldValue
+ WebSet pbServerOnChargingChange of oBatteryStatusAPI to (sNewValue = "1")
+ End_Procedure
+ End_Object
+
+ Object oWebCheckbox2 is a cWebCheckbox
+ Set piColumnSpan to 3
+ Set psCaption to "Level status"
+ Set pbServerOnChange to True
+ Set piColumnIndex to 3
+
+ Procedure OnChange String sNewValue String sOldValue
+ WebSet pbServerOnLevelChange of oBatteryStatusAPI to (sNewValue = "1")
+ End_Procedure
+ End_Object
+
+ Object oWebCheckbox3 is a cWebCheckbox
+ Set piColumnSpan to 3
+ Set psCaption to "Charging time status"
+ Set pbServerOnChange to True
+ Set piColumnIndex to 6
+
+ Procedure OnChange String sNewValue String sOldValue
+ WebSet pbServerOnChargingTimeChange of oBatteryStatusAPI to (sNewValue = "1")
+ End_Procedure
+ End_Object
+
+ Object oWebCheckbox4 is a cWebCheckbox
+ Set piColumnSpan to 3
+ Set psCaption to "Discharging time status"
+ Set pbServerOnChange to True
+ Set piColumnIndex to 9
+
+ Procedure OnChange String sNewValue String sOldValue
+ WebSet pbServerOnDischargingTimeChange of oBatteryStatusAPI to (sNewValue = "1")
+ End_Procedure
+ End_Object
+
+ Object oLogger is a cLogger
+ End_Object
+ End_Object
+
+ Procedure OnShow
+ Boolean bIsSupported
+
+ Forward Send OnShow
+
+ WebGet pbIsSupported of oBatteryStatusAPI to bIsSupported
+ If (bIsSupported) Begin
+ WebSet psCaption of oWebLabel to "BatteryStatus API is supported"
+ WebSet psTextColor of oWebLabel to "green"
+ End
+ Else Begin
+ WebSet psCaption of oWebLabel to "BatteryStatus API is NOT supported (try on Chrome, Edge or Opera)"
+ WebSet psTextColor of oWebLabel to "red"
+ End
+ End_Procedure
+End_Object
diff --git a/AppSrc/Dashboard.wo b/AppSrc/Dashboard.wo
index e83292a..c6459fb 100644
--- a/AppSrc/Dashboard.wo
+++ b/AppSrc/Dashboard.wo
@@ -23,6 +23,24 @@ Object oDashboard is a cWebView
WebSetResponsive piColumnCount rmTabletPortrait to 2
WebSetResponsive piColumnCount rmMobile to 1
+ Object oTileBatteryStatus is a cWebHtmlBox
+ Set pbServerOnClick to True
+ Set psCSSClass to "Tile"
+ Set psHtml to """
+
+
Battery Status API
+
info about battery status
+
https
+
+ """
+
+ WebRegisterPath ntNavigateForward oBatteryStatusDemo
+
+ Procedure OnClick
+ Send NavigatePath
+ End_Procedure
+ End_Object
+
Object oTileBroadcastChannel is a cWebHtmlBox
Set pbServerOnClick to True
Set psCSSClass to "Tile"
diff --git a/AppSrc/WebApp.src b/AppSrc/WebApp.src
index 8dd23e6..32ab661 100644
--- a/AppSrc/WebApp.src
+++ b/AppSrc/WebApp.src
@@ -54,6 +54,15 @@ Object oWebApp is a cWebApp
End_Procedure
End_Object
+ Object oWebMenuItemBatteryStatus is a cWebMenuItem
+ Set psCaption to "Battery Status Demo"
+ WebRegisterPath ntNavigateBegin oBatteryStatusDemo
+
+ Procedure OnClick
+ Send NavigatePath
+ End_Procedure
+ End_Object
+
Object oWebMenuItemBroadcastChannel is a cWebMenuItem
Set psCaption to "Broadcast Channel Demo"
WebRegisterPath ntNavigateBegin oBroadcastChannelDemo
@@ -285,6 +294,7 @@ Object oWebApp is a cWebApp
Use ScreenOrientationDemo.wo
Use WebStorageDemo.wo
Use MediaStreamRecordingDemo.wo
+ Use BatteryStatusDemo.wo
Set phoDefaultView to oDashboard
End_Object
diff --git a/AppSrc/cBatteryStatusAPI.pkg b/AppSrc/cBatteryStatusAPI.pkg
new file mode 100644
index 0000000..e27b75e
--- /dev/null
+++ b/AppSrc/cBatteryStatusAPI.pkg
@@ -0,0 +1,60 @@
+Use cWebObject.pkg
+
+Class cBatteryStatusAPI is a cWebObject
+
+ Procedure Construct_Object
+ Forward Send Construct_Object
+
+ { WebProperty=Client DesignTime=False }
+ Property Boolean pbIsSupported False
+
+ { WebProperty=Client }
+ Property Boolean pbServerOnChargingChange False
+ { WebProperty=Client }
+ Property String psClientOnChargingChange ""
+ { WebProperty=Client }
+ Property Boolean pbServerOnLevelChange False
+ { WebProperty=Client }
+ Property String psClientOnLevelChange ""
+ { WebProperty=Client }
+ Property Boolean pbServerOnChargingTimeChange False
+ { WebProperty=Client }
+ Property String psClientOnChargingTimeChange ""
+ { WebProperty=Client }
+ Property Boolean pbServerOnDischargingTimeChange False
+ { WebProperty=Client }
+ Property String psClientOnDischargingTimeChange ""
+
+ Set psJSClass to "WebAPIs.BatteryStatus"
+ End_Procedure
+
+ Procedure End_Construct_Object
+ Forward Send End_Construct_Object
+
+ WebPublishProcedure OnChargingChange
+ WebPublishProcedure OnLevelChange
+ WebPublishProcedure OnChargingTimeChange
+ WebPublishProcedure OnDischargingTimeChange
+ End_Procedure
+
+ { MethodType=Event }
+ Procedure OnChargingChange Boolean bCharging
+ // Reflects whether device is currently charging / connected to external power supply
+ End_Procedure
+
+ { MethodType=Event }
+ Procedure OnLevelChange Number nLevel
+ // Reflects the current battery charge level from 0.0 to 1.0
+ End_Procedure
+
+ { MethodType=Event }
+ Procedure OnChargingTimeChange Integer iRemainingSeconds
+ // Reflects time left to fully charged in seconds, or -1 if not charging
+ End_Procedure
+
+ { MethodType=Event }
+ Procedure OnDischargingTimeChange Integer iRemainingSeconds
+ // Reflects time left to fully discharged in seconds, or -1 if not discharging
+ End_Procedure
+
+End_Class
\ No newline at end of file
diff --git a/README.md b/README.md
index 4b97383..3064bc3 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,7 @@ DataFlex Custom Components for Web APIs.
Contains DataFlex implementations of:
+* [Battery Status API](https://developer.mozilla.org/en-US/docs/Web/API/Battery_Status_API)
* [Broadcast Channel API](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API)
* [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API)
* [Contact Picker API](https://developer.mozilla.org/en-US/docs/Web/API/Contact_Picker_API)
@@ -52,4 +53,4 @@ If you're not sure, or you explicitly support older browsers, including core-js
If you *do* use core-js, please [support that project](https://github.com/zloirock/core-js/blob/master/docs/2023-02-14-so-whats-next.md)!
-Including core-js will **not** implement API's that are not natively supported in a given browser. Always check the API pages linked above for browser support, and always check the `pbIsSupported` web property of each component at runtime before using it.
\ No newline at end of file
+Including core-js will **not** implement API's that are not natively supported in a given browser. Always check the API pages linked above for browser support, and always check the `pbIsSupported` web property of each component at runtime before using it.
diff --git a/src/battery-status.js b/src/battery-status.js
new file mode 100644
index 0000000..28cc1b9
--- /dev/null
+++ b/src/battery-status.js
@@ -0,0 +1,80 @@
+export default class BatteryStatus extends df.WebObject {
+ #battery;
+
+ constructor(sName, oParent) {
+ super(sName, oParent);
+ this.prop(df.tBool, 'pbIsSupported', false);
+ this.event('OnChargingChange');
+ this.event('OnLevelChange');
+ this.event('OnChargingTimeChange');
+ this.event('OnDischargingTimeChange');
+ }
+
+ async create(tDef) {
+ super.create(tDef);
+ this.set('pbIsSupported', 'getBattery' in navigator);
+ if (this.pbIsSupported) {
+ this.#battery = await navigator.getBattery();
+
+ this.#battery.addEventListener('chargingchange', () => {
+ this.#updateChargeInfo();
+ });
+ this.#updateChargeInfo();
+
+ this.#battery.addEventListener('levelchange', () => {
+ this.#updateLevelInfo();
+ });
+ this.#updateLevelInfo();
+
+ this.#battery.addEventListener('chargingtimechange', () => {
+ this.#updateChargingInfo();
+ });
+ this.#updateChargingInfo();
+
+ this.#battery.addEventListener('dischargingtimechange', () => {
+ this.#updateDischargingInfo();
+ });
+ this.#updateDischargingInfo();
+ }
+ }
+
+ #updateChargeInfo() {
+ this.fire('OnChargingChange', [df.fromBool(this.#battery.charging)]);
+ }
+
+ #updateLevelInfo() {
+ this.fire('OnLevelChange', [this.#battery.level]);
+ }
+
+ #updateChargingInfo() {
+ this.fire('OnChargingTimeChange', [this.#battery.chargingTime === Infinity ? -1 : this.#battery.chargingTime]);
+ }
+
+ #updateDischargingInfo() {
+ this.fire('OnDischargingTimeChange', [this.#battery.dischargingTime === Infinity ? -1 : this.#battery.dischargingTime]);
+ }
+
+ set_pbServerOnChargingChange(val) {
+ if (val) {
+ setTimeout(() => this.#updateChargeInfo());
+ }
+ }
+
+ set_pbServerOnLevelChange(val) {
+ if (val) {
+ setTimeout(() => this.#updateLevelInfo());
+ }
+ }
+
+ set_pbServerOnChargingTimeChange(val) {
+ if (val) {
+ setTimeout(() => this.#updateChargingInfo());
+ }
+ }
+
+ set_pbServerOnDischargingTimeChange(val) {
+ if (val) {
+ setTimeout(() => this.#updateDischargingInfo());
+ }
+ }
+}
diff --git a/src/index.js b/src/index.js
index b42713f..57acccb 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,3 +1,4 @@
+import BatteryStatus from "./battery-status";
import BroadcastChannel from './broadcast-channel';
import Clipboard from './clipboard';
import ContactPicker from './contact-picker';
@@ -29,6 +30,7 @@ global.WebAPIs = {
AbsoluteOrientationSensor,
AccelerometerSensor,
AmbientLightSensor,
+ BatteryStatus,
BroadcastChannel,
Clipboard,
ContactPicker,