Browser JavaScript Function Reference

Browser JavaScript Function Reference

Introduction

Below is a comprehensive list of methods grouped by the resource they interact with. These methods are available to the page under the fb_client object that is injected into the browser window. The PluginBrowserBridge provides the main JavaScript interface for Fishbowl applications to interact with the underlying Java system. This bridge enables web-based reports and applications to access database queries, API calls, file operations, reporting, printing, and window management directly from JavaScript.

All methods marked with @JsAccessible can be called from JavaScript running in the browser component. Unfortunately, we are unable to interact with these methods using native objects. So passing complex data is done by serializing objects into JSON strings, and vice-versa.

Methods

Application Logging

void logInformation(String message)

Logs an informational message to the application log and console.

Parameters:

  • message (String): The message to log

Example

fb_client.logInformation("Processing started for order 12345");

void logError(String message)

Logs an error message to the application log and console.

Parameters:

  • message (String): The error message to log

Example

fb_client.logError("Failed to process order: Invalid customer ID");

String logMessages()

Returns all logged messages for the current page session.

Returns: String containing all logged messages

Example

const allLogs = fb_client.logMessages(); console.log(allLogs);

String serverLogMessages()

Retrieves server-side log messages.

Returns: String containing server log messages

Example

const serverLogs = fb_client.serverLogMessages();

Database

String runQuery(String sql)

Executes a SQL query without parameters and returns an array of records as JSON objects. If there is an error, it returns an object. Note: All result properties will be returned in lowercase.

Parameters:

  • sql (String): SQL query to execute

Returns: JSON string containing query results or error information

Examples

Return a basic query with a single row.

var results = fb_client.runQuery("select * from company");

Return a basic query with multiple rows.

var results = fb_client.runQuery("select * from so limit 10");

What happens with a syntax error.

var results = fb_client.runQuery("select *, from so limit 10");

String runQueryParameters(String sql, String json_parameters)

Executes a SQL query with parameters to prevent SQL injection. Accepts a single object with parameters serialized as JSON. To define a parameter use :name syntax, and use all lower case parameter names in SQL and in the JSON object.

Parameters:

  • sql (String): SQL query with parameter placeholders (use :parameter_name syntax)

  • json_parameters (String): JSON object containing parameter values

Returns: JSON string containing query results or error information

Examples

Query sales orders by a specific customer id.

var params = JSON.stringify({customer_id:5}); var results = fb_client.runQueryParameters("select * from so where customerid = :customer_id", params );

Advanced example with multiple parameters:

const sql = "SELECT * FROM so WHERE customerid = :customer_id AND dateissued >= :start_date"; const params = JSON.stringify({ customer_id: "123", start_date: "2023-01-01" }); const results = fb_client.runQueryParameters(sql, params); const data = JSON.parse(results);

Error Response Example:

{ "is_error": true, "error_msg": "SQL syntax error: ..." }

void runQueryAsync(String sql, String callbackFunctionName)

Executes a SQL query asynchronously without parameters. The method returns immediately and executes the specified JavaScript callback function when the query completes.

Parameters:

  • sql (String): SQL query to execute

  • callbackFunctionName (String): Name of the JavaScript function to call when the query completes

Returns: void (method returns immediately)

Callback Function: The callback function receives one parameter: the JSON result object (same format as synchronous runQuery)

Example

// Define callback function function handleAsyncResult(result) { if (result.is_error) { console.error("Query failed:", result.error_msg); fb_client.dialogStatus("Query failed"); } else { console.log("Query succeeded, rows:", result.length); displayResults(result); fb_client.dialogStatus("Data loaded"); } } // Execute async query fb_client.dialogStatus("Loading data..."); fb_client.runQueryAsync("SELECT * FROM part WHERE activeflag = 1", "handleAsyncResult"); // Code continues immediately while query runs in background console.log("Query started, continuing with other work...");

void runQueryParametersAsync(String sql, String json_parameters, String callbackFunctionName)

Executes a SQL query asynchronously with parameters. The method returns immediately and executes the specified JavaScript callback function when the query completes.

Parameters:

  • sql (String): SQL query with parameter placeholders (use :parameter_name syntax)

  • json_parameters (String): JSON object containing parameter values

  • callbackFunctionName (String): Name of the JavaScript function to call when the query completes

Returns: void (method returns immediately)

Callback Function: The callback function receives one parameter: the JSON result object (same format as synchronous runQueryParameters)

Example

// Define callback function function processCustomerOrders(result) { if (result.is_error) { console.error("Customer order query failed:", result.error_msg); document.getElementById('orderStatus').textContent = 'Error loading orders'; return; } document.getElementById('orderStatus').textContent = `Found ${result.length} orders`; // Process results result.forEach(order => { addOrderToTable(order); }); fb_client.pbUpdate(100); fb_client.logInformation(`Loaded ${result.length} orders for customer`); } // Execute async parameterized query const customerId = document.getElementById('customerId').value; const startDate = document.getElementById('startDate').value; const sql = ` SELECT so.num, so.totalamount, so.dateissued, c.name as customer_name FROM so JOIN customer c ON so.customerid = c.id WHERE so.customerid = :customer_id AND so.dateissued >= :start_date ORDER BY so.dateissued DESC `; const params = JSON.stringify({ customer_id: customerId, start_date: startDate }); fb_client.pbUpdate(25); fb_client.dialogStatus("Loading customer orders..."); fb_client.runQueryParametersAsync(sql, params, "processCustomerOrders"); // Continue with other UI updates updateCustomerInfo(customerId);

API - REST

String restApiCall(String method, String path, String body)

Makes HTTP REST API calls to the Fishbowl API server using the current authentication token. This is a BETA feature, and is not guaranteed to work correctly or break in the future. You can find REST swagger docs using the Fishbowl Server web port, reference: XXXX.

Parameters:

  • method (String): HTTP method (GET, POST, PUT, DELETE)

  • path (String): API endpoint path

  • body (String): Request body (JSON string, null for GET requests)

Returns: JSON string with HTTP response details

Example

Get company information

var result = fb_client.restApiCall("GET","/company"); console.log(result);

Advanced Examples:

// GET request const getResponse = fb_client.restApiCall("GET", "/api/part/1234", null); const getData = JSON.parse(getResponse); // POST request const postData = JSON.stringify({ name: "New Part", description: "Part description" }); const postResponse = fb_client.restApiCall("POST", "/api/part", postData);

Response Format:

{ "http_code": "200", "response": "API response data", "is_error": false }

void restApiCallAsync(String method, String path, String body, String callbackFunctionName)

Makes HTTP REST API calls asynchronously to the Fishbowl API server. The method returns immediately and executes the specified JavaScript callback function when the API call completes.

Parameters:

  • method (String): HTTP method (GET, POST, PUT, DELETE)

  • path (String): API endpoint path

  • body (String): Request body (JSON string, null for GET requests)

  • callbackFunctionName (String): Name of the JavaScript function to call when the API call completes

Returns: void (method returns immediately)

Callback Function: The callback function receives one parameter: the JSON response object (same format as synchronous restApiCall)

Example

// Define callback function function handleApiResponse(response) { const data = JSON.parse(response); if (data.is_error) { console.error("API call failed:", data.error_msg); fb_client.dialogStatus("API error"); return; } console.log("HTTP Status:", data.http_code); if (data.http_code === "200") { const apiData = JSON.parse(data.response); console.log("API Response:", apiData); processApiData(apiData); fb_client.dialogStatus("API call successful"); } else { console.warn("Unexpected HTTP status:", data.http_code); } } // Execute async GET request fb_client.dialogStatus("Loading part data..."); fb_client.restApiCallAsync("GET", "/api/part/1234", null, "handleApiResponse");

API - Legacy

String runImportCSV(String import_type, String csv_data)

Creates and executes an ImportRequest, given a string of an import_type (Reference: Legacy Fishbowl CSV Import Reference ) and a CSV string. The method returns a JSON object as a string.

Parameters:

  • import_type (String): Type of import (e.g., "Part", "Customer", "SalesOrder")

  • csv_data (String): CSV formatted data with headers

Returns: JSON string containing import results

Examples

Import a Custom Field Data Import

var csv = ""; var import_type = "ImportCustomFieldData"; var result = fb_client.runImportCSV(import_type, csv); console.log(result); > ""

Advanced Example:

const csvData = `"PartNumber","Description","UOM" "TEST-001","Test Part 1","ea" "TEST-002","Test Part 2","ea"`; const result = fb_client.runImportCSV("Part", csvData); const importResult = JSON.parse(result);

String runImportCSV_JSON(String import_type, String json_list_strings)

Imports data from a JSON array of CSV row strings.

Parameters:

  • import_type (String): Type of import

  • json_list_strings (String): JSON array of CSV row strings

Example

const csvRows = JSON.stringify([ '"TEST-001","Test Part 1","ea"', '"TEST-002","Test Part 2","ea"' ]); const result = fb_client.runImportCSV_JSON("Part", csvRows);

String runApiJSON(String request_type, String json_payload)

Executes a legacy API call given a request_type, (Reference: Legacy Fishbowl XML/JSON API Call Types ), and a JSON Payload. The internal Fishbowl Legacy API is XML, and Fishbowl will convert our JSON to XML, and on a completed request will convert XML to JSON.

Take note that there are some bugs with the XML<>JSON conversion, namely if a property is intended to be a list but has a single record/object, it will serialize as an object, and not a list. Reference: TBD.

Parameters:

  • request_type (String): API call type (enum value from ApiCallType)

  • payload (String): JSON request payload

Returns: JSON string containing API response

Examples

var request = {}; var request_json = JSON.stringify(request); var result_json = fb_client.runApiJSON("XXX",request_json); var result = JSON.parse(result_json); console.log(result); > TBD

Advanced Example:

const request = JSON.stringify({ GetPartRq: { Number: "ABC-123" } }); const response = fb_client.runApiJSON("GET_PART", request); const data = JSON.parse(response);

void runApiJSONAsync(String request_type, String payload, String callbackFunctionName)

Executes legacy Fishbowl API requests asynchronously using XML/JSON conversion. The method returns immediately and executes the specified JavaScript callback function when the API call completes.

Parameters:

  • request_type (String): API call type (enum value from ApiCallType)

  • payload (String): JSON request payload

  • callbackFunctionName (String): Name of the JavaScript function to call when the API call completes

Returns: void (method returns immediately)

Example

// Define callback function function handleLegacyApiResponse(response) { const data = JSON.parse(response); if (data.is_error) { console.error("Legacy API call failed:", data.error_msg); fb_client.dialogStatus("API error"); return; } console.log("Legacy API Response:", data); processLegacyApiData(data); fb_client.dialogStatus("Legacy API call successful"); } // Execute async legacy API call const request = JSON.stringify({ GetPartRq: { Number: "ABC-123" } }); fb_client.dialogStatus("Loading part via legacy API..."); fb_client.runApiJSONAsync("GET_PART", request, "handleLegacyApiResponse");

void runImportCSVAsync(String import_type, String csv_data, String callbackFunctionName)

Imports CSV data asynchronously using the legacy API. The method returns immediately and executes the specified JavaScript callback function when the import completes.

Parameters:

  • import_type (String): Type of import (e.g., "Part", "Customer", "SalesOrder")

  • csv_data (String): CSV formatted data with headers

  • callbackFunctionName (String): Name of the JavaScript function to call when the import completes

Returns: void (method returns immediately)

Example

// Define callback function function handleImportResult(response) { const data = JSON.parse(response); if (data.is_error) { console.error("CSV import failed:", data.error_msg); fb_client.dialogStatus("Import failed"); return; } console.log("Import successful:", data); fb_client.dialogStatus("Import completed successfully"); fb_client.reloadObject(); // Refresh the current view } // Execute async CSV import const csvData = `"PartNumber","Description","UOM" "TEST-001","Test Part 1","ea" "TEST-002","Test Part 2","ea"`; fb_client.dialogStatus("Starting CSV import..."); fb_client.pbUpdate(0); fb_client.runImportCSVAsync("Part", csvData, "handleImportResult");

void runImportCSV_JSONAsync(String import_type, String json_list_strings, String callbackFunctionName)

Imports data asynchronously from a JSON array of CSV row strings. The method returns immediately and executes the specified JavaScript callback function when the import completes.

Parameters:

  • import_type (String): Type of import

  • json_list_strings (String): JSON array of CSV row strings

  • callbackFunctionName (String): Name of the JavaScript function to call when the import completes

Returns: void (method returns immediately)

Example

// Define callback function function handleJsonImportResult(response) { const data = JSON.parse(response); if (data.is_error) { console.error("JSON CSV import failed:", data.error_msg); fb_client.dialogStatus("Import failed"); return; } console.log("JSON import successful:", data); fb_client.dialogStatus("JSON import completed successfully"); } // Execute async JSON CSV import const csvRows = JSON.stringify([ '"TEST-001","Test Part 1","ea"', '"TEST-002","Test Part 2","ea"' ]); fb_client.dialogStatus("Starting JSON CSV import..."); fb_client.runImportCSV_JSONAsync("Part", csvRows, "handleJsonImportResult");

Window

boolean dialogClose()

Closes the current browser window. Warning, the page execution will stop once the browser is closed.

Returns: Boolean (always true)

Example

var closing = fb_client.dialogClose();

void showStatusBar(boolean show)

Hides/Shows the status bar of the browser window, which includes a status label, and a small progress bar.

Parameters:

  • show (Boolean): Whether to show the status bar

Examples

Show the status bar.

fb_client.showStatusBar(true);

Image TBD

Hide the status bar.

fb_client.showStatusBar(false);

Image TBD

void toggleFullscreen()

Toggles fullscreen mode for the dialog window.

Example

fb_client.toggleFullscreen();

void dialogStatus(String message)

Displays a short message in the status bar, approx. less than 100 characters.

Parameters:

  • message (String): Status message to display

Example

fb_client.dialogStatus("Hello");

Image TBD

void pbUpdate(int value)

Controls the Progress Bar component in the status bar. Use whole integers for 0-100, and -1 for indeterminate progress.

Parameters:

  • value (Integer): Progress value (0-100)

Examples

Set progress bar to 100%

fb_client.pbUpdate(100);

Image TBD

Set progress bar to 50%

fb_client.pbUpdate(50);

Image TBD

Set progress bar to indeterminate.

fb_client.pbUpdate(-1);

Image TBD

Advanced Progress Example:

for(let i = 0; i <= 100; i += 10) { fb_client.pbUpdate(i); // Perform work here }

Client

String getCompanyName()

Gets the current company name from the database.

Returns: String company name

Example

Get the company name

var company_name = fb_client.getCompanyName(); console.log(company_name);

int getUserId()

Gets the current user's ID.

Returns: Integer user ID

Example

var user_id = fb_client.getUserId(); console.log(user_id); > 1

String getUsername()

Gets the current user's username.

Returns: String username

Example

var user_name = fb_client.getUsername(); console.log(user_name); > "admin"

String getUserEmail()

Gets the current user's email address from the database.

Returns: String email address

Example

var user_email = fb_client.getUserEmail(); console.log(user_email); > "admin@example.com"

Array getUsersGroupIDs()

Gets the current user's group IDs.

Returns: Array of string group IDs

Example

const groupIds = fb_client.getUsersGroupIDs(); console.log("User groups:", groupIds);

String getPluginName()

Gets the current plugin name.

Returns: String plugin name

Example

const pluginName = fb_client.getPluginName(); console.log("Current plugin:", pluginName);

String getModuleName()

Gets the current module name from where it was launched.

Returns: String module name

Example

var module_name = fb_client.getModuleName(); console.log(module_name); > "Sales Order"

int getObjectId()

Gets the current object ID. If the page is launched from a Module, like Sales Order module, it will return the current Module's ID, example, the Sales Order ID that is currently displayed. Returns a -1 if the Page is not launched from a Module.

Returns: Integer object ID

Example

var sales_order_id = fb_client.getObjectId(); // 5

Comprehensive User Info Example:

const userInfo = { company: fb_client.getCompanyName(), username: fb_client.getUsername(), email: fb_client.getUserEmail(), userId: fb_client.getUserId(), groupIds: fb_client.getUsersGroupIDs(), plugin: fb_client.getPluginName(), module: fb_client.getModuleName(), objectId: fb_client.getObjectId() }; console.log("User Info:", userInfo);

boolean hasAccessRight(String name)

Checks if the current user has a specific access right.

Parameters:

  • name (String): Access right name

Returns: Boolean indicating access

Example

if (fb_client.hasAccessRight("ViewInventory")) { // Show inventory data } else { fb_client.logError("User lacks ViewInventory permission"); }

boolean savePluginDataByGroup(String group_name, String data_dictionary)

Saves data (JSON or Plain String) to the Fishbowl Plugin data tables (plugindata). The data dictionary is expected to be a JSON object (single level, no hierarchy). This data persists between sessions.

Parameters:

  • group_name (String): Group identifier

  • data_dictionary (String): JSON object containing key-value pairs

Returns: Boolean (always true)

Example

const data_to_store = ""; let my_dict = { plugin_property: data_to_store }; fb_client.savePluginDataByGroup('QuickOrderPage', JSON.stringify(my_dict));

Advanced Settings Example:

const settings = JSON.stringify({ theme: "dark", autoRefresh: "true", refreshInterval: "30" }); fb_client.savePluginDataByGroup("user_preferences", settings);

String getPluginData(String group_name, String key)

Retrieves a string, given a group_name, and key.

Parameters:

  • group_name (String): Group identifier

  • key (String): Data key

Returns: String value or null if not found

Example

const plugin_val = fb_client.getPluginData('QuickOrderPage','plugin_property');

With Default Values:

const theme = fb_client.getPluginData("user_preferences", "theme") || "light";

boolean deletePluginData(String group_name)

Deletes plugin data by the group_name.

Parameters:

  • group_name (String): Group identifier

Returns: Boolean (always true)

Example

fb_client.deletePluginData("user_preferences");

boolean reloadObject()

Reloads/refreshes the current modules object.

Returns: Boolean (always true)

Example

var refreshed = fb_client.reloadObject();

void hyperLink(String module, String param)

Launches a Fishbowl module by name, and if provided the param should open the record.

Parameters:

  • module (String): Module name (e.g., "Picking", "SalesOrder", "Part")

  • param (String): Parameter value (usually an ID)

Example

Launch the Customer Module, and open Customer ID 5;

fb_client.hyperLink("Customer","5"); Pick Example: fb_client.hyperLink("Picking",String(PickID));

More Examples:

// Navigate to a specific pick fb_client.hyperLink("Picking", "12345"); // Navigate to a sales order fb_client.hyperLink("SalesOrder", "SO-2023-001");

void runScheduledTask(String task_name)

Runs a scheduled task by name.

Parameters:

  • task_name (String): Name of the scheduled task

Example

fb_client.runScheduledTask("DailyInventorySync");

Reporting

void previewReport(String report_id, String report_parameters)

Opens a report preview window with the specified parameters.

Parameters:

  • report_id (String): Report ID from the Fishbowl database

  • report_parameters (String): JSON object containing report parameters

Example

const params = JSON.stringify({ StartDate: "2023-01-01", EndDate: "2023-12-31", CustomerID: "123" }); fb_client.previewReport("45", params);

String getReportPDF(String report_id, String report_parameters, boolean throw_exception)

Generates a PDF report and returns it as base64 encoded data.

Parameters:

  • report_id (String): Report ID

  • report_parameters (String): JSON object containing report parameters

  • throw_exception (Boolean): Whether to throw exceptions on error

Returns: JSON string containing base64 PDF data or error information

Report Parameters by Type:

// Different parameter types supported const params = JSON.stringify({ // String parameters CustomerName: "ABC Company", // Integer parameters CustomerID: 123, // Date parameters (yyyy-MM-dd format) StartDate: "2023-01-01", // Timestamp parameters (ISO format) StartDateTime: "2023-01-01T00:00:00", // Boolean parameters IncludeInactive: false, // Decimal parameters MinAmount: 100.50 });

Example

const params = JSON.stringify({ StartDate: "2023-01-01", EndDate: "2023-12-31" }); const pdfResult = fb_client.getReportPDF("45", params, false); const pdfData = JSON.parse(pdfResult); if (!pdfData.is_error) { // Use pdfData.pdf_bytes (base64 encoded PDF) const blob = new Blob([atob(pdfData.pdf_bytes)], {type: 'application/pdf'}); const url = URL.createObjectURL(blob); window.open(url); } else { fb_client.logError("Report generation failed: " + pdfData.message); }

String getMergedReportsPDF(String report_dictionary_json)

Generates a merged PDF from multiple reports with specified copies.

Parameters:

  • report_dictionary_json (String): JSON array of report definitions

Returns: Base64 encoded PDF string

Report Dictionary Format:

const reportDict = JSON.stringify([ { report_id: "45", copies: 1, params: { StartDate: "2023-01-01", EndDate: "2023-12-31" } }, { report_id: "46", copies: 2, params: { CustomerID: "123" } } ]); const mergedPdf = fb_client.getMergedReportsPDF(reportDict);

Printing

String localPrinters()

Gets a list of available local printers.

Returns: JSON string containing printer names

Example

const printersResult = fb_client.localPrinters(); const printers = JSON.parse(printersResult); console.log("Available printers:", printers.printers); // Display in a dropdown const select = document.getElementById('printerSelect'); printers.printers.forEach(printer => { const option = document.createElement('option'); option.value = printer; option.textContent = printer; select.appendChild(option); });

void printPDF(String printer_name, String pdf_base64_bytes, boolean show_print_dialog)

Prints a PDF document to a specified printer.

Parameters:

  • printer_name (String): Name of the printer (must match exactly)

  • pdf_base64_bytes (String): Base64 encoded PDF data

  • show_print_dialog (Boolean): Whether to show print dialog

Example

const pdfBase64 = "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8..."; // Base64 PDF data fb_client.printPDF("HP LaserJet Pro", pdfBase64, false);

void printReportPDF(String printer_name, int copies, String report_id, String report_parameters, boolean throw_exception)

Prints a report directly to a printer without generating intermediate files.

Parameters:

  • printer_name (String): Printer name

  • copies (Integer): Number of copies

  • report_id (String): Report ID

  • report_parameters (String): JSON report parameters

  • throw_exception (Boolean): Whether to throw exceptions

Example

const params = JSON.stringify({ OrderID: "12345" }); fb_client.printReportPDF("Label Printer", 2, "67", params, false);

void printMergedReportsPDF(String printer_name, int copies, String report_dictionary_json)

Prints a merged PDF of multiple reports.

Parameters:

  • printer_name (String): Printer name

  • copies (Integer): Number of copies

  • report_dictionary_json (String): JSON array of report definitions

void printMultipleReports_JasperReports(String report_dictionary_json, String printer_name)

Prints multiple reports using JasperReports engine.

Parameters:

  • report_dictionary_json (String): JSON array of report definitions

  • printer_name (String): Printer name

void printZPL(String printer_name, String zpl_document)

Prints a ZPL (Zebra Programming Language) document to a label printer.

Parameters:

  • printer_name (String): Printer name

  • zpl_document (String): ZPL formatted document

Example

const zplLabel = ` ^XA ^FO20,20^A0N,25,25^FDPART NUMBER:^FS ^FO20,50^A0N,30,30^FDABC-123^FS ^FO20,90^A0N,25,25^FDQTY: 100^FS ^XZ `; fb_client.printZPL("Zebra ZT230", zplLabel);

File

String getResourceFileString(String filename)

Reads a text file from the working directory and returns its contents. Warning: We do check for path traversal.

Parameters:

  • filename (String): Relative file path from working directory

Returns: String file contents or empty string on error

Security: File access is restricted to the working directory to prevent directory traversal attacks.

Example

Read a SQL file as a string.

var query_sql = fb_client.getResourceFileString("sql/test.sql");

Advanced Example:

const templateHtml = fb_client.getResourceFileString("templates/report_template.html"); if (templateHtml) { document.getElementById('content').innerHTML = templateHtml; } else { fb_client.logError("Template file not found"); }

String getResourceFileAsBase64(String filename)

Retrieves a file name from the root page of the folder, as a Base64 string of bytes. Warning: We do check for path traversal.

Parameters:

  • filename (String): Relative file path from working directory

Returns: Base64 encoded file contents or empty string on error

Example

Read an image file as Base64 string.

var image_b64 = fb_client.getResourceFileString("images/example.png"); console.log(image_b64); # > .....

Advanced Example:

const imageData = fb_client.getResourceFileAsBase64("images/logo.png"); if (imageData) { const imgElement = document.createElement('img'); imgElement.src = 'data:image/png;base64,' + imageData; document.body.appendChild(imgElement); }

void saveDataToFile(String title, String extension, String extension_description, String base64_data, String fileName, boolean openShell)

Shows a save dialog to save base64 data to a file. Displays a Java JFileChooser dialog so we can influence, control the window, and file filter in the dialog from JavaScript.

Parameters:

  • title (String): Dialog title

  • extension (String): File extension (e.g., "pdf", "xlsx")

  • extension_description (String): Extension description (e.g., "PDF Files")

  • base64_data (String): Base64 encoded file data

  • fileName (String): Default filename (optional)

  • openShell (Boolean): Whether to open file after saving (optional)

Example

Save a CSV.

var csv = ""; fb_client.saveDataToFile("Save CSV","csv","Excel (CSV)", btoa(csv) );

Advanced Example:

// Generate a report and save it const pdfResult = fb_client.getReportPDF("45", "{}", false); const pdfData = JSON.parse(pdfResult); if (!pdfData.is_error) { fb_client.saveDataToFile( "Save Report", "pdf", "PDF Files", pdfData.pdf_bytes, "inventory_report.pdf", true ); }

Developer Tools

String listMethods()

Returns a list of all available JavaScript methods with their signatures.

Returns: JSON array of method signatures

Example

const methods = fb_client.listMethods(); const methodList = JSON.parse(methods); console.log("Available methods:", methodList); // Display methods in console for debugging methodList.forEach(method => console.log(method));

Common Usage Patterns

1. Asynchronous Data Loading with Progress Updates

function loadLargeDatasetAsync() { let loadedTables = 0; const totalTables = 3; function updateProgress() { loadedTables++; const progress = Math.round((loadedTables / totalTables) * 100); fb_client.pbUpdate(progress); if (loadedTables === totalTables) { fb_client.dialogStatus("All data loaded successfully"); fb_client.logInformation("Async data loading completed"); } } function handlePartsData(result) { if (result.is_error) { fb_client.logError("Parts query failed: " + result.error_msg); return; } displayPartsTable(result); fb_client.logInformation(`Loaded ${result.length} parts`); updateProgress(); } function handleCustomersData(result) { if (result.is_error) { fb_client.logError("Customers query failed: " + result.error_msg); return; } populateCustomerDropdown(result); fb_client.logInformation(`Loaded ${result.length} customers`); updateProgress(); } function handleInventoryData(result) { if (result.is_error) { fb_client.logError("Inventory query failed: " + result.error_msg); return; } updateInventoryChart(result); fb_client.logInformation(`Loaded ${result.length} inventory records`); updateProgress(); } // Start all async queries simultaneously fb_client.dialogStatus("Loading data..."); fb_client.pbUpdate(0); fb_client.runQueryAsync("SELECT * FROM part WHERE activeflag = 1 LIMIT 1000", "handlePartsData"); fb_client.runQueryAsync("SELECT id, name FROM customer WHERE activeflag = 1", "handleCustomersData"); fb_client.runQueryAsync("SELECT * FROM qoh WHERE qty > 0", "handleInventoryData"); fb_client.logInformation("Started async loading of parts, customers, and inventory data"); }

2. Report Generation with User Parameters

function generateCustomerReport() { const customerId = document.getElementById('customerId').value; const startDate = document.getElementById('startDate').value; const endDate = document.getElementById('endDate').value; if (!customerId || !startDate || !endDate) { fb_client.logError("All fields are required"); return; } const params = JSON.stringify({ CustomerID: parseInt(customerId), StartDate: startDate, EndDate: endDate }); fb_client.pbUpdate(25); fb_client.dialogStatus("Generating report..."); try { const pdfResult = fb_client.getReportPDF("12", params, false); const pdfData = JSON.parse(pdfResult); fb_client.pbUpdate(75); if (pdfData.is_error) { fb_client.logError("Report generation failed: " + pdfData.message); fb_client.dialogStatus("Report failed"); return; } fb_client.pbUpdate(100); fb_client.dialogStatus("Report ready"); // Save the report fb_client.saveDataToFile( "Save Customer Report", "pdf", "PDF Files", pdfData.pdf_bytes, `customer_report_${customerId}_${startDate}_${endDate}.pdf`, true ); fb_client.logInformation("Customer report generated successfully"); } catch (error) { fb_client.logError("Error generating report: " + error.message); fb_client.dialogStatus("Error"); } }

3. User Preferences with Defaults

function saveUserPreferences() { const preferences = { theme: document.getElementById('theme').value, autoRefresh: document.getElementById('autoRefresh').checked.toString(), refreshInterval: document.getElementById('refreshInterval').value, dateFormat: document.getElementById('dateFormat').value }; fb_client.savePluginDataByGroup("user_settings", JSON.stringify(preferences)); fb_client.logInformation("User preferences saved"); fb_client.dialogStatus("Settings saved"); } function loadUserPreferences() { const defaultPrefs = { theme: "light", autoRefresh: false, refreshInterval: "30", dateFormat: "MM/dd/yyyy" }; // Load each preference with fallback to default Object.keys(defaultPrefs).forEach(key => { const value = fb_client.getPluginData("user_settings", key) || defaultPrefs[key]; const element = document.getElementById(key); if (element) { if (element.type === 'checkbox') { element.checked = value === 'true'; } else { element.value = value; } } }); fb_client.logInformation("User preferences loaded"); }

Error Handling Best Practices

1. Always Parse and Check JSON Results

function safeQuery(sql) { try { const results = fb_client.runQuery(sql); const data = JSON.parse(results); if (data.is_error) { fb_client.logError("Query failed: " + data.error_msg); return null; } return data; } catch (error) { fb_client.logError("Error parsing query results: " + error.message); return null; } }

2. Validate Parameters Before API Calls

function validateAndExecute(operation, params) { // Validate required parameters if (!params.customerId || !params.startDate) { fb_client.logError("Missing required parameters"); return false; } // Validate data types if (isNaN(parseInt(params.customerId))) { fb_client.logError("Customer ID must be a number"); return false; } // Proceed with operation return operation(params); }

3. Use Try-Catch for All Bridge Operations

function safeReportGeneration(reportId, params) { try { fb_client.dialogStatus("Generating report..."); const result = fb_client.getReportPDF(reportId, JSON.stringify(params), false); const data = JSON.parse(result); if (data.is_error) { throw new Error(data.message); } return data; } catch (error) { fb_client.logError("Report generation failed: " + error.message); fb_client.dialogStatus("Report failed"); return null; } }

Performance Tips

  1. Use Progress Updates: For long operations, update progress and status regularly

  2. Batch Database Operations: Use parameterized queries for multiple similar operations

  3. Cache Static Data: Store frequently accessed lookup data using plugin data storage

  4. Validate Early: Check user inputs before making expensive API calls

  5. Handle Large Results: Process large datasets in chunks to avoid memory issues

  6. Use Async Methods: For long-running operations, use async methods to keep UI responsive

Security Considerations

  1. SQL Injection Prevention: Always use runQueryParameters() instead of string concatenation

  2. Access Control: Check user permissions with hasAccessRight() before sensitive operations

  3. File Security: File operations are restricted to the working directory

  4. Input Validation: Validate all user inputs before processing

  5. Error Information: Don't expose sensitive system information in error messages

This documentation provides a comprehensive guide for developers to build applications and reports using the PluginBrowserBridge interface. All methods marked with @JsAccessible are available for use in JavaScript applications running within the Fishbowl browser component.