I posted a similar question at the Drupal Forum, but I haven't had much luck.
I'm upgrading a site from D6 to D7. So far it's gone well, but I'm getting a Javascript error that I just can't pin down a solution for.
This is a cut down version of the whole script:
(function($) {
function sign(secret, message) {
var messageBytes = str2binb(message);
var secretBytes = str2binb(secret);
if (secretBytes.length > 16) {
secretBytes = core_sha256(secretBytes, secret.length * chrsz);
}
var ipad = Array(16), opad = Array(16);
for (var i = 0; i < 16; i++) {
ipad[i] = secretBytes[i] ^ 0x36363636;
opad[i] = secretBytes[i] ^ 0x5C5C5C5C;
}
var imsg = ipad.concat(messageBytes);
var ihash = core_sha256(imsg, 512 + message.length * chrsz);
var omsg = opad.concat(ihash);
var ohash = core_sha256(omsg, 512 + 256);
var b64hash = binb2b64(ohash);
var urlhash = encodeURIComponent(b64hash);
return urlhash;
}
function addZero(n) {
return ( n < 0 || n > 9 ? "" : "0" ) + n;
}
Date.prototype.toISODate =
new Function("with (this)\nreturn " +
"getFullYear()+'-'+addZero(getMonth()+1)+'-'" +
"+addZero(getDate())+'T'+addZero(getHours())+':'" +
"+addZero(getMinutes())+':'+addZero(getSeconds())+'.000Z'");
function getNowTimeStamp() {
var time = new Date();
var gmtTime = new Date(time.getTime() + (time.getTimezoneOffset() * 60000));
return gmtTime.toISODate() ;
}
}(jQuery));
The part that keeps throwing an error I'm seeing in Firebug is at:
Date.prototype.toISODate =
new Function("with (this)\n return " +
"getFullYear()+'-'+addZero(getMonth()+1)+'-'" +
"+addZero(getDate())+'T'+addZero(getHours())+':'" +
"+addZero(getMinutes())+':'+addZero(getSeconds())+'.000Z'");
Firebug keeps stopping at "addZero is not defined". JS has never been my strong point, and I know some changes have been made in D7. I've already wrapped the entire script in "(function($) { }(jQuery));", but I must be missing something else. The same script works perfectly on the D6 site.
Here is the "fixed" version of the whole code with #Pointy suggestion added. All I left out is the part of the script for making the hash that goes to Amazon, and some of my declared variables.
(function($) {
var typedText;
var strSearch = /asin:/;
var srchASIN;
$(document).ready(function() {
$("#edit-field-game-title-und-0-asin").change(function() {
typedText = $("#edit-field-game-title-und-0-asin").val();
$.ajax({
type: 'POST',
data: {typedText: typedText},
dataType: 'text',
url: '/asin/autocomplete/',
success:function(){
document.getElementById('asin-lookup').style.display='none';
x = typedText.search(strSearch);
y = (x+5);
srchASIN = typedText.substr(y,10)
amazonSearch();
}
});
});
$("#search_asin").click(function() {
$("#edit-field-game-title-und-0-asin").val('');
document.getElementById('name-lookup').style.display='none';
$("#edit-field-game-title-und-0-asin").val('');
$("#edit-title").val('');
$("#edit-field-subtitle-und-0-value").val('');
$("#edit-field-game-edition-und-0-value").val('');
$("#edit-field-release-date-und-0-value-date").val('');
$("#edit-field-asin-und-0-asin").val('');
$("#edit-field-ean-und-0-value").val('');
$("#edit-field-amazon-results-und-0-value").val('');
$("#edit-body").val('');
srchASIN = $("#field-asin-enter").val();
amazonSearch();
});
$("#clear_search").click(function() {
$("#field-asin-enter").val('');
$("#edit-field-game-title-und-0-asin").val('');
$("#edit-title").val('');
$("#edit-field-subtitle-und-0-value").val('');
$("#edit-field-game-edition-und-0-value").val('');
$("#edit-field-release-date-und-0-value-date").val('');
$("#edit-field-release-dt2-und-0-value-date").val('');
$("#edit-field-asin-und-0-asin").val('');
$("#edit-field-ean-und-0-value").val('');
$("#edit-field-amazon-results-und-0-value").val('');
$("#field-amazon-platform").val('');
$("#field-amazon-esrb").val('');
$("#edit-body-und-0-value").val('');
document.getElementById('asin-lookup').style.display='';
document.getElementById('name-lookup').style.display='';
});
function amazonSearch(){
var ASIN = srchASIN;
var azScr = cel("script");
azScr.setAttribute("type", "text/javascript");
var requestUrl = invokeRequest(ASIN);
azScr.setAttribute("src", requestUrl);
document.getElementsByTagName("head").item(0).appendChild(azScr);
}
});
var amzJSONCallback = function(tmpData){
if(tmpData.Item){
var tmpItem = tmpData.Item;
}
$("#edit-title").val(tmpItem.title);
$("#edit-field-game-edition-und-0-value").val(tmpItem.edition);
$("#edit-field-release-date-und-0-value-date").val(tmpItem.relesdate);
$("#edit-field-release-dt2-und-0-value-date").val(tmpItem.relesdate);
$("#edit-field-asin-und-0-asin").val(tmpItem.asin);
$("#edit-field-ean-und-0-value").val(tmpItem.ean);
$("#field-amazon-platform").val(tmpItem.platform);
$("#field-amazon-publisher").val(tmpItem.publisher);
$("#field-amazon-esrb").val(tmpItem.esrb);
};
function ctn(x){ return document.createTextNode(x); }
function cel(x){ return document.createElement(x); }
function addEvent(obj,type,fn){
if (obj.addEventListener){obj.addEventListener(type,fn,false);}
else if (obj.attachEvent){obj["e"+type+fn]=fn; obj.attachEvent("on"+type,function(){obj["e"+type+fn]();});}
}
var styleXSL = "http://www.tlthost.net/sites/vglAmazonAsin.xsl";
function invokeRequest(ASIN) {
cleanASIN = ASIN.replace(/[-' ']/g,'');
var unsignedUrl = "http://xml-us.amznxslt.com/onca/xml?Service=AWSECommerceService&AssociateTag=theliterarytimes&IdType=ASIN&ItemId="+cleanASIN+"&Operation=ItemLookup&ResponseGroup=Medium,ItemAttributes,OfferFull&Style="+styleXSL+"&ContentType=text/javascript&CallBack=amzJSONCallback";
var lines = unsignedUrl.split("\n");
unsignedUrl = "";
for (var i in lines) { unsignedUrl += lines[i]; }
// find host and query portions
var urlregex = new RegExp("^http:\\/\\/(.*)\\/onca\\/xml\\?(.*)$");
var matches = urlregex.exec(unsignedUrl);
var host = matches[1].toLowerCase();
var query = matches[2];
// split the query into its constituent parts
var pairs = query.split("&");
// remove signature if already there
// remove access key id if already present
// and replace with the one user provided above
// add timestamp if not already present
pairs = cleanupRequest(pairs);
// encode the name and value in each pair
pairs = encodeNameValuePairs(pairs);
// sort them and put them back together to get the canonical query string
pairs.sort();
var canonicalQuery = pairs.join("&");
var stringToSign = "GET\n" + host + "\n/onca/xml\n" + canonicalQuery;
// calculate the signature
//var secret = getSecretAccessKey();
var signature = sign(secret, stringToSign);
// assemble the signed url
var signedUrl = "http://" + host + "/onca/xml?" + canonicalQuery + "&Signature=" + signature;
//document.write ("<html><body><pre>REQUEST: "+signedUrl+"</pre></body></html>");
return signedUrl;
}
function encodeNameValuePairs(pairs) {
for (var i = 0; i < pairs.length; i++) {
var name = "";
var value = "";
var pair = pairs[i];
var index = pair.indexOf("=");
// take care of special cases like "&foo&", "&foo=&" and "&=foo&"
if (index == -1) {
name = pair;
} else if (index == 0) {
value = pair;
} else {
name = pair.substring(0, index);
if (index < pair.length - 1) {
value = pair.substring(index + 1);
}
}
// decode and encode to make sure we undo any incorrect encoding
name = encodeURIComponent(decodeURIComponent(name));
value = value.replace(/\+/g, "%20");
value = encodeURIComponent(decodeURIComponent(value));
pairs[i] = name + "=" + value;
}
return pairs;
}
function cleanupRequest(pairs) {
var haveTimestamp = false;
var haveAwsId = false;
var nPairs = pairs.length;
var i = 0;
while (i < nPairs) {
var p = pairs[i];
if (p.search(/^Timestamp=/) != -1) {
haveTimestamp = true;
} else if (p.search(/^(AWSAccessKeyId|SubscriptionId)=/) != -1) {
pairs.splice(i, 1, "AWSAccessKeyId=" + accessKeyId);
haveAwsId = true;
} else if (p.search(/^Signature=/) != -1) {
pairs.splice(i, 1);
i--;
nPairs--;
}
i++;
}
if (!haveTimestamp) {
pairs.push("Timestamp=" + getNowTimeStamp());
}
if (!haveAwsId) {
pairs.push("AWSAccessKeyId=" + accessKeyId);
}
return pairs;
}
function sign(secret, message) {
var messageBytes = str2binb(message);
var secretBytes = str2binb(secret);
if (secretBytes.length > 16) {
secretBytes = core_sha256(secretBytes, secret.length * chrsz);
}
var ipad = Array(16), opad = Array(16);
for (var i = 0; i < 16; i++) {
ipad[i] = secretBytes[i] ^ 0x36363636;
opad[i] = secretBytes[i] ^ 0x5C5C5C5C;
}
var imsg = ipad.concat(messageBytes);
var ihash = core_sha256(imsg, 512 + message.length * chrsz);
var omsg = opad.concat(ihash);
var ohash = core_sha256(omsg, 512 + 256);
var b64hash = binb2b64(ohash);
var urlhash = encodeURIComponent(b64hash);
return urlhash;
}
Date.prototype.toISODate = function() {
function addZero(n) {
return ( n < 0 || n > 9 ? "" : "0" ) + n;
}
var d = this;
return d.getFullYear() + '-' +
addZero(d.getMonth() + 1) + '-' +
addZero(d.getDate()) + 'T' +
addZero(d.getHours()) + ':' +
addZero(d.getMinutes()) + ':' +
addZero(d.getSeconds()) + '.000Z';
};
function getNowTimeStamp() {
var time = new Date();
var gmtTime = new Date(time.getTime() + (time.getTimezoneOffset() * 60000));
return gmtTime.toISODate() ;
}
}(jQuery));
Here's a better version of your code:
Date.prototype.toISODate = function() {
function addZero(n) {
return ( n < 0 || n > 9 ? "" : "0" ) + n;
}
var d = this;
return d.getFullYear() + '-' +
addZero(d.getMonth() + 1) + '-' +
addZero(d.getDate()) + 'T' +
addZero(d.getHours()) + ':' +
addZero(d.getMinutes()) + ':' +
addZero(d.getSeconds()) + '.000Z';
};
That moves "addDate" inside the extension function, and it avoids the horrid with statement.
Related
I'm writing a google docs apps script in making a google docs add-on. When the user clicks a button in the sidebar, an apps script function is called named executeSpellChecking. This apps script function makes a remote POST call after getting the document's text.
total time = time that takes from when user clicks the button, until the .withSuccessHandler(, that means until executeSpellChecking returns = 2000 ms
function time = time that takes for the executeSpellChecking call to complete from its start to its end = 1400 ms
t3 = time that takes for the remote POST call to be completed = 800ms
t4 = time that takes for the same remote POST call to complete in a VB.NET app = 200ms
Problems:
Why total time to complete is bigger than total function time by a staggering 600ms, what else happens there? shouldn't they be equal? How can I improve it?
Why t3 is bigger than t4 ? Shouldn't they be equal? Is there something wrong with POST requests when happening from .gs? How can I improve it ?
the code is (sidebar.html):
function runSpellChecking() {
gb_IsSpellcheckingRunning = true;
//gb_isAutoCorrecting = false;
gi_CorrectionCurrWordIndex = -1;
$("#btnStartCorr").attr("disabled", true);
$("#divMistakes").html("");
this.disabled = true;
//$('#error').remove();
var origin = $('input[name=origin]:checked').val();
var dest = $('input[name=dest]:checked').val();
var savePrefs = $('#save-prefs').is(':checked');
//var t1 = new Date().getTime();
console.time("total time");
google.script.run
.withSuccessHandler(
function(textAndTranslation, element) {
if (gb_IsSpellCheckingEnabled) {
console.timeEnd("total time");
//var t2 = new Date().getTime();
go_TextAndTranslation = JSON.parse(JSON.stringify(textAndTranslation));
var pagewords = textAndTranslation.pagewords;
var spellchecked = textAndTranslation.spellchecked;
//alert("total time to complete:" + (t2-t1) + "###" + go_TextAndTranslation.time);
//irrelevant code follows below...
}
})
.withFailureHandler(
function(msg, element) {
showError(msg, $('#button-bar'));
element.disabled = false;
})
.withUserObject(this)
.executeSpellChecking(origin, dest, savePrefs);
}
and the called function code is (spellcheck.gs):
function executeSpellChecking(origin, dest, savePrefs) {
//var t1 = new Date().getTime();
console.time("function time");
var body = DocumentApp.getActiveDocument().getBody();
var alltext = body.getText();
var lastchar = alltext.slice(-1);
if (lastchar != " " && lastchar != "\n") {
body.editAsText().insertText(alltext.length, "\n");
alltext = body.getText();
}
var arr_alltext = alltext.split(/[\s\n]/);
var pagewords = new Object;
var pagewordsOrig = new Object;
var pagewordsOrigOffset = new Object;
var offset = 0;
var curWord = "";
var cnt = 0;
for (var i = 0; i < arr_alltext.length; i++) {
curWord = arr_alltext[i];
if (StringHasSimeioStiksis(curWord)) {
curWord = replaceSimeiaStiksis(curWord);
var arr3 = curWord.split(" ");
for (var k = 0; k < arr3.length; k++) {
curWord = arr3[k];
pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~##$%^&*()_|+\-="<>\{\}\[\]\\\/]/gi, '');
pagewordsOrig["" + (cnt+1).toString()] = curWord;
pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
offset += curWord.length;
cnt++;
}
offset++;
} else {
pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~##$%^&*()_|+\-="<>\{\}\[\]\\\/\n]/gi, '');
pagewordsOrig["" + (cnt+1).toString()] = curWord;
pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
offset += curWord.length + 1;
cnt++;
}
}
var respTString = "";
var url = 'https://www.example.org/spellchecker.php';
var data = {
"Text" : JSON.stringify(pagewords),
"idOffset" : "0",
"lexID" : "8",
"userEmail" : "test#example.org"
};
var payload = JSON.stringify(data);
var options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : payload
};
//var t11 = new Date().getTime();
console.time("POST time");
var response = UrlFetchApp.fetch(url, options);
console.timeEnd("POST time");
//var t22 = new Date().getTime();
var resp = response.getContentText();
respTString = resp;
var spellchecked = JSON.parse(respTString);
var style = {};
for (var k in pagewords){
if (pagewords.hasOwnProperty(k)) {
if (spellchecked.hasOwnProperty(k)) {
if (spellchecked[k].substr(0, 1) == "1") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#000000";
}
if (spellchecked[k].substr(0, 1) == "0") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#FF0000";
}
if (spellchecked[k].substr(0, 1) == "4") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#0000FF";
}
if (pagewordsOrigOffset[k] < alltext.length) {
body.editAsText().setAttributes(pagewordsOrigOffset[k], pagewordsOrigOffset[k] + pagewordsOrig[k].length, style);
}
}
}
}
//var t2 = new Date().getTime();
console.timeEnd("function time")
return {
"pagewords" : pagewords,
"pagewordsOrig" : pagewordsOrig,
"pagewordsOrigOffset" : pagewordsOrigOffset,
"spellchecked" : spellchecked
}
}
Thank you in advance for any help.
EDIT: I updated the code to use console.time according to the suggestion, the results are:
total time: 2048.001953125 ms
Jun 21, 2021, 3:01:40 PM Debug POST time: 809ms
Jun 21, 2021, 3:01:41 PM Debug function time: 1408ms
So the problem is not how time is measured. function time is 1400ms, while the time it takes to return is 2000ms, a difference of 600ms and the POST time is a staggering 800ms, instead of 200ms it takes in VB.net to make the exact same POST call.
Use console.time() and console.timeEnd():
https://developers.google.com/apps-script/reference/base/console
I modified the code for you. console.timeEnd() outputs the time duration in the console automatically, so I removed the alert for you that showed the time difference.
You might want the strings that I used as the parameter as some sort of constant variable, so there are no magic strings used twice. I hope this is of use to you.
function runSpellChecking() {
gb_IsSpellcheckingRunning = true;
//gb_isAutoCorrecting = false;
gi_CorrectionCurrWordIndex = -1;
$("#btnStartCorr").attr("disabled", true);
$("#divMistakes").html("");
this.disabled = true;
//$('#error').remove();
var origin = $('input[name=origin]:checked').val();
var dest = $('input[name=dest]:checked').val();
var savePrefs = $('#save-prefs').is(':checked');
console.time("total time");
google.script.run
.withSuccessHandler(
function(textAndTranslation, element) {
if (gb_IsSpellCheckingEnabled) {
console.timeEnd("total time");
go_TextAndTranslation = JSON.parse(JSON.stringify(textAndTranslation));
var pagewords = textAndTranslation.pagewords;
var spellchecked = textAndTranslation.spellchecked;
//irrelevant code follows below...
}
})
.withFailureHandler(
function(msg, element) {
showError(msg, $('#button-bar'));
element.disabled = false;
})
.withUserObject(this)
.executeSpellChecking(origin, dest, savePrefs);
}
function executeSpellChecking(origin, dest, savePrefs) {
console.time("function time");
var body = DocumentApp.getActiveDocument().getBody();
var alltext = body.getText();
var lastchar = alltext.slice(-1);
if (lastchar != " " && lastchar != "\n") {
body.editAsText().insertText(alltext.length, "\n");
alltext = body.getText();
}
var arr_alltext = alltext.split(/[\s\n]/);
var pagewords = new Object;
var pagewordsOrig = new Object;
var pagewordsOrigOffset = new Object;
var offset = 0;
var curWord = "";
var cnt = 0;
for (var i = 0; i < arr_alltext.length; i++) {
curWord = arr_alltext[i];
if (StringHasSimeioStiksis(curWord)) {
curWord = replaceSimeiaStiksis(curWord);
var arr3 = curWord.split(" ");
for (var k = 0; k < arr3.length; k++) {
curWord = arr3[k];
pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~##$%^&*()_|+\-="<>\{\}\[\]\\\/]/gi, '');
pagewordsOrig["" + (cnt+1).toString()] = curWord;
pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
offset += curWord.length;
cnt++;
}
offset++;
} else {
pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~##$%^&*()_|+\-="<>\{\}\[\]\\\/\n]/gi, '');
pagewordsOrig["" + (cnt+1).toString()] = curWord;
pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
offset += curWord.length + 1;
cnt++;
}
}
var respTString = "";
var url = 'https://www.example.org/spellchecker.php';
var data = {
"Text" : JSON.stringify(pagewords),
"idOffset" : "0",
"lexID" : "8",
"userEmail" : "test#example.org"
};
var payload = JSON.stringify(data);
var options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : payload
};
console.time("POST time");
var response = UrlFetchApp.fetch(url, options);
console.timeEnd("POST time");
var resp = response.getContentText();
respTString = resp;
var spellchecked = JSON.parse(respTString);
var style = {};
for (var k in pagewords){
if (pagewords.hasOwnProperty(k)) {
if (spellchecked.hasOwnProperty(k)) {
if (spellchecked[k].substr(0, 1) == "1") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#000000";
}
if (spellchecked[k].substr(0, 1) == "0") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#FF0000";
}
if (spellchecked[k].substr(0, 1) == "4") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#0000FF";
}
if (pagewordsOrigOffset[k] < alltext.length) {
body.editAsText().setAttributes(pagewordsOrigOffset[k], pagewordsOrigOffset[k] + pagewordsOrig[k].length, style);
}
}
}
}
console.timeEnd("function time");
return {
"pagewords" : pagewords,
"pagewordsOrig" : pagewordsOrig,
"pagewordsOrigOffset" : pagewordsOrigOffset,
"spellchecked" : spellchecked
}
}
Can some body help me modify this script.
The purpose of the script is to change bids for the keywords based on average position. One of the assumptions that the script has is that it sets a firstpagebid for the keyword but it won't allow for the bid to go below the firstpagebid even if the position is too high.
Is there a way to remove this restriction? so basically if the new cpc calculated is lower than the first page bid then it allows for the new cpc to be lower than the firstpage bid.
/**
*
* Average Position Bidding Tool
*
* This script changes keyword bids so that they target specified positions,
* based on recent performance.
*
* Version: 1.5
* Updated 2015-09-28 to correct for report column name changes
* Updated 2016-02-05 to correct label reading, add extra checks and
* be able to adjust maximum bid increases and decreases separately
* Updated 2016-08-30 to correct label reading from reports
* Updated 2016-09-14 to update keywords in batches
* Updated 2016-10-26 to avoid DriveApp bug
* Google AdWords Script maintained on brainlabsdigital.com
*
**/
// Options
var maxBid = 14.50;
// Bids will not be increased past this maximum.
var minBid = 3.0;
// Bids will not be decreased below this minimum.
var firstPageMaxBid = 10.00;
// The script avoids reducing a keyword's bid below its first page bid estimate. If you think
// Google's first page bid estimates are too high then use this to overrule them.
var dataFile = "AveragePositionData.txt";
// This name is used to create a file in your Google Drive to store today's performance so far,
// for reference the next time the script is run.
var useFirstPageBidsOnKeywordsWithNoImpressions = true;
// If this is true, then if a keyword has had no impressions since the last time the script was run
// its bid will be increased to the first page bid estimate (or the firsPageMaxBid if that is smaller).
// If this is false, keywords with no recent impressions will be left alone.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Advanced Options
var bidIncreaseProportion = 0.20;
var bidDecreaseProportion = 0.25;
var targetPositionTolerance = 0.3;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function main() {
var fieldJoin = ",";
var lineJoin = "$";
var idJoin = "#";
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
/*var files = DriveApp.getFilesByName(dataFile);
if (!files.hasNext()) {
var file = DriveApp.createFile(dataFile,"\n");
Logger.log("File '" + dataFile + "' has been created.");
} else {
var file = files.next();
if (files.hasNext()) {
Logger.log("Error - more than one file named '" + dataFile + "'");
return;
}
Logger.log("File '" + dataFile + "' has been read.");
}*/
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Get the current date/time
var currentTime = new Date(Utilities.formatDate(new Date(), AdWordsApp.currentAccount().getTimeZone(), "MMM dd,yyyy HH:mm:ss"));
var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
var hourOfDay = currentTime.getHours();
var dayOfWeek = days[currentTime.getDay()]; //Added on 9/21/2015
// Prevent adjustments if not in between 8am and 11pm and Diffrent running time by date - Added on 9/21/2015 (important allows to set time based on day)
switch (dayOfWeek) {
case 'Monday':
case 'Tuesday':
case 'Wednesday':
case 'Thursday':
case 'Friday':
if (hourOfDay < 8 || hourOfDay >= 21) {
Logger.log("Not the Right Time");
return;
}
break;
case 'Saturday':
case 'Sunday':
if (hourOfDay < 8 || hourOfDay >= 18) {
Logger.log("Not the Right Time");
return;
}
break;
}
Logger.log("Right Time");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
var labelIds = [];
var labelIterator = AdWordsApp.labels()
.withCondition("KeywordsCount > 0")
.withCondition("LabelName CONTAINS_IGNORE_CASE 'Position '")
.get();
while (labelIterator.hasNext()) {
var label = labelIterator.next();
if (label.getName().substr(0,"position ".length).toLowerCase() == "position ") {
labelIds.push(label.getId());
}
}
if (labelIds.length == 0) {
Logger.log("No position labels found.");
return;
}
Logger.log(labelIds.length + " position labels have been found.");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
var keywordData = {
//UniqueId1: {LastHour: {Impressions: , AveragePosition: }, ThisHour: {Impressions: , AveragePosition: },
//CpcBid: , FirstPageCpc: , MaxBid, MinBid, FirstPageMaxBid, PositionTarget: , CurrentAveragePosition:,
//Criteria: }
}
var ids = [];
var uniqueIds = [];
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
var report = AdWordsApp.report(
'SELECT Id, Criteria, AdGroupId, AdGroupName, CampaignName, Impressions, AveragePosition, CpcBid, FirstPageCpc, Labels, BiddingStrategyType ' +
'FROM KEYWORDS_PERFORMANCE_REPORT ' +
'WHERE Status = ENABLED AND AdGroupStatus = ENABLED AND CampaignStatus = ENABLED ' +
'AND LabelIds CONTAINS_ANY [' + labelIds.join(",") + '] ' +
'AND AdNetworkType2 = SEARCH ' +
'AND Device NOT_IN ["HIGH_END_MOBILE"] ' +
'DURING TODAY'
);
var rows = report.rows();
while(rows.hasNext()){
var row = rows.next();
if (row["BiddingStrategyType"] != "cpc") {
if (row["BiddingStrategyType"] == "Enhanced CPC"
|| row["BiddingStrategyType"] == "Target search page location"
|| row["BiddingStrategyType"] == "Target Outranking Share"
|| row["BiddingStrategyType"] == "None"
|| row["BiddingStrategyType"] == "unknown") {
Logger.log("Warning: keyword " + row["Criteria"] + "' in campaign '" + row["CampaignName"] +
"' uses '" + row["BiddingStrategyType"] + "' rather than manual CPC. This may overrule keyword bids and interfere with the script working.");
} else {
Logger.log("Warning: keyword " + row["Criteria"] + "' in campaign '" + row["CampaignName"] +
"' uses the bidding strategy '" + row["BiddingStrategyType"] + "' rather than manual CPC. This keyword will be skipped.");
continue;
}
}
var positionTarget = "";
if (row["Labels"].trim() == "--") {
continue;
}
var labels = JSON.parse(row["Labels"].toLowerCase()); // Labels are returned as a JSON formatted string
for (var i=0; i<labels.length; i++) {
if (labels[i].substr(0,"position ".length) == "position ") {
var positionTarget = parseFloat(labels[i].substr("position ".length-1).replace(/,/g,"."),10);
break;
}
}
if (positionTarget == "") {
continue;
}
if (integrityCheck(positionTarget) == -1) {
Logger.log("Invalid position target '" + positionTarget + "' for keyword '" + row["Criteria"] + "' in campaign '" + row["CampaignName"] + "'");
continue;
}
ids.push(parseFloat(row['Id'],10));
var uniqueId = row['AdGroupId'] + idJoin + row['Id'];
uniqueIds.push(uniqueId);
keywordData[uniqueId] = {};
keywordData[uniqueId]['Criteria'] = row['Criteria'];
keywordData[uniqueId]['ThisHour'] = {};
keywordData[uniqueId]['ThisHour']['Impressions'] = parseFloat(row['Impressions'].replace(/,/g,""),10);
keywordData[uniqueId]['ThisHour']['AveragePosition'] = parseFloat(row['AveragePosition'].replace(/,/g,""),10);
keywordData[uniqueId]['CpcBid'] = parseFloat(row['CpcBid'].replace(/,/g,""),10);
keywordData[uniqueId]['FirstPageCpc'] = parseFloat(row['FirstPageCpc'].replace(/,/g,""),10);
setPositionTargets(uniqueId, positionTarget);
}
Logger.log(uniqueIds.length + " labelled keywords found");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
setBidChange();
setMinMaxBids();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
/* var currentHour = parseInt(Utilities.formatDate(new Date(), AdWordsApp.currentAccount().getTimeZone(), "HH"), 10);
if (currentHour != 0) {
var data = file.getBlob().getDataAsString();
var data = data.split(lineJoin);
for(var i = 0; i < data.length; i++){
data[i] = data[i].split(fieldJoin);
var uniqueId = data[i][0];
if(keywordData.hasOwnProperty(uniqueId)){
keywordData[uniqueId]['LastHour'] = {};
keywordData[uniqueId]['LastHour']['Impressions'] = parseFloat(data[i][1],10);
keywordData[uniqueId]['LastHour']['AveragePosition'] = parseFloat(data[i][2],10);
}
}
}*/
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
findCurrentAveragePosition();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//Batch the keyword IDs, as the iterator can't take them all at once
var idBatches = [];
var batchSize = 5000;
for (var i=0; i<uniqueIds.length; i += batchSize) {
idBatches.push(uniqueIds.slice(i,i+batchSize));
}
Logger.log("Updating keywords");
// Update each batch
for (var i=0; i<idBatches.length; i++) {
try {
updateKeywords(idBatches[i]);
} catch (e) {
Logger.log("Error updating keywords: " + e);
Logger.log("Retrying after one minute.");
Utilities.sleep(60000);
updateKeywords(idBatches[i]);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Logger.log("Writing file.");
// var content = resultsString();
// file.setContent(content);
Logger.log("Finished.");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Functions
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function integrityCheck(target){
var n = parseFloat(target, 10);
if(!isNaN(n) && n >= 1){
return n;
}
else{
return -1;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function setPositionTargets(uniqueId, target){
if(target !== -1){
keywordData[uniqueId]['HigherPositionTarget'] = Math.max(target-targetPositionTolerance, 1);
keywordData[uniqueId]['LowerPositionTarget'] = target+targetPositionTolerance;
}
else{
keywordData[uniqueId]['HigherPositionTarget'] = -1;
keywordData[uniqueId]['LowerPositionTarget'] = -1;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function bidChange(uniqueId){
var newBid = -1;
if(keywordData[uniqueId]['HigherPositionTarget'] === -1){
return newBid;
}
var cpcBid = keywordData[uniqueId]['CpcBid'];
var minBid = keywordData[uniqueId]['MinBid'];
var maxBid = keywordData[uniqueId]['MaxBid'];
if (isNaN(keywordData[uniqueId]['FirstPageCpc'])) {
Logger.log("Warning: first page CPC estimate is not a number for keyword '" + keywordData[uniqueId]['Criteria'] + "'. This keyword will be skipped");
return -1;
}
var firstPageBid = Math.min(keywordData[uniqueId]['FirstPageCpc'], keywordData[uniqueId]['FirstPageMaxBid'], maxBid);
var currentPosition = keywordData[uniqueId]['CurrentAveragePosition'];
var higherPositionTarget = keywordData[uniqueId]['HigherPositionTarget'];
var lowerPositionTarget = keywordData[uniqueId]['LowerPositionTarget'];
var bidIncrease = keywordData[uniqueId]['BidIncrease'];
var bidDecrease = keywordData[uniqueId]['BidDecrease'];
if((currentPosition > lowerPositionTarget) && (currentPosition !== 0)){
var linearBidModel = Math.min(2*bidIncrease,(2*bidIncrease/lowerPositionTarget)*(currentPosition-lowerPositionTarget));
var newBid = Math.min((cpcBid + linearBidModel), maxBid);
}
if((currentPosition < higherPositionTarget) && (currentPosition !== 0)) {
var linearBidModel = Math.min(2*bidDecrease,((-4)*bidDecrease/higherPositionTarget)*(currentPosition-higherPositionTarget));
var newBid = Math.max((cpcBid-linearBidModel),minBid);
if (cpcBid > firstPageBid) {
var newBid = Math.max(firstPageBid,newBid);
}
}
if((currentPosition === 0) && useFirstPageBidsOnKeywordsWithNoImpressions && (cpcBid < firstPageBid)){
var newBid = firstPageBid;
}
if (isNaN(newBid)) {
Logger.log("Warning: new bid is not a number for keyword '" + keywordData[uniqueId]['Criteria'] + "'. This keyword will be skipped");
return -1;
}
return newBid;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function findCurrentAveragePosition(){
for(var x in keywordData){
if(keywordData[x].hasOwnProperty('LastHour')){
keywordData[x]['CurrentAveragePosition'] = calculateAveragePosition(keywordData[x]);
} else {
keywordData[x]['CurrentAveragePosition'] = keywordData[x]['ThisHour']['AveragePosition'];
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function calculateAveragePosition(keywordDataElement){
var lastHourImpressions = keywordDataElement['LastHour']['Impressions'];
var lastHourAveragePosition = keywordDataElement['LastHour']['AveragePosition'];
var thisHourImpressions = keywordDataElement['ThisHour']['Impressions'];
var thisHourAveragePosition = keywordDataElement['ThisHour']['AveragePosition'];
if(thisHourImpressions == lastHourImpressions){
return 0;
}
else{
var currentPosition = (thisHourImpressions*thisHourAveragePosition-lastHourImpressions*lastHourAveragePosition)/(thisHourImpressions-lastHourImpressions);
if (currentPosition < 1) {
return 0;
} else {
return currentPosition;
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function keywordUniqueId(keyword){
var id = keyword.getId();
var idsIndex = ids.indexOf(id);
if(idsIndex === ids.lastIndexOf(id)){
return uniqueIds[idsIndex];
}
else{
var adGroupId = keyword.getAdGroup().getId();
return adGroupId + idJoin + id;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function setMinMaxBids(){
for(var x in keywordData){
keywordData[x]['MinBid'] = minBid;
keywordData[x]['MaxBid'] = maxBid;
keywordData[x]['FirstPageMaxBid'] = firstPageMaxBid;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function setBidChange(){
for(var x in keywordData){
keywordData[x]['BidIncrease'] = keywordData[x]['CpcBid'] * bidIncreaseProportion/2;
keywordData[x]['BidDecrease'] = keywordData[x]['CpcBid'] * bidDecreaseProportion/2;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function updateKeywords(idBatch) {
var keywordIterator = AdWordsApp.keywords()
.withIds(idBatch.map(function(str){return str.split(idJoin);}))
.get();
while(keywordIterator.hasNext()){
var keyword = keywordIterator.next();
var uniqueId = keywordUniqueId(keyword);
var newBid = bidChange(uniqueId);
if(newBid !== -1){
keyword.setMaxCpc(newBid);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
/*function resultsString(){
var results = [];
for(var uniqueId in keywordData){
var resultsRow = [uniqueId, keywordData[uniqueId]['ThisHour']['Impressions'], keywordData[uniqueId]['ThisHour']['AveragePosition']];
results.push(resultsRow.join(fieldJoin));
}
return results.join(lineJoin);
}*/
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
}
As I understand, the script increases the cpcBid when the current average position is too high, and decreases it when the position is too low.
But when the bid is decreased and the previous bid is more than firstPageBid, the new bid will not decrease below firstPageBid.
Remove
if (cpcBid > firstPageBid) {
var newBid = Math.max(firstPageBid,newBid);
}
to allow your new bid to go lower than firstPageBid.
From the following question, I try to use part of the following code in an Adwords script
function runMe() {
var startTime= (new Date()).getTime();
//do some work here
var scriptProperties = PropertiesService.getScriptProperties();
var startRow= scriptProperties.getProperty('start_row');
for(var ii = startRow; ii <= size; ii++) {
var currTime = (new Date()).getTime();
if(currTime - startTime >= MAX_RUNNING_TIME) {
scriptProperties.setProperty("start_row", ii);
ScriptApp.newTrigger("runMe")
.timeBased()
.at(new Date(currTime+REASONABLE_TIME_TO_WAIT))
.create();
break;
} else {
doSomeWork();
}
}
//do some more work here
}
but I got ReferenceError: "PropertiesService" is not defined. (line 170) from google-apps-script. How could I fix that issue? Can you tell me if it works for you in Adwords?
UPDATED
Here is the function I build in considering the previous function :
function adjustCPCmax() {
//min CPC
var minCPC = 0.50;
var accountIterator = MccApp.accounts().get();
var mccAccount = AdWordsApp.currentAccount();
while(accountIterator.hasNext()) {
var account = accountIterator.next();
Logger.log('============================================== ' + account.getName() + ' ====================================================')
MccApp.select(account)
var campaignIterator = AdWordsApp.campaigns().get();
while (campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
try {
var maxCPC = getMaxCPC(account, campaign)
}
catch(e) {
}
if (maxCPC) {
var startTime= (new Date()).getTime();
Logger.log('The entrence worked with max CPC : ' + maxCPC + '\n')
keywordIterator = campaign.keywords().get();
while (keywordIterator.hasNext()) {
var keyword= keywordIterator.next()
var keywordId = Number(keyword.getId()).toPrecision()
Logger.log('THE NAME OF THE KEYWORDID IS ' + keywordId + '\n')
var report = AdWordsApp.report(
'SELECT Id, Criteria, CampaignName, CpcBid, FirstPageCpc, FirstPositionCpc, TopOfPageCpc, Criteria ' +
'FROM KEYWORDS_PERFORMANCE_REPORT ' +
'WHERE ' +
'Id = ' + keywordId);
var rows = report.rows();
while(rows.hasNext()) {
var row = rows.next();
var keywordIdReport = row['Id'];
var keywordNameReport = row['Criteria'];
var campaignName = row['CampaignName'];
var cpcBid = row['CpcBid'];
var firstPageCpc = row['FirstPageCpc'];
var firstPositionCpc = row['FirstPositionCpc'];
var topOfPageCpc = row['TopOfPageCpc'];
Logger.log('INFO')
Logger.log(keyword.getText())
Logger.log(keywordId)
Logger.log(keywordNameReport)
Logger.log(keywordIdReport + '\n')
if (keywordId === keywordIdReport) {
if (firstPositionCpc && (firstPositionCpc > 0 && firstPositionCpc <= maxCPC)) {
var newCPC = firstPositionCpc;
} else if (topOfPageCpc && (topOfPageCpc > 0 && topOfPageCpc <= maxCPC)) {
var newCPC = topOfPageCpc;
} else if (firstPageCpc && (firstPageCpc > 0 && firstPageCpc <= maxCPC )) {
var newCPC = firstPageCpc;
} else {
var newCPC = minCPC;
}
Logger.log('KeywordIdReport :' + keywordIdReport)
Logger.log('campaignName :' + campaignName)
Logger.log('CPCbid :' + cpcBid)
Logger.log('firstPositionCpc : ' + firstPositionCpc)
Logger.log('topOfPageCpc : ' + topOfPageCpc)
Logger.log('firstPageCpc : ' + firstPageCpc)
Logger.log('NewCPC : ' + newCPC + '\n')
keyword.bidding().setCpc(newCPC)
break;
}
}
var REASONABLE_TIME_TO_WAIT = 4*6000;
var MAX_RUNNING_TIME = 1*6000;
try {
var scriptProperties = PropertiesService.getScriptProperties();
}
catch(e){
Logger.log(e)
}
var startRow= scriptProperties.getProperty('start_row');
for(var ii = startRow; ii <= size; ii++) {
var currTime = (new Date()).getTime();
if(currTime - startTime >= MAX_RUNNING_TIME) {
scriptProperties.setProperty("start_row", ii);
ScriptApp.newTrigger("runMe")
.timeBased()
.at(new Date(currTime+REASONABLE_TIME_TO_WAIT))
.create();
break;
}
}
}
}
}
}
MccApp.select(mccAccount);
}
From that function, what could I do to fix that problem? It is bizarre because I could find documentation on the subject.
You are using AdWords Script which is different from Google Apps Script even though they share many APIs. Google Apps Script has access to Properties Service, AdWords Script does not. Evidence: the AdWords Script reference (screenshot) does not include Properties Service among Script Services.
You are using script properties to store one number, the current row number. An alternative is to store it in a spreadsheet, since AdWords Script has access to Spreadsheet service. So, at the beginning of the script you would have
var ss = SpreadsheetApp.openByUrl('...'); // url of some spreadsheet
var sheet = ss.getSheets()[0]; // first sheet in it
var cell = sheet.getRange("A1"); // storing the number in A1 cell
and then within the body of the script, replace
var startRow = scriptProperties.getProperty('start_row');
by
var startRow = cell.getValue() || 1; // 1 by default
and also replace
scriptProperties.setProperty("start_row", ii);
by
cell.setValue(ii);
This should do it.
Another angularJS question i have scope binding a click that should add one value on the first click ad another value on the second click but it just keeps returning and empty array and filling the first value again why? :
scope.dbclickalert = function (scope, $watch) {
var getCheckInDate = this.cellData.date;
var formatcheckindate = new Date(getCheckInDate);
var checkingdates = [];
var curr_datecell = formatcheckindate.getDate();
var padded_day = (curr_datecell < 10) ? '0' + curr_datecell : curr_datecell;
var curr_monthcell = formatcheckindate.getMonth() + 1;
var padded_month = (curr_monthcell < 10) ? '0' + curr_monthcell : curr_monthcell;
var curr_yearcell = formatcheckindate.getFullYear();
var date_stringcell = + padded_month + "/" + padded_day + "/" + curr_yearcell;
var checkindatestrg = "checkindate";
console.log(checkingdates.length);
if (checkingdates.length < 2) {
alert("element exists in array");
checkingdates.push('checkoutdate');
checkingdates.push(date_stringcell);
console.log(checkingdates + checkingdates.length);
} else {
checkingdates.push('checkindate');
checkingdates.push(date_stringcell);
}
var setCheckInDate = el.hasClass('checkInDate');
if (checkingdates === true) {
alert('You have allready set your check In Date');
} else {
el.addClass('checkInDate');
$('#checkoutbar').addClass('datePickerchecout');
}
$(".date-cell").each(function removeclasses() {
$(this).removeClass('true');
});
return getCheckInDate;
};
ok so when i declare this outside of the function i get undefined error:
scope.checkingdates = [];
scope.dbclickalert = function(scope, $watch){
var getCheckInDate = this.cellData.date;
var formatcheckindate = new Date(getCheckInDate);
var checkingdates = scope.checkingdates;
var curr_datecell = formatcheckindate.getDate();
var padded_day = (curr_datecell < 10) ? '0'+curr_datecell : curr_datecell;
var curr_monthcell = formatcheckindate.getMonth() + 1;
var padded_month = (curr_monthcell < 10) ? '0'+curr_monthcell : curr_monthcell;
var curr_yearcell = formatcheckindate.getFullYear();
var date_stringcell = + padded_month + "/" + padded_day + "/" + curr_yearcell;
var checkindatestrg = "checkindate";
console.log(checkingdates.length);
if (checkingdates.length < 2){
alert("element exists in array");
checkingdates.push('checkoutdate');
checkingdates.push(date_stringcell);
console.log(checkingdates+checkingdates.length);
}else{
checkingdates.push('checkindate');
checkingdates.push(date_stringcell);
}
var setCheckInDate = el.hasClass('checkInDate');
if (checkingdates === true){
alert('You have allready set your check In Date');
} else{
el.addClass('checkInDate');
$('#checkoutbar').addClass('datePickerchecout');
}
$(".date-cell").each(function removeclasses() {
$(this).removeClass('true');
});
return getCheckInDate;
};
ok in the third version of this it the same data "the date" again if the same div has been clicked but not if a second div with the same ng-click="dbclickalert()" is clicked why?
link: function(scope, el, attributes, dateSheetCtrl, $watch) {
scope.checkingdatesarry = [];
scope.dbclickalert = function(){
var getCheckInDate = this.cellData.date;
var formatcheckindate = new Date(getCheckInDate);
var checkingdates = scope.checkingdates;
var curr_datecell = formatcheckindate.getDate();
var padded_day = (curr_datecell < 10) ? '0'+curr_datecell : curr_datecell;
var curr_monthcell = formatcheckindate.getMonth() + 1;
var padded_month = (curr_monthcell < 10) ? '0'+curr_monthcell : curr_monthcell;
var curr_yearcell = formatcheckindate.getFullYear();
var date_stringcell = + padded_month + "/" + padded_day + "/" + curr_yearcell;
var checkindatestrg = "checkindate";
var checkoutdatestrg = "checkoutdate";
if( $.inArray('checkindate', scope.checkingdates) !== -1 ) {
scope.checkingdatesarry.push(checkoutdatestrg);
scope.checkingdatesarry.push(date_stringcell);
console.log(scope.checkingdatesarry + scope.checkingdatesarry.length);
}
else{
scope.checkingdatesarry.push(checkindatestrg);
scope.checkingdatesarry.push(date_stringcell);
console.log(scope.checkingdatesarry + scope.checkingdatesarry.length);
}
var setCheckInDate = el.hasClass('checkInDate');
if (scope.checkingdates === true){
alert('You have allready set your check In Date');
} else{
el.addClass('checkInDate');
$('#checkoutbar').addClass('datePickerchecout');
}
$(".date-cell").each(function removeclasses() {
$(this).removeClass('true');
});
return scope.checkingdatesarry;
};
ok for anyone that cares the answer was that because my div's where being created with a angularJS directive it was returning and array per div instead of one global array I have taken the array all the way out of the directive and moved it into a service and it works fine.
Because you redefined the array with empty list in the dbclickalert action. So every time when the action is triggered, the array will be empty.
var checkingdates = [];
You should move it outside the function and declare as
$scope.checkingdates = []; //In your code, you may use scope.checkingdates = []; if you renamed the $scope when you inject it
I have found similar threads about this but I cant seem to make their solutions work for my specific issue. I currently have a calendar that will highlight the starting date of an Event. I need to change this to highlight the Start Date through the End Date.
Note: I did not write this code. It seems like whoever wrote this left a lot of junk in here. Please don't judge.
attachTocalendar : function(json, m, y) {
var arr = new Array();
if (json == undefined || !json.month || !json.year) {
return;
}
m = json.month;
y = json.year;
if (json.events == null) {
return;
}
if (json.total == 0) {
return;
}
var edvs = {};
var kds = new Array();
var offset = en4.ynevent.getDateOffset(m, y);
var tds = $$('.ynevent-cal-day');
var selected = new Array(), numberOfEvent = new Array();
for (var i = 0; i < json.total; ++i) {
var evt = json.events[i];
var s1 = evt.starttime.toTimestamp();
var s0 = s1;
var s2 = evt.endtime.toTimestamp();
var ds = new Date(s1);
var de = new Date(s2);
var id = ds.getDateCellId();
index = selected.indexOf(id);
if (index < 0)
{
numberOfEvent[selected.length] = 1;
selected.push(id);
}
else
{
numberOfEvent[index] = numberOfEvent[index] + 1;
}
}
for (var i = 0; i < selected.length; i++) {
var td = $(selected[i]);
if (td != null) {
if (!(td.hasClass("otherMonth"))){
td.set('title', numberOfEvent[i] + ' ' + en4.core.language.translate(numberOfEvent[i] > 1 ? 'events' : 'event'));
td.addClass('selected');
}
}
}
},
Instead of trying to select them all, I recommend you iterate over them instead. So something like this:
function highlightDates(startDate, endDate) {
var curDate = startDate;
var element;
$('.selected').removeClass('selected'); // reset selection
while (curDate <= endDate) {
element = getElementForDate(curDate)
element.addClass('selected');
curDate.setDate(curDate.getDate() + 1); // add one day
}
}
function getElementForDate(someDate) {
return $('#day-' + someDate.getYear() + "-" + someDate.getMonth() + "-" + someDate.getDay());
}