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,386 through 2,400 (of 2,985 total)
  • Author
    Search Results
  • #36811
    Sam Moffatt
    Participant

    I’ve been dwelling on this a little and one of the challenges is how the pick lists are stored. It’s essentially still a text field, even with the multiple select, which is why you can tick them and also manually type items in. If you get it exactly correct, it’ll match as the pick list too. I’m not sure Brendan can easily change that using the existing field type, it needs to be a new field type dedicated to the pick list.

    As is often my solution here on the forums, you can use a script field to help you out. To make this work I did some minor tweaks, for the pick list I prefixed it with a number and colon sort of format and use that to split apart the string from the pick list. The pick list values I used look like this:

    – 1: Something, I think, that will help.
    – 2: This is, to be sure, the right path!
    – 3: The path of caution, butterfly.

    This is something that looks ok, doesn’t feel too janky but gives me a character to work with: the colon! If you need to use colons, I’d actually suggest using a pipe character (|) which is an old favourite of mine because not many people use that character in ordinary sentences.

    This has comments inline that should explain as it goes:

    // This cleans out the Tap Forms comma and space delimiter.
    function cleanString(input)
    {
    	// I had an input length check because the first array
    	// element is going to actually be empty but then I put
    	// in a filter and this if statement ended up being redundant.
    	if (input.length)
    	{
    		// What we're looking for is a space OR comma multiple
    		// times at the end of the string (the dollar sign means
    		// end of string) and we want to replace that with an
    		// empty string.
    		return input.replace(/[\s,]*$/, "");
    	}
    }
    
    // Boilerplate :D
    function Restructured() {
    	// Replace this with the field that stores your pick list.
    	var sentence = record.getFieldValue('fld-6d04efdd9e334ad29399bc3c4aef4f06');
    	
    	// Step 1: take the sentence and split it based on "Number: ", e.g. "1: ".
    	var cleaned = sentence.split(/[0-9]*: /)
    	// Step 2: Filter removes elements from an array that don't match.
    	//         In this case, if the string length is greater than zero, keep it.
    	//         The 'x' here is short hand for the array element and this could
    	//         have also been implemented as another function.
    		.filter(x => x.length > 0)
    	// Step 3: Map executes a function per element and creates a new array with
    	//         the new values. What we're doing is using "cleanString" to clean
    	//         the values and remove the Tap Forms delimeters. This could also
    	//         have been done inline too: .map(x => x.replace(/[\s,]*$/, ""))
    		.map(cleanString);
    
    	// Last but not least we return the value to our caller. In this case
    	// we're joining the array with a single space however you could also do
    	// this with a new line character (e.g. '\n') or any other string that
    	// makes sense for your use case.
    	return cleaned.join(' ');
    }
    
    Restructured();

    This function makes use of Javascript’s chaining functionality. That is where you immediately use the object returned from the earlier method with the next method. The Restructured() method itself could actually be one line completely chained but I broke it up a little to help with the explanation. Put this into a script field and it’ll automatically reformat the pick list field to what I think you actually want. You will have to mutate your pick list to the format it expects (again that number, followed by a colon and ending with a space) though you could tweak the script not to care so much about that too.

    Attachments:
    You must be logged in to view attached files.
    #36810
    john cesta
    Participant

    I need to send emails to members. I have a form which contains various pieces of text I routinely send mostly when there is no phone number associated with a members information.

    I’d like to include fields from the record in the email like…

    Dear [firstName]

    Your address is [city] [state] [zip]

    Well, you get the idea.

    Is there a way to do this in tapforms? Perhaps thru a calculation field or a script?

    Thanks,

    #36805
    Sam Moffatt
    Participant

    Thanks! It turned out to be reasonably straight forward, the Javascript API having the flexibility to do it all is the neat bit for me. If there were document level scripts then you could have it run on any form without having to add it per form.

    #36783
    Sam Moffatt
    Participant

    I couldn’t resist giving this a chop. I ended up going with something that just did a copy, you could add a delete in though but I’d want to verify the new record first. YMMV. I posted it over on the Script Talk forum.

    #36782
    Sam Moffatt
    Participant

    Over on the main forum is a topic about move records from one form to another which I was curious about being able to solve.

    This gives the user a list of forms excluding the currently selected one, checks to see if at least each of the fields in the source record are available in the destination and then creates a new record. In my limited testing it seems to work properly though by design it only copies records, it doesn’t delete the original so you need to do that after verification (trust, but verify).

    I went through and put some comments in it that will hopefully make sense. There are two functions: the copyHandler is a callback that does the heavy lifting and the Copy_Record_To_Form function sets up the initial form list and prompter.

    // Handler for prompter callback
    var copyHandler = function()
    {
    	// Validate that we got a form name passed in.
    	if (typeof formName == 'undefined' || formName.trim() == '')
    	{
    		console.log('Empty or undefined formName sent, cancelling.');
    		return;
    	}
    
    	// Mapping of source field to target field
    	// - the key will be source field and the value will be target field.
    	var fieldMap = {};
    
    	// List of fields in the source form that weren't found in the target form.
    	var missingFields = [];
    
    	// We shouldn't be here but let's check again.
    	if (form.name == formName)
    	{
    		Utils.alertWithMessage('Unable to copy record to self', 'Please use the duplicate button to create a new record in the same form');
    		return;
    	}
    
    	// Get the target form.
    	var target = document.getFormNamed(formName);
    	
    	// Get the source fields.
    	var sourceFields = form.getFields();
    	
    	// Iterate through each of them.
    	for (sourceId in sourceFields)
    	{
    		// Look for a target field with the same name as the source field.
    		var targetField = target.getFieldNamed(sourceFields[sourceId].name);
    		if (targetField == null)
    		{
    			// If a targetField is missing, add the source field to the missing field list.
    			missingFields.push(sourceFields[sourceId].name);
    		}
    		else
    		{
    			// Map the source field ID to the target field ID.
    			fieldMap[sourceFields[sourceId].getID()] = targetField.getID();
    		}
    	}
    	
    	// If we had any missing fields.
    	if (missingFields.length)
    	{
    		// Prompt a message with the missing fields and let the user know it's aborted.
    		var fullMessage = ["The following fields weren't found in the target form:", "", ...missingFields];
    		Utils.alertWithMessage('Copy Aborted!', fullMessage.join("\n"));
    		return;
    	}
    	
    	// Create the record data object and start to iterate through the field map.
    	var recordData = {};
    	for (sourceFieldId in fieldMap)
    	{
    		// Set in the record data the field ID of the target field as the key
    		// and then get the current value of the source field.
    		recordData[fieldMap[sourceFieldId]] = record.getFieldValue(sourceFieldId);
    	}
    	
    	// Don't know if this works, set a secret value to the original record URL for linking.
    	recordData['copy-source'] = record.getUrl();
    	
    	// Add a new record to the target form.
    	var targetRecord = target.addNewRecord();
    	
    	// Set the field values for the newly created record.
    	targetRecord.setFieldValues(recordData);
    	
    	// Save the data and log some values for reference.
    	document.saveAllChanges();
    	console.log('Original URL: ' + record.getUrl());
    	console.log('Destination URL: ' + targetRecord.getUrl());
    }
    
    function Copy_Record_To_Form() {	
    	// Get all of the forms.
    	var forms = document.getForms();
    	
    	// A place to store a list of form names for the prompter.
    	var formNames = [];
    
    	// Iterate through all of the forms.
    	for(var formId in forms)
    	{
    		// Ignore the currently selected form from the list.
    		if (forms[formId].name == form.name)
    		{
    			continue;
    		}
    		
    		// Append this form name to the list of form names for the prompter.
    		formNames.push(forms[formId].name);
    	}
    	
    	// Create a new prompter anddisplay the form list.
    	var formPrompter = Prompter.new();
    	formPrompter.cancelButtonTitle = 'Cancel';
    	formPrompter.continueButtonTitle = 'Copy record';
    	formPrompter.addParameter('Destination Form: ', 'formName', 'popup', formNames)
    		.show('Select form to copy record: ', copyHandler);
    }
    
    Copy_Record_To_Form();
    
    #36766

    In reply to: x-callback-url

    Brendan
    Keymaster

    I’ve added document.getID(); to the next update.

    But also you can do record.getUrl(); to get the whole link to the record. That’s in the online docs for the Script API.

    #36763

    In reply to: x-callback-url

    Sam Moffatt
    Participant

    You just make that line the script entirely or if you want to wrap it in a function, put in return at the end. The function scaffolding is there to help you wrap things a little easier and make it so that you can return early easier but it isn’t purely necessary. For something truly as simple as this, you don’t need it.

    Attachments:
    You must be logged in to view attached files.
    #36760
    Sam Moffatt
    Participant

    To move from one form to the other, you need to map the field ID’s across. Even if you duplicate the same form, the field ID’s are different between the forms. Essentially you need to go through each of the forms and grab the ID’s.

    The simple way of doing this is to use record.getFieldValue() to get each of the values, then create a new record in your target form with var newRecord = form.addNewRecord() and then with the new record, set the values and save: newRecord.setFieldValue(). A slight variation on this is to use a dictionary and newRecord.setFieldValues() which might look a little better. I’ve done something like that to merge fields from a child record and it’s parent record to create a grandchild record, some of that script is elsewhere on the forum.

    If you’re up for a bit more of a challenge, you could take this a step further and use some of the more interesting parts of API. If you checkout the JavaScript API documentation, you’ll see there is a couple of things that could help you automate some of this via a form script:

    – There is a document.getForms() that you could use with prompter to ask which form to move the currently selected record.
    – There is a form.getFields() that you could use to get the fields in the form.
    – There is a field.name for each of those fields that you can then use to map 1:1 fields from the first form to the second form and then use field.getId() with record.getFieldValue() and newRecord.setFieldValue().

    Assuming you keep the field names consistent on both sides (and if you’re missing a field, you raise an error!), then you could use the methods above to make a generic record copy script. To productionalise it I’d really, really want something that confirmed the field mapping and asked the user (prompter use case again), I’d avoid automatically deleting the record (hello data loss!) and I’d probably want to have a special field that links me to the new record in the new form so that I can quickly get to that record from my old one, verify it’s all correct and then manually delete the old one.

    #36758
    Sam Moffatt
    Participant

    Wrap the search term in quotes and it might find it with the slash in it.

    I commonly have a section heading for small fields like this at the bottom of the record, either called “Calcs”, “Join Fields” or “Linking Metadata” that I hide these calculation or script fields in. This helps me split out these sorts of fields that I use for search purposes (like combining shipping tracking numbers together or computing alternate order ID’s) and then collapse the section to hide them. You can also hide the collapsed section heading field to make it all disappear entirely without having to toggle the hidden state on each field. For me collapsing the section heading is enough but depending on your environment you might be interested in hiding it as well.

    #36757

    In reply to: x-callback-url

    Sam Moffatt
    Participant

    On the Mac, there is a “Copy Record Link” option to get the link back to the record in the UI. Something like that would work as an addition to the record menu on iOS.

    That said to get you out of a quick bind, you can use a script field like this to generate a link in your forms manually:

    'tapformz://record/view/db-14f9b6b609904da9b6fb89e4df20d42c/' + form.getID() + '/' + record.getID();

    Unfortunately there is no document.getID(), so you’ll have to get the document ID from the sync page and put your document ID in. That should generate a URL you can copy and paste from.

    #36750
    john cesta
    Participant

    I agree on the pick list thing and I use this method for other things, certainly works great.

    But with my brain and the importance of the prospects and not forgetting about them or mistagging them etc I need to have them in a separate standout form for quick easy simplified access.

    The way I have it now is ok and it’s not a big hassle to move them over but I think I’ll take the challenge and try and create a script to copy them over.

    Attachments:
    You must be logged in to view attached files.
    #36749
    Richard Riffle
    Participant

    Thanks Sam and Brendan. I took your advice and got a refurbished Mac mini to run Tap Forms on and was able to write a working script within a couple hours of getting it delivered. I doubt I’d ever been able to do so just using the iPod/iPhone. I’ll probably be bothering you with scripting questions once I get further along. Thanks again.

    #36747
    Brendan
    Keymaster

    Hi Scott,

    A Script is not required for this.

    Tap Forms will generate an average from a set of records for you.

    If you’re using the Mac version, switch to the multi-column list view, then click the Sigma button to show the Calculations row. Then beneath your Selling Price field, click the popup button. Choose Average and you’ll be able to always display the average of the selling prices for the properties.

    There’s an equivalent way to do it on the iOS version too. Go to the Field Options screen when editing the field in your form template, then set the Calculation Summary option to Average.

    If that’s not what you’re looking for, let me know.

    Thanks!

    Brendan

    #36745
    Brendan
    Keymaster

    @John, well, you can accomplish the same thing with Saved Searches. Instead of moving records from one form to another where one form is a list of prospects and another is a list of members, each with the same kind of information, just create a field you use as a sort of Contact Type where you have a Pick List defined with the different types (e.g. Prospect, Member, etc.). Then create a Saved Search for each of those types. Now when a Prospect becomes a Member, just switch the Contact Type and you’re done. With a Saved Search for each Contact Type, you can then filter your master list and show only the prospects independently from the members, etc.

    And when you select a Saved Search to view only those specific contacts, the export records or email function would work on just the set of records found.

    Yes, you could also write a script to copy the records from one form to another if you like.

    #36742
    Scott MacLennan
    Participant

    Let’s begin with I know ZERO about scripts but it looks like a script would be the most effective way to do something I want to do. I have a database of sold houses, simple enough. I need to find a way to get the average price of a home from the “selling price” field in my database. Is a script the best bet or ???? Newbie, total Newbie and as I said, I know nothing about scripts.

Viewing 15 results - 2,386 through 2,400 (of 2,985 total)