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
}
}
I have a function that return something like [object object] no my value that I wanted , I do almost every thing to get the value but no hope.
When I try to show that object using toSource() I got something like that.
({state:(function (){return state;}), always:(function (){deferred.done(arguments).fail(arguments);return this;}), then:(function (){var fns=arguments;return jQuery.Deferred(function(newDefer){jQuery.each(tuples,function(i,tuple){var action=tuple[0],fn=fns[i];deferred[tuple[1]](jQuery.isFunction(fn)?function(){var returned=fn.apply(this,arguments);if(returned&&jQuery.isFunction(returned.promise)){returned.promise().done(newDefer.resolve).fail(newDefer.reject).progress(newDefer.notify);}else{newDefer[action+"With"](this===deferred?newDefer:this,[returned]);}}:newDefer[action]);});fns=null;}).promise();}), promise:(function (obj){return obj!=null?jQuery.extend(obj,promise):promise;}), pipe:(function (){var fns=arguments;return jQuery.Deferred(function(newDefer){jQuery.each(tuples,function(i,tuple){var action=tuple[0],fn=fns[i];deferred[tuple[1]](jQuery.isFunction(fn)?function(){var returned=fn.apply(this,arguments);if(returned&&jQuery.isFunction(returned.promise)){returned.promise().done(newDefer.resolve).fail(newDefer.reject).progress(newDefer.notify);}else{newDefer[action+"With"](this===deferred?newDefer:this,[returned]);}}:newDefer[action]);});fns=null;}).promise();}), done:(function (){if(list){var start=list.length;(function add(args){jQuery.each(args,function(_,arg){var type=jQuery.type(arg);if(type==="function"){if(!options.unique||!self.has(arg)){list.push(arg);}}else if(arg&&arg.length&&type!=="string"){add(arg);}});})(arguments);if(firing){firingLength=list.length;}else if(memory){firingStart=start;fire(memory);}}
return this;}), fail:(function (){if(list){var start=list.length;(function add(args){jQuery.each(args,function(_,arg){var type=jQuery.type(arg);if(type==="function"){if(!options.unique||!self.has(arg)){list.push(arg);}}else if(arg&&arg.length&&type!=="string"){add(arg);}});})(arguments);if(firing){firingLength=list.length;}else if(memory){firingStart=start;fire(memory);}}
return this;}), progress:(function (){if(list){var start=list.length;(function add(args){jQuery.each(args,function(_,arg){var type=jQuery.type(arg);if(type==="function"){if(!options.unique||!self.has(arg)){list.push(arg);}}else if(arg&&arg.length&&type!=="string"){add(arg);}});})(arguments);if(firing){firingLength=list.length;}else if(memory){firingStart=start;fire(memory);}}
return this;})})
Could any one explain me? And I know my function is Asynchronous.
How could solve this problem ?
Here is my code:
module.Order = Backbone.Model.extend({
initialize: function (attributes) {
Backbone.Model.prototype.initialize.apply(this, arguments);
this.pos = attributes.pos;
this.sequence_number = this.pos.pos_session.sequence_number++;
debugger;
var odoo = []
var call = this
this.uid = this.generateUniqueId();
this.pro = this.get_the_other_main().done(
function (result) {
}).always(function (result) {
odoo.push(result)
call.set({
creationDate: new Date(),
orderLines: new module.OrderlineCollection(),
paymentLines: new module.PaymentlineCollection(),
name: _t("Order ") + this.uid,
client: null,
sales_person: null,
sales_person_name: null,
new_id: odoo[0]
})});
alert(odoo[0])//// Must be adddddedd
this.selected_orderline = undefined;
this.selected_paymentline = undefined;
this.screen_data = {}; // see ScreenSelector
this.receipt_type = 'receipt'; // 'receipt' || 'invoice'
this.temporary = attributes.temporary || false;
return this;
},
get_the_other_main: function () {
var dfd = new jQuery.Deferred();
new instance.web.Model("pos.order").call('get_the_product', []).done(
function (results) {
var result = results.toString().split(',');
var stringsl = result[1];
var thenum = stringsl.replace(/^\D+/g, '');
var sasa = parseInt(thenum, 10) + 1
var zika = ('00' + sasa).slice(-4)
var the_str = result[1].slice(0, -4).toString();
var new_seq_sasa = the_str + zika
dfd.resolve(new_seq_sasa);
}).always(function(results) {
var result = results.toString().split(',');
var stringsl = result[1];
var thenum = stringsl.replace(/^\D+/g, '');
var sasa = parseInt(thenum, 10) + 1
var zika = ('00' + sasa).slice(-4)
var the_str = result[1].slice(0, -4).toString();
var new_seq_sasa = the_str + zika
dfd.resolve(new_seq_sasa);
}).always(function(results) {
var result = results.toString().split(',');
var stringsl = result[1];
var thenum = stringsl.replace(/^\D+/g, '');
var sasa = parseInt(thenum, 10) + 1
var zika = ('00' + sasa).slice(-4)
var the_str = result[1].slice(0, -4).toString();
var new_seq_sasa = the_str + zika
dfd.resolve(new_seq_sasa);
});
alert('')////If i remove that it will return undefind for this.pos
return dfd
You seem to have problem of asynchronous call.
(see the comments below)
// you call get_the_other_main which return a Promise !
this.get_the_other_main().then(
function (result) {
// when the Promise resolve you set this.pro,
// what is this here ?? are you sure of the beahviour ?
// |
// V
this.pro=result//got it right <---------------------- +
// |
// |
});// |
// You set this.pro to another Promise, at this moment the previous this.pro is not set !
this.pro=this.get_the_other_main().then(
function (result) {
this.pro=result //got it right <----------------------------------------+
}); // |
// when you call alert, this.pro is a Promise not resolved !at this moment the previous this.pro is not set !
alert(this.pro.toSource()) //[object object]
// logicaly it show the code source of your deffered / Promise !
to solve your issue try like that :
module.Order = Backbone.Model.extend({
initialize: function(attributes) {
var curOrder = this;
Backbone.Model.prototype.initialize.apply(this, arguments);
this.pos = attributes.pos;
this.sequence_number = this.pos.pos_session.sequence_number++;
debugger; // ??????
this.uid = this.generateUniqueId();
var odoo = []
this.get_the_other_main().then(
function(result) {
curOrder.pro = result; //got it right
curOrder.set({
creationDate : new Date(),
orderLines : new module.OrderlineCollection(),
paymentLines : new module.PaymentlineCollection(),
name : _t("Order ") + curOrder.uid,
client : null,
sales_person : null,
sales_person_name: null,
new_id : curOrder.pro
});
curOrder.selected_orderline = undefined;
curOrder.selected_paymentline = undefined;
curOrder.screen_data = {}; // see ScreenSelector
curOrder.receipt_type = 'receipt'; // 'receipt' || 'invoice'
curOrder.temporary = attributes.temporary || false;
curOrder.trigger('orderready' , curOrder);
});
return this;
// be careful because the process above is not done again, when you return this, it will be resolved later
},
get_the_other_main: function() {
var dfd = new jQuery.Deferred();
new instance.web.Model("pos.order").call('get_the_product', []).done(
function(results) {
var result = results.toString().split(',');
var stringsl = result[1];
var thenum = stringsl.replace(/^\D+/g, '');
var sasa = parseInt(thenum, 10) + 1
var zika = ('00' + sasa).slice(-4)
var the_str = result[1].slice(0, -4).toString();
var new_seq_sasa = the_str + zika
dfd.resolve(new_seq_sasa);
});
return dfd
},
I am using this version of the store locator https://github.com/googlemaps/js-store-locator
I would like to display the distance to each location once the user has submitted their search input (Enter a location). https://googlemaps.github.io/js-store-locator/examples/panel.html
I tried creating a duplicate of storeLocator.Store.prototype.distanceTo on line 441 of http://pastebin.com/ZGrWN6ib
storeLocator.Store.prototype.distanceTo = function(a) {
var b = this.getLocation(),
c = storeLocator.toRad_(b.lat()),
d = storeLocator.toRad_(b.lng()),
b = storeLocator.toRad_(a.lat()),
e = storeLocator.toRad_(a.lng());
a = b - c;
d = e - d;
c = Math.sin(a / 2) * Math.sin(a / 2) + Math.cos(c) * Math.cos(b) * Math.sin(d / 2) * Math.sin(d / 2);
return 12742 * Math.atan2(Math.sqrt(c), Math.sqrt(1 - c))
};
I am able to pass the first parameter but the second parameter var b = this.getLocation() keeps coming up as undefined
Can I check to see to see if the user location is set, and if so run the function? or do i need to hook into one of the listeners?
if(!this.getLocation()){
return 0;
}
else {
var b = this.getLocation(),
c = storeLocator.toRad_(b.lat()),
d = storeLocator.toRad_(b.lng()),
b = storeLocator.toRad_(a.lat()),
e = storeLocator.toRad_(a.lng());
a = b - c;
d = e - d;
c = Math.sin(a / 2) * Math.sin(a / 2) + Math.cos(c) * Math.cos(b) * Math.sin(d / 2) * Math.sin(d / 2);
return 12742 * Math.atan2(Math.sqrt(c), Math.sqrt(1 - c));
}
You are using this.getLocation(), that means your file has to be a storeLocator.Store.prototype.
The getLocation() method probably belongs to the store-locator.min.js, which should be included in your html file, maybe thats why you can not find the getLocation() method.
In the Google Maps GitHub example page, the store-locator.min.js is included in the panel.html file.
From this example folder, you can see the structure of files.
Got it! So if you want to display the distance in the store list view here's what you can do:
First beautify the store-locator.min.js file for easier reading with something like http://jsbeautifier.org/
Then modify this portion of function storeLocator.Panel.prototype.init_
if (b.geometry) {
this.directionsFrom_ = b.geometry.location;
a.directionsVisible_ && a.renderDirections_();
var c = a.get("view");
c.highlight(null);
var d = c.getMap();
b.geometry.viewport ? d.fitBounds(b.geometry.viewport) : (d.setCenter(b.geometry.location), d.setZoom(12));
c.refreshView();
a.listenForStoresUpdate_();
// New Addition
// You will need to create helper functions to set the cookie, i will include below
storeLocator.setCookie("searchAddy",b.geometry.location,1);
// End New Addition
} else a.searchPosition(b.name)
Then add this function right above storeLocator.Panel.prototype.stores_changed
storeLocator.Panel.prototype.ifDistanceFrom = function(b) {
var str = storeLocator.getCookie('searchAddy');
var regex = /\((-?[0-9]+\.[0-9]+), (-?[0-9]+\.[0-9]+)\)/g;
var latlonArray = [];
var match = regex.exec(str);
while (match) {
latlonArray.push({
"lat" : match[1],
"lon" : match[2]
});
match = regex.exec(str);
};
var a = new google.maps.LatLng(latlonArray[0].lat,latlonArray[0].lon),
b = b.getLocation(),
c = storeLocator.toRad_(b.lat()),
d = storeLocator.toRad_(b.lng()),
b = storeLocator.toRad_(a.lat()),
e = storeLocator.toRad_(a.lng());
a = b - c;
d = e - d;
c = Math.sin(a / 2) * Math.sin(a / 2) + Math.cos(c) * Math.cos(b) * Math.sin(d / 2) * Math.sin(d / 2);
return 12742 * Math.atan2(Math.sqrt(c), Math.sqrt(1 - c));
};
Now modify this portion of function storeLocator.Panel.prototype.stores_changed
for (var b = function() {
a.highlight(this.store, !0)
}, e = 0, f = Math.min(10, c.length); e < f; e++) {
var g = c[e].getInfoPanelItem();
g.store = c[e];
// New Addition
if(storeLocator.checkCookie() != null) {
var distance = this.ifDistanceFrom(g.store);
$(g).find('input').val(distance.toFixed(1));
}
else {
$(g).find('.dist-span').hide();
}
// End New Addition
d && c[e].getId() == d.getId() && $(g).addClass("highlighted");
g.clickHandler_ || (g.clickHandler_ = google.maps.event.addDomListener(g, "click", b));
this.storeList_.append(g)
}
Lastly modify your Data Feed file DataSource.prototype.parse_ function
DataSource.prototype.parse_ = function(csv) {
var stores = [];
var rows = csv.split('\n');
var headings = this.parseRow_(rows[0]);
for (var i = 1, row; row = rows[i]; i++) {
row = this.toObject_(headings, this.parseRow_(row));
var features = new storeLocator.FeatureSet;
// If you have features
features.add(this.FEATURES_.getById('featureName1-' + featureName1));
// New Addition
var distInput = "<span class='dist-span'>Distance: <input class='dist-input' value='' size='2' type='text' /> mi.</span>"
// End New Addition
var position = new google.maps.LatLng(row.Ycoord, row.Xcoord);
var shop = this.join_([row.Street_add], ', ');
var locality = row.Locality+', '+row.State+' '+row.Postcode;
var store = new storeLocator.Store(row.Fcilty_typ, position, features, {
title: row.Fcilty_nam,
// New Addition
address: this.join_([shop, locality, distInput], '<br>'),
// End New Addition
hours: row.Hrs_of_bus
});
stores.push(store);
}
return stores;
};
Below are the helper functions you will need to add to store-locator.min.js for setting the cookie.
storeLocator.setCookie = function(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires="+d.toUTCString();
document.cookie = cname + "=" + cvalue + "; " + expires;
// alert('Cookie set: '+ cvalue);
};
storeLocator.getCookie = function (cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1);
if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
};
return "";
};
storeLocator.checkCookie = function () {
var a = storeLocator.getCookie("searchAddy");
if (a != "") {
return 1;
}
else {
return null;
}
};
Inside the DataSource.prototype.parse_ function I added a new div element within the misc parameter, and used the store id as a unique div class.
var id = row.name.toLowerCase().replace(/[\. ,:-]+/g, '-');
var position = new google.maps.LatLng(row.latitude, row.longitude);
var locality = this.join_([row.state, row.postal_code], ', ');
var store = new storeLocator.Store(id, position, features, {
title: row.name,
address: this.join_([row.street, locality], '<br>'),
phone: row.phone_number,
misc: '<div class="distance '+id+'"></div>',
});
And then inside the DataSource.prototype.toObject_ I just added some jQuery for updating the text when a location is searched.
var panelDiv = document.getElementById('panel');
var panel = new storeLocator.Panel(panelDiv, {
view: view
});
google.maps.event.addListener(panel, 'geocode', function(result) {
panel.stores.forEach(function(store){
var distance = Math.round(store.distanceTo(result.geometry.location));
jQuery('.distance').each(function(){
if (jQuery(this).hasClass(store.getId())) {
jQuery(this).text(distance);
}
});
});
});
There's probably a better way, but this worked in my case.
I'm not very familiar with js and now I need to do something very important for me, but I really don't know how to do it.
I'd like to include google translation api to my site, but I need to change some code in their js files. I have the element.js file on local host:
(function () {
var d = window,
e = document,
f = ".",
g = "UTF-8",
h = "complete",
k = "head",
l = "link",
m = "script",
n = "stylesheet",
p = "text/css",
q = "text/javascript";
Math.random();
function r(b) {
var a = e.getElementsByTagName(k)[0];
a || (a = e.body.parentNode.appendChild(e.createElement(k)));
a.appendChild(b)
}
function _loadJs(b) {
var a = e.createElement(m);
a.type = q;
a.charset = g;
a.src = b;
r(a)
}
function _loadCss(b) {
var a = e.createElement(l);
a.type = p;
a.rel = n;
a.charset = g;
a.href = b;
r(a)
}
function _isNS(b) {
b = b.split(f);
for (var a = d, c = 0; c < b.length; ++c) if (!(a = a[b[c]])) return !1;
return !0
}
function _setupNS(b) {
b = b.split(f);
for (var a = d, c = 0; c < b.length; ++c) a = a[b[c]] || (a[b[c]] = {});
return a
}
d.addEventListener && "undefined" == typeof e.readyState && d.addEventListener("DOMContentLoaded",
function () {
e.readyState = h
}, !1);
if (_isNS('google.translate.Element')) {
return
}
var c = _setupNS('google.translate._const');
c._cl = 'en';
c._cuc = 'googleSectionalElementInit';
c._cac = '';
c._cam = '';
var h = 'translate.googleapis.com';
var b = (window.location.protocol == 'https:' ? 'https://' : 'http://') + h;
c._pah = h;
c._pbi = b + '/translate_static/img/te_bk.gif';
c._pci = b + '/translate_static/img/te_ctrl3.gif';
c._phf = h + '/translate_static/js/element/hrs.swf';
c._pli = b + '/translate_static/img/loading.gif';
c._plla = h + '/translate_a/l';
c._pmi = b + '/translate_static/img/mini_google.png';
c._ps = b + '/translate_static/css/sectionalelement.css';
c._puh = 'translate.google.com';
_loadCss(c._ps);
_loadJs(b + '/translate_static/js/element/main_se.js');
})();
(If it's important, link to this file from web page is "element.js?cb=googleSectionalElementInit&ug=section&hl=en" )
And I need to get main_se.js (the last link in the file) on localhost too, but I don't know how to change link in element.js to this file to make it local. I need it, because I have to replace some html tags in this file to make api work properly for me.
Hope that somebody will advice me what to do.
If I understand correctly, elements.js produces a <script tag with src pointing to translate.googleapi.com and you want it to point to localhost.
The answer is quite easy in this case, simply remove the b+ as b is http://translate.googlapi.com you will get the following script tag
<script src="/transalte_static/js/element/main_se.js"></script>
All you have to do now, it make sure you return the right file (your localhost copy) from this path.
Let me know if you need anything else.
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.