error with javascript globals and jquery call back functions - javascript

i'm trying to make an array of value's to be checked to see if that value has been added before.
if it has show an alert.
if it hasn't added it to the array and conduct a post ajax query to the server to retrieve a corresponding table row.
i'm mostly a novice when it comes to javascript and i'm finding it hard to debug because a fault in syntax breaks the entire script.
here is my code if someone see's an error could u tell me how to fix it.
also if you know a program to help with debugging java-script that would be really helpful.
I know that the jquery calls work fine because i added in the array check afterwards.
var selectedProductsArray = new array();
var selectedProductsCount = 0;
$(function() {
$('.selectProductID').live('click', function(event) {
var count = 0;
var found = false;
while(count < selectedProductsCount)
{
if(selectedProductsArray[count] == $(this).val())
{
found = true;
break;
}
count++;
}
if(found)
{
alert("you can only add one line for each product.");
}else{
selectedProductsArray[selectedProductsCount] = $(this).val();
selectedProductsCount++;
$.post("order/getitem", "ProductID="+$(this).val(), function(data){
$("#orderItems tbody").append(data);
selectedProductsCount++;
});
}
return false;
});
});

Firstly, there is no "array" class so I'm surprised that you even getting passed that; you want:
var selectedProductsArray = new Array();
or
var selectedProductsArray = [ ];
Also, you don't need to keep computing $(this).val() over and over again, you should just say:
var count = 0;
var found = false;
var value = $(this).val();
above the while loop and reference value instead of $(this).val() in the rest. You're also incrementing selectedProductsCount twice when I think you only want to do it once, this will leave empty/null entries in your selectedProductsArray and that might confuse things later on.
I can't eye-ball any other glaring errors but that new array() one should be a show stopper. Hard to say without a fully functioning example.
Does order/getitem get called? Does it send anything back?
For debugging and trying things out:
Firebug
jsfiddle

Related

Querying from an API to a Google Spreadsheet / G Apps Script and obtaining filtered results

I'm trying to build a spreadsheet based around DataDT's excellent API for 1-minute Forex data. I'm trying to build a function that 1) Reads a value ("Date time") from a cell 2) Searches for that value in a given URL from the aforementioned API 3) Prints 2 other properties (open & close price) for that same date.
In other words, It would take input from rows N and O, and output the relevant values (OPEN and CLOSE from the API) in rows H and I.
(Link to current GSpreadsheet)
This spreadsheet would link macroeconomic news and historic prices and possibly reveal useful insights for Forex users.
I already managed to query data from the API effectively but I can't find a way to filter only for the datetimes I'm asking. Much less iterating for different dates! With the help from user #Cooper I got the following code that can query entire pages from the API but can't efficiently filter yet. I'd appreciate any help that you might provide.
This is the current status of the code in Appscript:
(Code.gs)
function searchOnEdit(e) {
//e.source.toast('Entry');// I use these lines for debugging
var sh=e.range.getSheet();
if(sh.getName()!='API') return;
var checkedValue='TRUE';//these are the defaults if you install the checkboxes from the Insert Menu
var uncheckedValue='FALSE';
if(e.range.columnStart==17 && e.range.rowStart>1 && e.value==checkedValue) {
e.range.setValue(uncheckedValue);//this was commented out it should not have been sorry for that Cooper
//e.source.toast('flag1');
var r=sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getValues()[0];
var obj={datetime:r[14],url:r[13],event:e};
var dObj=getDataDT1(obj);
//Logger.log(dObj);
sh.getRange(e.range.rowStart,4).setValue(dObj.OPEN);//loading OPEN on your spreadsheet
sh.getRange(e.range.rowStart,5).setValue(dObj.CLOSE);//loadding CLOSE on your spreadsheet
}
}
//{datetime:'',url:'',event:e}
function getDataDT1(obj) {
Logger.log(JSON.stringify(obj));//I need to see this
var r=UrlFetchApp.fetch(obj.url);
var data=JSON.parse(r.getContentText("UTF-8"));
//Logger.log(data);
var pair='USDJPY';
var dat=new Date(obj.datetime);
var dtv=new Date(dat.getFullYear(),dat.getMonth(),dat.getDate(),dat.getHours(),dat.getMinutes()).valueOf();
for(var i=0;i<data.length;i++) {
var dt=data[i].DATE_TIME.split(' ');
var sd=new Date(data[i].DATE_TIME);
var sdv=new Date(sd.getFullYear(),sd.getMonth(),sd.getDate(),sd.getHours(),sd.getMinutes()).valueOf();
if(sdv==dtv) {
var d=dt[0].split('-');
var t=dt[1].split(':');
var datestring=Utilities.formatString('%s/%s/%s',d[1],d[2],d[0]);
var timestring=Utilities.formatString('%s:%s',t[0],t[1]);
var rObj={DATE:datestring,TIME:timestring,PAIR:pair,OPEN:data[i].OPEN.toFixed(3),CLOSE:data[i].CLOSE.toFixed(3)};
break;
}
}
//Logger.log(rObj);
return rObj;
}
(Appscript.json)
{
"timeZone": "America/Caracas",
"dependencies": {
},
"exceptionLogging": "STACKDRIVER",
"oauthScopes": ["https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/script.external_request","https://www.googleapis.com/auth/script.scriptapp","https://www.googleapis.com/auth/spreadsheets"]
}
(Trigger.js)
function createSearchOnEditTrigger() {
var ss=SpreadsheetApp.getActive();
ScriptApp.newTrigger('searchOnEdit').forSpreadsheet(ss.getId()).onEdit().create();
}
onEdit Search
You will need to add a column of checkboxes to column 17 and also create an installable onEdit trigger. You may use the code provided or do it manually via the Edit/Project Triggers menu. When using the trigger creation code please check to insure that only one trigger was creates as multiple triggers can cause problems.
Also, don't make the mistake of naming your installable trigger onEdit(e) because it will respond to the simple trigger and the installable trigger causing problems.
I have an animation below showing you how it operates and also you can see the spreadsheet layout as well. Please notice the hidden columns. I had to do that to make the animation as small as possible. But I didn't delete any of your columns.
It's best to wait for the the check box to get reset back to off before checking another check box. It is possible to check them so fast that script can't keep up and some searches may be missed.
I also had to add these scopes manually:
"oauthScopes":["https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/script.external_request","https://www.googleapis.com/auth/spreadsheets"]
You can put them into your appsscript.json file which is viewable using the View/Show Manifest File. Here's a reference that just barely shows you what they look like. But the basic idea is to put a comma after the last entry before the closing bracket and add the needed lines.
After you have created the trigger it's better to go into View/Current Project triggers and set the Notifications to Immediate. If you get scoping errors it will tell you which ones to add. You add them and then run a function and you can reauthorize the access with the additional scopes. You can even run a null function like function dummy(){};.
This is the onEdit function:
function searchOnEdit(e) {
//e.source.toast('Entry');// I use these lines for debugging
var sh=e.range.getSheet();
if(sh.getName()!='API') return;
var checkedValue='TRUE';//these are the defaults if you install the checkboxes from the Insert Menu
var uncheckedValue='FALSE';
if(e.range.columnStart==17 && e.range.rowStart>1 && e.value==checkedValue) {
e.range.setValue(uncheckedValue);
//e.source.toast('flag1');
var r=sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getValues()[0];
var obj={datetime:r[14],url:r[13],event:e};//you dont really need e here
var dObj=getDataDT1(obj);
//Logger.log(dObj);
sh.getRange(e.range.rowStart,4).setValue(dObj.OPEN);//loading OPEN on your spreadsheet
sh.getRange(e.range.rowStart,5).setValue(dObj.CLOSE);//loadding CLOSE on your spreadsheet
}
}
This is the search function. I tried caching the data but it was too large. So if you can reduce the size significantly that would help speed things up for consecutive searches.
//{datetime:'',url:'',event:e}
function getDataDT1(obj) {
var r=UrlFetchApp.fetch(obj.url);
var data=JSON.parse(r.getContentText("UTF-8"));
//Logger.log(data);
var pair='USDJPY';
var dat=new Date(obj.datetime);
var dtv=new Date(dat.getFullYear(),dat.getMonth(),dat.getDate(),dat.getHours(),dat.getMinutes()).valueOf();
for(var i=0;i<data.length;i++) {
var dt=data[i].DATE_TIME.split(' ');
var sd=new Date(data[i].DATE_TIME);
var sdv=new Date(sd.getFullYear(),sd.getMonth(),sd.getDate(),sd.getHours(),sd.getMinutes()).valueOf();
if(sdv==dtv) {
var d=dt[0].split('-');
var t=dt[1].split(':');
var datestring=Utilities.formatString('%s/%s/%s',d[1],d[2],d[0]);
var timestring=Utilities.formatString('%s:%s',t[0],t[1]);
var rObj={DATE:datestring,TIME:timestring,PAIR:pair,OPEN:data[i].OPEN.toFixed(3),CLOSE:data[i].CLOSE.toFixed(3)};
break;
}
}
//Logger.log(rObj);
return rObj;
}
This is the create Trigger function. Becareful not to run this more than once and always go check to see that there is only one and set the notifications to immediate when you first turn it on so you'll get emails pretty quickly after errors occur.
function createSearchOnEditTrigger() {
var ss=SpreadsheetApp.getActive();
ScriptApp.newTrigger('searchOnEdit').forSpreadsheet(ss.getId()).onEdit().create();
}
Animation:
This is a copy of your spreadsheet with the check boxes.
If you have any difficulties feel free to come back and get some help. I know some of this stuff sounds a bit daunting but it's kind of like going metric. Once you've measured and weighed a few things it begins to sound and feel natural.
Here's my code exactly as I have it in my script which is running right now. Perhaps I have a typo in it due to editing in comments. This has some debugging lines in which run the Logger and display toasts which you should probably comment out.
function searchOnEdit(e) {
e.source.toast('Entry');
var sh=e.range.getSheet();
if(sh.getName()!='API') return;
var checkedValue='TRUE';
var uncheckedValue='FALSE';
if(e.range.columnStart==17 && e.range.rowStart>1 && e.value==checkedValue) {
e.range.setValue(uncheckedValue);
e.source.toast('flag1');
var r=sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getValues()[0];
var obj={datetime:r[14],url:r[13],event:e};
var dObj=getDataDT1(obj);
Logger.log(dObj);
sh.getRange(e.range.rowStart,4).setValue(dObj.OPEN);
sh.getRange(e.range.rowStart,5).setValue(dObj.CLOSE);
}
}
//{datetime:'',url:''}
function getDataDT1(obj) {
var r=UrlFetchApp.fetch(obj.url);
var data=JSON.parse(r.getContentText("UTF-8"));
//Logger.log(data);
var pair='USDJPY';
var dat=new Date(obj.datetime);
var dtv=new Date(dat.getFullYear(),dat.getMonth(),dat.getDate(),dat.getHours(),dat.getMinutes()).valueOf();
for(var i=0;i<data.length;i++) {
var dt=data[i].DATE_TIME.split(' ');
var sd=new Date(data[i].DATE_TIME);
var sdv=new Date(sd.getFullYear(),sd.getMonth(),sd.getDate(),sd.getHours(),sd.getMinutes()).valueOf();
if(sdv==dtv) {
var d=dt[0].split('-');
var t=dt[1].split(':');
var datestring=Utilities.formatString('%s/%s/%s',d[1],d[2],d[0]);
var timestring=Utilities.formatString('%s:%s',t[0],t[1]);
var rObj={DATE:datestring,TIME:timestring,PAIR:pair,OPEN:data[i].OPEN.toFixed(3),CLOSE:data[i].CLOSE.toFixed(3)};
break;
}
}
//Logger.log(rObj);
return rObj;
}
function createSearchOnEditTrigger() {
var ss=SpreadsheetApp.getActive();
ScriptApp.newTrigger('searchOnEdit').forSpreadsheet(ss.getId()).onEdit().create();
}

Cannot get ExecuteScriptAsync() to work as expected

I'm trying to set a HTML input to read-only using ExecuteScriptAsync. I can make it work, but it's not an ideal scenario, so I'm wondering if anyone knows why it doesn't work the way I would expect it to.
I'm using Cef3, version 63.
I tried to see if it's a timing issue and doesn't appear to be.
I tried invalidating the view of the browser but that doesn't seem to help.
The code I currently have, which works:
public void SetReadOnly()
{
var script = #"
(function(){
var labelTags = document.getElementsByTagName('label');
var searchingText = 'Notification Initiator';
var found;
for (var i=0; i<labelTags.length; i++)
{
if(labelTags[i].textContent == searchingText)
{
found = labelTags[i]
break;
}
}
if(found)
{
found.innerHTML='Notification Initiator (Automatic)';
var input;
input = found.nextElementSibling;
if(input)
{
input.setAttribute('readonly', 'readonly');
}
}})()
";
_viewer.Browser.ExecuteScriptAsync(script);
_viewer.Browser.ExecuteScriptAsync(script);
}
now, if I remove
found.innerHTML='Notification Initiator (Automatic)';
the input is no longer shown as read-only. The HTML source of the loaded webpage does show it as read-only, but it seems like the frame doesn't get re-rendered once that property is set.
Another issue is that I'm executing the script twice. If I run it only once I don't get the desired result. I'm thinking this could be a problem with V8 Context that is required for the script to run. Apparently running the script will create the context, so that could be the reason why running it twice works.
I have been trying to figure this out for hours, haven't found anything that would explain this weird behaviour. Does anyone have a clue?
Thanks!

Edit checkboxes based on url on page back

I have been struggling for a few hours with something that sounds very simple.
What i have is a list of checkboxes, if a checkbox is checked the page url will change (to save a filter option, so you can share the url to the filter). It works perfectly except one point, when the user wants to go back. the checkboxes should be unchecked.
Using jQuery
setBoxes() is the function;
I tried:
function pageLoad() {
setBoxes();
}
And
$(document).ready(function(){
setBoxes();
}
Also I added
window.onunload = function(){};
But none of these solutions worked ( the function doesn't run, i checked it).
After that I thought I might could do it with php (get the url to an array, if in the array echo checked), but php wont run again (I guess its cashed).
Is there any option i can try cause I really cant solve this simple looking problem.
because my code is very big I made a very small example http://jsfiddle.net/yzoztp05/1/ of the situation, updating the url in jsfiddle is blocked so it doesn't work completely.
To make the situation more clear i made a video https://www.youtube.com/watch?v=jaSc1fmaJD4&feature=youtu.be.
the code to set my checkboxes
//convert the url to array
function getQueryVariable(variable)
{
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
}
return(false);
}
// Set the checkboxes to checked if they are in the array
function setBoxes()
{
var prijsUrl = getQueryVariable("prijs");
// first set all checkboxes on unchecked
$('.prijsFilterBox').prop('checked', false);
alert("Loaded");
if(prijsUrl != false)
{
var res = prijsUrl.split("-");
for(var i = 0; i < res.length; i++ )
{
$('.prijsFilterBox[value='+res[i]+']').prop('checked', true);
console.log("prijs = "+res[i]);
}
}
else
{
console.log("prijs = null");
}
}
It works if I refresh the page, but it wont run on when user presses the back button. If its not possible to run javascript on page back I will try to make a different script with php.
TLDR
How can i run a jquery function on page back (all browsers)?
It may be possible ( and I think that many are using this way ) to have timeOut function that is called every 500ms that checks if URL has changed, but instead of using '?' use hash '#' so user is always on same page and you can catch URL change.
If you need to stick to '?' , maybe you could do something with window.onbeforeunload function.

"Can't execute code from a freed script" in IE8 using Javascript w/Prototype

This is my first question on here so here goes....
I've got an issue in IE8 where I have a popup form (window.showDialog()) used to edit receipt information in an accounting system.
This was working fine up until I had to add more content by adding a dynamically built table of input fields. I'm getting the information back in an array, however that's where my error seems to be occurring. var pinputs = []; is what seems to be causing the issue.
js function in the popup form:
function saveForm() {
if($('user_id')){
var user_id = $F('user_id');
} else {
var user_id = 0;
}
var payments = $$('.payment');
var pinputs = [];
for(var i=0; i<payments.length; i++){
pinputs.push($F(payments[i]));
}
window.returnValue = {received_of: $F('received_of'), user_id: user_id,
note: $F('note'), work_date: $F('work_date'), payment: pinputs};
window.close();
}
js function in the parent js file:
function modifyReceiptInformation(id) {
return window.showModalDialog('mod.php?mod=receipts&mode=receipt_edit_popup&wrapper=no&receipt_id=' + id, 'Modify Receipt',"dialogWidth:600px;dialogHeight:500px");
}
I found a similar situation already on here but that was involving the calling of functions from the child form which I'm not doing here. Perhaps I didn't understand the solution? I'm not an expert with JS so any input will be helpful.
--Edit--
Forgot to also add in here that the var payments = $$('.payment'); is the array of input fields in my template file.
You're probably trying to access methods on the array returned by the popup after the popup is closed. That returned array was constructed on the popup, and is dependent on the popup still existing to be usable.
So you have a few options:
don't close the popup from within the popup script. Get your parent handler to do what it needs with the array (such as cloning it in an array of its own with [].concat(popupArray) for example), then have it close the popup.
convert your array to a string to cross the popup/parent boundary. JSON.stringify()/JSON.parse() would do the job nicely if you don't care about IE6/7. That way, you can still close the popup from within the popup script (apparently, string objects don't get that particular problem with IE.)
I had the same problem, so I wrote this handy function to work around the issue.
// The array problem is when modalDialogue return values are arrays. The array functions
// such as slice, etc... are deallocated when the modal dialogue closes. This is an IE bug.
// The easiest way to fix this is to clone yourself a new array out of the remnants of the old.
//
// #param[in] ary
// The array, which has been passed back from a modal dialogue (and is broken) to clone
// #returns
// A new, unbroken array.
function cloneArray(ary) {
var i;
var newAry = [];
for(i=0; i<ary.length; i++){
if(Object.prototype.toString.call(ary[i]) == '[object Array]') {
newAry.push(cloneArray(ary[i]));
} else{
newAry.push(ary[i]);
}
}
return newAry;
}
Then you can use it thusly:
var selectedAry = window.showModalDialog("Window.jsp", inputAry, "dialogWidth:900px; dialogHeight:700px; center:yes; resizable: yes;");
var newAry = cloneArray(selectedAry);

Use both jQuery.checkbox & jQuery.field

I am trying to use two jQuery solutions on the one form, but I am unable to get the desired result after working on it for several hours.
The first jQuery solution enables a better look and feel
http://www.envirotalk.com.au/jquery/jquery-checkbox.htm
The second jQuery solution enables a limit to be set on the number of checkboxes selected.
http://www.envirotalk.com.au/jquery/jquery-field.htm
This is my attempt at combining the two.
http://www.envirotalk.com.au/jquery/combined.htm
I believe the problem relates to this line of code, but I cannot be certain.
setLimitSelection();
The outcome I am trying to achieve.
Look and feel; jquery-checkbox
Limit to the number of checkboxes one
can select; jquery-field
The error message; jquery-field
Clearing the extra field value once
exceeded limit; jquery-field.
If someone has the time to take a look and help me, that would be greatly appreciated.
The two plug-ins are probably conflicting with each other, since the code that you're using is the same as the ones given in the individual examples. For limiting checkboxes that can be selected, you can try this:
function setLimitSelection(){
$("input[type=checkbox]").click(function(){
var checkboxes_to_allow = 3;
if($('input[type=checkbox]:checked').length == (checkboxes_to_allow+1)){
//show error message
return false;
} else {
//clear message
}
});
}
I think the code is clear enough to not need comments?
Hello I think you can solve the problem with a small status variable like checkfield:
var checkfield = false;
$("input[name ='name']").limitSelection({
limit: 3,
onfailure: function (n){
checkfield = true;
return false;
}
}).click(function (){
if (field6error)
{
$(this).checkBox('changeCheckStatus', false);
checkfield = false;
alert("Not more than 3 values!")
return false;
}});

Categories

Resources