How to concatenate strings without using eval? - javascript

How do I concatenate these strings to get value from a variable. I want to avoid eval as so many of you are not keen on its use.
function getLesson() {
var lesson = "lesson" + localStorage.lessonNGS;
document.getElementById("lessonNumber").innerHTML = "Lesson " + (eval(lesson + "." + number));
document.getElementById("lessonTitle").innerHTML = (eval(lesson + "." + title));
document.getElementById("lessonScore").src = (eval(lesson + "." + score));
document.getElementById("mp3").src = (eval(lesson + "." + trackmp3));
document.getElementById("ogg").src = (eval(lesson + "." + trackogg));
document.getElementById("lessonTrack").load();
}
This works but I'm told it will cause me conflicts in some browsers.

Simply remove the eval
// Demo data
localStorage.setItem("lessonNGS",1);
var lesson1 = {
number: "1",
title: "Quarter Notes",
score: "scores/01_quarternotes.jpg",
trackmp3: "tracks/mp3/01_quarternotekeyexercises.mp3",
trackogg: "tracks/ogg/01_quarternotekeyexercises.ogg"
};
function getLesson() {
debugger;
var lesson = window["lesson" + localStorage.lessonNGS];
document.getElementById("lessonNumber").innerHTML = "Lesson " + lesson.number;
document.getElementById("lessonTitle").innerHTML = lesson.title;
document.getElementById("lessonScore").src = lesson.score;
document.getElementById("mp3").src = lesson.trackmp3;
document.getElementById("ogg").src = lesson.trackogg;
document.getElementById("lessonTrack").load();
}

Javascript String.prototype.concat():
str.concat(string2, string3[, ..., stringN])
Example:
var hello = 'Hello, ';
console.log(hello.concat('Kevin', ' have a nice day.'));

Related

Use variable from callback as global variable

I made a block in which the request to the specified URL occurs.
Inside this block, I can work with the data from response, but outside this block I can not get this data because of asynchrony.
Is it possible to simulate a synchronous request in blockly or in some other way, save the received data to a global variable?
code of the created block:
Blockly.Blocks['request'] =
'<block type="request">'
+ ' <value name="URL">'
+ ' <shadow type="text">'
+ ' <field name="TEXT">text</field>'
+ ' </shadow>'
+ ' </value>'
+ ' <value name="LOG">'
+ ' </value>'
+ ' <value name="WITH_STATEMENT">'
+ ' </value>'
+ ' <mutation with_statement="false"></mutation>'
+ '</block>';
Blockly.Blocks['request'] = {
init: function() {
this.appendDummyInput('TEXT')
.appendField('request');
this.appendValueInput('URL')
.appendField('URL');
this.appendDummyInput('WITH_STATEMENT')
.appendField('with results')
.appendField(new Blockly.FieldCheckbox('FALSE', function (option) {
var delayInput = (option == true);
this.sourceBlock_.updateShape_(delayInput);
}), 'WITH_STATEMENT');
this.appendDummyInput('LOG')
.appendField('log level')
.appendField(new Blockly.FieldDropdown([
['none', ''],
['info', 'log'],
['debug', 'debug'],
['warning', 'warn'],
['error', 'error']
]), 'LOG');
this.setInputsInline(false);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(230);
this.setTooltip('Request URL');
this.setHelpUrl('https://github.com/request/request');
},
mutationToDom: function() {
var container = document.createElement('mutation');
container.setAttribute('with_statement', this.getFieldValue('WITH_STATEMENT') === 'TRUE');
return container;
},
domToMutation: function(xmlElement) {
this.updateShape_(xmlElement.getAttribute('with_statement') == 'true');
},
updateShape_: function(withStatement) {
// Add or remove a statement Input.
var inputExists = this.getInput('STATEMENT');
if (withStatement) {
if (!inputExists) {
this.appendStatementInput('STATEMENT');
}
} else if (inputExists) {
this.removeInput('STATEMENT');
}
}};
Blockly.JavaScript['request'] = function(block) {
var logLevel = block.getFieldValue('LOG');
var URL = Blockly.JavaScript.valueToCode(block, 'URL', Blockly.JavaScript.ORDER_ATOMIC);
var withStatement = block.getFieldValue('WITH_STATEMENT');
var logText;
if (logLevel) {
logText = 'console.' + logLevel + '("request: " + ' + URL + ');\n'
} else {
logText = '';
}
if (withStatement === 'TRUE') {
var statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
if (statement) {
var xmlhttp = "var xmlHttp = new XMLHttpRequest();";
var xmlopen = "xmlHttp.open('POST', " + URL + ", true);";
var xmlheaders = "xmlHttp.setRequestHeader('Content-type', 'application/json');\n" +
"xmlHttp.setRequestHeader('Authorization', 'Bearer psokmCxKjfhk7qHLeYd1');";
var xmlonload = "xmlHttp.onload = function() {\n" +
" console.log('recieved:' + this.response);\n" +
" var response = this.response;\n" +
" var brightness = 'brightness: ' + JSON.parse(this.response).payload.devices[0].brightness;\n" +
" " + statement + "\n" +
"}";
var json = JSON.stringify({
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"inputs": [{
"intent": "action.devices.QUERY",
"payload": {
"devices": [{
"id": "0",
"customData": {
"smartHomeProviderId": "FkldJVJCmDNSaoLkoq0txiz8Byf2Hr"
}
}]
}
}]
});
var xmlsend = "xmlHttp.send('" + json + "');";
var code = xmlhttp + '\n' + xmlopen + '\n' + xmlheaders + '\n' + xmlonload + '\n' + xmlsend;
return code;
} else {
var xmlhttp = "var xmlHttp = new XMLHttpRequest();";
var xmlopen = "xmlHttp.open('POST', " + URL + ", true);";
var xmlheaders = "xmlHttp.setRequestHeader('Content-type', 'application/json');\n" +
"xmlHttp.setRequestHeader('Authorization', 'Bearer psokmCxKjfhk7qHLeYd1');";
var xmlonload = "xmlHttp.onload = function() {\n" +
" console.log('recieved:' + this.response);\n" +
"}";
var json = JSON.stringify({
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"inputs": [{
"intent": "action.devices.QUERY",
"payload": {
"devices": [{
"id": "0",
"customData": {
"smartHomeProviderId": "FkldJVJCmDNSaoLkoq0txiz8Byf2Hr"
}
}]
}
}]
});
var xmlsend = "xmlHttp.send('" + json + "');";
var code = xmlhttp + '\n' + xmlopen + '\n' + xmlheaders + '\n' + xmlonload + '\n' + xmlsend;
return code;
}
} else {
var xmlhttp = "var xmlHttp = new XMLHttpRequest();";
var xmlopen = "xmlHttp.open('POST', " + URL + ", true);";
var xmlheaders = "xmlHttp.setRequestHeader('Content-type', 'application/json');\n" +
"xmlHttp.setRequestHeader('Authorization', 'Bearer psokmCxKjfhk7qHLeYd1');";
var xmlonload = "xmlHttp.onload = function() {\n" +
" console.log('recieved:' + this.response);\n" +
"}";
var json = JSON.stringify({
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"inputs": [{
"intent": "action.devices.QUERY",
"payload": {
"devices": [{
"id": "0",
"customData": {
"smartHomeProviderId": "FkldJVJCmDNSaoLkoq0txiz8Byf2Hr"
}
}]
}
}]
});
var xmlsend = "xmlHttp.send('" + json + "');";
var code = xmlhttp + '\n' + xmlopen + '\n' + xmlheaders + '\n' + xmlonload + '\n' + xmlsend;
return code;
}};
We actually use Promises extensively in our Blockly environment. My suggestion would be to Promisify this and then use a generator function. For example, we use the co library to wrap our generated code, then use yield statements for asynchronous values to make them behave synchronously. For example:
For a block setup similar to this --
The generated code would be something like this (simplified) --
co(function* () {
var getUsername;
// getFieldValue makes an asynchronous call to our database
getUsername = (yield getFieldValue("username", "my user record Id", "users"));
Promise.all(inputPromises)
let inputPromises = [];
inputPromises.push('User name is');
inputPromises.push(getUsername);
yield new Promise(function(resolve, reject) {
Promise.all(inputPromises).then(function(inputResults) {
let [TITLE, MESSAGE] = inputResults;
let activity = "toastMessage";
let LEVEL = "success";
try {
var params = {message: MESSAGE, title: TITLE, level: LEVEL};
interface.notification(params);
return resolve();
} catch(err) {
return reject(err);
}
}).catch(reject);
});
return true;
}
As you may have noticed, though, this isn't always as easy as just sticking a "yield" before the block. Depending on your setup, you may have to get more creative using Promise.all to get values in your block, etc. (We actually wound up editing a bunch of the Blockly core blocks to append 'yield' in front of inputs which had a "promise" type set amongst their output types in order to make this work, but based on your setup, this may be overkill.)
Obviously, you would need to make sure this was either transpiled or run in an environment which supports ES6.
Of course, once you enter an asynchronous setup, there's not really any going back -- co functions themselves return a Promise, so you will need to deal with that appropriately. But in general, we've found this to be a pretty robust solution, and I'm happy to help you figure it out in more detail.
You can have blocks that execute asynchronously without Promises, async functions, or callbacks by using the JS Interpreter (docs, GitHub), conveniently written by the same guy that created Blockly. JS Interpreter is a JavaScript-in-JavaScript implementation. This does mean there needs to be a lot of code to connect the functions/commands of the main JS VM to the interpreter's embedded implementation.
Blockly has a few demonstrations of doing this (src). In particular, you'll want to investigate async-execution.html and the wait block implementation. You can find the wait block running live here.
Conveniently, the interpreter's doc's section on External API happens to use XMLHttpRequest as its example implementation. This should should be a good starting point for your request block's implementation.

Javascript object set to another object is undefined

For my chrome extension, I have a function called storeGroup that returns an object. However, in function storeTabsInfo, when I call storeGroup and set it equal to another object, the parts inside the object are undefined. The object is being populated correctly in storeGroup, so I'm not sure why it's undefined?
function storeTabsInfo(promptUser, group)
{
var tabGroup = {};
chrome.windows.getCurrent(function(currentWindow)
{
chrome.tabs.getAllInWindow(currentWindow.id, function(tabs)
{
/* gets each tab's name and url from an array of tabs and stores them into arrays*/
var tabName = [];
var tabUrl = [];
var tabCount = 0;
for (; tabCount < tabs.length; tabCount++)
{
tabName[tabCount] = tabs[tabCount].title;
tabUrl[tabCount] = tabs[tabCount].url;
}
tabGroup = storeGroup(promptUser, group, tabName, tabUrl, tabCount); // tabGroup does not store object correctly
console.log("tabGroup: " + tabGroup.tabName); // UNDEFINED
chrome.storage.local.set(tabGroup);
})
})
}
function storeGroup(promptUser, group, name, url, count)
{
var groupObject = {};
// current count of group
var groupCountValue = group.groupCount;
var groupName = "groupName" + groupCountValue;
groupObject[groupName] = promptUser;
var tabName = "tabName" + groupCountValue;
groupObject[tabName] = name;
var tabUrl = "tabUrl" + groupCountValue;
groupObject[tabUrl] = url;
var tabCount = "tabCount" + groupCountValue;
groupObject[tabCount] = count;
var groupCount = "groupCount" + groupCountValue;
groupObject[groupCount] = groupCountValue + 1;
// successfully shows parts of groupObject
console.log("Final group: " + groupObject[groupName] + " " + groupObject[tabName] + " " + groupObject[tabUrl] + " " + groupObject[tabCount] + " " + groupObject[groupCount]);
return groupObject;
}
As i said in the comment above you created the groupObject dict keys with the group count so you should use it again to access them or remove it, if you want to use it again although i think this isnt necessary so use:-
... ,tabGroup[tabName + group.groupCount]...
But if you want to get it easily as you wrote just write this code instead of your code:-
function storeGroup(promptUser, group, name, url, count)
{
var groupObject = {};
// current count of group
groupObject['groupName'] = promptUser;
groupObject['tabName'] = name;
groupObject['tabUrl'] = url;
groupObject['tabCount'] = count;
groupObject['groupCount'] = group.groupCount + 1;
// successfully shows parts of groupObject
console.log("Final group: " + groupObject['groupName'] +
" " + groupObject['tabName'] + " " + groupObject['tabUrl'] +
" " + groupObject['tabCount'] + " " +
groupObject['groupCount']);
return groupObject;
}

wpf webbrowser javascript callback

if have javascript:
function calculateValues(callback)
{
window.external.getHistoryRange(0,1,"",function(res){
var hist = eval(res);
histCount = hist.historyCount;
hist = hist.historyContent;
if (histCount == 0)
{
return;
}
$("#history_table").show();
var $row = addAlertHistoryRow(hist[0]);
var rowHeight = $row.height();
pageItemsCount = Math.floor(contentHeight / rowHeight);
curPageNum = 0;
$row.remove();
if (callback) callback();
});
}
in function calculateValues(callback) callback parameter is:
function(){statItempos = 0; gethistoryandshow(pageNum,startItemsPos,callback);}
and c# code, that works with that script (ObjectForScripting):
public string getHistoryRange(string strVar0 = "", string strVar1 = "", string strVar2 = "", string strVar3 = "")
{
string res = "";
using (DeskAlertsDbContext db = new DeskAlertsDbContext())
{
var alerts = db.HistoryAlerts.OrderBy(a => a.ReciveTime)
.Include(b => b.alert.WINDOW)
.ToList();
foreach (var alert in alerts)
{
res += ("{\"id\":" + System.Web.HttpUtility.JavaScriptStringEncode(alert.alert.Alert_id) +
",\"date\":\"" +
System.Web.HttpUtility.JavaScriptStringEncode(
alert.ReciveTime.ToString(CultureInfo.InvariantCulture)) + "\",\"alert\":\"" +
System.Web.HttpUtility.JavaScriptStringEncode(alert.alerttext) + "\",\"title\":\"" +
System.Web.HttpUtility.JavaScriptStringEncode(alert.alert.Title) + "\",\"acknow\":\"" +
System.Web.HttpUtility.JavaScriptStringEncode(alert.alert.Acknown) + "\",\"create\":\"" +
System.Web.HttpUtility.JavaScriptStringEncode(alert.alert.Create_date) + "\",\"class\":\"" +
"1" + "\",\"urgent\":\"" + System.Web.HttpUtility.JavaScriptStringEncode(alert.alert.Urgent) +
"\",\"unread\":\"" + Convert.ToInt32(alert.isclosed).ToString() + "\",\"position\":\"" +
System.Web.HttpUtility.JavaScriptStringEncode(alert.alert.Position) + "\",\"ticker\":\"" +
alert.alert.Ticker + "\",\"to_date\":\"" +
System.Web.HttpUtility.JavaScriptStringEncode(alert.alert.To_date) + "\"},");
}
res = res.TrimEnd(','); //trim right ","
res = "({\"historyCount\":" + alerts.Count.ToString() + ",\"historyContent\":[" + res + "]});";
Browserwindow.Wb.InvokeScript("eval", new object[] { strVar3 });
Browserwindow.Wb.InvokeScript("CallbackFunction", new object[] { res });
return res;
}
}
On string: "Browserwindow.Wb.InvokeScript("eval", new object[] { strVar3 });"
I try to call anonymous function from javascript and have an error.
Question is: how to make this logic. How to perform the JS function of the parameters a different function. And then continue JS. If i tryed to give name to function, and invoke it, function works, but global context(if (callback) callback();) becomes unavailible
Your callback function name is not correct.
Replace
Browserwindow.Wb.InvokeScript("CallbackFunction", new object[] { res });
With
Browserwindow.Wb.InvokeScript("calculateValues", new object[] { res });
Hmmm... Just maked my variable dynamic (not string), and all worked
public string getHistoryRange(string strVar0 = "", string strVar1 = "", string strVar2 = "", dynamic strVar3 = null)
{
string res = "";
using (DeskAlertsDbContext db = new DeskAlertsDbContext())
{
var alerts = db.HistoryAlerts.OrderBy(a => a.ReciveTime)
.Include(b => b.alert.WINDOW)
.ToList();
foreach (var alert in alerts)
{
res += ("{\"id\":" + System.Web.HttpUtility.JavaScriptStringEncode(alert.alert.Alert_id) +
",\"date\":\"" +
System.Web.HttpUtility.JavaScriptStringEncode(
alert.ReciveTime.ToString(CultureInfo.InvariantCulture)) + "\",\"alert\":\"" +
System.Web.HttpUtility.JavaScriptStringEncode(alert.alerttext) + "\",\"title\":\"" +
System.Web.HttpUtility.JavaScriptStringEncode(alert.alert.Title) + "\",\"acknow\":\"" +
System.Web.HttpUtility.JavaScriptStringEncode(alert.alert.Acknown) + "\",\"create\":\"" +
System.Web.HttpUtility.JavaScriptStringEncode(alert.alert.Create_date) + "\",\"class\":\"" +
"1" + "\",\"urgent\":\"" + System.Web.HttpUtility.JavaScriptStringEncode(alert.alert.Urgent) +
"\",\"unread\":\"" + Convert.ToInt32(alert.isclosed).ToString() + "\",\"position\":\"" +
System.Web.HttpUtility.JavaScriptStringEncode(alert.alert.Position) + "\",\"ticker\":\"" +
alert.alert.Ticker + "\",\"to_date\":\"" +
System.Web.HttpUtility.JavaScriptStringEncode(alert.alert.To_date) + "\"},");
}
res = res.TrimEnd(','); //trim right ","
res = "({\"historyCount\":" + alerts.Count.ToString() + ",\"historyContent\":[" + res + "]});";
dynamic variable = Browserwindow.Wb.InvokeScript("eval", new object[] { strVar3 });
variable(res);
return res;
}
}

access an object in a function using javascript

I am new to JS and have created this original problem from CodeAcademy which works. Now I wanted to put my flock of sheep into an object and access it using my sheepCounter function. I am new to accessing key/values from an object and am stuck on what I am doing wrong. Thanks in advance!
Original Code
var sheepCounter = function (numSheep, monthNumber, monthsToPrint) {
for (monthNumber = monthNumber; monthNumber <= monthsToPrint; monthNumber++) {
numSheep *= 4;
console.log("There will be " + numSheep + " sheep after " + monthNumber + " month(s)!");
}
return numSheep;
}
New Code:
var flock = {
sheep: 4,
month: 1,
totalMonths: 12
};
var sheepCounter = function (counter) {
for (counter[month] = counter[month]; counter[month] <= counter[totalMonths]; counter[month]++) {
numSheep *= 4;
console.log("There will be " + counter[sheep] + " sheep after " + counter[month] + " month(s)!");
}
return counter[sheep];
}
Found the error in your solution:
var sheepCounter = function (counter) {
for (counter['month'] = counter['month']; counter['month'] <= counter['totalMonths']; counter['month']++) {
counter['sheep'] *= 4;
console.log("There will be " + counter['sheep'] + " sheep after " + counter['month'] + " month(s)!");
}
return counter['sheep'];
}
You can access your Flock Object like so,
alert(flock.sheep); //4
If you have an array in an object, like
names: ['joe','tom','bob'];
You would access that like so,
alert(flock.names[0]); // joe
alert(flock.names[2]); // bob

How can I compare these strings in jQuery?

This program right now reads in xml code, gets a stock abbreviation, alphabetically sorts them, and then prints them out in an uo list. If you hover over the abbreviations the color will change to red. The goal I'm having is when you hover over an abbreviation, it will show all the data from the xml data just for that company. I tried using the if statement saying if the symbol (abbreviation in xml file) is equivalent to the name (abbreviation in array) then it prints out all the junk for it. The line that prints everything out works correctly in the format I want. I just need to work on the if statement.
What I have figured out is I cannot compare two variables with the ==. Keep in mind symbol is an attribute as well, and name is from an array that stores the symbols. I also tried just saying - if(checkPassword(name, symbol)) - and print it all out as I did in the jQuery code below, but that did not work.
I put a comment next to the if statement I am working on, it's towards the bottom of the jQuery.
HTML:
<body onload="onBodyLoad()">
<div id="stockList"></div>
<br />
<br />
<br />
<div id="stockInfo"></div>
jQuery:
$(document).ready(function () {
$.ajax({
type: "GET",
url: "stocks.xml",
dataType: "xml",
success: function (xml) {
var companyNames = [];
$(xml).find('Stock').each(function () {
var symbol = $(this).attr('symbol');
companyNames.push(symbol);
});
companyNames.sort();
$.each(companyNames, function (index, name) {
$('#stockList').append('<div><li>' + name + '</li></div>');
});
function CheckPassword(val, val2) {
var strInput = val.value;
var strInput2 = val2.value;
if (strInput != strInput2) {
val2.focus();
val2.select();
return false;
} else
return true;
}
$(xml).find('Stock').each(function () {
var company = $(this).find('Company').text();
var symbol = $(this).attr('symbol');
var market = $(this).find('Market').text();
var sector = $(this).find('Sector').text();
var price = $(this).find('Price').text();
var low = $(this).find('Low').text();
var high = $(this).find('High').text();
var amount = $(this).find('Amount').text();
var yieldx = $(this).find('Yield').text();
var frequency = $(this).find('Frequency').text();
$('*').mouseover(function () {
$('#stockList li').text($(this).attr('comparison'));
});
$('#stockList li').hover(
function () {
$(this).css({ color: 'red' }); //mouseover
if (name == symbol) { // THIS IS THE STATEMENT YOU'RE LOOKING FOR PROGRAMMING GODS
$('#stockInfo').append('<div><ol><li>' + "Company = " + company + '</li><br/><li>' + "Market = " + market + '</li><br/><li>' + "Sector = " + sector + '</li><br/><li>' + "Price = " + price + '</li><br/><li>' + "Year Range = " + low + " " + high + '</li></ol><br/>');
}
},
function () {
$(this).css({ color: 'navy' }); // mouseout
$('#stockInfo').empty();
}
);
});
}
});
});
XML sample:
<Products>
<Stock symbol="GOOG">
<Company>Google</Company>
<Market>NASDAQ</Market>
<Sector>Software</Sector>
<Price>$487.80</Price>
<YearRange>
<Low>$331.55</Low>
<High>$488.50</High>
</YearRange>
<Dividend available="false"/>
</Stock>
<Stock symbol="BA">
<Company>Boeing Company</Company>
<Market>NYSE</Market>
<Sector>Aerospace</Sector>
<Price>$79.05</Price>
<YearRange>
<Low>$63.70</Low>
<High>$89.58</High>
</YearRange>
<Dividend available="true">
<Amount>$1.20</Amount>
<Yield>$1.50</Yield>
<Frequency>QTR</Frequency>
</Dividend>
</Stock>
<Stock symbol="MO">
<Company>Altria Group</Company>
<Market>NYSE</Market>
<Sector>Comsumables</Sector>
<Price>$81.70</Price>
<YearRange>
<Low>$68.36</Low>
<High>$85.00</High>
</YearRange>
<Dividend available="true">
<Amount>$3.44</Amount>
<Yield>$4.2</Yield>
<Frequency>ANNUAL</Frequency>
</Dividend>
</Stock>
</Products>
var companyData = [];
$(xml).find('Stock').each(function () {
var symbol = $(this).attr('symbol');
companyNames.push(symbol);
companyData[symbol] = {
company: $(this).find('Company').text(),
symbol: $(this).attr('symbol'),
market: $(this).find('Market').text(),
sector: $(this).find('Sector').text(),
price: $(this).find('Price').text(),
low: $(this).find('Low').text(),
high: $(this).find('High').text(),
amount: $(this).find('Amount').text(),
yieldx: $(this).find('Yield').text(),
frequency: $(this).find('Frequency').text()
};
});
...
$("#stocklist li").hover(function() {
$(this).css({ color: 'red' }); //mouseover
var info = companyData[$(this).text()];
$('#stockInfo').append('<div><ol><li>' + "Company = " + info.company + '</li><br/><li>' + "Market = " + info.market + '</li><br/><li>' + "Sector = " + info.sector + '</li><br/><li>' + "Price = " + info.price + '</li><br/><li>' + "Year Range = " + info.low + " " + info.high + '</li></ol><br/>');
});

Categories

Resources