passing JavaScript array of long to code behind? - javascript

I have returned object from signature device and when i make quick watch on it, it told me that its an array of long and when i pass it to web method in my code behind (vb.net) it gives me nothing.
i need some help..
note: i'm using an activeX to capture the signature from the device.
this is javascript code :
function OnSave() {
var sign = document.FORM1.SigPlus1.SignatureString;
PageMethods.Save(sign);
}
this is my webmethod:
<WebMethod()> _
Public Shared Function Save(ByVal obj As Object) As String
Dim obj1 As New PFSIGNATURELib.SigniShellSignature
obj1.SignatureMime = obj
obj1.SaveBitmapToFile(System.AppDomain.CurrentDomain.BaseDirectory() & "\sign1.bmp", 200, 200)
Return "\sign1.bmp"
End Function

I don't know much about ASP.Net, but it seems like the PageMethods.Save function can't handle an array of long. Another possibility is that the sign variable is null in the javascript code.
Try adding
alert(sign);
in the middle your Javascript function, or better yet, install firebug and do
console.log(sign);
instead. This way you'll make sure the sign var actually contains what you think it does.
If it indeed contains an array of numbers (javascript doesn't have a long type), maybe you need to convert it to something else before calling the PageMethods.Save function.
For example, this javascript snippet will convert sign into a space-separated string of numbers:
s = ""
for (i in sign) {
s += sign[i] + " ";
}
sign = s
If you manage to pass this string to your webmethod, you can use some string parsing to get back the original array.

Related

How do I create a custom javascript variable that selects part of an already existing javascript variable?

I am trying to create a custom javascript variable in GTM that returns part of a javascript variable that already exists.
Variable that already exists: window.ShopifyAnalytics.meta.product.variants.0.name
returns this: "Bamboo Basic String - Schwarz - S"
However I want to code a custom javascript variable to just return the Schwarz part, is this possible? If so what is the code that I would need?
Please can someone let me know what code to put into GTM to create this variable?
TIA
If all names are pretty much the same you could use split to get that part of string and then remove whitespaces. It would look like this:
window.ShopifyAnalytics.meta.product.variants.0.name.split('-')[1].replace(/
/g,'');
If the already existing variable is always structured the same way you could do something like this:
let variable = window.ShopifyAnalytics.meta.product.variants.0.name.split('-')
Then by calling varaible[1] you get the 'Schwartz' part of the variable.
If you want a return value you can use a function like the following and call it wherever you want.
Simply make sure to pass the correct argument content
// Declaring a function getColor that returns the second element in the list,
// trimmed (without spaces before and after)
const getColor = (content) => {
return content.split('-')[1].trim();
}
const test = "Bamboo Basic String - Schwarz - S";
console.log(getColor(test));
//console.log(getColor(window.ShopifyAnalytics.meta.product.variants.0.name));
You could split the string on the hypens (-) like this:
const productName = window.ShopifyAnalytics.meta.product.variants.0.name;
const part = productName.split(' - ')[1];
Assuming you have a consistent format, and you always want the second part after that hyphen.
split will separate parts of a string into an array where it finds a match for the argument. The first index [0] will be the product name, the second [1] will be the part you're looking for.
This could cause issues if you have a product name with a - in it too though so use with care!
If it needs to be an anonymous function for GTM, you could try the following (though I'm not a GTM expert):
function () {
const productName = window.ShopifyAnalytics.meta.product.variants.0.name;
return productName.split(' - ')[1] || 'Unknown';
}

Jint (.NET javascript parser) always returns ExpandoObject

I try to write a mod for a game. This is totally new territory for me, so I might be on the wrong track here.
The game is written in Unity and you are able to add a .script file to your mod. The .script file can contain javascript that is parsed by Jint.
I tried to output a simple string from one of the game DLLs:
var UnityEngine = importNamespace("UnityEngine");
var IceEngine = importNamespace("IceEngine");
var GameMain = importNamespace("GameMain");
var output = GameMain.Game.ModPath;
UnityEngine.Debug.Log("----- Testmod Output Start-----");
UnityEngine.Debug.Log(output);
UnityEngine.Debug.Log("----- Testmod Output End-----");
In the GameMain.dll it says:
public class Game : MonoBehaviour, IUserManagerListener, IAccountMsg, IMsg, IRenderListener
{
private static string modPath = Game.userPath + "/Mods";
// lots of other code...
public static string ModPath
{
get
{
return Game.modPath;
}
}
My understanding is that GameMain.Game.ModPath should give me a string. But instead the output in the log file is this:
----- Testmod Output Start-----
System.Dynamic.ExpandoObject
----- Testmod Output End-----
No matter wehat I try to output, I get a System.Dynamic.ExpandoObject and don't know what to do with it.
Maybe someone can give me tips/resources to help. :)
The ExpandoObject is the nearest equivalent that .Net has for a JavaScript Object - that is an object to which members can be added or removed on-the-fly.
This suggests to me that the underlying JavaScript method is actually returning an object rather than a string.
You can use Newtonsoft.Json to serialize the object:
var json = (string)JsonConvert.SerializeObject(GameMain.Game.ModPath);
Which will allow you to see if there's a property you should be using. So let's say this gives you {"modPath":"..."}, you should access that property directly like this:
var modPath = (string)GameMain.Game.ModPath.modPath;

Node.JS - Filename won't accept a variable

doesn't work:
console.log(obj.html_template); // outputs "myfile.html"
var html = fs.readFileSync(JSON.stringify(obj.html_template)); // file not found.
works:
console.log(obj.html_template); // "myfile.html"
var html = fs.readFileSync("myfile.html"); // Works.
I'm going crazy.
> JSON.stringify('myfile.html')
""myfile.html""
Your code is looking for the file "myfile.html" (note the superfluous quotes) in the filesystem. It doesn't exist.
Just look for it without stringification:
var html = fs.readFileSync(obj.html_template);
When you call JSON.stringify, it will convert all the Strings to the JSON format Strings, with surrounding double quotes. Quoting ECMAScript 5.1 Specification for JSON.stringify,
If Type(value) is String, then return the result of calling the abstract operation Quote with argument value.
And the Quote operation, is defined here, which basically surrounds the string with " and takes care of special characters in the String.
So JSON.stringify converts, a string, for example, abcd.txt to "abcd.txt", like this
console.log(JSON.stringify("abcd.txt"));
// "abcd.txt"
which is not equal to abcd.txt.
console.log(JSON.stringify("abcd.txt") == "abcd.txt");
// false
but equal to "abcd.txt".
console.log(JSON.stringify("abcd.txt") == '"abcd.txt"');
// true
So, your program searches for a file named "abcd.txt" instead of abcd.txt. That is why it is not able to find the file and fails.
To fix this problem, just drop the JSON.stringify and pass the string directly, like this
var html = fs.readFileSync(obj.html_template);
why are you using JSON.stringify in the first place? you should be able to just do
var html = fs.readFileSync(obj.html_template);

Need to get an array of the names of all applicationScope variables

In an application I am working on I need to get a list of the names of all applicationScope variable then I need to cycle through them and filter out the ones starting with a know string say $xyx. I thought that the applicationScope.keySet().
I'm using this code for starter:
var col = applicationScope.keySet();
var itr:java.util.Iterator = col.iterator();
if (itr.hasNext()){
var str:String = itr.next();
dBar.info(str,"Value = ");
}
if I put the variable col in a viewScope it shows a list of all the keys. but when I run the script the values displayed in the dBar info are not the keys but some other information that I'm not sure where it comes from.
I should just be able to iterat through the list of keys, am I missing something?
This code is in the before page loads event
After some poking around and experimenting I got this to work:
var col = applicationScope.keySet();
var itr:java.util.Iterator = col.iterator();
while (itr.hasNext()){
var str:Map.Entry = itr.next();
if (str.substring(0,9) == "$wfsLock_"){
//do stuff
}
}
so I'm now a happy camper.
Although your code works in SSJS, it is not correct (and that's why I don't like SSJS...).
The applicationScope is an implementation of the java.util.Map interface and the keySet() method returns a Set containing the keys in that Map. Every entry is (probably) a String (other data types like integers are actually also valid). The line
var str:Map.Entry = itr.next();
doesn't cast it to a Map.Entry: it doesn't really do anything: str remains a string.
The Map interface also has an entrySet() method that returns the entries (Map.Entry). You can use that to retrieve the key as well as the value:
var it = applicationScope.entrySet().iterator();
while (it.hasNext()) {
var entry = it.next();
print( entry.getKey() + " = " + entry.getValue() );
}
(in this code the print() line will use the toString() method of the key as well as the value to send information to the console)
I see from your code that you've installed my XPages Debug Toolbar. You can also use that to quickly check what's in the scopes and what the actual datatype is.

call JS function via url

i got a got a little embedded system that can be controlled via a webinterface.
the page looks like:
...
foo
...
is there a way to call this function just by http? like
http://<the-devices-ip>:80/javascipt:foo(bar) //wrong
thank you
You can do so by passing a querystring or a hash into the URL and execute a piece of JS which checks it during onload.
var query = window.location.search; // Gets '?foo=bar' from http://example.com/page.html?foo=bar
var hash = window.location.hash; // Gets '#foo' from http://example.com/page.html#foo
You only have to parse it further yourself or by using a 3rd party JS framework with plugin capabilities, like jQuery.
page1.html:
foo
page2.html:
<script type="text/javascript">
if(window.location.hash)
eval(window.location.hash)
</script>
I'm not saying it's a good idea. It might be helpful to document why you think you need to do this, there are probably better ways to accomplish whatever the actual goal is.
Note that doing this will not allow you to pass variables around. You need to have only static values in the javascript code executed on page2.html, or generate the href in page1.html dynamically.
Caveat: this will potentially open up your code to HTML and/or script injections. Filter rigorously.
I recently had to do something similar for a project that I was contracted out on. Like others, I used the hash portion of the URL to pass in JavaScript functions and parameters. However, the main difference was that I didn't do a simple eval of the entire string. I established a specific format to 1) narrow the amount of functions that could be executed, and 2) sanitize any input that the method required
The format, in full, is as follows:
http://somedomain.tld/path/?query=blah#specific.controller.object/method/['array', 'of', {json: 'arguments'}]
So, basically, you end up with the following string:
specific.controller.object/method/['array', 'of', {json: 'arguments'}]
I then wrote a parser to handle this string. Restrictions where exacted over what objects could be called by prepending with a sort of "namespace" object, in other words, calling it as part of a member of an existing, predetermined static object. For example, specific.controller.object, would be called as new com.project.specific.controller.object();. Here's something similar to my parser:
var data = location.hash.substr(1).split('/'),
controller = ("my.namespace." + data[0]).split("."),
// You can provide a default method if you want, my framework used `show`
method = data[1] || "show",
// must be an array for use with `apply`
params = data[2] || "[]";
// Parse the controller to find the appropriate object to instantiate.
// All objects are in reference to the global window object. Break
// them apart by their dot composition and step down through the object
// tree starting at window.
var composition = window;
for ( var i=0; i<controller.length; i++ ) {
composition = composition[ controller[i] ];
}
var obj = new composition;
// Handle the parameters. It may be the case that there "/" is present
// in the last argument. If so, add anything that was left out.
if ( data.length > 3 ) {
for ( var i=3; i<data.length; i++ ) {
params += '/' + data[i];
}
}
// Convert params from a string to an array.
// ***Possible injection point here***
params = dojo.fromJson(params);
// Make sure that the method runs in the proper context and
// pass it all of the parameters
obj[method].apply(obj, params);
Because the way the parser works, you required to provide parameters if none are needed, and in some cases, if you choose to allow default methods as I have, you don't have to specify which member on the object to call, which simplifies that construction of these URL's greatly.
Instead of using a static namespace object to restrict what objects could be instantiated, it would be trivial to use a white list of safe objects and methods.
foo represents the calling of a function, not the call to a url. There is no direct mapping between a url and a JavaScript function.

Categories

Resources