I'm trying to refactor a portion of a Google AdWords script I've written in order to not have to repeat an if statement that I'm hoping I can dynamically update via an instance of "this". However, I'm receiving a "Cannot find function push in object firstKeywords. (line 34)" error. When I simply insert "firstKeywords.push", instead of "this.keywordsArray.push" the script works. Was wondering if there's a way to have the "this" instance be considered an array or if there's another work around?
Error: this.keywordsArray.push
Non-working script:
var firstKeywords = [];
var secondKeywords = [];
var thirdKeywords = [];
function main() {
function testKeywords(adgr, keywordsArray) {
this.adgr = adgr;
this.keywordsArray = keywordsArray;
}
testKeywords.prototype.move = function () {
var campaignIterator = AdWordsApp.campaigns()
.withCondition("Status = ENABLED")
.withCondition("Name CONTAINS_IGNORE_CASE 'High'")
.get();
while (campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
var adGroupIterator = campaign.adGroups()
.withCondition("Name CONTAINS_IGNORE_CASE 'Blogs'")
.get();
while (adGroupIterator.hasNext()) {
var adGroup = adGroupIterator.next();
var adGroupName = adGroup.getName();
var keywordIterator = adGroup.keywords()
.withCondition("SystemServingStatus = RARELY_SERVED")
.get();
while (keywordIterator.hasNext()) {
var keyword = keywordIterator.next();
var keywordText = keyword.getText();
var adgroupArray = this.keywordsArray;
if (adGroupName === this.adgr) {
this.keywordsArray.push(keywordText);
keyword.pause();
}
}
}
}
}
var test01 = new testKeywords("General Music Blogs", "firstKeywords");
var test02 = new testKeywords("Hip Hop Music Blogs", "secondKeywords");
var test03 = new testKeywords("Indie Music Blogs", "thirdKeywords");
test01.move();
test02.move();
test03.move();
}
The below script works the correct way, but with the if statements repeated.
var firstKeywords = [];
var secondKeywords = [];
var thirdKeywords = [];
function main() {
function testKeywords() {
var campaignIterator = AdWordsApp.campaigns()
.withCondition("Status = ENABLED")
.withCondition("Name CONTAINS_IGNORE_CASE 'High'")
.get();
while (campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
var adGroupIterator = campaign.adGroups()
.withCondition("Name CONTAINS_IGNORE_CASE 'Blogs'")
.get();
while (adGroupIterator.hasNext()) {
var adGroup = adGroupIterator.next();
var adGroupName = adGroup.getName();
var keywordIterator = adGroup.keywords()
.withCondition("SystemServingStatus = RARELY_SERVED")
.get();
while (keywordIterator.hasNext()) {
var keyword = keywordIterator.next();
var keywordText = keyword.getText()
if (adGroupName === 'General Music Blogs') {
firstKeywords.push(keywordText);
keyword.pause();
}
if (adGroupName === 'Hip Hop Music Blogs') {
secondKeywords.push(keywordText);
keyword.pause();
}
if (adGroupName === 'Indie Music Blogs') {
thirdKeywords.push(keywordText);
keyword.pause();
}
}
}
}
}
}
Thanks in advance.
In your testKeyword you are passing string literals and not the object refs.
So change
var test01 = new testKeywords("General Music Blogs", "firstKeywords");
var test02 = new testKeywords("Hip Hop Music Blogs", "secondKeywords");
var test03 = new testKeywords("Indie Music Blogs", "thirdKeywords");
to
var test01 = new testKeywords("General Music Blogs", firstKeywords);
var test02 = new testKeywords("Hip Hop Music Blogs", secondKeywords);
var test03 = new testKeywords("Indie Music Blogs", thirdKeywords);
Related
I've been trying to create a script which shows Bitcoin and Ethereum price according to users preference. So if an user clicks on bitcoin button it shows bitcoin price and when user clicks on Ethereum button it shows Ethereum.
Everything kind of works but when you click on Bitcoin button and then on Ethereum button it creates a conflict and keeps switching between Bitcoin and Ethereum price.
I have tried to use
pricesWs1.close(); and pricesWs.close(); but it completely closes 1 websocket and you can't swap between the prices.
Javascript
const pricesWs = new WebSocket('wss://ws.coincap.io/prices?assets=bitcoin')
const pricesWs1 = new WebSocket('wss://ws.coincap.io/prices?assets=ethereum')
$(document).ready(function() {
$('.buttonbtc').click(function(e) {
pricesWs.onmessage = function (msg) {
var str = msg.data
var matches = str.match (/\b\d+(?:.\d+)?/);
var finalprice = parseFloat(matches);
document.getElementById("btc").innerHTML = finalprice;
}
});
});
$(document).ready(function() {
$('.buttoneth').click(function(e) {
pricesWs1.onmessage = function (msgg) {
var str = msgg.data
var matches = str.match (/\b\d+(?:.\d+)?/);
var finalprice = parseFloat(matches);
document.getElementById("btc").innerHTML = finalprice;
}
});
});
LIVE DEMO: https://jsfiddle.net/s9rv1agu/
The problem seems to be that you're getting constant response messages from the coinbase server.
You can prevent the text display from being updated onmessage unless the socket that sent it matches the last clicked button.
In this case I stored the value of the last clicked button in a variable named cp and only update the display on message if it was sent by the corresponding socket.
Code:
const pricesWs = new WebSocket('wss://ws.coincap.io/prices?assets=bitcoin')
const pricesWs1 = new WebSocket('wss://ws.coincap.io/prices?assets=ethereum');
var cp = -1;//current_price
$(document).ready(function() {
$('.buttonbtc').click(function(e) {
cp = 0;
document.getElementById("btc").innerHTML = "pending...";
pricesWs.onmessage = function (msg) {
if(cp == 0) {
var str = msg.data
var matches = str.match (/\b\d+(?:.\d+)?/);
var finalprice = parseFloat(matches);
document.getElementById("btc").innerHTML = finalprice;
}
}
});
});
$(document).ready(function() {
$('.buttoneth').click(function(e) {
cp = 1;
document.getElementById("btc").innerHTML = "pending...";
pricesWs1.onmessage = function (msgg) {
if(cp == 1) {
var str = msgg.data
var matches = str.match (/\b\d+(?:.\d+)?/);
var finalprice = parseFloat(matches);
document.getElementById("btc").innerHTML = finalprice;
}
}
});
});
If you however also want to stop the root cause of the problem(the constant messages being sent by the server) you will need to iniate the socket connection and close the connection after a message (or possibly some configuration with coinbase which will only send back 1 message).
var pricesWs;
var pricesWs1;
const wlist = ['wss://ws.coincap.io/prices?assets=bitcoin',
'wss://ws.coincap.io/prices?assets=ethereum'];
var cp = -1;//current_price
$(document).ready(function() {
$('.buttonbtc').click(function(e) {
cp = 0;
document.getElementById("btc").innerHTML = "pending...";
pricesWs = new WebSocket(wlist[0]);
pricesWs.onopen = function() {
pricesWs.onmessage = function (msg) {
if(cp == 0) {
var str = msg.data
var matches = str.match (/\b\d+(?:.\d+)?/);
var finalprice = parseFloat(matches);
document.getElementById("btc").innerHTML = finalprice;
}
pricesWs.close();
}
}
});
});
$(document).ready(function() {
$('.buttoneth').click(function(e) {
cp = 1;
document.getElementById("btc").innerHTML = "pending...";
pricesWs1 = new WebSocket(wlist[1]);
pricesWs1.onopen = function() {
pricesWs1.onmessage = function (msgg) {
if(cp == 1) {
var str = msgg.data
var matches = str.match (/\b\d+(?:.\d+)?/);
var finalprice = parseFloat(matches);
document.getElementById("btc").innerHTML = finalprice;
}
pricesWs1.close();
}
}
});
});
an additional check can also be added to ensure the sockets are not in the process of being opened when a button is clicked
Is it possible, depending on the environment of the company, that some features of Google are non-existent? I tried some functions with my personal email and it works; but, in a professional environment it doesn't work.
function getDataForSearch() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName("PEP FORMULAR");
return ws.getRange(6, 1, ws.getLastRow()-1, 6).getValues();
}
var data;
function setDataForSearch(){
google.script.run.withSuccessHandler(function(dataReturned){
data = dataReturned.slice();
}).getDataForSearch();
}
function search(){
var searchInput = document.getElementById("searchInput").value.toString().toLowerCase().trim();
var searchWords = searchInput.split(/\s+/);
//var searchColumns = [0,1,2,3,4,5];
var searchColumns = [0];
//and
var resultsArray = searchInput == "" ? [] : data.filter(function(r){
return searchWords.every(function(word){
return searchColumns.some(function(colIndex){
return r[colIndex].toString().toLowerCase().indexOf(word) != -1;
});
});
});
var searchResultsBox = document.getElementById("searchResults");
var templateBox = document.getElementById("rowTemplate");
var template = templateBox.content;
searchResultsBox.innerHTML = "";
resultsArray.forEach(function(r){
var tr = template.cloneNode(true);
var typeInitiativeColumn = tr.querySelector(".type-initiative");
var pepRefColumn = tr.querySelector(".pep-ref");
var projectNameColumn = tr.querySelector(".project-name");
pepRefColumn.textContent = r[0];
typeInitiativeColumn.textContent = r[2];
projectNameColumn.textContent = r[5];
searchResultsBox.appendChild(tr);
});
}
This code works but, when I try to reproduce it in a professional environment, the function setDataForSerach() is not able to get the data from the function getDataForSearch() and make a copy.
I have a loop in which I am calling rec_append() recursively, apparently the first pass alone works, then the loop stops.
I have an array of 4 elements going into that $.each loop but I see only the first element going into the function recursively. Help!
I switched it for a element.forEach but that gives me only the second element and I am stuck, is there a better solution to process a tree of elements? My array is a part of a tree.
var data = JSON.parse(JSON.stringify(result))
var graph = $(".entry-point");
function rec_append(requestData, parentDiv) {
var temp_parent_details;
$.each(requestData, function (index, jsonElement) {
if (typeof jsonElement === 'string') {
//Element construction
//Name and other details in the form of a : delimited string
var splitString = jsonElement.split(':');
var details = document.createElement("details");
var summary = document.createElement("summary");
summary.innerText = splitString[0];
details.append(summary);
temp_parent_details = details;
parentDiv.append(details);
var kbd = document.createElement("kbd");
kbd.innerText = splitString[1];
summary.append(' ');
summary.append(kbd);
var div = document.createElement("div");
div.className = "col";
details.append(div);
var dl = document.createElement("dl");
div.append(dl);
var dt = document.createElement("dt");
dt.className = "col-sm-1";
dt.innerText = "Path";
div.append(dt);
var dd = document.createElement("dd");
dd.className = "col-sm-11";
dd.innerText = splitString[2];
div.append(dd);
var dt2 = document.createElement("dt");
dt2.className = "col-sm-1";
dt2.innerText = "Type";
div.append(dt2);
var dd2 = document.createElement("dd");
dd2.className = "col-sm-11";
dd2.innerText = splitString[1];
div.append(dd2);
} else {
$.each(jsonElement, function (jsonElementArrIndx, jsonChildElement) {
rec_append(jsonChildElement, temp_parent_details); //Only 1 pass works, rest skip
});
}
});
}
rec_append(data, graph);
Sample data:enter image description here
I am using the below JavaScript code to get the title of all lists in SharePoint 2013. How can i adapt this to return the URL of each list as well?
I've tired this but it doesn't work:
//listUrl = oList.get_url();
//console.log(listUrl);
Code:
function retrieveAllListProperties() {
var clientContext = new SP.ClientContext('/StrategicProjectOffice');
var oWebsite = clientContext.get_web();
this.collList = oWebsite.get_lists();
clientContext.load(collList);
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded)
);
}
function onQuerySucceeded() {
var listTitle = '';
var listEnumerator = collList.getEnumerator();
while (listEnumerator.moveNext()) {
var oList = listEnumerator.get_current();
listTitle = oList.get_title();
//listUrl = oList.get_url();
//console.log(listUrl);
if (listTitle.indexOf("SPO") >= 0) {
getItemsFromView(listTitle, "All Tasks");
}
}
}
List Url could be retrieved via SPList.RootFolder property, in your example the line:
clientContext.load(collList);
needs to be replaced with
clientContext.load(collList,'Include(RootFolder.ServerRelativeUrl)');
which tells to construct a query to return RootFolder.ServerRelativeUrl property of List object.
Example
Here is my version which retrieves lists and prints its url:
var ctx = SP.ClientContext.get_current();
var web = ctx.get_web();
var lists = web.get_lists();
ctx.load(lists,'Include(RootFolder.ServerRelativeUrl)');
ctx.executeQueryAsync(
function () {
for(var i = 0; i < lists.get_count(); i++){
var list = lists.getItemAtIndex(i);
var listUrl = list.get_rootFolder().get_serverRelativeUrl();
console.log(listUrl);
}
},
function(sender,args){
console.log(args.get_message());
}
);
I have a JavaScript Win Pivot Application
Into the Hub I am retrieving some information:
function initPages(options) {
for (var i = 0; i < options.length ; i++) {
var menuItem = options[i];
menuItem.showBanner = (i == 0);
definePages(options);
}
}
and in a .Js file I have the definePages function created:
functions.js:
function definePages(item) {
var action = item[0];
var animation = item[1];
var scyfy = item[2];
var localmovies = item[3];
var clasic = item[4];
var comedy = item[5];
var biography = item[6];
var drama = item[7];
var kids = item[8];
var musical = item[9];
var romantic = item[10];
var suspense = item[11];
var horror = item[12];
var art = item[13];
var personalities = item[14];
var history = item[15];
var society = item[16];
}
Now, in my section 1 I initialize the page by calling another function there:
ready: function (element, options) {
// TODO: Inicializar la página aquí.
options = options || {};
initMovies();
},
function initMovies() {
var element = document.getElementById("movieContainer");
//var movies = ??????????????????????????
//console.log(movies);
//it keeps going
}
I need to be able to retrive, in that var movies, the var action, from the functions.Js or, which is the same, the items[0]...
However, if I call a function in functions.Js, which is defined in section1Page, it won´t work...
I can call functions and pass data from anywhere to functions.Js, but not the other way around...
Any ideas on what should I do? Thanks!!!
I fixed it... I created a global var in function.Js and I get the info from the array in each section later on:
function definePages(item) {
tooSleepyToThink = item;
}
section1Page:
function initMovies() {
var elemento = document.getElementById("movieContainer");
console.log(tooSleepyToThink[0].text);
}