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,476 through 2,490 (of 2,984 total)
  • Author
    Search Results
  • #36100
    D J Leason
    Participant

    @Sam Moffatt

    Thanks, Good to know. I am reading about JavaScript now. Not sure I have time to learn it all in it’s entirety, but I will learn the basics. I think that would come in handy for the small screen of an iPhone. Can I feel free to ask you questions form time to time? I’ll understand completely if you don’t have time.

    @DJ

    #36099
    D J Leason
    Participant

    @Brendan,

    Oh. OK. Thanks. Good to know. Should I go ahead and download the iOS versions for iPad and iPhone to make sure it works there or should I wait until I complete the database. Is there a 5.3 version of iOS available and is it included with the Mac version 5.3? Is there a link to the download for it? Is iPhone 6s+ still supported?

    Are the Tap Forms syntax rules the same as for JavaScript? Are spaces ignored in calculation editor? Is there a way to move the calculations editor window so you can see refer to the form as you enter stuff?

    #36097

    Topic: For Help

    in forum Script Talk
    talal alotaibi
    Participant

    hello

    I wish everyone a happy day

    How to use a tool larger than or smaller than with a replacement

    Example

    if X>Y print “No balance”

    Can I do it through the calculator
    Or should be placed in a script

    If you put it in a script, add it in the form

    #36079
    Sam Moffatt
    Participant

    @djleason yes there is a prompter that let’s you popup windows and then store it’s result somewhere, there is an example at the bottom of the JavaScript API page on how to use the prompter. You can use a prompter within a form script to populate regular fields in your form or create other records as is the example I provided.

    You need to wrap the date fields with a DATE([Field]; "yyyy-MM-dd") function to format them instead of returning the raw timestamp you’re seeing.

    The other thing would be to guard your field accesses or ensure they have default values set. There’s a warning on the Calculations page about if not all fields have values in them for your record, you will get an empty result.

    I also personally find using JavaScript a little easier to debug than the calculation fields, the JS editor will let you run your script inside the editor to preview it’s value making the develop/debug cycle quicker and it is usually good about giving you errors for where you made a mistake. The downside is that is a level lower than the calculation fields and can be a little confusing to map across the field ID’s and values all of the time compared to the calculation editor. I realise I might be unique here as I’ve been working with JavaScript for roughly two decades now back when it was a limited tool for interacting with web pages.

    #36073

    In reply to: Watched TV Shows

    Peter Riley
    Participant

    This is brilliant, thanks. Until now I have been tracking my TV show progress with a spreadsheet, but this script does a much better job.

    One issue though – the table seems to miss some episodes, even though they’re there on IMDb (see attached).

    Attachments:
    You must be logged in to view attached files.
    #36072
    D J Leason
    Participant

    Replying to Sam Moffat
    Prompter? Are you saying that using JavaScript, you can write code within Tap Forms, allowing you to make a window pop open and prompt you for answers to either single or multiple choice questions then add those answers to a record and use them in calculations? If so, are you a teacher?

    #36066
    Sam Moffatt
    Participant

    If you’re willing to learn some JavaScript, JS has some options here as well and a lot more power around linked forms if this is relevant.

    Combine multiple values from a child Link to Form fields into a single value
    Form Script to quickly add a new record in Link to Form

    #36053
    Ryan Stewart
    Participant

    This script does almost exactly what I want to do, but I can’t get it to function exactly.

    I’d like to run a form script that moves a field in FORM A to a new record in FORM B. The appropriate JSON is generated, but the new record is not being created as expected.

    Anyone care to take a look? Thanks in advance.

    // Posted: Case Field ID
    var posted_case_id = 'fld-bd5454484fab41d1a4fd75cf8af6f358';
    var posted_case_value = record.getFieldValue(posted_case_id);
    
    // Perioperative: Record Field IDs
    var periop_case_id = 'fld-416eb25e66aa48af949e528a2132d00e';
    
    function move_to_periop() {
    	
    	var data = {
    			[periop_case_id]: posted_case_value,
    		};
    	var periopRecord = record.addNewRecordToField(periop_case_id);
    	periopRecord.setFieldValues(data);
    	document.saveAllChanges();	
    	console.log(JSON.stringify(data));	
    }
    
    move_to_periop();
    #36044
    Sam Moffatt
    Participant

    I posted a field script that does this with a pick list field over in the Script Talk forum under “Populate image based on pick list”. It’s not an ideal solution but demonstrates how to achieve what I was talking about. If you only edit on your own Mac, then you can put the images locally and use MacOS’ built in web server and use that to host the files you want to include. It’s not a great solution to the problem but it is an example of how to solve it with a script field. Would love to see custom embedded layouts for Link From Form fields because I think that would solve your problem here.

    #36042
    Sam Moffatt
    Participant

    In Linking Images in a Database an ask was made to pick images and whilst that’d be cool to see somehow with form links, I decided to implement this as a quick field script as an example though a Link from Form field with the ability to embed a custom layout I think would be a cool way to solve the problem..

    This script borrows some publicly available images to solve the problem and uses a picklist to limit choices. I noticed I needed to hit refresh because the field script wasn’t being triggered. It will also not do anything if an image is already there, you have to manually delete the image to change it. Very simple sample form attached as well.

    var disc_type = record.getFieldValue('fld-d829341555114d4fb0a1f6d05a80930a');
    var disc_type_logo = record.getFieldValue('fld-9cd36df80c1141d4a87f59496222ebb0');
    console.log(disc_type);
    console.log(JSON.stringify(disc_type_logo));
    
    if (!disc_type_logo.length)
    {
    	var url = '';
    	switch (disc_type)
    	{
    		case 'CD':
    			url = 'http://pluspng.com/img-png/file-cd-logo-png-1024.png';			break;
    		case 'DVD':
    			url = 'http://pluspng.com/img-png/dvd-movie-png-dvd-logo-600.png';			break;
    		case 'Bluray':
    			url = 'http://pluspng.com/img-png/ama-flat-track-logo-vector-png-blu-ray-disc-logo-400.png';
    			break;
    		case 'LP':
    			url = 'http://pluspng.com/img-png/turntable-hd-png-turntables-png-cliparts-2640178-1000.png';
    			break;
    	}
    	if (url.length)
    	{
    		record.addPhotoFromUrlToField(url, 'fld-9cd36df80c1141d4a87f59496222ebb0');
    	}
    }
    else
    {
    	console.log('Skipping setting logo');
    }
    
    console.log('All done');
    
    Attachments:
    You must be logged in to view attached files.
    #36038

    In reply to: Transactional Logs

    Sam Moffatt
    Participant

    TapForms uses CouchbaseLite behind the scenes and that exposes a CouchDB compatible stream. Each change that happens to a document in TapForms is propagated to a change log which can be used for replication or in your case, recording each individual change that happens.

    There are a few complications here:

    • This change log isn’t guaranteed to be comprehensive. Some changes maybe squished together for the sake of efficiency and historic records may be removed to reclaim space. This may happen manually if you click “Compact Database” under preferences or it may happen automatically.
    • If you are recording this via an iOS device and then sync’ing to your Mac using the CouchDB based replication options (P2P, Cloudant, CouchDB) then your iOS device will only send the latest change it had. If you have make multiple changes out in the field to a document and then sync them, your Mac will only get the latest change.
    • Getting to this log is non-trivial. TapForms uses a randomised port each time the app starts per database which means you have to figure out what that port is via Bonjour/mDNS before you can get to the API. If you sync to an external CouchDB server, getting to the log is a little easier.

    I’m not sure how detailed CASA want to be, I suspect by default TapForms is actually more conformant than they’d care to think. If you don’t have iOS, or you’re fine with only one remote change making it back to your Mac, then you can use this API to extract out the raw documents and changes from the TapForms document. In theory you could extract the changes from the iOS devices via the same API but that’s a little more complicated.

    If you are interested in setting up a CouchDB instance, you can have TapForms replicate to it and then use it’s change log as your source of truth. If your devices are always online and the CouchDB server is always online then it will obviously replicate the changes as you go automatically.

    Ok, so how do we get the changes? The first step is to get an application called “Discovery” from the App Store. Discovery is a Bonjour/mDNS/DNS-SD browser that will let you find instances of TapForms on your personal network. Once you’ve downloaded it, open it up and scroll down to the bottom to find the entry “_tapforms-sync._tcp.” and expand it out. It should list all of the instances of TapForms running on your network with an entry each for the documents that are open. It looks like this:

    If you have more than one document open, you’ll need to know the ID of the document that you’re interested in. You can find this in the Preferences pop over for your document under the “Sync” tab

    Once you’ve got this document ID, you’ll need to expand it out and copy the line that has the IP address on it, in my case “10.0.1.145:57343”. You’ll need to use this with the database ID to get the change log.

    Next up, grab “Terminal” from “Applications” > “Utilities” and run a command like this:

    curl -k https://[YOUR_IP_ADDRESS:YOUR_PORT]/[YOUR_DB_ID]/_changes?include_docs=true

    For me with the example above, it looks like this:

    curl -k https://10.0.1.145:57343/db-f8365d0d8a99446db370477295e705fe/_changes?include_docs=true

    When you run that, it’ll spit out a raw transaction log of all of the changes that this TapForms instance is currently retaining.

    You can checkout the CouchDB docs on the _changes endpoint for some more details about how it works and it’s limitations.

    Now the complication of this is that you need to find the new port each time you open and close TapForms. I tried to build some automation for this because I was curious about building an automatic network backup tool to find TapForms instances on my network and automatically backup their change logs but I never got it finished and it never worked reliably. What I do is I actually use a CouchDB server on my local network and replicate the changes to there. I use that to then build automatic hourly snapshots of my database using GIT.

    I have two tools I use to keep backups, the first is a Time Machine based backup solution which I have put up on GitHub. I don’t think this will work for you because that method is inherently lossy. The second one I built scrapes the CouchDB and pulls out the internal revisions of the documents to store to disk. I don’t have that online yet, I need to integrate it properly into the little framework I’ve built but it isn’t a transaction log per se but a per record version history. The challenge with both of these is that inherently they don’t offer non-repudiation and are themselves in theory editable. You control all of the devices and at that point there is no audit pathway. Short of relying upon a third party service that is fully managed by someone else, I’m not sure you could assure an auditor of the veracity of your logs.

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

    Topic: VLOOKUP Script

    in forum Script Talk
    Sam Moffatt
    Participant

    Originally noted in the general forum, this is a method equivalent to Excel’s VLOOKUP. It’s actually mostly templated from the snippets, the child records loop snippet looks mostly like the vlookup function and the prompter snippet was in the other form script POC.

    This will work, it requires using script field instead of calc field but it’s not that bad. You need to tell it the value you want to lookup with, the “join” field (table or link to form), the search field to match the lookup value on and then the field to return.

    Create a new form script called “vlookup” with the following contents:

    function vlookup(lookup, join_field, search_field, return_field) {
    	var entries = record.getFieldValue(join_field);
    
    	for (var index = 0, count = entries.length; index < count; index++){
         	var target = entries[index].getFieldValue(search_field);
    		if (target && target == lookup) {
    			return entries[index].getFieldValue(return_field);
    		}
    	}
    	return "";
    }

    Then create a script field to map the values across:

    form.runScriptNamed('vlookup');
    var addresses_id = 'fld-34e22de8a7cf438fb4a83146108f0511';
    var address_name_id = 'fld-f05929829d674141aaed98efe11e29f1';
    var street_id = 'fld-04ec2a23e3554770b3e1f1d771157dd6';
    var primary_address = record.getFieldValue('fld-9b2865aa57b74b70bd4421b27081d65b');
    
    vlookup(primary_address, addresses_id, address_name_id, street_id);
    

    In the script editor, select the fields from the linked form and use the “ID” button instead of double clicking them to get the var syntax. You’ll want to change the last field to match your fields across.

    I’ve attached a sample archive which should demonstrate what I’m talking about. It also has another form script using a prompter to handle the address change but for some reason the script fields aren’t updating afterwards, you have to manually press refresh on the record.

    Sample archive link.

    #36029
    Sam Moffatt
    Participant

    There is one other way I can think of doing it which would be to use the scripting API to download the image from a known location into the document with either a prompter to pick the type via a form script or a field script watching a text field with a pick list configured. There are two problems with this: the first is that it would duplicate the attachment for each document which could get expensive if you have a lot of records and the second is you’d also need a web server somewhere to download it from. A new API for copying images could work here as well to remove the web server requirement but the duplication is a side effect of copying the image to every document.

    #36010
    Sam Moffatt
    Participant

    This is another one of my convenience functions that adds rows to a table if a given key/value pair are missing. This does mean that you can have duplicate ‘keys’ with different values and this is intentional. The use case is for picking up attributes from external sites like eBay or AliExpress that have this sort of attribute or variant data available to hand. This is another one in my ‘Script Manager’ form which I’m going to attach for reference as well. It includes the four modules I’ve posted for the logger, the currency conversion, setIfEmpty and this addToTableIfMissing function.

    // ========== addToTableIfMissing Start ========== //
    // NAME: addToTableIfMissing
    // VERSION: 1.0.1
    // CHANGELOG:
    //      1.0.1: Add support for specifying a custom record to use.
    
    document.getFormNamed('Script Manager').runScriptNamed('Logger');
    
    /**
     * Add's a key/value pair to a table if and only if it's missing.
     *
     * If you have a key that exists already but with a different value,
     * then this will add another table row for 
     *
     * fieldId:			The field ID of the table field.
     * keyField:		The field ID of the key field in the table field.
     * key:				The value of the key field to check against.
     * valueField:		The field ID of the value field in the table field.
     * value:			The value of the value field to check against.
     *
     * return: Empty return value in all cases.
     */
    function addToTableIfMissing(fieldId, keyField, key, valueField, value, currentRecord)
    {
    	if (!currentRecord)
    	{
    		currentRecord = record;
    	}
    	logger.logMessage(<code>Adding to ${fieldId} with ${key} and ${value}</code>);
    
    	var table = currentRecord.getFieldValue(fieldId);
    	for (var index = 0, count = table.length; index < count; index++)
    	{
         	var targetKey = table[index].getFieldValue(keyField);
         	var targetValue = table[index].getFieldValue(valueField);
    
    		if (targetKey == key && targetValue == value)
    		{
    			logger.logMessage(<code>Found existing value for ${fieldId} with ${key} and ${value}</code>);
    			return;
    		}
    	}
    
    	var newRecord = currentRecord.addNewRecordToField(fieldId);
    	newRecord.setFieldValue(keyField, key);
    	newRecord.setFieldValue(valueField, value);
    	return;
    }
    // ========== addToTableIfMissing End ========== //
    

    Here’s a sample of one of the note parsers that I use to take key/value summary data and turn it into something mildly useful. Most of the heavy lifting is done by a PHP script that I run locally to process and extract the data, this script is just handling the response data:

    document.getFormNamed('Script Manager').runScriptNamed('Logger');
    document.getFormNamed('Script Manager').runScriptNamed('setIfEmpty');
    document.getFormNamed('Script Manager').runScriptNamed('addToTableIfMissing');
    
    function noteParser()
    {
    	var note_id = 'fld-bf19d52c18cb4f5198df191ef7902e1b';
    	var notes = record.getFieldValue(note_id);
    	
    	if (!notes)
    	{
    		return "Notes field empty";
    	}
    
    	var result = Utils.postContentToUrlWithContentType(notes, "http://localhost/~pasamio/research/scrape/extract_note.php", "text/plain");
    
       if (!result)
       {
          return "no result returned from web service";
       }
       
    
    	if ("title" in result.fields)
    	{
    		setIfEmpty(record, 'fld-0d0edd2552ea461e929f806a4e5552b5', result.fields.title, null);
    	}
    
    	if ("price" in result.fields)
    	{
    		setIfEmpty(record, 'fld-08129d71ab0f4fa4a2749456281fca07', result.fields.price, null);
    	}
    
    	if ("brand" in result.fields)
    	{
    		setIfEmpty(record, 'fld-1e250019d7b249f282cc572814d3e71d', result.fields.brand, null);
    	}
    	
    	if ("itemkey" in result.fields)
    	{
    		setIfEmpty(record, 'fld-ae7379d699e9473aa2ab16a2a2f002d4', result.fields.itemkey, null);
    	}
    
    	if ("colour" in result.fields)
    	{
    		setIfEmpty(record, 'fld-a8626656cc90455ea9336dd2488d4aef', result.fields.colour, null);
    	}
    	
    	if ("category" in result.fields)
    	{
    		setIfEmpty(record, 'fld-6fdd09891a8c4d73be1b24aa07d077be', result.fields.category, null);
    	}
    	
    	var variant_data_id = 'fld-eb212e705eb34e9ea5cc4386ea7a9b1f';
    	var key_id = 'fld-ecc1b1ede8414912a63ec144012fa9e9';
    	var value_id = 'fld-e4ce093c1c22416192eb80554272d6cd';
    
    	if (result.data)
    	{
    		for(datum in result.data)
    		{
    			addToTableIfMissing(variant_data_id, key_id, datum, value_id, result.data[datum])
    		}
    	}
    
    	document.saveAllChanges();
    	
    	return result;
    }
    
    logger.consoleHeader('Note Parser', 'Purchases');
    var result = noteParser();
    logger.consoleFooter('Note Parser', 'Purchases');
    
    JSON.stringify(result);
    

    I quite often use JSON.stringify to take an object and turn it into JSON that is stored in the field. This helps with debugging and seeing the contents of the execution after it has run. This used to be more necessary before the console was added but is still useful to have a durable copy of the last execution.

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

    Topic: setIfEmpty Script

    in forum Script Talk
    Sam Moffatt
    Participant

    This is a script that will only set a field value if it is currently set to an empty value or is set to a specified default value. This is useful for blindly setting a value on a field without having to do the check work yourself.

    If you use my ‘Script Manager’ form, I call this one ‘setIfEmpty’ and you load it as:

    document.getFormNamed('Script Manager').runScriptNamed('setIfEmpty');

    // ========== setIfEmpty Start ========== //
    // NAME: setIfEmpty
    // VERSION: 1.0
    /**
     * Set a field if it is currently empty or matches the default value.
     *
     * target: 			The record to use (TFFormEntry object)
     * fieldId:			The field ID (e.g. <code>fld-hash</code>) to set.
     * value:			The value to set in the field.
     * defaultValue:	The default value of the field.
     *
     * return: boolean true if set or boolean false if unset.
     */
    function setIfEmpty(target, fieldId, value, defaultValue)
    {
    	var current = target.getFieldValue(fieldId);
    	if ((!current || current == defaultValue) && current != value)
    	{
    		console.log('setIfEmpty passed for ' + fieldId + ', setting to: ' + value);
    		target.setFieldValue(fieldId, value);
    		return true;
    	}
    	else
    	{
    		console.log('setIfEmpty failed for ' + fieldId + ', skipping.');
    		return false;
    	}
    }
    // ========== setIfEmpty End ========== //
    

    Simple example of how to use it:

    setIfEmpty(record, 'fld-39ca9564ef2347ac93f933bc9a2316ac', result.fields.title, null);
    setIfEmpty(record, 'fld-39379cdff743496f9a1ccbdc1ae56297', result.fields.quantity, 1);

    The first has a default of null (TapForms’ default default value) and the second has a default of 1 which obviously is a configured value for a number field.

Viewing 15 results - 2,476 through 2,490 (of 2,984 total)