I am trying to build a basic single-page web shop (images of the products, onclick = "addtocart()" and a button "Buy" onclick="buyprem()".
On buy, the JSON is sent to my Java Application via a Websocket.
After buying, I want to reset the JSON representing the order. But whenever I do this, the default JSON is sent.
json = {
products: [],
composite: false,
premium: false,
}
i = 0;
function addtocart(name) {
setTimeout(function() {
var elem = document.getElementById(name);
elem.innerHTML = "";
}, 2000);
document.getElementById(name).innerHTML = i;
json.products[i] = name;
i = i + 1;
}
function buyprem() {
json.premium = true;
var websocket = new WebSocket("ws://localhost:4444");
console.log(JSON.stringify(json))
websocket.onopen = () => {
websocket.send(JSON.stringify(json));
}
//--------------------------
json = {
products: [],
composite: false,
premium: false,
}
i = 0;
//--------------------------
websocket.close;
}
When I comment the marked part out, everything works fine and Java gets the correct JSON.
But when I reset the json variable in this way, Java gets:
Message from client: {"products":[],"composite":false,"premium":false}
(With marked code commented out:
Message from client: {"products":["dog","donatello","twitch"],"composite":false,"premium":true}
where dog, donatello and twitch are the names of the products)
better to do:
function buyprem()
{
json.premium = true
let StrJSON = JSON.stringify(json)
json.products.length = 0
json.composite = false
json.premium = false
i = 0
var websocket = new WebSocket("ws://localhost:4444");
console.log(StrJSON)
websocket.onopen = () =>
{
websocket.send(StrJSON);
}
//--------------------------
websocket.close();
}
because
json = {
products: [],
composite: false,
premium: false,
}
i = 0;
use new memory for json
(in JS, json is a pointer )
Related
I am trying to use javascript URLSearchParameters in which a user can type in certain fields to get particular data sets in json file.
The URLSearchParameter seems to work for when you select certain fields but it does not seem to parse the URL correctly in certain situations.
For Example symbol and apikey is a required field.
Optional fields are start date and end date.
When I type in symbol and apikey and leave all of the optional fields empty, the script breaks. When I type any one of the optional fields, it works. My code is provided below. My schema is not like this but below is an example that is similar. I have more optional fields in my final code but if all of them are empty my code continues to break.
Also I would like to know if there is any simpler way to write this code as I'm repeating the code in if else statements and I am repeating the code the same way.
(function() {
// Create the connector object
var myConnector = tableau.makeConnector();
// Define the schema
myConnector.getSchema = function(schemaCallback) {
var cols = [{
id: "symbol",
alias: "symbol",
dataType: tableau.dataTypeEnum.string
}, {
id: "date",
alias: "date",
dataType: tableau.dataTypeEnum.date
}
];
var tableSchema = {
id: "My data",
alias:"My daily data ",
columns: cols
};
schemaCallback([tableSchema]);
};
// Download the data
myConnector.getData = function(table, doneCallback) {
var dataObj = JSON.parse(tableau.connectionData);
const searchParams = new URLSearchParams (dataObj);
const apiCall = `https://mywebsite/getMyData.json?${searchParams}`;
$.getJSON(apiCall, function(resp) {
var feat = resp.results,
tableData = [];
// Iterate over the JSON object
for (var i = 0, len = feat.length; i < len; i++) {
tableData.push({
"symbol": feat[i].symbol,
"date": feat[i].date,
});
}
table.appendRows(tableData);
doneCallback();
});
};
tableau.registerConnector(myConnector);
// Create event listeners for when the user submits the form
$(document).ready(function() {
$("#submitButton").click(function()
{
if ($('#symbol').val().trim().length == 0 || $('#apikey').val().trim().length == 0)
{
$('#errorMsg').show().html("Symbol and APi key can't be blank.");
}
else if ($('#start-date').val().trim().length == 0){
var dataObj = {
apikey: $('#apikey').val().trim(),
symbol: $('#symbol').val().trim(),
endDate: $('#end-date').val().trim(),
}
tableau.connectionData = JSON.stringify(dataObj);
tableau.connectionName = "My Data";
tableau.submit();
}
else if ($('#end-date').val().trim().length == 0){
var dataObj = {
apikey: $('#apikey').val().trim(),
symbol: $('#symbol').val().trim(),
startDate: $('#start-date').val().trim(),
}
tableau.connectionData = JSON.stringify(dataObj);
tableau.connectionName = "My Data";
tableau.submit();
}
else if ($('#start-date').val().trim().length == 0 && $('#end-date').val().trim().length == 0){
var dataObj = {
apikey: $('#apikey').val().trim(),
symbol: $('#symbol').val().trim(),
type: $('#type').val().trim(),
}
tableau.connectionData = JSON.stringify(dataObj);
tableau.connectionName = "My Data";
tableau.submit();
}
else{
var dataObj = {
apikey: $('#apikey').val().trim(),
symbol: $('#symbol').val().trim(),
startDate: $('#start-date').val().trim(),
endDate: $('#end-date').val().trim(),
};
tableau.connectionData = JSON.stringify(dataObj);
tableau.connectionName = "My Data";
tableau.submit();
}
});
});
})();
I'm making a hybrid app and using WKWebView.
I need to pass a JavaScript Object to the emitter command to open the edit dialog.
Here is my code:
let statDict: [String: Any] = [
"income" : account.stat.income,
"expense" : account.stat.expense,
"summary" : account.stat.summary,
"incomeShorten" : account.stat.incomeShorten,
"expenseShorten" : account.stat.expenseShorten,
"summaryShorten": account.stat.summaryShorten
]
let accountDict: [String: Any] = [
"id": account.id,
"name": account.name,
"description": "",
"icon": account.icon,
"currency": account.currency,
"customer_contact_id": account.customer_contact_id ?? 0,
"is_archived": account.is_archived,
"sort": account.sort,
"create_datetime": account.create_datetime,
"update_datetime": account.update_datetime ?? "",
"stat": statDict
]
let accountData = try! JSONSerialization.data(withJSONObject: accountDict, options: JSONSerialization.WritingOptions(rawValue: 0))
guard let accountString = String(data: accountData, encoding: .utf8) else {
return
}
webView.evaluateJavaScript("function parse(string){ return JSON.parse(string)}") { result, error in
if error == nil { // this is returns correct staff
}
}
webView.evaluateJavaScript("parse('\(accountString)')") { object, error in
if error == nil {
let object = object as AnyObject
print("parse object \(object)")
webView.evaluateJavaScript("window.emitter.emit('openDialog', 'Account', \(object))") { (result, error) in
if error == nil { // here the error "Unexpected token '='..."
webView.evaluateJavaScript("window.emitter.on('closeDialog', function(){ window.webkit.messageHandlers.emitterMessage.postMessage('closeDialog'); })") { (result, error) in
if error == nil {
}
}
webView.evaluateJavaScript("window.emitter.on('createAccount', function(){ window.webkit.messageHandlers.emitterMessage.postMessage('createAccount'); })") { (result, error) in
if error == nil {
}
}
} else {
print(error as Any)
}
}
}
}
The \ (object) returned by the function looks like this:
{
"create_datetime" = "2021-08-24 19:19:28";
currency = RUB;
"customer_contact_id" = 1;
description = "";
icon = "";
id = 7;
"is_archived" = 0;
name = "Business 111";
sort = 0;
stat = {
expense = 0;
expenseShorten = 0;
income = 300000;
incomeShorten = 300K;
summary = 300000;
summaryShorten = 300K;
};
"update_datetime" = "";
}
but it should look like this:
{
create_datetime: "2021-08-24 19:19:28",
currency: "RUB",
customer_contact_id: 1,
description: "",
icon: "",
id: 7,
is_archived: false,
name: "Business 111",
sort: 0,
stat: {
expense: 0,
expenseShorten: "0",
income: 300000,
incomeShorten: "300K",
summary: 300000,
summaryShorten: "300K"
},
update_datetime: ""
}
With such an object, the compiler generates the error Unexpected token '='. Expected an identifier as property name.
The parse (string) function will return the correct object if you run it in the js compiler, but in swift the output is not correct.
How to bring an object to the correct form?
You are trying to pass the string interpolated representation of a Swift object (NSMutableDictionary in your case) to Javascript.
Instead you can directly pass the JSON representation to JS context since JSON is a native Javascript object it should do what you are trying to achieve :
/// Sample emitter function that consumes object an prints its local parameter, also assigns it to sample object value in window.
self.webView?.evaluateJavaScript(
"window.emitter = (sampleObject) => { window.sampleObject = sampleObject;setTimeout(function(){console.log('Hello sampleObject : ',sampleObject.name); }, 7000);}"
) { result, error in
if error == nil { // this is returns correct staff
}
}
self.webView?.evaluateJavaScript("window.emitter(\(accountString));") { result, error in
if error == nil {
print("parse object \(result)")
}
}
Result in window :
I've been trying to crack my problem for quite some time however no matter what I do I can't figure this out. Currently, following the docs from TinyMCE, this code is provided by them.
/* This represents a database of users on the server */
var userDb = {};
userNames.map(function(fullName) {
var name = fullName.toLowerCase().replace(/ /g, '');
var description = descriptions[Math.floor(descriptions.length * Math.random())];
var image = 'https://s3.amazonaws.com/uifaces/faces/twitter/' + images[Math.floor(images.length * Math.random())] + '/128.jpg';
return {
id: name,
name: name,
fullName: fullName,
description: description,
image: image
};
}).forEach(function(user) {
userDb[user.id] = user;
});
/* This represents getting the complete list of users from the server with only basic details */
var fetchUsers = function() {
return new Promise(function(resolve, _reject) {
/* simulate a server delay */
setTimeout(function() {
var users = Object.keys(userDb).map(function(id) {
return {
id: id,
name: userDb[id].name,
};
});
resolve(users);
}, 500);
});
};
/* This represents requesting all the details of a single user from the server database */
var fetchUser = function(id) {
return new Promise(function(resolve, reject) {
/* simulate a server delay */
setTimeout(function() {
if (Object.prototype.hasOwnProperty.call(userDb, id)) {
resolve(userDb[id]);
}
reject('unknown user id "' + id + '"');
}, 300);
});
};
return {
fetchUsers: fetchUsers,
fetchUser: fetchUser
};
})();
/* These are "local" caches of the data returned from the fake server */
var usersRequest = null;
var userRequest = {};
var mentions_fetch = function(query, success) {
/* Fetch your full user list from somewhere */
if (usersRequest === null) {
usersRequest = fakeServer.fetchUsers();
}
usersRequest.then(function(users) {
/* query.term is the text the user typed after the '#' */
users = users.filter(function(user) {
return user.name.indexOf(query.term.toLowerCase()) !== -1;
});
users = users.slice(0, 10);
/* Where the user object must contain the properties `id` and `name`
but you could additionally include anything else you deem useful. */
success(users);
});
};
When I try to change the fake server to get data from my actual server through an API route, however, I get .filter is not a function error. So I figured I would use the Object. values() method, but that doesn't return anything and the console log shows up empty.
This is my logic in my controller (I'm using Laravel btw)
public function getUsers(Request $request) {
$user = User::all();
return $user;
}
The filter problem happens when I change this line :
if (usersRequest === null) {
usersRequest = fakeServer.fetchUsers();
}
To my API call like this:
if (usersRequest === null) {
usersRequest = fetch('api/users/mention');
}
My API response is as follows:
[{id: 1, name: "John", email: "john#doe.com", email_verified_at: null,…},…]
0: {id: 1, name: "John", email: "john#doe.com", email_verified_at: null,…}
1: {id: 2, name: "Admin", email: "vi#example.com", email_verified_at: "2021-02-07 12:01:18",…}
2: {id: 3, name: "Admin2", email: "di#example", email_verified_at: "2021-02-07 12:01:46",…}
Figured it out! After painstakingly trying and trying, I managed to find a solution.
Wrap the tinymce script in a function, I wrapped mine in a function called function tinyMCE()
before the function, run an ajax api call
var usergetNames = [];
$.ajax({
url: '/api/users/mention',
method: 'get',
dataType: 'json',
contentType: 'application/json',
success: function (data) {
usergetNames = data;
tinyMCE();
},
error: function (ex) {
alert(ex.responseText);
}
});
In tinyMCE, replace var userNames line with this
var userNames = usergetNames;
You can get the rest of the code for tinymce mentions in their official documentation page.
I am having trouble with listsQuery not executing by the time everything gets sent to the browser. I know I need a Promise or something in there, but my attempts are so far unsuccessful. Help!
function processNavigation(navigation) {
var nav = [];
_.each(navigation, function(navItems) {
var navProperties = {
name: navItems.get("Name"),
longName: navItems.get("LongName"),
icon: navItems.get("Icon"),
url: navItems.get("Url"),
module: navItems.get("Module"),
runScript: navItems.get("RunScript"),
sortOrder: navItems.get("SortOrder")
};
switch (navItems.get("Module")) {
case "lists":
var listsQuery = new Parse.Query("ListItems"); // This should return back! But it's async? Needs promise?
listsQuery.ascending("SortOrder");
listsQuery.find().then(
function(results) {
var list = [];
_.each(results, function(listItems) {
var listProperties = {
name: listItems.get("Name"),
subName: listItems.get("Subname"),
sortOrder: listItems.get("SortOrder")
};
});
list.push(listProperties);
navProperties["source"] = list;
},
function() {
res.send('error');
}
);
break;
default:
navProperties["source"] = null;
break;
}
nav.push(navProperties);
});
res.send(nav);
}
This should give you something to go on, im not sure if it will work but it should show you the concept.
What you need to do is create an array of promises as it looks like your performing a query for each item in an array, and because the queries take some time your response is sent before the queries are complete. You then evaluate the array of promises and send your response back only when they are resolved.
I would suggest you split your logic into a few more functions as it's a little hard to follow.
Take a look at the parallel promises section
function processNavigation(navigation) {
var nav = [];
var promises = []
_.each(navigation, function(navItems) {
var navProperties = {
name: navItems.get("Name"),
longName: navItems.get("LongName"),
icon: navItems.get("Icon"),
url: navItems.get("Url"),
module: navItems.get("Module"),
runScript: navItems.get("RunScript"),
sortOrder: navItems.get("SortOrder")
};
switch (navItems.get("Module")) {
case "lists":
promises.push((function(navProperties){
var listsQuery = new Parse.Query("ListItems"); // This should return back! But it's async? Needs promise?
listsQuery.ascending("SortOrder");
listsQuery.find().then(
function(results) {
var list = [];
_.each(results, function(listItems) {
var listProperties = {
name: listItems.get("Name"),
subName: listItems.get("Subname"),
sortOrder: listItems.get("SortOrder")
};
});
list.push(listProperties);
navProperties["source"] = list;
promise.resolve();
},
function() {
promise.reject();
res.send('error');
}
);
})(navProperties))
break;
default:
navProperties["source"] = null;
break;
}
nav.push(navProperties);
});
Parse.Promise.when(promises).then(function(){
res.send(nav);
})
}
I have been reading ALL of the documentation on this and I still cannot get it to work.
I have a Web API which provides a JSON object. It's a list of 22 things. Just 22 lines of text.
I want to take these and form a TreeView. Each of these 22 strings will have items under them but I just want to get the first part working.
My first question is, how do I extract data from an API and populate a treeView with it?
On my main page, I have this:
<div id="treeView"></div>
On my JavaScript file I have this:
$("#treeView").kendoTreeView({
checkboxes: true,
dataSource: {
transport: {
read: {
url: "http://...",
dataType: "json"
}
}
}
});
When I try to run the page, I get "Request failed." [Retry]
If I open up a browser and go to this URL, data is returned fine as a JSON object.
What am I doing wrong here?
EDIT -
Code that is returning the JSON:
public List<string> getNotificationByUser(int id)
{
List<string> notificationTitles = new List<string>();
foreach (var notification in notifications)
{
notificationTitles.Add(notification.ToString());
}
return notificationTitles;
}
Ok! I've been able to reproduce your error. The question is that 22 lines of text are not a valid JSON.
Returning something like:
This
is
a
test
Is not a valid JSON.
But a valid JSON is not enough, you should return something like this:
[
{ "text": "This" },
{ "text": "is" },
{ "text": "a" },
{ "text": "test" }
]
I.e.: The result should be an array of objects where each object has a text field.
NOTE I know that it does not have to be called text but for simplicity I used it since it is the default value.
I figured out all of my answers:
function CreateNotificationTree(userId)
{
debugger;
var data = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: "../api/notifications/byuserid/" + userId,
contentType: "application/json"
}
},
schema: {
model: {
children: "notifications"
}
}
});
$("#treeview").kendoTreeView({
dataSource: data,
loadOnDemand: true,
dataUrlField: "LinksTo",
checkboxes: {
checkChildren: true
},
dataTextField: ["notificationType", "NotificationDesc"],
select: treeviewSelect
});
function treeviewSelect(e)
{
var node = this.dataItem(e.node);
window.open(node.NotificationLink, "_self");
}
}
[HttpGet]
public List<Node> getNotifications(int id)
{
var bo = new HomeBO();
var list = bo.GetNotificationsForUser(id);
var notificationTreeNodes = (from GBLNotifications n in list
where n.NotificationCount != 0
select new NotificationTreeNode(n)).ToList();
var li = notificationTreeNodes.Select(no => new Node
{
notificationType = no.NotificationNode.NotificationType + " " + "(" + no.NotificationNode.NotificationCount + ")", notifications = bo.GetNotificationsForUser(id, no.NotificationNode.NotificationTypeId).Cast<GBLNotifications>().Select(item => new Notification
{
ID = item.NotificationId, NotificationDesc = item.NotificationDescription, Params = new List<NotificationParam>
{
new NotificationParam
{
ParamName = item.Param1, ParamVal = item.ParamValue1
},
new NotificationParam
{
ParamName = item.Param2, ParamVal = item.ParamValue2
},
new NotificationParam
{
ParamName = item.Param3, ParamVal = item.ParamValue3
},
new NotificationParam
{
ParamName = item.Param4, ParamVal = item.ParamValue4
},
new NotificationParam
{
ParamName = item.Param5, ParamVal = item.ParamValue5
},
},
ActionPageName = item.ActionPageName
}).ToList()
}).ToList();
li.ForEach(i => i.notifications.ForEach(x => x.SetNotificationLink()));
return li;
}