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 - 1,726 through 1,740 (of 2,952 total)
  • Author
    Search Results
  • #41599
    Rocky Machado
    Participant

    Hi Brendan – Sorry I missed your response. I’m actually looking for a container that would allow me to run a widget. For example, this TradeView widget is something I would put in the Tapform Layout interface. Here is a snippet of the embed code Anyway, I thought I would ask.

    <!-- TradingView Widget BEGIN -->
    <div class="tradingview-widget-container">
      <div id="tradingview_e1957"></div>
      <div class="tradingview-widget-copyright"><a href="https://www.tradingview.com/symbols/NASDAQ-AAPL/" rel="noopener" target="_blank"><span class="blue-text">AAPL Chart</span></a> by TradingView</div>
      https://s3.tradingview.com/tv.js
      <script type="text/javascript">
      new TradingView.widget(
      {
      "width": 980,
      "height": 610,
      "symbol": "NASDAQ:AAPL",
      "interval": "D",
      "timezone": "Etc/UTC",
      "theme": "light",
      "style": "1",
      "locale": "en",
      "toolbar_bg": "#f1f3f6",
      "enable_publishing": false,
      "allow_symbol_change": true,
      "container_id": "tradingview_e1957"
    }
      );
      </script>
    </div>
    <!-- TradingView Widget END -->
    #41597
    Vincent Nunez
    Participant

    Hi Sir Moffat – I do appreciate your time and your complete reply. Thanks to your emphasis on that ‘child records loop’ snippet, and thanks to all the tutorials available through the website here, I took a more patient look and Approach #1 is now working for what I need at this time. Honestly it’s been awhile since I last hacked about with scripts. I didn’t realize how (relatively) easy Tap Forms was making it for me. I’ll keep at it! – Respectfully, Vincent

    #41591
    Sam Moffatt
    Participant

    A JOIN field is a many to many relationship, you need to iterate over the values. For Approach #1, use the ‘child records loop’ snippet with the field you are interested in and it will put the rest of the loop scaffolding in for you. You will have to choose what you do from there, merge everything together, return the first one you see or something in the middle.

    I’m not sure why Approach #2 isn’t working, though I’ve not used that syntax and I suspect the JOIN link messes with it as well for similar reasons to Attempt #3.

    The JOIN type’s many to many relationship is why Attempt #3 with the calculation field is giving you issues because there could be more than one record linked, so it defaults to giving you a count because the calculation tool doesn’t have the depth to let you handle multiple values.

    If this is supposed to be a singular value, I’d recommend creating a Link to Form in your other form as 1:M and then ticking show inverse relationship. It’ll create a Link From Form field in your current form which will simplify Attempt #1 and Attempt #3 will let you pick the individual fields.

    If using the Link From Form doesn’t get you across the line you can also have the scripting create the CSV for you and then copy it to the pasteboard (not recommended for terribly large amounts of data but a few MB of data shouldn’t stress it too much). Then you’d run a form script to populate your pasteboard and you can paste it into a destination app or TextEdit to save to disk.

    #41589
    Vincent Nunez
    Participant

    Any further developments here?

    I want to lookup values in an external table. I am joining the two tables by matching with fields both tables have in common. I *believe* these are properly linked with a Join field. But my external table does not seem to be returning values no matter what I try. The external table’s fields do appear to be available. Yet are they really?..

    Approach #1 — I attempt to use a script field. I get the ‘ReferenceError: Can’t find variable’ error. (I am wondering, why would I have an index to iterate with when I am using a field-level script? I pull from a source, I assign a waiting destination field – yet nothing goes through. I can run the script with local table information, no problem.)

    Approach #2 – I attempt to use “mail merge” syntax like so – [ExternalTable::JoinedField]. But this does not update when printed (to PDF). Local merge fields are updating (when out to PDF) no problem.

    Approach #3 – I attempt to use a calculation field as text output. But when I try to use any of the external table values I only seem to be able to access them through Count operation. I want to access a string, not a count of values.

    Approach #4 – Almost forgot. The closest I have gotten was actually my first attempt of embedding my external lookup into a plain layout. I am able to export that out as hardcopy, yet what I need is a reliable CSV export, not a copy/pasting activity based on PDFs. (Approach #2 would be ideal..)

    What basic ideas am I missing?

    Thanks,
    Vincent

    #41576
    Brendan
    Keymaster

    Done!

    https://www.tapforms.com/help-mac/5.3/en/topic/scripts

    The second blue banner box on the above page has a link to your tutorial.

    Thanks!

    #41575
    T.L. Ford
    Participant

    I’d be honored if you’d link it in your Scripting documentation.

    – T

    #41574
    Brendan
    Keymaster

    This is awesome!

    Do you mind if I put a link to your tutorial in my Scripting documentation?

    Thanks!

    Brendan

    #41567
    Sam Moffatt
    Participant

    Javascript’s Array has a lot of fun stuff in them to make use of interesting properties, another example is map which lets you apply a closure to every item automatically and filter which can remove elements from an array. forEach is another useful one to use plus for (x of y) and for (x in y) syntax for iteration.

    Here’s the same method rewritten to use map to extract the chore name and update some state and then filter to remove the empty array elements (not exactly a good use case as we’re essentially using map as a for loop or forEach construct):

    function Chore_Report() {
    	let current_chores = [];
    	let done_count = 0;
    	let chores = 0;
    	current_chores = record.getFieldValue('fld-08db542d325b434faea0d99cec89e1c9').map(rec => {
    		let done = rec.getFieldValue('fld-0dba6e502e1e4151ab34d9d8afa2cd19');
    		chores++;
    		if (done) {
    			done_count++;
    			return undefined;
    		}
    		else
    		{
    			return rec.getFieldValue('fld-2c5a9c565a7c480680659d1664daae3e');
    		}
    	}).filter(chore => { return chore !== undefined });
    
    	var report = "Chores total: " + chores + ", Done: " + done_count + "\n" + current_chores.join(", ");
    	console.log(report);
    
    	return report;
    }
    
    Chore_Report();

    To be honest I think purely correct or efficient at times isn’t as educational because there isn’t always a journey, things breaking, seeing issues as they arise and then fixing them. We learn more by the mistakes than by perfection or at the very least seeing how to overcome mistakes is useful when you run into your own issues.

    Also I’m loathe to reboot though there is something screwy with the GPU in my MBP so every so often I get a kernel panic to reset things.

    Look forward to seeing where to from here once you get some more time :)

    Sam Moffatt
    Participant

    I did a script to copy records from one form to another generically a while back as well, a little longer than Daniel’s script but also leverages a prompter to offer a target form to use.

    Daniel Leu
    Participant

    Hi Victor,

    When I run the script where the Enquiry form has more fields than the Contact form, then the script creates errors. In my case, the additional field is before some of the valid fields and this results in not all fields being copied…

    I have enhanced the script by adding a check to verify that the Contact form contains a field with the same name:

    function New_Client_Contact() {
    
    	// Define client form 
    	const clientForm = document.getFormNamed("Client Contact");
    	
    	// Create new record
    	let clientRecord = clientForm.addNewRecord();
    	
    	for (field of form.getFields()){
    		if (clientForm.getFieldNamed(field.name)){
    			let clientFieldId = clientForm.getFieldNamed(field.name).getId();
    			clientRecord.setFieldValue(clientFieldId, record.getFieldValue(field.getId()));
    		} else {
    			console.log("Waring: Field '" + field.name + "' not found in 'Client Contact' form");
    		}
    	} 
    	// Save
    	clientForm.saveAllChanges();
    }
    
    New_Client_Contact();

    Cheers, Daniel

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

    Victor Warner
    Participant

    T.L. and Daniel,

    Thank you both for the scripts. I am very grateful.

    Daniel,

    I have query on your second script. Using the Form names based on the following:

    1. the Client Enquiry has more fields then the 3 in the example but the additional fields do not exist in the Client Contact form.
    2. when the second script is run all the fields are copied for a record into the Client Contact form but although the ones for First Name, Last Name and Description are copied across to the Client Contact form the rest of disregarded.

    There is no downside (data corruption etc)?

    #41560
    T.L. Ford
    Participant

    Thank you for the feedback, Sam! It’s never possible to proofread your own work and find all of the errors (I did try). I added a “next” link to each page.

    I wanted to add many more things (walk-throughs of all of the snippets, not just a couple, and some more useful examples). I ran out of time (time-sensitive projects queued) and I figured for 101, this bridges the gap between “I have never written a script in anything in my life… Help!” and “ok, I’m capable of figuring out code posted to the forums…”.

    I made some decisions to “keep things as simple as possible”. For example, console.log and JavaScript – a true beginner will not understand the nuances of the under-hood implementation of JavaScript/Objective C. If I explain it as OOC, it adds a ton of web tutorials that can help explain objects which is a useful concept for grasping how to use forms, records, fields, etc. At the point in their programming career where they have jumped to a compiled language, they’ll know enough to be able to appreciate the difference. As a programmer, it’s cringeworthy. As a teacher for the utter newbie, the concept works.

    I hope you don’t mind that I added your description for console.log and JavaScript as a footnote.

    “For Section 6, why did you pick the basic loop over the child records loop?” – Failure to remember that such a thing existed until after I’d already done it and too lazy to go back and change it. I did mention it afterwards.

    “As an aside third parameter comment” I liked Objective C data types. Oddball syntax but once you got used to it, it was nice enough. Swift data types (when I played with it) were pure [profanity deleted].

    “For Section 7, the .length property is generally cached these days by the runtime. Google and V8 drove that optimisation which meant everyone else (including Apple) picked it up.” I learn something new every day. :)

    I added your array / join to the downloaded zip and put a note about it on the page, because it’s definitely worth noting. I liked the additional reinforcement of string concatenation (true beginners struggle with it a bit), but array/join is more efficient. I’m a super-guru Microsoft Access VBA developer. Array.join() is a magnificent thing.

    This is the same reasoning behind letting the code do the full string concatenation and then whacking off the ending comma. It keeps the inside loop block as simple as possible to focus on the process of looping. A string can be logged and easily understood. An array is very fuzzy in the minds of utter newbies.

    “For the audio it sounds like fan noise” It’s definitely the computer fan – I even tried killing our air conditioning which blows just overhead and can add a hum (not very useful for the heat problem, but in this heat wave, I certainly didn’t leave it off long enough for the room temperature to change).

    I ran one of the audios through Adobe Audition (the one where I sound like I’m standing in an auditorium). I have Audacity, too, but didn’t try that. I was busy grumbling at my computer. I’ve done a lot of videos. Some setting has gotten mucked up and changed the pickup threshold. I’ll get it sorted out before I do another video (my current theory is iTunes’ no-stealy implementation + Discord voice chat + SnapZ screwing up the capture, and could also have been the detour through the accidental click on my EOS Utility/OBS – next up: how to abuse your computer 101). It likely needs a reboot and some preference tweaking, but I had too many things open to do a reboot just then.

    More “correct/efficient” Tap Forms walkthroughs would definitely be useful. I don’t feel savvy enough yet with Tap Forms to know the best ways. (example: why didn’t I use that Child records loop? Although I might make the lame excuse ‘so people could see how that basic loop can be edited’, which would be cool if that were the reasoning, not just my overlooking it.)

    Again, I really appreciate the feedback!

    #41558
    Sam Moffatt
    Participant

    Love the styling on the pages though I would have liked a more obvious “next” button to go to the next section. Look forward to seeing more expansion here though! Walk through guides for Tap Forms is something that I feel is missing but could be very useful. Perhaps you’ll end up writing “Tap Forms 5: The Missing Manual” at the end of it all.

    Minor bug on the functions page, you reference console_log not console.log. Additionally console.log will return to you the value of the property, for built-ins it’ll be a wrapper around native code though pure Javascript functions will return the implementation. Javascript is also generally referred to as a prototype based language and as such doesn’t have classes, just objects that you can extend upon (in a sense they’re all just dictionaries with some self referential sugar). It’s a slightly different approach than class based object orientated programming hierarchies.

    For Section 6, why did you pick the basic loop over the child records loop? As an aside third parameter comment is probably more correct than wrong because of the way Javascript treats falsey types. I wouldn’t be surprised if it’s not coerced to a boolean before being marshalled back to Objective-C.

    For Section 7, the .length property is generally cached these days by the runtime. Google and V8 drove that optimisation which meant everyone else (including Apple) picked it up.

    Instead of doing string concatenation, I’d use an array and join:

    let current_chores = [];
    ...
    current_chores.push(chores[index].getFieldValue(chore_id));
    ...
    console.log(current_chores.join(", "));
    

    A similar one solution would work for the name list as well which would make it easy to prefix or suffix titles, add middle names or more. Saves you having to deal with substring and let’s Javascript do the heavy lifting for you.

    An alternative trick is to check if the string has a length and append the join characters in the middle after the first iteration of the loop:

    if (current_chores.length) current_chores += ", ";
    current_chores += chores[index].getFieldValue(chore_id);

    For the audio it sounds like fan noise, try grabbing Audacity and using it’s noise reduction plugin on the audio to see if it can clean it up. Fan noise is the bane of my own recording existence.

    Looking forward to seeing what you tackle next though!

    Daniel Leu
    Participant

    Yes, you would use a form script for this and start it from the client inquiry form. If you use a custom layout, you can even put a button there to start this script!

    Following is a form script that creates a new record in the form named “Client Contact” and copies first name, last name and description fields. This script assumes that the field names are “First Name”, “Last Name”, and “Description”:

    // Define enquiry form ids
    const firstNameId = form.getFieldNamed("First Name").getId();
    const lastNameId = form.getFieldNamed("Last Name").getId();
    const descriptionId = form.getFieldNamed("Description").getId();
    
    console.log(record.getFieldValue(firstNameId));
    
    function New_Client_Contact() {
    
    	// Define client form and ids
    	const clientForm = document.getFormNamed("Client Contact");
    	const clientFirstNameId = clientForm.getFieldNamed("First Name").getId();
    	const clientLastNameId = clientForm.getFieldNamed("Last Name").getId();
    	const clientDescriptionId = clientForm.getFieldNamed("Description").getId();
    
    	// Create new record
    	let clientRecord = clientForm.addNewRecord();
    	
    	// Populate new record
    	clientRecord.setFieldValue(clientFirstNameId, record.getFieldValue(firstNameId));
    	clientRecord.setFieldValue(clientLastNameId, record.getFieldValue(lastNameId));
    	clientRecord.setFieldValue(clientDescriptionId, record.getFieldValue(descriptionId));
    	
    	
    	// Save
    	clientForm.saveAllChanges();
    }
    
    New_Client_Contact();

    The beauty of this script is that it doesn’t use hard coded field ids. But if a field name changes down the road, the script will not run anymore. That’s the disadvantage of not using hard coded field ids ¯\_(ツ)_/¯

    If you want to copy all fields from “Client Enquiry” to “Client Contact”, I have a shorter version of the script that just loops over the fields. This script assumes that the fields are named the same in both forms and have the same type (eg, text field):

    function New_Client_Contact() {
    
    	// Define client form 
    	const clientForm = document.getFormNamed("Client Contact");
    	
    	// Create new record
    	let clientRecord = clientForm.addNewRecord();
    	
    	// Loop over fields and copy their content
    	for (field of form.getFields()){
    		let clientFieldId = clientForm.getFieldNamed(field.name).getId();
    		clientRecord.setFieldValue(clientFieldId, record.getFieldValue(field.getId()));
    	}	
    	// Save
    	clientForm.saveAllChanges();
    }
    
    New_Client_Contact();

    Note: I personally would use one form and have a field “status” that identifies if this is just an enquiry or if it turned into a client.

    Cheers, Daniel

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

    T.L. Ford
    Participant

    Here’s a code solution and how I did it. Ignore where I went and got the form id – didn’t need it. There’s no sound (me and my computer recording software are at war just now).

    You can make a menu shortcut to run the script if you want. That’s at the bottom under the script name.

    Basically, the script gets the values for the fields on the current record, and puts those values on a new record on the Client Contact form. Your field IDs will be different.

    – T

    Attachments:
    You must be logged in to view attached files.
Viewing 15 results - 1,726 through 1,740 (of 2,952 total)