Object doesn't support this property or method in JavaScript - javascript

Okay, so I think I'm derping here again.. I'm using this code in a HTA (for a intranet application) instead of using just a normal HTML page.. when I "submit" my code I get the error message "Object doesn't support this property or method on line: 24 (which is where I close my file (via activexobjects)
HTML page uses:
<input name="Button1" type="button" value="Submit" onclick="getFormContent()" />
My Javascript file (external .js page) :
// Global Variables First!
var AllFormContent
var ManagerValue
function managerValueTrue(ManagerValue) {
ManagerValue = "Yes"
}
function managerValueFalse(ManagerValue) {
ManagerValue = "No"
}
function getFormContent(ManagerValue) {
var Mudkips = document.getElementById('ManagerName');
var ManagerName = Mudkips.options[Mudkips.selectedIndex].text;
var RandomText = document.getElementById('RandomText').value;
var Comment = document.getElementById('Comments').value;
AllFormContent = ManagerName + ", " + ManagerValue + ", " + RandomText + ", " + Comments
writeMyFile();
}
function writeMyFile(AllFormContent) {
var filesys = new ActiveXObject("Scripting.FileSystemObject");
var filetxt = filesys.OpenTextFile("C:\\MyFile.csv", 8) ;
filetxt.WriteLine(AllFormContent);
filetxt.Close;
}
"line 24" refers to "filetext.close" though I imagine it might have to do with "AllFormContent" or a previous line? I've tested the code, I know I get to the writeMyFile function, I know the ActiveXObject works fine.. Any ideas on what I'm derping with here?
Thanks :]

As everyone suggested in the comments but didn't answer, just add parantheses to Close at writeMyFile().
function writeMyFile(AllFormContent) {
var filesys = new ActiveXObject("Scripting.FileSystemObject");
var filetxt = filesys.OpenTextFile("C:\\MyFile.csv", 8) ;
filetxt.WriteLine(AllFormContent);
filetxt.Close();
}
Close is a method of the Scripting.FileSystemObject in JavaScript while it's more like a subprocedure for VBScript. To call functions and methods in JavaScript, you have to close the reference with parantheses while in VBScript it is unnecessary to call a Sub with parantheses and with multiple params it even gives an error (I think?).
There is not alot of documentation for JScript and the ActiveXObjects for WScript, most of it is covered in VBScript so there is often confusion in this aspect.

Related

D365 Error when calling function from another JS

I am having an issue calling JS function from another JS file.
Main JS where the function is defined.
var Common = Common || {};
Common.BaseAction = Common.BaseAction || {};
Common.BaseAction.SetNotification = function (message, level, uniqueId)
{
Xrm.Page.ui.setFormNotification(message, level, uniqueId);
}
Common.BaseAction.clearNotification = function (uniqueId) {
Xrm.Page.ui.clearFormNotification(uniqueId);
}
JS from where I am calling the function
var apItem = apItem || {};
apItem.BaseForm = apItem.BaseForm || {};
apItem.BaseForm.SetName = function ()
{
var bookName = Xrm.Page.getAttribute("ap_bookid").getValue()[0].name;
var condition = Xrm.Page.getAttribute("ap_condition").getText();
if (bookName !== null && condition !== null) {
Xrm.Page.getAttribute("ap_name").setValue(bookName + " - " + condition);
}
}
apItem.BaseForm.CountOverDueBy = function() {
var rentedTill = Xrm.Page.getAttribute("ap_rented_till").getValue();
var nowD = Date.now();
if (rentedTill !== null) {
var overdueBy = parseInt((Date.now() - rentedTill) / 86400000);
if (overdueBy > 0) {
Xrm.Page.getAttribute("ap_overdue_by").setValue(overdueBy);
Common.BaseAction.SetNotification("Book is Overdue by " + overdueBy
+ " Days.", "WARNING", "OverDueWarning");
}
else {
Xrm.Page.getAttribute("ap_overdue_by").setValue(null);
Common.BaseAction.clearNotification("OverDueWarning");
}
}
}
In the entity's form, I have added both above files with common.js being at the top and from the event handler I am calling function apItem.BaseForm.CountOverDueBy
Save + Published and Ctrl + F5 gives following error
ReferenceError: Common is not defined
at Object.apItem.BaseForm.CountOverDueBy (https://<domain>/%7B636651014350000438%7D/WebResources/ap_ItemFormBase.js?ver=2091450722:24:13)
at eval (eval at RunHandlerInternal (https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:153:1), <anonymous>:1:17)
at RunHandlerInternal (https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:159:1)
at RunHandlers (https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:118:1)
at OnScriptTagLoaded (https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:233:1)
at https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:202:1
I have tried everything but nothing seems to be working.
The way you register the JS files in form, starting from common.js on top & then ap_ItemFormBase.js should work. But product team made few performance improvements around script files like lazy script loading/parallel script loading. This is little tricky & modern scripting is messy between different clients like UUI & web.
Like explained in blog post, if you set the pre-requisite js as dependency, it will load before you consume it in dependent files.
Open the ap_ItemFormBase.js web resource from solution (not from Form Properties), go to Dependencies tab & add the common.js. This will make sure file is ready before reference is used.

In Karate DSL, calling a javascript file returns java.lang.RuntimeException

I have a javascript file I want to call. contents are below. When I tried calling the file, I keep getting a "no variable found with name: response" even though there is clearly a variable defined. The file executes fine within command-line using node so the javascript function is valid. Any thoughts? I attached the error message in a screenshot.
Javascript content in snippet below.
Karate script:
Scenario: Call JavaScript:
* def sample = read('classpath:reusable/gen-data.js')
* print someValue
function createTestData(sampleJson, fieldsToChange, numRecords) {
var testData = [];
for (var i = 0; i < numRecords; i++) {
var copy = JSON.parse(JSON.stringify(sampleJson));
fieldsToChange.forEach(function(fieldToChange) {
copy[fieldToChange] = copy[fieldToChange] + i;
});
testData.push(copy);
}
return {content: testData};
}
var testData = {
"country": "US",
"taskStatusCode" : "Closed",
"facilityCode" : "US_203532",
};
function getTestData() {
String testData = JSON.stringify(createTestData(testData, ["taskStatusCode", "facilityCode"], 1), null, 1);
console.log("all done getTestData()");
console.log("test data: \n" + testData);
return testData;
};
console.log("calling getTestData()");
getTestData();
I think this error is thrown when the JavaScript is not correct. For example in my case this JS file:
/* Set the custom authentication header */
function fn() {
var authToken = karate.get('authToken');
var out = {};
out['Auth-Token'] = authToken
return out;
}
This file will produce the "no variable found with name: response".
The reason is because "the right-hand-side (or contents of the *.js file if applicable) should begin with the function keyword." according to the karate docs (link).
Now by moving the comment and making the function keyword the first bit of text it works as expected:
function fn() {
/* Set the custom authentication header */
var authToken = karate.get('authToken');
var out = {};
out['Auth-Token'] = authToken
return out;
}
In the OP, the function keyword is the first thing in the file, but there is javascript outside the original function -- which I don't think is legal for karate syntax. In other words, everything has to be in the outer function.
My workaround was to use java instead of JavaScript.

.gBrowser is undefined

I'm writing a restartless Firefoxextension where I have to enumerate all open tabs and work with them.
Here's the code-part that throws the error:
getInfoString : function ()
{
infos = "";
HELPER.alerting("url", "URL-Function");
var winMediator = Components.classes["#mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
HELPER.alerting("url", "Mediator initialized");
var mrw = winMediator.getEnumerator(null);
while(mrw.hasMoreElements())
{
var win = mrw.getNext();
var t = win.gBrowser.browsers.length;
HELPER.alerting("url", "browsers: " + t);
for (var i = 0; i < t; i++)
{
var b = win.gBrowser.getBrowserAtIndex(i);
if(b.currentURI.spec.substr(0,3) != "http")
{
continue;
}
HELPER.alerting(b.title,b.currentURI.spec);
var doc = b.contentDocument;
var src = doc.documentElement.innerHTML;
infos = infos + src
HELPER.alerting("doc", src);
}
}
return infos;
}
I have a JavascriptDebugger-Addon running while testing this and Firefox executes everything fine to the line
HELPER.alerting("url", "browsers: " + t);
But AFTER this line, the debugger-addons throws an error, saying that:
win.gBrowser is undefined
... pointing to the line:
var t = win.gBrowser.browsers.length;
But before it throws the error I get my alertmessage which gives me the correct number of tabs. So the error is thrown after the line was executed and not directly WHEN it was executed.
Does anyone has an idea how to fix this, because the extension stops working after the error has been thrown.
Greetz
P.S.: If someone has a better headline for this, feel free to edit it.
Using winMediator.getEnumerator(null) would give you all types of window, that may or may not be browser windows. You should try changing the following line
var mrw = winMediator.getEnumerator(null);
with
var mrw = winMediator.getEnumerator('navigator:browser');
I finally figured out that this behavior can happen sometimes.
I just rearranged the code a bit, removing some alerts inside the for-loop and it works just fine again.
So if someone has this error too, just rearrange your code and it should work like a charm again.

Including objects from external .js files

I have been searching for many hours over several days for this answer and though there are many topics on how to include files in a project (also here at Stack Overflow), I have not yet found THE solution to my problem.
I'm working on a project where I want to include one single object at a time, from many different files (I do not want to include the files themselves, only their content). All the object in all the files have the same name, only the content is different.
It is important that I do not get a SCRIPT tag in the head section of the page as all the content from the files will have the same names. None of the files will have functions anyways, only one single object, that will need to be loaded one at the time and then discarded when the next element is loaded.
The objects will hold the data that will be shown on the page and they will be called from the menu by an 'onclick' event.
function setMenu() // The menu is being build.
{
var html = '';
html += '<table border="0">';
for (var i = 0; i<menu.pages.length; i++)
{
html += '<tr class="menuPunkt"><td width="5"></td><td onclick="pageName(this)">'+ menu.pages[i] +'</td><td width="5"></td></tr>';
}
// menu is a global object containing elements such as an array with
// all the pages that needs to be shown and styling for the menu.
html += '</table>';
document.getElementById("menu").innerHTML = html;
style.setMenu(); // The menu is being positioned and styled.
}
Now, when I click on a menu item the pageName function is triggered and I'm sending the HTML element to the function as well, it is here that I want the content from my external file to be loaded into a local variable and used to display content on the page.
The answer I want is "How to load the external obj into the function where I need it?" (It may be an external file, but only in the term of not being included in the head section of the project). I'm still loading the the file from my own local library.
function pageName(elm) // The element that I clicked is elm.
{
var page = info.innerHTML; // I need only the innerHTML from the element.
var file = 'sites/' + page + '.js'; // The file to be loaded is created.
var obj = ?? // Here I somehow want the object from the external file to be loaded.
// Before doing stuff the the obj.
style.content();
}
The content from the external file could look like this:
// The src for the external page: 'sites/page.js'
var obj = new Object()
{
obj.innerHTML = 'Text to be shown';
obj.style = 'Not important for problem at hand';
obj.otherStuff = ' --||-- ';
}
Any help will be appreciated,
Molle
Using the following function, you can download the external js file in an ajax way and execute the contents of the file. Please note, however, that the external file will be evaluated in the global scope, and the use of the eval is NOT recommended. The function was adopted from this question.
function strapJS(jsUrl) {
var jsReq = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
if (jsReq === null) {
console.log("Error: XMLHttpRequest could not be initiated.");
}
jsReq.onload = function () {
try {
eval(jsReq.responseText);
} catch (e) {
console.log("Error: The script file contains errors." + e);
}
};
try {
jsReq.open("GET", jsUrl, true);
jsReq.send(null);
} catch (e) {
console.log("Error: Cannot retrieving data." + e);
}
}
JSFiddle here
Edit: 1
After some refactoring, I came up with this:
function StrapJs(scriptStr, jsObjName) {
var self = this;
self.ScriptStr = scriptStr;
self.ReturnedVal = null;
function _init() {
eval(self.ScriptStr);
self.ReturnedVal = eval(jsObjName);
}
_init();
}
You can then get the script string any way you want and just instantiate a new StrapJs object with the script string and name of the object to return inside the script string. The ReturnedVal property of the StrapJs object will then contain the object you are after.
Example usage:
var extJS = "var obj = " +
"{ " +
" innerHTML : 'Text to be shown', " +
" style : 'Not important for problem at hand', " +
" otherStuff : ' --||-- ' " +
"}; ";
var extJS2 = "var obj = " +
"{ " +
" innerHTML : 'Text to be shown 2', " +
" style : 'Not important for problem at hand 2', " +
" otherStuff : ' --||-- 2' " +
"}; ";
var strapJS = new StrapJs(extJS, 'obj');
var strapJS2 = new StrapJs(extJS2, 'obj');
console.log(strapJS.ReturnedVal.innerHTML);
console.log(strapJS2.ReturnedVal.innerHTML);
See it in action on this fiddle

Problem creating an email with an attachment in Javascript

I'm initiating an email create, by calling the code below, and adding an attachment to it.
I want the user to be able to type in the receipient, and modify the contents of the message, so I'm not sending it immediately.
Why do I get a RangeError the 2nd time the method is called?
(The first time it works correctly.)
function NewMailItem(p_recipient, p_subject, p_body, p_file, p_attachmentname)
{
try
{
var objO = new ActiveXObject('Outlook.Application');
var objNS = objO.GetNameSpace('MAPI');
var mItm = objO.CreateItem(0);
mItm.Display();
if (p_recipient.length > 0)
{
mItm.To = p_recipient;
}
mItm.Subject = p_subject;
if (p_file.length > 0)
{
var mAts = mItm.Attachments;
mAts.add(p_file, 1, p_body.length + 1, p_attachmentname);
}
mItm.Body = p_body;
mItm.GetInspector.WindowState = 2;
} catch(e)
{
alert('unable to create new mail item');
}
}
The error is occuring on the mAts.add line. So when it tries to attach the document, it fails.
Also the file name (p_file) is a http address to a image.
Won't work outside of IE, the user needs to have Outlook on the machine and an account configured on it. Are you sure you want to send an email this way?
I'm trying it with this little snippet, and it works flawlessly:
var objO = new ActiveXObject('Outlook.Application');
var mItm = objO.CreateItem(0);
var mAts = mItm.Attachments;
var p_file = [
"http://stackoverflow.com/content/img/vote-arrow-up.png",
"http://stackoverflow.com/content/img/vote-arrow-down.png"
];
for (var i = 0; i < p_file.length; i++) {
mAts.add(p_file[i]);
}
Note that I left off all optional arguments to Attachments.Add(). The method defaults to adding the attachments at the end, which is what you seem to want anyway.
Can you try this standalone snippet? If it works for you, please do a step-by-step reduction of your code towards this absolute minimum, and you will find what causes the error.
first do mItm.display()
then write mItm.GetInspector.WindowState = 2;
this will work

Categories