I've got a functional script on my site that allows me to open a link in a new window when a specific class is added to the link. I need a lot of those on my site though so I figured I'd make the script a bit easier to edit by working with variables.
In the process of changing out hardcoded strings for variables my script stopped working though. The only one that works is the var where I set the url.
I'm learning that ${} doesn't work everywhere. Hope that someone can point out where my thinking is wrong. Also hope that I got the terminology right, trying to learn though! :-)
var function1Name = "test_function";
var function1Url = "https://www.google.com";
var function1Class = ".test_function_class";
function ${function1Name}() {
window.open(function1Url, "_blank", "height=200");
}
jQuery("${function1Class}").click(function(){
${function1Name}()
});
None of your uses of ${} are valid JavaScript syntax.
Your function declaration van be replaced with:
window[function1Name] = function () {
window.open(function1Url, "_blank", "height=200");
}
Please note that the function will no longer be hoisted when declared this way, so order of operation matters.
The click handler can be written as follows:
jQuery(function1Class).click(function() { // Note that I just used the variable there.
window[function1Name]();
});
There is a ${} concept in JavaScript, but that is only in template literals:
const myVariable = "Foo";
const message = `myVariable contains: "${myVariable}"!`;
console.log(message);
There's several syntax issues here.
Firstly, function ${function1Name}() is not valid syntax. Function names must be defined before runtime. If you want to dynamically access a function, place it in an object and set the key with the variable reference.
Secondly, ${function1Name}() is again not valid syntax. You cannot invoke a function like that dynamically. Referring to the suggestion above, you can access an object dynamically so the first point fixes this problem.
Thirdly, string interpolation only works within template literals, so you need to delimit the string with backticks: ``. However it's completely redundant here as you can just use $(function1Class)
With those issues in mind, here's an updated example:
var function1Name = "test_function";
var function1Url = "https://www.google.com";
var function1Class = ".test_function_class";
var funcObj = {
[function1Name]: function() {
console.log(`function called, window would open here containing ${function1Url}...`);
// window.open(function1Url, "_blank", "height=200");
}
}
$(function1Class).click(function() {
funcObj[function1Name]()
});
/*
alternative using a template literal, although note that it's redundant here
$(`${function1Class}`).click(function() {
funcObj[function1Name]()
});
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Click me
One last thing to note is that no version of IE supports template literals, so be sure of your browser support requirements before using them.
So cool, I got it to work!
var function1Name = "test_function_1";
var function1Url = "https://www.google.com";
var function1Class = ".test_function_class1";
var function2Name = "test_function_2";
var function2Url = "https://www.cnn.com";
var function2Class = ".test_function_class2";
// Function 1
window[function1Name] = function () {
window.open(function1Url, "_blank", "toolbar=no,status=no,scrollbars=yes,resizable=yes,top=500,left=500,width=600,height=745");
}
jQuery(function1Class).click(function() {
window[function1Name]();
});
// Function 2
window[function2Name] = function () {
window.open(function2Url, "_blank", "toolbar=no,status=no,scrollbars=yes,resizable=yes,top=500,left=500,width=600,height=745");
}
jQuery(function2Class).click(function() {
window[function2Name]();
});
I can now add a bunch of url's and corresponding classes as was my intention. Super happy about that.
A follow up question though, as I'll have to experiment with what the ideal window parameters will be I'm trying to make those arguments variables as well. I've tried the examples of how to insert a variables output from the functional code but those methods don't work there. Here's that code:
var windowWidth = 250
var function1Name = "test_function_1";
var function1Url = "https://www.google.com";
var function1Class = ".test_function_class1";
var function2Name = "test_function_2";
var function2Url = "https://www.cnn.com";
var function2Class = ".test_function_class2";
// Function 1
window[function1Name] = function () {
window.open(function1Url, "_blank", "toolbar=no,status=no,scrollbars=yes,resizable=yes,top=500,left=500,width=[windowWidth],height=745");
}
jQuery(function1Class).click(function() {
window[function1Name]();
});
// Function 2
window[function2Name] = function () {
window.open(function2Url, "_blank", "toolbar=no,status=no,scrollbars=yes,resizable=yes,top=500,left=500,width=600,height=745");
}
jQuery(function2Class).click(function() {
window[function2Name]();
});
How would I insert the variables value (2nd line of Function1) there ?
I have been told my function:
for (const key of Object.keys(temp)) {
this.sessionData.push(temp[key]);
}
Must now use a .map instead,
I have tried this below:
Object.keys(temp).map(function(key) {
this.sessionData[key];
})
But 1 I don't know if it's actually accurate, and also, it cant access the data outside of the scope of the function it is in, here is the whole function below:
public sessionData;
sessionDates(sessionsData) {
const temp = {};
this.sessionData = [];
sessionsData.forEach(session => {
const date = moment(session.startDatetime).format('DDMMYYYY');
if (temp[date]) {
temp[date].push(session);
} else {
temp[date] = [session];
}
});
Object.keys(temp).map(function(key) {
this.sessionData[key];
})
TRYING TO USE THIS BELOW... session data is undefined, it can't access out of the scope?
Object.keys(temp).map(function(key) {
this.sessionData[key];
})
But this works..
for (const key of Object.keys(temp)) {
this.sessionData.push(temp[key]);
}
So this new .map method can't access anything out of its scope.. sigh!
If anybody can help that would be amazing! Thanks!
In Javascript all functions can access variables from outside (called "higher scope") - it's one of the strengths of the language and is called "capture".
The reason your code is failing is because it's using this.sessionData inside a function declaration, which cases problems because this in javascript is... somewhat complex. But you don't need it!
You also need to make sure you return the value you want to output. Here's how I would write it:
this.sessionData = Object.keys(temp).map(key => temp[key]);
This seems like a very basic question. But how do I create a class structure within Google Apps Script?
Lets say I want to call: myLibrary.Statistics.StandardDeviation(). I have to instead call: myLibrary.StandardDeviation().
I cannot seem to break it down any further, or organize it into classes.
How can I do this?
I suspect there's something more that you're not telling us about your situation. It is possible to set up a function as a property of an object that is itself a property of an object, and thus support the calling structure you've described.
function test() {
Logger.log( myLibrary.Statistics.StandardDeviation([5.3,5.2,5,2.0,3.4,6,8.0]) ); // 1.76021798279042
};
myLibrary.gs
var myLibrary = {};
myLibrary.Statistics = {}
myLibrary.Statistics.StandardDeviation = function( array ) {
// adapted from http://stackoverflow.com/a/32201390/1677912
var i,j,total = 0, mean = 0, diffSqredArr = [];
for(i=0;i<array.length;i+=1){
total+=array[i];
}
mean = total/array.length;
for(j=0;j<array.length;j+=1){
diffSqredArr.push(Math.pow((array[j]-mean),2));
}
return (Math.sqrt(diffSqredArr.reduce(function(firstEl, nextEl){
return firstEl + nextEl;
})/array.length));
}
This is some JS code
var methodArr = ['firstFunc','secondFunc','thirdFunc'];
for(var i in methodArr)
{
window[methodName] = function()
{
console.log(methodName);
}
}
My problem is that how to get the name of a function in JS.
In JS, use this.callee.name.toString() can get the function name. But in this situation, it is a null value. How can i get the 'funName' string?
Sorry, I didn't make it clear.
I want to create functions in a for loop, all these functions has almost the same implementation which need its name. But others can call these functions use different name.I want to know what methodName function is called.
it seems a scope problem.
Try this:
var methodArr = ['firstFunc','secondFunc','thirdFunc'];
for(var i in methodArr) {
var methodName = methodArr[i]; // <---- this line missed in your code?
window[methodName] = (function(methodName) {
return function() {
console.log(methodName);
}
})(methodName);
}
window['secondFunc'](); // output: secondFunc
I want to merge a argument of a function with a variable
But i don't know how to do that.
firstDates = [];
function myFunction(partOne) {
partOne + Dates.push(someOtherVar);
}
myFunction(first);
I know that this not works, but what would be the right way?
why not something like this?
var dates = {};
function myFunction(partOne) {
dates[partOne] = []; // dates["first"] = []
dates[partOne].push(someOtherVar); // dates["first"].push(someOtherVar)
}
myFunction("first");
Otherwise what you are trying to accomplish is an eval type of set up. This is generally a very bad idea. Don't use dynamically named variables.