jqgrid, autocomplete under several input boxes - jqgrid-php

For jqGrid, how to do autocomplete under several input boxes, namely A, B, C. After the input A, autocomplete values provided by B need to have a reference from input A.
For the dataInit at input B, I can only get the original content of input A, not the current input one.
Any idea or link so that I can pay attention to. Thanks
B/R
Gene Leung
Here is the code:
...
{ name:'order_no',
index:'order_no',
align:"center",
width:80,
editable:true,
editoptions:
{
dataInit: function (elem) {
myAutocomplete(elem, "./autoComplete.php?id=sales_no");
},
dataEvents: [
{ type: 'change',
fn: function(e) {
savedSalesNo = $(this).val();
//console.log( savedSalesNo );
}
}
]
}
},
{ name:'item_no',
index:'item_no',
width:120,
editable:true,
editoptions:
{
dataInit: function (elem) {
myAutocomplete(elem, "./autoComplete.php?id=sales_items&vchr_no=" + savedSalesNo);
}
}
},
... php code: ...
if isset($_GET["term"]))
$maskTP = $_GET['term'];
else
$maskTP = "";
$sWhere = "WHERE 1=1";
if($maskTP!='') {
switch ($_GET["id"]) {
case "sales_no":
$sWhere.= " AND name LIKE '%$maskTP%'";
$sSQL = "SELECT name AS order_no FROM sale_order ". $sWhere ." ORDER BY name";
break;
case "sales_items":
$sWhere.= " AND name LIKE '%$maskTP%'";
$sSQL = "SELECT name AS order_no FROM sale_order ". $sWhere ." ORDER BY name";
break;
}
}
$result = $db->Execute( $sSQL );

Can you post some code snippet it will be helpful.
But looking at your question what i understand is you need to autocomplete in B based on A and so on.
So what you can do is while making ajax request for the B autocomplete check the value A and pass it in your call and perform your business logic.

Related

Is there a way to map a json object for the below example?

excel snippet
I am using Mule 4 and am trying to read an excel file, then convert into JSON using Dataweave and update them in salesforce.
Below is the payload which I am getting while I read the excel. I need to convert this into the requested Output Payload.
The values are dynamic. There might be more objects.
Any ideas appreciated.
Thanks.
Input Payload:
{
"X":[
{
"A":"Key1",
"B":"Key2",
"C":"Key3",
"D":"value1",
"E":"value2"
},
{
"A":"",
"B":"",
"C":"Key4",
"D":"value3",
"E":"value4"
},
{
"A":"Key5",
"B":"Key6",
"C":"Key7",
"D":"Value5",
"E":"Value6"
},
{
"A":"",
"B":"",
"C":"Key8",
"D":"Value7",
"E":"Value8"
}
]
}
Output Payload:
[
{
"Key1":{
"Key2":{
"Key3":"value1",
"Key4":"value3"
}
},
"Key5":{
"Key6":{
"Key7":"Value5",
"Key8":"Value7"
}
}
},
{
"Key1":{
"Key2":{
"Key3":"value2",
"Key4":"value4"
}
},
"Key5":{
"Key6":{
"Key7":"Value6",
"Key8":"Value8"
}
}
}
]
The following seems to work.
This is JavaScript. I don't know what the underlying syntax or scripting language is for DataWeave, but between the C-family syntax and inline comments you can probably treat the JS like pseudo-code and read it well enough to recreate the logic.
// I assume you started with a table structure like this:
//
// A B C D E
// == == == == ==
// K1 K2 K3 v1 v2 <~ X[0]
// __ __ K4 v3 v4 <~ X[1]
// K5 K6 K7 v5 v6 <~ X[2]
// __ __ K8 v7 v8 <~ X[3]
//
// So I'm going to call A,B,C,D,E "column labels"
// and the elements in `X` "rows".
// Here's the original input you provided:
input = {
"X": [
{
"A":"Key1",
"B":"Key2",
"C":"Key3",
"D":"value1",
"E":"value2"
},
{
"A":"",
"B":"",
"C":"Key4",
"D":"value3",
"E":"value4"
},
{
"A":"Key5",
"B":"Key6",
"C":"Key7",
"D":"Value5",
"E":"Value6"
},
{
"A":"",
"B":"",
"C":"Key8",
"D":"Value7",
"E":"Value8"
}
]
}
// First let's simplify the structure by filling in the missing keys at
// `X[1].A`, `X[1].B` etc. We could keep track of the last non-blank
// value while doing the processing below instead, but doing it now
// reduces the complexity of the final loop.
input.X.forEach((row, row_index) => {
(Object.keys(row)).forEach((col_label) => {
if (row[col_label].length == 0) {
row[col_label] = input.X[row_index - 1][col_label]
}
});
});
// Now X[1].A is "Key1", X[1].B is "Key2", etc.
// I'm not quite sure if there's a hard-and-fast rule that determines
// which values become keys and which become values, so I'm just going
// to explicitly describe the structure. If there's a pattern to follow
// you could compute this dynamically.
const key_column_labels = ["A","B","C"]
const val_column_labels = ["D","E"]
// this will be the root object we're building
var output_list = []
// since the value columns become output rows we need to invert the loop a bit,
// so the outermost thing we iterate over is the list of value column labels.
// our general strategy is to walk down the "tree" of key-columns and
// append the current value-column. we do that for each input row, and then
// repeat that whole cycle for each value column.
val_column_labels.forEach((vl) => {
// the current output row we're populating
var out_row = {}
output_list.push(out_row)
// for each input row
input.X.forEach((in_row) => {
// start at the root level of the output row
var cur_node = out_row
// for each of our key column labels
key_column_labels.forEach((kl, ki) => {
if (ki == (key_column_labels.length - 1)) {
// this is the last key column (C), the one that holds the values
// so set the current vl as one of the keys
cur_node[in_row[kl]] = in_row[vl]
} else if (cur_node[in_row[kl]] == null) {
// else if there's no map stored in the current node for this
// key value, let's create one
cur_node[in_row[kl]] = {}
// and "step down" into it for the next iteration of the loop
cur_node = cur_node[in_row[kl]]
} else {
// else if there's no map stored in the current node for this
// key value, so let's step down into the existing map
cur_node = cur_node[in_row[kl]]
}
});
});
});
console.log( JSON.stringify(output_list,null,2) )
// When I run this I get the data structure you're looking for:
//
// ```
// $ node json-transform.js
// [
// {
// "Key1": {
// "Key2": {
// "Key3": "value1",
// "Key4": "value3"
// }
// },
// "Key5": {
// "Key6": {
// "Key7": "Value5",
// "Key8": "Value7"
// }
// }
// },
// {
// "Key1": {
// "Key2": {
// "Key3": "value2",
// "Key4": "value4"
// }
// },
// "Key5": {
// "Key6": {
// "Key7": "Value6",
// "Key8": "Value8"
// }
// }
// }
// ]
// ```
Here's a JSFiddle that demonstrates this: https://jsfiddle.net/wcvmu0g9/
I'm not sure this captures the general form you're going for (because I'm not sure I fully understand that), but I think you should be able to abstract this basic principle.
It was a challenging one. I was able to at least get the output you expect with this Dataweave code. I'll put some comments on the code.
%dw 2.0
output application/json
fun getNonEmpty(key, previousKey) =
if(isEmpty(key)) previousKey else key
fun completeKey(item, previousItem) =
{
A: getNonEmpty(item.A,previousItem.A),
B: getNonEmpty(item.B,previousItem.B)
} ++ (item - "A" - "B")
// Here I'm filling up the A and B columns to have the complete path using the previous items ones if they come empty
var completedStructure =
payload.X reduce ((item, acc = []) ->
acc + completeKey(item, acc[-1])
)
// This takes a list, groups it by a field and let you pass also what to
// want to do with the grouped values.
fun groupByKey(structure, field, next) =
structure groupBy ((item, i) -> item[field]) mapObject ((v, k, i1) ->
{
(k): next(k,v)
}
)
// This one was just to not repete the code for each value field
fun valuesForfield(structure, field) =
groupByKey(structure, "A", (key,value) ->
groupByKey(value, "B", (k,v) ->
groupByKey(value, "C", (k,v) -> v[0][field]))
)
var valueColumns = ["D","E"]
---
valueColumns map (value, index) -> valuesForfield(completedStructure,value)
EDIT: valueColumns is now Dynamic

How do i get a randomly selected string name and still select an existing substring without the code coming out as text

I'm currently trying to get info off of an object but that's randomly selected. I believe that the true problem is that what I wrote is not being taken as a variable for selecting an existing object if not as the variable for the object, I don't know if this is a clear message or not.
Example of what I have tried:
let PK = ["Random1", "Random2", "Random3"]
let PKS = Math.floor(Math.random() * PK.length)
let Random1 = {
name: "Random1",
number: "010"
}
let Random2 = {
name: "Random2",
number: "011"
}
if(message.content.toLowerCase() == "random"){
message.channel.send(PK[PKS].number)
}
There is another thing I have tried which is by using ${}. These are the results:
"Random1.number" or "Random2.number" when what I was looking for is actually "010" or "011".
You should wrap your objects inside some collection such as an Array and then you just compare the value from your random selection to the value find in the collection (if any (randoms)):
let PK = ["Random1", "Random2", "Random3"];
let PKS = Math.floor(Math.random() * PK.length);
const randoms = [
{
name: "Random1",
number: "010",
},
{
name: "Random2",
number: "011",
},
];
if (message.content.toLowerCase() == "random") {
const findRandom = randoms.find((v) => v.name === PK[PKS]);
if (findRandom) {
message.channel.send(findRandom.number);
}
}

How to make selectable option in OPC-UA?

Assuming having a read/write variable called Fruit.
Selectable options are Apple, Pear, Strawberry & Pineapple.
Using OptionSetType seems to be the most suiteable way.
But I did not find any examples for node-opcua
Can somebody provide an example or is there another/better/smarter way?
Enumeration become my best friend
const fruitEnumType = ownNameSpace.addEnumerationType({
browseName: "Fruits",
enumeration: ["apple", "pear", "strawberry", "pineapple"],
});
let selected = "apple";
ownNameSpace.addVariable({
browseName: "Fruit",
componentOf: folder,
dataType: fruitEnumType,
value: {
get: () =>
new Variant({
dataType: DataType.String,
value: selected,
}),
set: (value: Variant) => {
selected = value.value;
return StatusCodes.Good;
},
},
});
The UAVariable class in node-opcua comes with two helpers methods that make it easy to deal with enumeration. readEnumValue and writeEnumValue .
You will find this form more practical:
const fruit2 = ownNameSpace.addVariable({
browseName: "Fruit2s",
componentOf: myObject,
dataType: fruitEnumType
});
fruit2.writeEnumValue("strawberry");
console.log("enum value = ", fruit2.readEnumValue());
console.log("enum value name = ", fruit2.readEnumValue().name);
console.log("enum value value = ", fruit2.readEnumValue().value);
console.log("dataValue is ", fruit2.readValue().toString());
enum value = { value: 2, name: 'strawberry' }
enum value name = strawberry
enum value value = 2
dataValue is { /* DataValue */
value: Variant(Scalar<Int32>, value: 2)
statusCode: Good (0x00000)
serverTimestamp: 2021-01-23T08:59:04.273Z $ 990.400.000
sourceTimestamp: 2021-01-23T08:59:04.273Z $ 990.400.000
}
Note: that you don't need to use the get/set form as well as the value is already store inside the variable.

How do I download data trees to CSV?

How can I export nested tree data as a CSV file when using Tabulator? I tried using the table.download("csv","data.csv") function, however, only the top-level data rows are exported.
It looks like a custom file formatter or another option may be necessary to achieve this. It seems silly to re-write the CSV downloader, so while poking around the csv downloader in the download.js module, it looks like maybe adding a recursive function to the row parser upon finding a "_children" field might work.
I am having difficulty figuring out where to get started.
Ultimately, I need to have the parent-to-child relationship represented in the CSV data with a value in a parent ID field in the child rows (this field can be blank in the top-level parent rows because they have no parent). I think I would need to include an ID and ParentID in the data table to achieve this, and perhaps enforce the validation of that key using some additional functions as data is inserted into the table.
Below is currently how I am exporting nested data tables to CSV. This will insert a new column at the end to include a parent row identifier of your choice. It would be easy to take that out or make it conditional if you do not need it.
// Export CSV file to download
$("#export-csv").click(function(){
table.download(dataTreeCSVfileFormatter, "data.csv",{nested:true, nestedParentTitle:"Parent Name", nestedParentField:"name"});
});
// Modified CSV file formatter for nested data trees
// This is a copy of the CSV formatter in modules/download.js
// with additions to recursively loop through children arrays and add a Parent identifier column
// options: nested:true, nestedParentTitle:"Parent Name", nestedParentField:"name"
var dataTreeCSVfileFormatter = function(columns, data, options, setFileContents, config){
//columns - column definition array for table (with columns in current visible order);
//data - currently displayed table data
//options - the options object passed from the download function
//setFileContents - function to call to pass the formatted data to the downloader
var self = this,
titles = [],
fields = [],
delimiter = options && options.delimiter ? options.delimiter : ",",
nestedParentTitle = options && options.nestedParentTitle ? options.nestedParentTitle : "Parent",
nestedParentField = options && options.nestedParentField ? options.nestedParentField : "id",
fileContents,
output;
//build column headers
function parseSimpleTitles() {
columns.forEach(function (column) {
titles.push('"' + String(column.title).split('"').join('""') + '"');
fields.push(column.field);
});
if(options.nested) {
titles.push('"' + String(nestedParentTitle) + '"');
}
}
function parseColumnGroup(column, level) {
if (column.subGroups) {
column.subGroups.forEach(function (subGroup) {
parseColumnGroup(subGroup, level + 1);
});
} else {
titles.push('"' + String(column.title).split('"').join('""') + '"');
fields.push(column.definition.field);
}
}
if (config.columnGroups) {
console.warn("Download Warning - CSV downloader cannot process column groups");
columns.forEach(function (column) {
parseColumnGroup(column, 0);
});
} else {
parseSimpleTitles();
}
//generate header row
fileContents = [titles.join(delimiter)];
function parseRows(data,parentValue="") {
//generate each row of the table
data.forEach(function (row) {
var rowData = [];
fields.forEach(function (field) {
var value = self.getFieldValue(field, row);
switch (typeof value === "undefined" ? "undefined" : _typeof(value)) {
case "object":
value = JSON.stringify(value);
break;
case "undefined":
case "null":
value = "";
break;
default:
value = value;
}
//escape quotation marks
rowData.push('"' + String(value).split('"').join('""') + '"');
});
if(options.nested) {
rowData.push('"' + String(parentValue).split('"').join('""') + '"');
}
fileContents.push(rowData.join(delimiter));
if(options.nested) {
if(row._children) {
parseRows(row._children, self.getFieldValue(nestedParentField, row));
}
}
});
}
function parseGroup(group) {
if (group.subGroups) {
group.subGroups.forEach(function (subGroup) {
parseGroup(subGroup);
});
} else {
parseRows(group.rows);
}
}
if (config.columnCalcs) {
console.warn("Download Warning - CSV downloader cannot process column calculations");
data = data.data;
}
if (config.rowGroups) {
console.warn("Download Warning - CSV downloader cannot process row groups");
data.forEach(function (group) {
parseGroup(group);
});
} else {
parseRows(data);
}
output = fileContents.join("\n");
if (options.bom) {
output = "\uFEFF" + output;
}
setFileContents(output, "text/csv");
};
as of version 4.2 it is currently not possible to include tree data in downloads, this will be comming in a later release

Using Stored Data to Define Sub Menu Entries

My extension should use the user's options to build submenus under the main extension context menu entry. The options are stored in a table, where each line is defining a submenu. The whole table is stored as a json string in chrome.local.storage with the key jsondata.
The manifest is:
"background": {
"persistent": true,
"scripts": [ "js/storage.js", "js/backgroundlib.js", "js/background.js" ]
},
...
"permissions": [ "storage", "contextMenus", "http://*/*", "https://*/*", "tabs", "clipboardRead", "clipboardWrite" ],
...
In the background script, I'm trying to get the data using:
window.addEventListener('load', function () {
var key = 'jsondata';
storage.area.get(key, function (items){
console.log(items[key]);
build_submenu(items[key]);});
});
function build_submenu(json) {
console.log("build_submenu: " + json);
}
and build_submenu should then call multiple chrome.contextMenus.create({... }) to add the submenus.
For now, I can't get build_submenu being called. Am I trying to do something that is not possible or am I just missing something obvious?
Thanks, F.
Replace storage.area.get with chrome.storage.local.get.
Another suggestion would be removing the outer window.onload listener, since you are using background scripts and window.onload makes no sense.
OK, I finally got this, that works:
manifest.json
"background": {
"persistent": false,
"scripts": [ "js/storage.js", "js/backgroundlib.js", "js/background.js" ]
},
in background.js, The context menu is build in the callback function when reading from storage. This reading is called when onInstalled is fired.
I use a global var that is saved onSuspend et read again onStartup. and that associate the submenu id and the corresponding row from the user's option. The onClick listener test if the global variable is defined. If not it is read again from storage.
var regex = new Object();
chrome.runtime.onInstalled.addListener( function () {
console.log("onInstalled called");
var key = 'jsondata';
storage.area.get(key, function (items){ get_jsondata(items[key]);});
function get_jsondata(value){
var data = JSON.parse(value);
var fcb =[ {fcb_context: "fcb_copy", title:"Copy filtered", context: ["selection", "link"]}, {fcb_context:"fcb_paste", context:["editable"], title:"Paste filtered"}];
for (var i=0; i<fcb.length; i++) {
var menu = fcb[i];
chrome.contextMenus.create({
//title: "Look up: %s",
title: menu.title,
id: menu.fcb_context,
contexts: menu.context,
});
var last = data.length;
//var sel = info.selectionText;
for (var j=0; j<last; j++){
chrome.contextMenus.create({
title: data[j].name,
contexts: menu.context,
id: menu.fcb_context + "_" + j,
parentId: menu.fcb_context,
//onclick: function(info, tab){ run_cmd( data[j].regex, info, menu.fcb_context ); }
});
regex[ menu.fcb_context + "_" + j] = data[j];
//console.log(regex[menu.fcb_context + "_" + j]);
}// for j
} // for i
}//get_jsondata
}); //add listener
chrome.contextMenus.onClicked.addListener(function(info, tabs){
var id = info.menuItemId;
if (typeof regex === "undefined" ){
storage.area.get("regex", function(items){
regex = JSON.parse(items["regex"]);
console.log("get " + items["regex"] + " from storage");
run_cmd( regex, info );
});
} else {
console.log("regex was defined... " + JSON.stringify(regex));
run_cmd( regex, info );
}
});
chrome.runtime.onSuspend.addListener(function() {
// Do some simple clean-up tasks.
console.log("onSuspend called saving " + JSON.stringify(regex));
storage.area.set({ "regex" : JSON.stringify(regex)}, function(){console.log("regex saved");} );
});
chrome.runtime.onStartup.addListener(function() {
console.log("onStartup called");
storage.area.get("regex", function(items){
regex = JSON.parse(items["regex"]);
console.log("get " + items["regex"] + " from storage");
});
});
function getSelectedText(info){
var sel = info.selectionText;
chrome.tabs.executeScript(null, {file:"js/script.js"});
}
function pasteFilteredText(info){
chrome.tabs.executeScript(null, {file:"js/script.js"});
}
function run_cmd(regex, info){
var id = info.menuItemId;
var data = regex[id];
var sel = info.selectionText;
var fcb_context = info.parentMenuItemId;
//console.log("run_cmd regex " + data.regex + " sel " + (sel ? sel : ""));
alert("run_cmd regex " + data.regex + " sel " + (sel ? sel : "") + " fcb_context: " + fcb_context);
}
Thanks for pointing me what is superfluous or missing.

Resources