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.
Logs an informational message to the application log and console.
Parameters:
message
(String): The message to logExample
fb_client.logInformation("Processing started for order 12345"); |
Logs an error message to the application log and console.
Parameters:
message
(String): The error message to logExample
fb_client.logError("Failed to process order: Invalid customer ID"); |
Returns all logged messages for the current page session.
Returns: String containing all logged messages
Example
const allLogs = fb_client.logMessages(); console.log(allLogs); |
Retrieves server-side log messages.
Returns: String containing server log messages
Example
const serverLogs = fb_client.serverLogMessages(); |
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 executeReturns: 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"); |
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 valuesReturns: 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: ..." } |
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 executecallbackFunctionName
(String): Name of the JavaScript function to call when the query completesReturns: 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..."); |
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 valuescallbackFunctionName
(String): Name of the JavaScript function to call when the query completesReturns: 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); |
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 pathbody
(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 } |
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 pathbody
(String): Request body (JSON string, null for GET requests)callbackFunctionName
(String): Name of the JavaScript function to call when the API call completesReturns: 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"); |
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 headersReturns: 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); |
Imports data from a JSON array of CSV row strings.
Parameters:
import_type
(String): Type of importjson_list_strings
(String): JSON array of CSV row stringsExample
const csvRows = JSON.stringify([ '"TEST-001","Test Part 1","ea"', '"TEST-002","Test Part 2","ea"' ]); const result = fb_client.runImportCSV_JSON("Part", csvRows); |
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 payloadReturns: 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); |
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 payloadcallbackFunctionName
(String): Name of the JavaScript function to call when the API call completesReturns: 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"); |
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 headerscallbackFunctionName
(String): Name of the JavaScript function to call when the import completesReturns: 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"); |
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 importjson_list_strings
(String): JSON array of CSV row stringscallbackFunctionName
(String): Name of the JavaScript function to call when the import completesReturns: 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"); |
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(); |
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 barExamples
Show the status bar.
fb_client.showStatusBar(true); |
Image TBD
Hide the status bar.
fb_client.showStatusBar(false); |
Image TBD
Toggles fullscreen mode for the dialog window.
Example
fb_client.toggleFullscreen(); |
Displays a short message in the status bar, approx. less than 100 characters.
Parameters:
message
(String): Status message to displayExample
fb_client.dialogStatus("Hello"); |
Image TBD
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 } |
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); |
Gets the current user's ID.
Returns: Integer user ID
Example
var user_id = fb_client.getUserId(); console.log(user_id); > 1 |
Gets the current user's username.
Returns: String username
Example
var user_name = fb_client.getUsername(); console.log(user_name); > "admin" |
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" |
Gets the current user's group IDs.
Returns: Array of string group IDs
Example
const groupIds = fb_client.getUsersGroupIDs(); console.log("User groups:", groupIds); |
Gets the current plugin name.
Returns: String plugin name
Example
const pluginName = fb_client.getPluginName(); console.log("Current plugin:", pluginName); |
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" |
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); |
Checks if the current user has a specific access right.
Parameters:
name
(String): Access right nameReturns: Boolean indicating access
Example
if (fb_client.hasAccessRight("ViewInventory")) { // Show inventory data } else { fb_client.logError("User lacks ViewInventory permission"); } |
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 identifierdata_dictionary
(String): JSON object containing key-value pairsReturns: 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); |
Retrieves a string, given a group_name, and key.
Parameters:
group_name
(String): Group identifierkey
(String): Data keyReturns: 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"; |
Deletes plugin data by the group_name.
Parameters:
group_name
(String): Group identifierReturns: Boolean (always true)
Example
fb_client.deletePluginData("user_preferences"); |
Reloads/refreshes the current modules object.
Returns: Boolean (always true)
Example
var refreshed = fb_client.reloadObject(); |
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"); |
Runs a scheduled task by name.
Parameters:
task_name
(String): Name of the scheduled taskExample
fb_client.runScheduledTask("DailyInventorySync"); |
Opens a report preview window with the specified parameters.
Parameters:
report_id
(String): Report ID from the Fishbowl databasereport_parameters
(String): JSON object containing report parametersExample
const params = JSON.stringify({ StartDate: "2023-01-01", EndDate: "2023-12-31", CustomerID: "123" }); fb_client.previewReport("45", params); |
Generates a PDF report and returns it as base64 encoded data.
Parameters:
report_id
(String): Report IDreport_parameters
(String): JSON object containing report parametersthrow_exception
(Boolean): Whether to throw exceptions on errorReturns: 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); } |
Generates a merged PDF from multiple reports with specified copies.
Parameters:
report_dictionary_json
(String): JSON array of report definitionsReturns: 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); |
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); }); |
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 datashow_print_dialog
(Boolean): Whether to show print dialogExample
const pdfBase64 = "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8..."; // Base64 PDF data fb_client.printPDF("HP LaserJet Pro", pdfBase64, false); |
Prints a report directly to a printer without generating intermediate files.
Parameters:
printer_name
(String): Printer namecopies
(Integer): Number of copiesreport_id
(String): Report IDreport_parameters
(String): JSON report parametersthrow_exception
(Boolean): Whether to throw exceptionsExample
const params = JSON.stringify({ OrderID: "12345" }); fb_client.printReportPDF("Label Printer", 2, "67", params, false); |
Prints a merged PDF of multiple reports.
Parameters:
printer_name
(String): Printer namecopies
(Integer): Number of copiesreport_dictionary_json
(String): JSON array of report definitionsPrints multiple reports using JasperReports engine.
Parameters:
report_dictionary_json
(String): JSON array of report definitionsprinter_name
(String): Printer namePrints a ZPL (Zebra Programming Language) document to a label printer.
Parameters:
printer_name
(String): Printer namezpl_document
(String): ZPL formatted documentExample
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); |
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 directoryReturns: 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"); } |
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 directoryReturns: 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); } |
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 titleextension
(String): File extension (e.g., "pdf", "xlsx")extension_description
(String): Extension description (e.g., "PDF Files")base64_data
(String): Base64 encoded file datafileName
(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 ); } |
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)); |
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"); } |
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"); } } |
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"); } |
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; } } |
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); } |
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; } } |
runQueryParameters()
instead of string concatenationhasAccessRight()
before sensitive operationsThis 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.