Tap Forms app icon half
Tap Forms Forum text image
Blue gradient background

Exchange tips and ideas with the Tap Forms community

Search Results for 'script'

Viewing 15 results - 2,251 through 2,265 (of 2,986 total)
  • Author
    Search Results
  • #37886

    In reply to: Time delay in scripts

    Sam Moffatt
    Participant

    Even if setTimeout existed, it’d require the Javascript execution to be fully async but that would then cause potential race conditions with other scripts executing and changing values. It might make sense for form scripts but making that async in an environment like Tap Forms is a recipe for hard to debug issues that would make any seasoned operations person have nightmares.

    I have a similar use case of a large amount work that a form script is doing which pauses Tap Forms due to doing heavy network I/O. Some sort of progress bar interface that I could use to at least communicate where it’s at and maybe do a clean cancellation would be useful.

    #37874
    Brendan
    Keymaster

    Hi Rocky,

    I have a script here which continues execution after the results of the prompter are determined. Perhaps this will help you with what you want to do:

    var second_prompt;
    
    var output2 = function printOut2() {
    	console.log('second prompt: ' + second_prompt);
    }
    
    var output = function printOut(continueClicked) {
    	console.log(username + ", " + password + ", " + email_address + ", " + other_field + ", " + genre);
    		
    	if (continueClicked == true) {
    		let prompter2 = Prompter.new();
    		prompter2.addParameter('Did it work?: ', 'second_prompt')
    		.show('A second prompt', output2);
    	}
    	
    }
    
    var username;
    var password;
    var email_address;
    var other_field;
    var genre;
    var genres = ['Action & Adventure', 'Comedy', 'Drama', 'Horror', 'Science Fiction'];
    
    let prompter = Prompter.new();
    prompter.addParameter('Username: ', 'username')
    .addParameter('Password: ', 'password', 'secure')
    .addParameter('Email Address: ', 'email_address')
    .addParameter('Other: ', 'other_field')
    .addParameter('Genre: ', 'genre', 'popup', genres)
    .show('Enter a Username and Password and Stuff', output);
    

    Basically when the first prompter is run, the output of that is the execution of the output function which creates another prompter. Then that prompter is displayed. And the output of that is output2. So that’s how you can chain things together using the prompter.

    #37860
    Daniel Leu
    Participant

    I hope that one day I can use the Prompter for scanning items. Then things could be automated with a script.

    Cheers, Daniel

    ---
    See https://lab.danielleu.com/tapformspro/ for scripts and tips&tricks

    #37856
    Sam Moffatt
    Participant

    I’m not sure you can fully do what you need with a script right now, the scripting interface doesn’t have a way of scanning anything.

    That said, what you can do is use the barcode scanner the search feature has to look up the record and if you had a checkmark for registration you could add a field script to watch that checkmark field and do what ever business process you need.

    #37849
    Brendan
    Keymaster

    @George, on the iOS version in the Script Editor, there’s a button on the toolbar just above the keyboard that kind of looks like a vertical set of boxes. Those are to represent fields. When you tap on that, Tap Forms will display the list of fields with a function selector for getting the field value or the field ID. When you tap on the field, Tap Forms will insert the variable into your source code, thus giving you the field ID or the value from the record and field that you’re looking for.

    #37846
    Brendan
    Keymaster

    In the context of AppleScript, there is no current record so you have to select one first. You can’t call record.getId() because there is no current record.

    The function that handles the AppleScript command will take 3 arguments. A form, a script, and a search.

    - (void)handleRunScriptCommand:(NSScriptCommand *)command {
    	NSString *formName = command.evaluatedArguments[@"form"];
    	NSString *scriptName = command.evaluatedArguments[@"script"];
    	NSString *searchName = command.evaluatedArguments[@"search"];
     ... do stuff
    }

    Once it has all that stuff, it runs the script:

    [self runScript:form search:(TFSearch *)search record:nil script:script];

    Passing in nil for the record because there’s no current record.

    The reason for this is the script is being run outside the context of the state of the user interface. So Tap Forms doesn’t have the current record. However, I could probably modify it so that it does pass in the current record to that call. And I’ve just done that.

    #37843
    Peter Wolf
    Participant

    Doh! I am struggling to make sense of the examples although I do know Google Apps Script for Sheet. Can someone kindly help get me started with scripting my planned application?

    I have successfully imported into TF on iPhone a .csv file of names, membership numbers and some other details of ticket bookings for an event. Each ticket will have a printed QR or barcode of the person’s membership number. I wish to create a TF script which enables the QR or barcode on each ticket to be scanned by the iPhone on attendee registration, retrieving the relevant ticket and automatically completing a field in the form to record their attendance. That’s all . . .

    Thanks in hope and in advance!

    #37838

    In reply to: Time delay in scripts

    Sam Moffatt
    Participant

    The only way I can think of would be to create a busy loop and check to see if time has elapsed. Something like this should work:

    function delay(duration)
    {
    	let now = new Date();
    	let future = now.getTime() + duration;
    	while((new Date()).getTime() < future) { }
    }
    
    function Timer() {
    	console.log(new Date());
    	delay(5000);
    	console.log(new Date());
    }
    
    Timer();

    Sample Execution:

    Tue Nov 05 2019 17:58:36 GMT-0800 (PST)
    Tue Nov 05 2019 17:58:41 GMT-0800 (PST)

    There might be a better way but this will work in a pinch.

    You might want to push the logic for the delay into the method call itself. If this is running inside a big loop, it should work ok. If you have multiple field scripts that you’re executing then I’m not sure this will be as effective so give it a try first:

    var lastCalled = 0;
    
    function delay(duration)
    {
    	let now = new Date();
    	let future = now.getTime() + duration;
    	while((new Date()).getTime() < future) { }
    }
    
    function rateLimitedLogger(message, minTime = 5000)
    {
    	let now = (new Date()).getTime();
    	let nextExecution = lastCalled + minTime;
    	if (now < nextExecution)
    	{
    		console.log(<code>Waiting ${nextExecution - now}ms</code>);
    		delay(nextExecution - now);
    	}
    	lastCalled = (new Date()).getTime();
    	console.log(new Date() + ' ' + message);
    
    }
    
    function Timer() {
    	rateLimitedLogger('Message 1');
    	rateLimitedLogger('Message 2');
    	delay(3000);
    	rateLimitedLogger('Message 3');
    	delay(6000);
    	rateLimitedLogger('Message 4');
    }
    
    Timer();

    Sample output:

    Tue Nov 05 2019 18:05:40 GMT-0800 (PST) Message 1
    Waiting 4999ms
    Tue Nov 05 2019 18:05:45 GMT-0800 (PST) Message 2
    Waiting 2000ms
    Tue Nov 05 2019 18:05:50 GMT-0800 (PST) Message 3
    Tue Nov 05 2019 18:05:56 GMT-0800 (PST) Message 4
    

    Obviously you’d need to swap out the console logging for your own implementation. This should work fine though and you can see that in my case it works fine. The examples are:

    1. The first launch, should always run.
    2. An immediately following execution (should be max time though looks like we lost a millisecond)
    3. I put in a manual delay for 3000 ms to demonstrate it properly accounting for that as the offset of 2000ms.
    4. I put in a manual delay for 6000 ms to demonstrate it properly accounting for being able to run immediately.

    Depending on what you’re doing, you might want to set the last called variable from another record somewhere and update it as you’re going. This would be important for if you are changing fields that are being watched by field scripts however this sort of script will pause TF because of the nature of how it’s running.

    Are you using a form script for this that you manually execute or field scripts?

    #37835
    Nigel Hughes
    Participant

    Hi,
    I’m just starting the coding of scripts in Tap Forms but have come to a bit of a road block. My goal is to calculate the nutrients in my weekly food shop. So I’ve created my shopping list as a database – with he records being all the common shopping items and record fields properties of those items including their nutrients and the date they were last bought. However to create a summary of the total for each of the 100 odd nutrients for each week’s shopping list i have created another linked form with a JavaScript doing the totalling of each of the nutrients in all the shopping items In the first form (for a particular day). I am trying to use the function getTotalOfField to do this ona search of a days shopping (in the first database) but am running into errors in its use that I don’t understand how to get around. Following the example on the Tap Forms JavaScript API webpage I have found the search object and then used the getTotalOfField function on this. However I keep getting the error:
    TypeError: NutrientSearch_object.getMinOfField is not a function. (In ‘NutrientSearch_object.getMinOfField(nutrient_ID)’, ‘NutrientSearch_object.getMinOfField’ is undefined)
    I’ve attached screen shots of the code and resulting consult log in the hope that someone might be able to help me see what I’m doing wrong. Thanks in advance!

    Attachments:
    You must be logged in to view attached files.
    #37834
    Grant Anderson
    Participant

    Hi, I’m updating entries in my database and need to access an online barcode lookup system. It only allows lookups every 5 seconds so as not to overload the server. How can I add a time delay in a script? I tried using Javascript’s setTimeout which would call a function after a specified time but Tap Forms compiler doesn’t seem to understand that. Any ideas?

    #37832
    Daniel Leu
    Participant

    No idea what happened to my comment…. you can repost it for context. No problem with me.

    Good thing I still have my test document…. store_id and store_name_id are variables that need to be defined in your script. So this all belongs together as part of the script field options > script. This way the script know from where to fetch the necessary data.

    var store_id = 'fld-xxxx';
    var store_name_id = 'fld-xxxx';
    
    function joinChildField(childLinkId, fieldId){
    	let entries = record.getFieldValue(childLinkId);
    	var list = Array();
    	for (entry of entries){
    		list.push(entry.getFieldValue(fieldId));
    	}
    	return list.join(', ');
    }
    
    joinChildField(store_id, store_name_id);

    The function definition uses parameter names that make sense for different applications. So when you call this function with joinChildField(store_id, store_name_id);, store_id will become childLinkId and store_name_id becomes fieldId inside the function.

    Cheers, Daniel

    ---
    See https://lab.danielleu.com/tapformspro/ for scripts and tips&tricks

    #37824
    Daniel Leu
    Participant

    I have to admit that I do all my development work on a desktop…. So I’m discovering the process along with you :)

    Let’s assume you have two forms in your document, Store and Wines. When you see them, there is an ‘Edit’ button on the top right. Click on it. Now you can edit the forms. Select Wines.
    I currently have three fields: ‘Wine Name’ (text), ‘Store’ (linked field to Store form, many-to-many type because I can buy the same wine at two stores and the stores usually have many wines, inverse relationship selected), and ‘Store TXT’ (field script). Just for completeness, in the ‘Store’ form, I have ‘Store Name’ (txt), ‘Wines’ (link), ‘Wines TXT’ (script).
    Click on ‘Store TXT’ and then ‘Field Options’ then ‘Script’. This is where your field script resides.

    You already noticed the Brenan’s and my field ids are different, so will be yours! To get the one you are looking for, touch in the text field somewhere to get the keyboard view. There is a small row with symbols. The one between fx and ABC is of interest. No idea how this symbol is called. Anyway, click on it. On the top, you can select between ‘getFieldValue()’ and ‘field_id’. The background behind these two options is ugly, looks like a bug where the background is not cleared. Here we need field_id. So select field_id.
    Since we are in the Wines form, we need the id of the ‘Store’ field (link to stores) and the name of the store.
    So click on ‘Store’. Now you are back in the editor with new text like
    var store_id = 'fld-....';
    Next we need the id of the store name. So again get the keyboard view and click on the icon between fx and ABC, click on ‘Store Name’ and you are back in the script editor with something like:
    var store_name_id = 'fld-....';
    These are the two items that are custom to your from and which are different to ours.

    Now finish the code as follows:

    function joinChildField(childLinkId, fieldId){
    	let entries = record.getFieldValue(childLinkId);
    	var list = Array();
    	for (entry of entries){
    		list.push(entry.getFieldValue(fieldId));
    	}
    	return list.join(', ');
    }
    
    joinChildField(store_id, store_name_id);

    The result will appear in the ‘Stores TXT’ field. Now you got to do for the ‘Store’ form and then you can search.

    Hope you were able to follow along….

    Update: Added my TF document for your reference

    Attachments:
    You must be logged in to view attached files.

    Cheers, Daniel

    ---
    See https://lab.danielleu.com/tapformspro/ for scripts and tips&tricks

    #37818
    George Cx
    Participant

    Hey everyone, thanks for the awesome responses.

    First up, apologies to Brendan. I wasn’t trying to be unkind – TapForms is awesome – and is in pretty much every way far more flexible and cool than AT. Its amazing what you’ve created – and I only wanted to give an example to show what I was seeing, not to criticize – thank you for taking it in that spirit (and I’m rooting for your first billion! Lets have this conversation on your yacht!)

    Second up – I’m sorry to be such a dummy, but I’m not quite sure how to make these scripts work their magic on iOS.

    Firstly I went to one of the records, selected “run a script” from the top right menu, then pasted in Brendans code, saved it, then backed out, then went back in and ran the script. Much as monkeys throwing screwdrivers at a typewriter to write Shakespeare, it created the exact response I’d feared ie nothing, because I guess I’m not sure where the results are put, not sure how to figure out the specific variable names of my field ie var actors_id = ‘fld-984cf79ccafb45a381b0f95b0aa28e78’; var last_name_id = ‘fld-a907066570844290a27940d34de98b4f’; ie I’m assuming that long key is particular to the field of the record. (I note that Brendan and Daniel have different field references but I’m assuming thats because they ran this on their unique instances of their forms.)

    Then I backed out and edited the form itself, added a “script field” pasted in the text. Then pulled up the record and there was the script field. But this time even the typewriter was undented – the field sure said script, but clicking on it didn’t seem to invoke anything.

    If I could lean on everyone’s kindness and expertise one more time and assume you are teaching this code to a fifth grader (and not one of those really bright fifth graders) – is there a screencast or stepwise instructions that goes step by step through
    a) how to set up the code so those long keys actually related to fields my system will recognize
    b) where to paste said code
    c) how to invoke, and where to look for the results (and/or how to set up a special field to capture results*)

    *What I’m sensing will/should happen is that the code goes into the “linked” field – scrapes the returned value (say store name) then pastes “store name” as text ideally in some dedicated field so it shows on the multi-column view – then you can search/filter on that text. Anytime you update that record, you run the script again to make sure the latest scrape is in that text field – am I close?

    I could paste you a quick screen cast of my pitiable attempts, but just imagine a whole lot of nothing happening and you’ve got the gist.

    Thanks again for the pointers on this, I’m hoping my cluelessness might help others on the forum.

    Cheers y’all

    #37815
    Daniel Leu
    Participant

    Martin, the purpose of my script was just to show that you can get access to the field values using Javascript’s Date methods. I posted my response to your original question before I received your progress update :)

    Cheers, Daniel

    ---
    See https://lab.danielleu.com/tapformspro/ for scripts and tips&tricks

    #37813
    Martin Inchley
    Participant

    Actually, Daniel, a couple of things about your script.
    1. I think you need to use getDate() rather than getDay(), in order to get the day of the month, and not the day of the week.
    2. In your final calculation, I think d and m are round the wrong way. Also the w3schools JS tutorial says to be alert for the need to add 1 to the month, because January = 0. But in my script, it works without it.

    var date_and_time_id = 'fld-a74f18a96d4c42489a40a367f54f45ee';
    var date_id = 'fld-3ef5526b645947c89317b8272dffd659';
    var time_id = 'fld-95075cb1f5604be59afbc73094591e7a';
    
    var date = record.getFieldValue('fld-3ef5526b645947c89317b8272dffd659');
    var time = record.getFieldValue('fld-95075cb1f5604be59afbc73094591e7a');
    
    var m = date.getMonth();
    var d = date.getDate();
    var y = date.getFullYear();
    var h = time.getHours();
    var mins = time.getMinutes();
    
    var compDate = new Date(y, m, d, h+1, mins)
    
    record.setFieldValue(date_and_time_id, compDate);
    form.saveAllChanges();
    
    console.log(compDate)

    However, I do currently have to add an hour to the hours, because of the problem I flagged in another thread, to which no one has yet come up with an answer.

Viewing 15 results - 2,251 through 2,265 (of 2,986 total)