I am making a website that grabs data from an API. The API essentially consists of a script normally ran as such
<script type="text/javascript" src="https://www.fxblue.com/users/dynascalp_demo/overviewscript"></script>
it will simply create an array and push the data I need from it, like this:
if (!document.MTIntelligenceAccounts) document.MTIntelligenceAccounts = new Array(); document.MTIntelligenceAccounts.push({ "userid": "dynascalp_demo","balance": 9275.95,"equity": 9275.95,"closedProfit": -724.05,"floatingProfit": 0,"freeMargin": 9275.95,"totalDeposits": 10000,"totalWithdrawals": 0,"totalBankedGrowth": -7.24,"monthlyBankedGrowth": -0.67,"weeklyBankedGrowth": -0.16,"dailyBankedGrowth": -0.03,"bankedProfitFactor": 0.66,"deepestValleyCash": -819.04,"deepestValleyPercent": -8.19,"troughInBalance": 9175.79,"peakInBalance": 10020.11,"historyLengthDays": 331,"averageTradeDurationHours": 2.17,"worstDayPercentage": -1.44,"worstWeekPercentage": -2.32,"worstMonthPercentage": -4.31,"tradesPerDay": 2.5,"totalClosedPositions": 589,"totalOpenPositions": 0,"bankedWinningTrades": 382,"bankedLosingTrades": 207,"bankedBreakEvenTrades": 0,"bankedWinPips": 1486.3,"bankedLossPips": -1604.6,"initialDeposit": 10000,"totalBankedPips":-118.3,"totalOpenPips":0,"peakPercentageLossFromOutset": -8.24,"riskReturnRatio": -1.21,"openAndPendingOrders": []});
My idea is to run this code conditionally, in another, bigger script. I will query my database and check whether the data is already in the database. If it is, then skip the request altogether and send the data from the database through an ajax request handled by the server, which will return a JSON. If it isn't or the data has expired, meaning it has not been updated for at least a day, it should grab the data from the API and update the database. This is done by the front-end as there is no Node.js support in the back-end.
The only thing I'm missing is how I should execute this script from mine, instead of calling it directly in the HTML.
For example, Fetch() does not work. I believe the request is malformed, or it is not the type of request it expects. Unexpected end of input is thrown and the request does not succeed.
This code should result in a number being shown
function fxBlue_retrieveAPI() {
document.MTIntelligenceAccounts = new Array();
const url = "https://www.fxblue.com/users/dynascalp_demo/overviewscript";
//var fxblue_API_Names = ["dynascalp_demo", "fxprogoldrobot", "fxprosilverrobot", "forex_gump_ea"];
var varNames = ["totalDeposits", "balance", "totalBankedGrowth", "monthlyBankedGrowth", "deepestValleyPercent", "historyLengthDays"];
var experts = [];
var s = document.createElement("script");
s.setAttribute("type", "text/javascript");
s.setAttribute("src", url);
document.body.appendChild(s);
for (var i = 0; i < document.MTIntelligenceAccounts.length; i++) {
experts.push({ name: document.MTIntelligenceAccounts[i].userid, id: i });
if (document.getElementById(experts[i].name + varNames[0])) { document.getElementById(experts[i].name + varNames[0]).innerHTML = document.MTIntelligenceAccounts[experts[i].id].totalDeposits; }
if (document.getElementById(experts[i].name + varNames[1])) { document.getElementById(experts[i].name + varNames[1]).innerHTML = document.MTIntelligenceAccounts[experts[i].id].balance; }
if (document.getElementById(experts[i].name + varNames[2])) { document.getElementById(experts[i].name + varNames[2]).innerHTML = document.MTIntelligenceAccounts[experts[i].id].totalBankedGrowth + "%" };
if (document.getElementById(experts[i].name + varNames[3])) { document.getElementById(experts[i].name + varNames[3]).innerHTML = document.MTIntelligenceAccounts[experts[i].id].monthlyBankedGrowth };
if (document.getElementById(experts[i].name + varNames[4])) { document.getElementById(experts[i].name + varNames[4]).innerHTML = document.MTIntelligenceAccounts[experts[i].id].deepestValleyPercent + "%" };
if (document.getElementById(experts[i].name + varNames[5])) { document.getElementById(experts[i].name + varNames[5]).innerHTML = document.MTIntelligenceAccounts[experts[i].id].historyLengthDays };
}
}
<script type="text/javascript" src="/cdn-cgi/scripts/API/jquery-3.1.1.min.js" async></script>
<script type="text/javascript" src="/cdn-cgi/scripts/API/test.js"></script>
<body onload="fxBlue_retrieveAPI()">
<h3>Total banked growth data example</h3>
<p id="dynascalp_demototalBankedGrowth"></p>
</body>
Assuming (or hoping) that you won't experience CORS problems with your data source (here at SO it is not possible to reach the source), you could do something like this to get to the actual contents of the script file:
const actualText=`if (!document.MTIntelligenceAccounts) document.MTIntelligenceAccounts = new Array();\ndocument.MTIntelligenceAccounts.push({\n"userid": "dynascalp_demo","balance": 9275.95,"equity": 9275.95,"closedProfit": -724.05,"floatingProfit": 0,"freeMargin": 9275.95,"totalDeposits": 10000,"totalWithdrawals": 0,"totalBankedGrowth": -7.24,"monthlyBankedGrowth": -0.67,"weeklyBankedGrowth": -0.16,"dailyBankedGrowth": -0.03,"bankedProfitFactor": 0.66,"deepestValleyCash": -819.04,"deepestValleyPercent": -8.19,"troughInBalance": 9175.79,"peakInBalance": 10020.11,"historyLengthDays": 331,"averageTradeDurationHours": 2.17,"worstDayPercentage": -1.44,"worstWeekPercentage": -2.32,"worstMonthPercentage": -4.31,"tradesPerDay": 2.5,"totalClosedPositions": 589,"totalOpenPositions": 0,"bankedWinningTrades": 382,"bankedLosingTrades": 207,"bankedBreakEvenTrades": 0,"bankedWinPips": 1486.3,"bankedLossPips": -1604.6,"initialDeposit": 10000,"totalBankedPips":-118.3,"totalOpenPips":0,"peakPercentageLossFromOutset": -8.24,"riskReturnRatio": -1.21,"openAndPendingOrders": []});`;
// fetch("https://www.fxblue.com/users/dynascalp_demo/overviewscript")
fetch("https://jsonplaceholder.typicode.com/users/3") // (some dummy data source for demo purposes only)
.then(r=>r.text())
.then(text=>{ text=actualText; // mimmic the text received from www.fxblue.com ...
obj=JSON.parse(text.replace(/(?:.|\n)*push\(/,"").replace(/\);$/,""))
console.log(obj)
})
It is then up to you to decide whether you want to use the data or not.
Whatever you do, it is important that the action happens in the callback function of the last . then() call. Alternatively you can of course also work with an async function and use await inside.
My idea is to run this javascript code conditionally, by querying my database
For this you could do an jquery ajax call, and act based on the response you get. I recommend using jquery for the ajax call. Here is the jquery ajax call where you pass whatever data is necessary to the controller.
$.ajax({
type: "GET",
url: "/ControllerName/ActionName",
data: { data: UserIdOrSomething },
success: function(response) {
// you can check the response with an if, and implement your logic here.
}
});
You can place this ajax call in the document.ready function to automatically call it whenever the page loads.
$( document ).ready(function() {
// place the above code here.
});
As an example, here is how an asp.net core controller action would look like that would handle this ajax call;
[HttpGet("ActionName/{data:string}")]
public IActionResult ActionName(string data) // parameter name should match the one in jquery ajax call
{
// do stuff. query your database etc.
var response = "the response";
return Json(response);
}
finally, keep in mind handling sensitive data in javascript is generally not a good idea, as the javascript code is open to everyone. For example, in this case, you will be giving out a way for people to check if a user exists in your database, which could be problematic. I would suggest using guid as id for the users table if possible, which may or may not be useful to mitigate the dangers depending on how you query the database.
I have an Input that takes a name, and I want to take that name from input and set the url accordingly .. Here's the code, and an example
.form-group
%input.form-control{'type':'name','placeholder':'Name',id:'wisher_name'}
%input.form-control{'type':'name','placeholder':'Special Message'}
%button.btn.btn.btn-success{'id':'wisher_btn'} Wish
Javascript
$(document).ready(function() {
$(document).on('click', '#wisher_btn', function() {
var e = document.getElementById("wisher_name");
var diwali_wisher = e.value
location.replace("localhost:3000" + "/loccasion/diwali/" + diwali_wisher);
});
});
But the last statement is never reached, I don't know why?
This is a very basic problem, but I am a beginner so need some help.
You need to use a full url, like https://stackoverflow.com.
Add the http protocol.
diwali_wisher= Input parameter name in receiver function
diwali_wisher = e.value
location.replace("localhost:3000" + "/loccasion/diwali?diwali_wisher=" + diwali_wisher);
I have a form inside my page for user that want to register inside the site. After registration I insert user inside database create an activation key and send an email, until user doesn't click the link inside the email with the activation key he can't login inside the site.
With CasperJS I would like to test this functionality, the fillForm is ok but how can I test the activation key?
I have thought to create an input hidden with the activation key (only if is in TEST mode not i production!) and retrieve this value with getFieldValue function.
Is this the right way to do it or there is a better mode to do?
this is my casperjs test to retrieve activation key after registration (I create an input hidden with the activation code):
view = 'users/registered';
casper
.start(webroot + view)
.then(function() {
__utils__.log("Retrieving data from input activation-key");
activationKey = __utils__.getFieldValue('activation-key');
}).then(function() {
__utils__.log("Activating account with the key " + activationKey);
}).then(function(){
this.evaluate(function() {
__utils__.log("Activating account with the key " + activationKey);
window.location = webroot + 'users/activate/' + activationKey;
});
}).then(function(){
this.echo(this.getCurrentUrl());
});
casper.run(function() {
this.echo('test registeration successful!').exit();
});
casper.viewport(page.width, page.height);
casper.test.done();
I managed to do what i wanted with registration, it could help you : CasperJS- Register on a site and validate the mail sent on Gmail -for both slimer and phantom-
And before i did some scraping with an activation code too, for manual activation (pure JS, no jQuery here, i didn't want to inject JQuery on gmail DOM environment) :
this.waitForSelector("div.msg",function(){
this.test.assertSelectorHasText("a","Activation message");
//var code declared in the main scope
code = this.evaluate(function(){
var strongs = document.getElementsByTagName('strong')
,i
,l = strongs.length
;
for (i = 0; i < l; ++i) {
if(strongs[i].textContent === "activation code:"){
//get back the code in DOM context -> split to get back only what I want
return (strongs[i].parentNode.textContent.split(' ')[2]);
}
}
});
this.echo("code : " + code,"INFO");
});
I have been trying to put together a proof of concept of JavaScript talking to Flash. I am using JQuery and Flash CS5, ActionScript 3.
I am not a Flash developer so apologies for the code, if I can prove this works the Flash will be given to someone who knows what they are doing.
The Actionscript is on a layer in the timeline in the first frame, with a couple of elements in the root movie:
output = new TextField();
output.y = -200;
output.x = -200;
output.width = 450;
output.height = 325;
output.multiline = true;
output.wordWrap = true;
output.border = true;
output.text = "Initializing...\n";
root.bgClip.addChild(output);
try{
Security.allowDomain("*");
flash.external.ExternalInterface.marshallExceptions = true;
output.appendText("External Interface Available? " + ExternalInterface.available + "\n");
output.appendText("External Interface ObjectId: " + ExternalInterface.objectID + "\n");
flash.external.ExternalInterface.addCallback("getMenuItems", returnMenuItems);
flash.external.ExternalInterface.addCallback("changeText", changeText);
flash.external.ExternalInterface.addCallback("changeBgColour", changeBgColour);
flash.external.ExternalInterface.call("populateMenu", returnMenuItems());
} catch (error:SecurityError) {
output.appendText("Security Error: " + error.message + "\n");
} catch (error:Error) {
output.appendText("Error: " + error.message + "\n");
}
function returnMenuItems():String{
return "[{\"menu option\": \"javascript:callFlash('changeBgColour','4CB9E4')\"}]";
}
function changeText(t:String){
root.textClip.text = t;
}
function changeBgColour(colour:String) {
var c:ColorTransform = root.bgClip.transform.colorTransform;
c.color = uint(colour);
root.bgClip.transform.colorTransform = c;
}
The JavaScript and HTML are:
function populateMenu(message){
$("#options").changeType("Options", $.parseJSON(message));
$("#options").addMenuActions();
}
function callFlash(methodToCall, param){
alert("method: " + methodToCall + ", param: " + param);
if(param == undefined){
$("#AJC")[methodToCall]();
}else{
$("#AJC")[methodToCall](param);
}
}
var flashvars = {};
var params = {allowScriptAccess: "always"};
var attributes = {name: "AJC"};
swfobject.embedSWF("http://192.168.184.128/ActionscriptJavascriptCommunication.swf", "AJC", "600", "400", "9", "", flashvars, params, attributes);
and
<body>
<div id="wrapper">
<div id="topBar" class="top-bar"></div>
<div id="flashContainer">
<div id="AJC">Loading Flash...</div>
</div>
<ul class="dropdown" id="games"></ul>
<ul class="dropdown" id="options"></ul>
</div>
</body>
Now I know the ActionScript is awful, the reason it looks like it does is because I have read a lot of threads about possible issues to do with contacting Flash from JavaScript (hence the allow security domain * and adding a debug text box etc).
The JavaScript I am using is within a script tag in the head. The changeType and addMenuActions are just JQuery methods I have added. These are just JavaScript methods that have been tested independently but do work.
You'll notice that the last line of my try catch in the ActionScript is:
flash.external.ExternalInterface.call("populateMenu", returnMenuItems());
This does work, it populate my menu with the text sent from Flash. The only thing that doesn't work is trying to call the methods exposed using the addCallback function.
I get the alert which says:
method: changeBgColour, param: 4CB9E4
but an error saying:
Error: $("#AJC")[methodToCall] is not a function
Source File: http://192.168.184.128/test.html#
Line: 88
I set up a local VM to run Apache, which relates to the 192.168.184.128, I wondering if this was the issue, I have seen a couple of threads mention that trying to communicate with flash locally won't work, which is why I set up the VM with apache?
Any ideas? I know people have got this working, it is very frustrating.
Thanks.
Simple mistake: jQuery's factory method produces jQuery.init object, which acts very similar to an array. You need to call the method on the actual DOM element, which is the first member in the "array".
$('#AJC')[0][methodToCall]
If you had security issues, you wouldn't be able to communicate between Flash and JavaScript at all.
The problem is in the way you are accessing your flash object. SwfObject has a built-in function that take care of that, it works great across all browsers:
function callFlash(methodToCall, param)
{
var obj = swfobject.getObjectById("AJC");
if(param == undefined){
$(obj)[methodToCall]();
}else{
$(obj)[methodToCall](param);
}
}
I havent tested the code above, but I guess it should work!
I have a Toogle function that uses to show/hide a div bloack to end users. However, some users said the IE generate an error when they clicks on this link. I am wondering whether I can use try catch statement in JavaScript to catach the error the users got and send to Googel Analytics.
If Yes, How I can do that. I have google analytcis set up in our site.
For instance, I have a div section call dynamic phone number.
<div id = "cs_DynamicForm">
"Phone number..."
<div>
When users click on Phone us link, i am able to track it in google.
<a onclick="javascript: pageTracker._trackPageview('/Contact/UK/phone');" id="phoneNumberToggle" class="more-info-link" href=" javascript:void(0);">Phone us</a>
In the back end, my toggle function works, like that
_dynamicPhoneNumber: function(type, arg)
{
var phoneNumber = document.getElementById("cs_DynamicForm");
var vis =phoneNumber.style;
//alert(vis);
if(vis.display==''&&phoneNumber.offsetWidth!=undefined&&phoneNumber.offsetHeight!=undefined)
vis.display = (phoneNumber.offsetWidth!=0&&phoneNumber.offsetHeight!=0)?'block':'none';
vis.display = (vis.display==''||vis.display=='block')?'none':'block';
}
If i have to rewrite this function, i think it will look likes that:
try{
var phoneNumber = document.getElementById("cs_DynamicForm");
var vis =phoneNumber.style;
//alert(vis);
if(vis.display==''&&phoneNumber.offsetWidth!=undefined&&phoneNumber.offsetHeight!=undefined)
vis.display = (phoneNumber.offsetWidth!=0&&phoneNumber.offsetHeight!=0)?'block':'none';
vis.display = (vis.display==''||vis.display=='block')?'none':'block';
}
catch (e)
{
var errorMsg=e.message;
if (typeof (e.number) != "undefined") {
document.write ("<br />");
document.write ("The error code: <b>" + e.number + "</b>");
}
if (typeof (e.lineNumber) != "undefined") {
document.write ("<br />");
document.write ("The error occurred at line: <b>" + e.lineNumber + "</b>");
}
//And send the errorMsg to google analytics. how I should do that
}
Any helps,
Cheers,
Qing
first catch the error simply like:
try {
tes.ting = 123;
}
catch(e) {
errors.push(e);
}
then push it to Google
_gaq.push(['_trackEvent', 'Testing', 'Error', errors.toString()]);
You can use the trackEvent as has been pointed here - but I believe the easiest way is to use trackPage, as you did for the other pages.
I use something like this:
try {
...
} catch (e)
{
pageTracker._trackPageview('/errors/'+e.toString());
}
You can replace 'errors/' with whatever makes sense to you ('virtual-errors-list/' for example).
In addition, consider adding the error tracking to window.onerror handler:
window.onerror = function(errorMsg, url, lineNumber){
pageTracker._trackPageview('/errors/'+errorMsg);
}