<?xml version="1.0"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Team DF and Weetbicks blogs and news</title>
		<link>https://www.teamdf.com/blogs/</link>
		<atom:link href="https://www.teamdf.com/blogs/" rel="self" type="application/rss+xml" />
		<description></description>

		
		<item>
			<title>RAG Bots In FileMaker - An Early Exploration</title>
			<link>https://www.teamdf.com/blogs/rag-bots-in-filemaker-an-early-exploration/</link>
			<description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;In our previous articles we have looked at what &lt;a title=&quot;an-ai-overview&quot; href=&quot;https://www.teamdf.com/blogs/an-ai-overview/&quot; target=&quot;_blank&quot;&gt;AI&lt;/a&gt; is, how &lt;a title=&quot;semantic-search&quot; href=&quot;https://www.teamdf.com/blogs/semantic-search/&quot; target=&quot;_blank&quot;&gt;semantic search&lt;/a&gt; works, how AI features like &lt;a title=&quot;harnessing-ai-in-filemaker&quot; href=&quot;https://www.teamdf.com/blogs/harnessing-ai-in-filemaker/&quot; target=&quot;_blank&quot;&gt;embeddings&lt;/a&gt; are showing up in FileMaker, how to &lt;a title=&quot;generate-response-from-model&quot; href=&quot;https://www.teamdf.com/blogs/generate-response-from-model/&quot; target=&quot;_blank&quot;&gt;generate a response&lt;/a&gt; from a model, and most recently the &quot;&lt;a title=&quot;natural-language-queries-in-filemaker-2&quot; href=&quot;https://www.teamdf.com/blogs/natural-language-queries-in-filemaker-2/&quot; target=&quot;_blank&quot;&gt;Perform SQL Query by Natural Language&lt;/a&gt;&quot; script step. If you&#039;ve been following along, you may have noticed we&#039;re building towards something practical…&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;em&gt;A way to literally talk to your data!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We want to build a chatbot that we can have a natural conversation with about a specific client or project. Not a generic AI that knows a bit about everything, but something that knows our data: meeting notes, project history, correspondence, and anything else we know about that client. Something we can ask questions of and get useful answers back.&lt;/p&gt;
&lt;p&gt;The technology that makes this possible is called RAG, Retrieval-Augmented Generation. In this article we&#039;re going to look at what RAG actually is, how it works, what we&#039;re trying to build with it, and the three main ways we see that you could approach it.&lt;/p&gt;
&lt;h6&gt;&lt;strong&gt;Disclaimer: &lt;/strong&gt;At the time of publishing, all prices and storage limits in the article were accurate. But the world of AI is moving fast and changing quickly. Please be sure to verify the costs and limits against recent documentation.&lt;/h6&gt;
&lt;h3&gt;So What Is RAG?&lt;/h3&gt;
&lt;p&gt;RAG stands for &lt;strong&gt;Retrieval-Augmented Generation&lt;/strong&gt;, and it’s the core idea behind any system that lets you chat with your own data.&lt;/p&gt;
&lt;p&gt;To understand why it matters, it helps to think about the problem it solves. Language models are trained on enormous amounts of text, but that training has a cutoff date, and more importantly it doesn&#039;t include your data. If you ask a language model about a meeting you had with a client last Tuesday, it has no built-in knowledge of that at all... and nor should it!&lt;/p&gt;
&lt;p&gt;This is where AI systems can start to get into trouble. Newer models are better at admitting when they don&#039;t have enough information, but they can still guess, fill in gaps, or sound more certain than they should. Without access to the real client data, that&#039;s exactly the kind of situation where you can end up with a plausible-sounding answer that isn&#039;t actually true.&lt;/p&gt;
&lt;p&gt;One obvious way around this is to just include all your data in the conversation. Dump all your client docs into the prompt and ask the model to answer based on them. That gives the conversation Context.&lt;/p&gt;
&lt;p&gt;We do not recommend sending your raw data to an AI...&lt;/p&gt;
&lt;p&gt;(Or any other API type service for that matter — your accounting system might be the exception.)&lt;/p&gt;
&lt;p&gt;If data privacy matters, that usually means using a paid AI model rather than a free one. Even then, it is worth checking the settings carefully to make sure your data is not being retained or used for training. That can improve things, but it still does not give you full control. If you want the highest level of security and ownership over your client data, a local setup is really the only option.&lt;/p&gt;
&lt;p&gt;RAG is the smarter solution, instead of throwing everything at the model, you first retrieve only the most relevant pieces of information, then add just those to the prompt before asking the model to respond. It&#039;s more targeted, more efficient, and helps ensure the answers generated are based on real data. That&#039;s what reduces the risk of hallucinations.&lt;/p&gt;
&lt;p&gt;The &quot;space&quot; where your embedded documents live, is what we are calling a &lt;strong&gt;RAG space.&lt;/strong&gt; OpenAI calls theirs Vector Stores; other providers use different terminology, but the concept is the same.&lt;br&gt;RAG works in two stages:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Retrieval:&lt;/strong&gt; when the user asks a question, the system searches the RAG space to find the most relevant pieces of information.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generation:&lt;/strong&gt; those pieces are handed to a language model, which reads them and uses them to produce a response.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/RAG-Bots-In-FileMaker/_resampled/ResizedImage660370-chatgpt-rag-flow.png&quot; alt=&quot;chatgpt rag flow&quot; width=&quot;660&quot; height=&quot;370&quot;&gt;&lt;/p&gt;
&lt;h3&gt;So How Does Retrieval Work?&lt;/h3&gt;
&lt;p&gt;The retrieval stage is essentially a semantic search. If you have read our &lt;a title=&quot;semantic-search&quot; href=&quot;https://www.teamdf.com/blogs/semantic-search/&quot; target=&quot;_blank&quot;&gt;Diving Into Semantic Search&lt;/a&gt; article, a lot of this will be familiar. If not we encourage you to read that article for more detail.&lt;/p&gt;
&lt;p&gt;The first step is to embed all of your documents using an embedding model to get a vector for each one. These vectors are what is actually stored in your RAG space. You could think of the vectors as a sort of index based on meaning.&lt;/p&gt;
&lt;p&gt;When a user asks a question, that question is embedded using the same model, producing its own vector. The system then compares the question&#039;s vector against every document vector in your RAG space using cosine similarity. The documents with the highest &lt;strong&gt;cosine similarity&lt;/strong&gt; scores are the ones retrieved and passed to the language model.&lt;/p&gt;
&lt;p&gt;It&#039;s also worth noting that retrieval quality is heavily influenced by how you chunk and structure your documents before embedding them. Smaller, focused chunks tend to produce more precise results, because the vectors are based on smaller chunks of text, and therefore the meaning the vector represents is more precise.&lt;/p&gt;
&lt;p&gt;Large monolithic documents can dilute the semantic signal and make it harder to find the right content. We touched on that in our semantic search article, and the same principles apply here.&lt;/p&gt;
&lt;h3&gt;Building a RAG Bot for Client Data&lt;/h3&gt;
&lt;p&gt;Now that we understand what RAG is, let&#039;s talk about what we are actually trying to build.&lt;/p&gt;
&lt;p&gt;The goal is a chatbot that knows about a specific client: their meeting notes, project history, correspondence, and anything else relevant. This is where a lot of the earlier pieces start to come together: embeddings, semantic search, and generating responses from models all in one workflow. The model never needs to be trained on any of this data. Instead, each time a user asks a question, the most relevant documents are fetched from that client&#039;s RAG space and placed in front of the model in real time.&lt;/p&gt;
&lt;p&gt;The key design decision is that we want a &lt;strong&gt;separate RAG space for each client.&lt;/strong&gt; This way when a user opens a chat for Client A, the system retrieves from Client A&#039;s space only. This keeps responses focused and avoids the risk of information from one client bleeding into answers about another.&lt;/p&gt;
&lt;p&gt;So the question becomes: what&#039;s the best system to build this on? We will be looking at 3 different options:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;OpenAI Vector Stores&lt;/li&gt;
&lt;li&gt;Claude / Anthropic with an External Vector Database&lt;/li&gt;
&lt;li&gt;Local RAG with FileMaker AI Server&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;As we investigate each option we will post accompanying articles.&lt;/p&gt;</description>
			<pubDate>Wed, 13 May 2026 09:55:36 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/rag-bots-in-filemaker-an-early-exploration/</guid>
		</item>
		
		<item>
			<title>Welcome Matt!</title>
			<link>https://www.teamdf.com/blogs/welcome-matt-haughton/</link>
			<description>&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/matt-haughton-1.png&quot; alt=&quot;matt haughton 1&quot; width=&quot;660&quot; height=&quot;880&quot;&gt;&lt;/p&gt;
&lt;p&gt;Firstly, we’d like to announce and warmly welcome Matt Haughton to the team here at Digital Fusion. Matt joined us in late February and has already become a valued member of the team.&lt;/p&gt;
&lt;p&gt;Now onto Matt himself—and importantly, what makes him a special person and a great developer?&lt;br&gt;The good news is we didn’t need to dig too far; he provided plenty of nuggets of gold himself.&lt;/p&gt;
&lt;p&gt;Matt comes to us with a Bachelor of Science in Artificial Intelligence. In 2026 that’s very relevant—but he was awarded the degree in 2002, so he was clearly ahead of his time. Claude tells me that was when the rest of us were still trying to master Snake on our Nokia 3310s.&lt;/p&gt;
&lt;p&gt;After completing his degree, Matt moved into the world of FileMaker, working across multiple industries in the UK. In 2009, he joined a UK Claris Partner, MaJic Solutions, based in Milton Keynes.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/matt-haughton-3.png&quot; alt=&quot;matt haughton 3&quot; width=&quot;660&quot; height=&quot;880&quot;&gt;&lt;/p&gt;
&lt;p&gt;You may be wondering what brought Matt to New Zealand. Well, this is where the real nuggets of gold start to appear.&lt;/p&gt;
&lt;p&gt;Matt was an avid player of the game Clash of Clans, as was his clan leader—who just so happened to be based in New Zealand. Over a number of years, a romance blossomed, with the clan leader eventually travelling to the UK to meet Matt in person.&lt;/p&gt;
&lt;p&gt;The relationship continued to grow, and the pair were married in Christchurch in 2016. They then returned to the UK, where they lived for seven years before ultimately making their way back to New Zealand.&lt;/p&gt;
&lt;p&gt;We’re pleased they saw the light and are now living and working in Christchurch, along with Matt’s daughter.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage660880-matt-haughton-2.png&quot; alt=&quot;matt haughton 2&quot; width=&quot;660&quot; height=&quot;880&quot;&gt;&lt;/p&gt;
&lt;p&gt;Matt’s a man of many talents—and a few quirky life choices…&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;He may look very innocent, but he’s trained in the art of Brazilian Jiu-Jitsu.&lt;/li&gt;
&lt;li&gt;Like all good modern men, he’s a dab hand in the kitchen and enjoys pairing his meals with a well-made cocktail.&lt;/li&gt;
&lt;li&gt;Matt didn’t arrive in Christchurch empty-handed—he also brought along his three cats: Christopher, Jasper, and Kevin.&lt;/li&gt;
&lt;li&gt;And in one of life’s more questionable decisions, Matt once drove a Ford Ka completely decked out in Astroturf. If that raises a few questions, be sure to check out the photo below.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/matt-haughton-4.png&quot; alt=&quot;matt haughton 4&quot; width=&quot;660&quot; height=&quot;564&quot;&gt;&lt;/p&gt;
&lt;p&gt;We’re thrilled to have Matt as part of the Digital Fusion team. He brings an extraordinary depth of experience, a razor-sharp technical mind, and the kind of personality that makes the office an even better place.&lt;/p&gt;</description>
			<pubDate>Fri, 10 Apr 2026 11:39:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/welcome-matt-haughton/</guid>
		</item>
		
		<item>
			<title>Natural Language Queries in FileMaker (2)</title>
			<link>https://www.teamdf.com/blogs/natural-language-queries-in-filemaker-2/</link>
			<description>&lt;h2 class=&quot;ace-copy-paste-skip-this-tag&quot;&gt;&lt;span style=&quot;font-size: 1.5em;&quot;&gt;Introduction&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;If you haven’t yet read &lt;a href=&quot;https://www.teamdf.com/blogs/natural-language-queries-in-filemaker-1/&quot;&gt;Part 1&lt;/a&gt; of the Reconnect article, we suggest you read that first. &lt;a href=&quot;https://www.teamdf.com/blogs/natural-language-queries-in-filemaker-1/&quot;&gt;Part 1&lt;/a&gt; covers the Perform SQL Query by Natural Language script step, the different available variables and how to set them. We also cover how the script step works and interacts with the selected LLM.&lt;/p&gt;
&lt;p&gt;In this article, we are diving into the different methods you can use to improve the results of the script step. We will look at how you can set up LLM comments in your database and the kind of information that needs to be in these LLM comments. We will also be covering how you can set up different prompt templates and the sort of information that you can include in them.&lt;/p&gt;
&lt;h2&gt;The DDL and LLM Comments&lt;/h2&gt;
&lt;p&gt;Now I am sure there is some confusion around the DDL at this point, so let&#039;s try and clear that up. In my opinion, the DDL is misnamed. What DDL actually stands for is &lt;em&gt;Data Definition Language&lt;/em&gt;, which makes the “Get DDL” action the equivalent of a “Get English” action. What you are actually getting with the “Get DDL” action is the &lt;strong&gt;database schema&lt;/strong&gt;, expressed in the Data Definition Language, for the tables you’ve allowed the model to access. So really, a “Get Table Schema” action would make more sense.&lt;/p&gt;
&lt;p&gt;Even Claris’ own documentation describes it this way:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Returns the database schema (in Data Definition Language) that this script step generates and sends to the model.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a title=&quot;Claris Help – Perform SQL Query by Natural Language&quot; href=&quot;https://help.claris.com/en/pro-help/content/perform-sql-query-by-natural-language.html&quot; target=&quot;_blank&quot;&gt;(Claris Help – Perform SQL Query by Natural Language)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;What’s in the DDL&lt;/h2&gt;
&lt;p&gt;When you run the &lt;strong&gt;Perform SQL Query by Natural Language&lt;/strong&gt; script step, FileMaker builds a DDL structure for each table you’ve selected.&lt;/p&gt;
&lt;p&gt;The DDL includes:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The table name&lt;/li&gt;
&lt;li&gt;The field names&lt;/li&gt;
&lt;li&gt;Each field’s data type (text, number, date, etc.)&lt;/li&gt;
&lt;li&gt;And any &lt;strong&gt;comments&lt;/strong&gt; associated with those fields&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;For example: &lt;/p&gt;
&lt;p&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natural-Language-Queries-part-2/_resampled/ResizedImage66099-create-table-contacts.png&quot; alt=&quot;create table contacts&quot; width=&quot;660&quot; height=&quot;99&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you haven’t set up any LLM comments, the entire schema for every selected table is sent through. This is rarely what you want. In larger systems with wide tables, this can mean hundreds of fields and long comment strings being transmitted — adding unnecessary tokens and irrelevant detail for the model to process.&lt;/p&gt;
&lt;h2&gt;How LLM Comments Change the DDL&lt;/h2&gt;
&lt;p&gt;FileMaker provides a way to control what is actually sent to the model by marking specific comments as&lt;em&gt; LLM comments&lt;/em&gt;. These are just ordinary field comments in the Database Manager, but when you prefix them with `[LLM]`, FileMaker recognises them as AI-specific instructions.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natural-Language-Queries-part-2/_resampled/ResizedImage66047-contact-record-status.png&quot; alt=&quot;contact record status&quot; width=&quot;660&quot; height=&quot;47&quot;&gt;&lt;/p&gt;
&lt;p&gt;Once you add even one LLM comment to a table, FileMaker changes its behaviour, and only fields with LLM comments are included in the DDL; all other fields in that table are excluded&lt;/p&gt;
&lt;p&gt;This has three key benefits:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Token efficiency&lt;/strong&gt; – the DDL sent to the model is much smaller, so requests cost fewer tokens and execute faster.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Privacy contro&lt;/strong&gt;l – sensitive fields like driver’s licence numbers, tax IDs, or internal notes are simply omitted from the data the model ever sees.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced context noise&lt;/strong&gt; – irrelevant or low-value fields (such as system flags, constants, or relationship keys) are excluded, so the model focuses only on the schema that’s meaningful to the query. This makes its understanding sharper and reduces the chance of it generating SQL that references unrelated tables or join conditions.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;From Claris’ own best-practice guidance:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Add the [LLM] tag to limit fields included”&lt;/em&gt;&lt;br&gt;&lt;a title=&quot;Schema Best Practices for SQL Generation&quot; href=&quot;https://help.claris.com/en/pro-help/content/schema-best-practices-for-sql-generation.html&quot; target=&quot;_blank&quot;&gt;(Schema Best Practices for SQL Generation)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Writing Effective LLM Comments&lt;/h2&gt;
&lt;p&gt;Because the model only sees schema and comments (not live data), a well-written LLM comment needs to include all the context a human developer could infer from the data itself.&lt;/p&gt;
&lt;p&gt;That means describing:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;What the field represents&lt;/li&gt;
&lt;li&gt;Possible or expected values&lt;/li&gt;
&lt;li&gt;How those values should be used or filtered&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Good example:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natural-Language-Queries-part-2/_resampled/ResizedImage66029-good-example.png&quot; alt=&quot;good example&quot; width=&quot;660&quot; height=&quot;29&quot;&gt;&lt;/p&gt;
&lt;p&gt;Poor example: &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natural-Language-Queries-part-2/_resampled/ResizedImage66034-poor-example.png&quot; alt=&quot;poor example&quot; width=&quot;660&quot; height=&quot;34&quot;&gt;&lt;/p&gt;
&lt;p&gt;The first one gives the model usable context to generate the right SQL, even when multiple fields or tables could be relevant.&lt;/p&gt;
&lt;h2&gt;Best Practices for LLM Comments and DDL&lt;/h2&gt;
&lt;p&gt;Using LLM comments turns that schema into a &lt;strong&gt;controlled vocabulary&lt;/strong&gt; for the model, ensuring it understands what each field means while keeping your solution efficient and private.&lt;/p&gt;
&lt;p&gt;If you’re building anything more than a quick demo, start by adding LLM comments to your most important fields. It’s the easiest way to shape how the model sees your data — and just as importantly, what it &lt;em&gt;doesn’t&lt;/em&gt; see.&lt;/p&gt;
&lt;p&gt;A few habits make a big difference when setting up LLM comments and managing what goes into the DDL:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Keep it focused&lt;/strong&gt; - Add LLM comments only to fields the model needs. Once you add even one, only those fields are sent — keeping the schema smaller, faster, and cheaper to process.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exclude what you don’t want shared &lt;/strong&gt;- Leaving [LLM] off a field is the easiest way to hide sensitive or irrelevant data, such as licence numbers, constants, or internal keys.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Explain intent, not just names &lt;/strong&gt;- The model can’t see your data, so be explicit. Describe what the field means, possible values, and how it should be used.[LLM] Record status. Values: &#039;active&#039;, &#039;deleted&#039;. Only include &#039;active&#039; records.`&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stay consistent &lt;/strong&gt;- Use a clear, repeatable format for comments — what the field is, what values it holds, and how to use them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Iterate as you go &lt;/strong&gt;- Test a few queries, see what the model gets wrong or overuses, and adjust your LLM comments to guide it better next time.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Being deliberate with your LLM comments keeps the schema lightweight, protects private data, and gives the model just enough context to produce accurate SQL without guesswork.&lt;/p&gt;
&lt;h2&gt;Prompt Templates&lt;/h2&gt;
&lt;p&gt;Now that we’ve covered the DDL and how the model understands your schema, the next question is: &lt;em&gt;how does it know what to do with it?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That’s where &lt;strong&gt;Prompt Templates&lt;/strong&gt; come in.&lt;/p&gt;
&lt;p&gt;Prompt Templates act as predefined instruction sets that tell the LLM &lt;em&gt;how&lt;/em&gt; to behave when interpreting a query. They sit between the user’s natural language prompt and the database schema, giving you a consistent and controllable framework for how SQL is generated and how responses are phrased.&lt;/p&gt;
&lt;p&gt;You configure them using the &lt;strong&gt;Configure Prompt Template&lt;/strong&gt; script step, and then reference the template name inside &lt;strong&gt;Perform SQL Query by Natural Language.&lt;/strong&gt; Each template can hold two optional components — &lt;strong&gt;an SQL Prompt &lt;/strong&gt;and a&lt;strong&gt; Natural Language Prompt&lt;/strong&gt; — which are sent along with every request.&lt;/p&gt;
&lt;h2&gt;The Two Prompt Types&lt;/h2&gt;
&lt;p&gt;Each template has two prompt options you can enable:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;SQL Prompt&lt;/li&gt;
&lt;li&gt;Natural Language Prompt&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;They do very different things.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SQL Prompt&lt;/strong&gt;&lt;br&gt;The SQL Prompt gives the LLM a list of rules on how to structure its SQL. This is essentially the system prompt for the query generation part. It defines things like:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;How to format field names and dates&lt;/li&gt;
&lt;li&gt;Which functions to avoid&lt;/li&gt;
&lt;li&gt;How to limit rows&lt;/li&gt;
&lt;li&gt;What parts of the schema are allowed to use&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Here’s an example based on one of my templates:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natural-Language-Queries-part-2/_resampled/ResizedImage660324-sql-template.png&quot; alt=&quot;sql template&quot; width=&quot;660&quot; height=&quot;324&quot;&gt;&lt;/p&gt;
&lt;p&gt;During testing, I found the model kept returning queries that used the DATE_TRUNC function, which isn’t recognised in FileMaker. So I added a rule to tell it not to use that function. These prompts will probably evolve as you discover little quirks or unsupported syntax that cause errors.&lt;br&gt;You can also use the SQL prompt as a bit of a safety net. For example, you might add information about a field like “record_status” so that if a full LLM comment is missed, the model still knows how that field should be used.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Natural Language Prompt&lt;/strong&gt;&lt;br&gt;The Natural Language Prompt is much simpler. It just tells the model how to return the final answer — the format and style of the response, not the SQL itself.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natural-Language-Queries-part-2/_resampled/ResizedImage66046-natural-language-prompt-example.png&quot; alt=&quot;natural language prompt example&quot; width=&quot;660&quot; height=&quot;46&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can think of this as the “presentation layer” for the model’s response. In most cases, you won’t need to edit it much — once you’ve got a format you’re happy with, you’ll likely leave it as-is.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Using Prompt Templates in Practice&lt;/strong&gt;&lt;br&gt;Prompt templates are stored in memory once configured, so I normally call &lt;strong&gt;Configure Prompt Template&lt;/strong&gt; early in the process — usually during file open or before the first query is made. After that, I just pass the template name into any &lt;em&gt;Perform SQL Query by Natural Language&lt;/em&gt; script steps that need it.&lt;br&gt;Because the templates are separate from the scripts, you can update and refine them without touching any user-facing code. This is especially handy when you’re trying to fix small issues — you can adjust your SQL rules, add or remove restrictions, or fine-tune the tone of the model’s answers without needing to edit multiple scripts.&lt;/p&gt;
&lt;h2&gt;Best Practices for Prompt Templates&lt;/h2&gt;
&lt;p&gt;Here are a few things that have worked well in practice:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Create different templates for different contexts &lt;/strong&gt;- Keep the rules focused on one area of your system (e.g. contacts, sales, projects). This makes it easier to manage and debug.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Iterate as you go &lt;/strong&gt;- Start with the defaults and adjust the SQL Prompt whenever you notice recurring issues — like invalid SQL functions or unwanted joins.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use a numbered list &lt;/strong&gt;- The model follows instructions more reliably when rules are listed clearly in order. Avoid vague instructions such as “try to”.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Always include the schema reference &lt;/strong&gt;- End your SQL Prompt with `Only utilise the following database schema: :schema:` so the model stays anchored to your actual tables.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep the Natural Language Prompt simple &lt;/strong&gt;- It doesn’t need much tweaking beyond defining how you want the answer displayed (plain text, summary, etc.).&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Summing Up&lt;/h2&gt;
&lt;p&gt;The new &lt;em&gt;Perform SQL Query by Natural Language&lt;/em&gt; script step opens up a completely different way to interact with FileMaker data — but it’s not magic out of the box. To get meaningful, accurate results, you need to teach the model how your system works.&lt;br&gt;The DDL defines what the model can see. LLM comments let you refine that definition, focusing only on the fields that matter and stripping away the noise. Prompt templates then shape how the model interprets that schema and writes SQL, giving you consistent, predictable behaviour across different contexts.&lt;br&gt;When you combine clear [LLM] comments with well-tuned prompt templates, you turn FileMaker’s “natural language” query from a novelty into a genuinely useful interface for exploring data — one that feels simple for the user but is carefully engineered behind the scenes.&lt;/p&gt;</description>
			<pubDate>Thu, 06 Nov 2025 10:08:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/natural-language-queries-in-filemaker-2/</guid>
		</item>
		
		<item>
			<title>Natural Language Queries in FileMaker (1)</title>
			<link>https://www.teamdf.com/blogs/natural-language-queries-in-filemaker-1/</link>
			<description>&lt;h2&gt;Reconnect - The Illusion of Simplicity: Natural Language Queries in FileMaker&lt;/h2&gt;
&lt;p&gt;If you attended Reconnect  2025, you will have seen our presentation on integrating natural language queries with FileMaker. If you missed it, consider &lt;a title=&quot;Reconnect Conference - All things FileMaker and Claris&quot; href=&quot;https://reconnect.fm&quot; target=&quot;_blank&quot;&gt;saving the date for next year&lt;/a&gt;. These companion articles build on that session, offering more detail and letting you explore the concepts at your own pace.&lt;/p&gt;
&lt;p&gt;But first the original presentation:&lt;/p&gt;
&lt;p&gt;&lt;div class=&quot;media leftAlone&quot;&gt;&lt;iframe width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://www.youtube.com/embed/yuudzUFdMN8?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; title=&quot;Natural Language Queries in FileMaker | Reconnect 2025&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;The session explored how &lt;em&gt;natural language queries&lt;/em&gt; can enable users to interact with their solution and data using the “Perform SQL Query by Natural Language” script step to create a chatbot. But it&#039;s not as simple as just plugging in the script step and giving it a chatbot interface. For example, here we do have a correct answer in that there are 5504 records in our contacts table; however, in our system, we use soft deletes, so 1500 of those contacts are not visible in the system and should not be counted.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage660342-app-assist.png&quot; alt=&quot;app assist&quot; width=&quot;660&quot; height=&quot;342&quot;&gt;&lt;/p&gt;
&lt;p&gt;We walked through:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The script step and the various parameters that can be set&lt;/li&gt;
&lt;li&gt;How the script step interacts with the LLM&lt;/li&gt;
&lt;li&gt;Different ways to improve the results&lt;/li&gt;
&lt;li&gt;LLM Comments&lt;/li&gt;
&lt;li&gt;Prompt templates&lt;/li&gt;
&lt;li&gt;A simple use case &lt;/li&gt;
&lt;li&gt;A summary of good practices to get into&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;In this article, we cover the first two points, first going over the script step, followed by how it works and interacts with the selected LLM. In the second article, we cover the different ways that you can improve the results.&lt;/p&gt;
&lt;h2&gt;Perform SQL Query by Natural Language Script Step&lt;/h2&gt;
&lt;p&gt;This script step lets you query your database using plain language instead of writing SQL by hand. It uses an AI model to interpret your prompt, understand the database structure, and generate the right SQL queries. Once those queries are run, the model can return the results in natural language.&lt;/p&gt;
&lt;p&gt;The process typically works like this:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;The script step sends your prompt and the relevant database schema (based on the Data Tables you’ve specified) to the configured AI model. This can include any extra context from a prompt template.&lt;/li&gt;
&lt;li&gt;The model analyses both the prompt and schema, then generates one or more SQL queries to get the requested data.&lt;/li&gt;
&lt;li&gt;The script step receives the generated SQL and executes it.&lt;/li&gt;
&lt;li&gt;The results of the SQL query are sent back to the model.&lt;/li&gt;
&lt;li&gt;If the model decides that more data or further refinement is needed to answer the prompt fully, it can generate and run additional queries (repeating steps 2–4). This allows for more complex, multi-step queries.&lt;/li&gt;
&lt;li&gt;Once the model has what it needs, it produces a final response based on the original prompt and the query results.&lt;/li&gt;
&lt;li&gt;The script step then stores that final response in the Response Target.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600185-script-step-blank.png&quot; alt=&quot;script step blank&quot; width=&quot;600&quot; height=&quot;185&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is a large script step with a lot going on, a minimum of 11 different options you can set, so we broke this down into each of the different options. &lt;/p&gt;
&lt;h2&gt;Account Name&lt;/h2&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600185-script-step-acc-name.png&quot; alt=&quot;script step acc name&quot; width=&quot;600&quot; height=&quot;185&quot;&gt;&lt;/p&gt;
&lt;p&gt;Before any of the new AI script steps are used, you first need to call the “Configure AI Account” script step once. This script step really only needs to be called once at file open, and then the account name used in that call can then be used for all the other AI script steps. &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage60034-configure-image-1.png&quot; alt=&quot;configure image 1&quot; width=&quot;600&quot; height=&quot;34&quot;&gt;&lt;/p&gt;
&lt;p&gt;This script step allows you to set an account name (plain text), select your model provider (a drop-down list of the following providers: OpenAI, Anthropic, Cohere, or Custom), and also enter an API key (plain text).&lt;/p&gt;
&lt;h2&gt;Model&lt;/h2&gt;
&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600185-script-step-model.png&quot; alt=&quot;script step model&quot; width=&quot;600&quot; height=&quot;185&quot;&gt;&lt;/p&gt;
&lt;p&gt;The model is the Large Language Model (LLM) that you want to use for this script step. This is entered in plain text, and must be a model from the provider that was specified in the “Configure AI Account script step.&lt;/p&gt;
&lt;h2&gt;Prompt&lt;/h2&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600185-script-step-prompt.png&quot; alt=&quot;script step prompt&quot; width=&quot;600&quot; height=&quot;185&quot;&gt;&lt;/p&gt;
&lt;p&gt;This can be a variable or a field, and is simply the question you want answered. From our example, this would be: “How many contacts in the system?&lt;/p&gt;
&lt;h2&gt;Options specified&lt;/h2&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600185-script-step-options.png&quot; alt=&quot;script step options&quot; width=&quot;600&quot; height=&quot;185&quot;&gt;&lt;/p&gt;
&lt;p&gt;There are a couple of different ways to set the options. First, there is the “From List” option, which gives you access to a dropdown list of &lt;strong&gt;Actions&lt;/strong&gt;, a few different ways to select tables that the script step will have access to, and also shows the“Stream” checkbox option (which we will cover later in this article). The second way to set the options is via a JSON Structure, which allows a more dynamic way to setup the script step. You can generate the JSON in the script and pass it as a variable to the script step, this means that you don&#039;t need to edit the script step when you want to do things like change the tables that you want access to.&lt;/p&gt;
&lt;h2&gt;Actions&lt;/h2&gt;
&lt;p&gt;There are 5 different actions available. Most of these are to enable you to see what the LLM is sending back in response to the script step being run, but one action is to expose some of the information that you are sending through to the LLM.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600159-sql-query-from-list.png&quot; alt=&quot;sql query from list&quot; width=&quot;600&quot; height=&quot;159&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600363-table.png&quot; alt=&quot;table&quot; width=&quot;600&quot; height=&quot;363&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Tables&lt;/h2&gt;
&lt;p&gt;To select the tables that you want to be able to query, there are three different options: From list, By name, and By DDL.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600115-sql-table.png&quot; alt=&quot;sql table&quot; width=&quot;600&quot; height=&quot;115&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;From list:&lt;/strong&gt; Select specific tables from a list.&lt;/p&gt;
&lt;p&gt;This allows you to select any table occurrences in your current file. This is an important thing to note if you have a data separation model (a user interface file and a data file). You will need to make sure that you have a table occurrence of any tables from your data file if you want to have access to them.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600752-specify-tables.png&quot; alt=&quot;specify tables&quot; width=&quot;600&quot; height=&quot;752&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By name:&lt;/strong&gt; Provide a list of table names as a text expression.&lt;/p&gt;
&lt;p&gt;Separate multiple table names with carriage returns. A simple text list of the table occurrence names. Again, these have to be in the file you are currently in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By DDL:&lt;/strong&gt; Provide a custom DDL text expression.&lt;/p&gt;
&lt;p&gt;This allows you to control exactly which schema information is sent to the model.&lt;/p&gt;
&lt;p&gt;We will discuss DDL further on in this article, but in short, the other options for selecting tables will automatically send the DDL for the tables you select through to the LLM to allow it to understand the data structure. If you select the “ByDDL” option, then you will need to construct the DDL for the tables yourself, and this is what is sent through.&lt;/p&gt;
&lt;h2&gt;Stream&lt;/h2&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600185-script-step-stream.png&quot; alt=&quot;script step stream&quot; width=&quot;600&quot; height=&quot;185&quot;&gt;&lt;/p&gt;
&lt;p&gt;The stream option determines how the response is delivered when the &lt;strong&gt;Action&lt;/strong&gt; is a &lt;strong&gt;Query&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;On: The response is retrieved and delivered incrementally (word by word or in phrases). This can make the FileMaker client feel more responsive.&lt;/li&gt;
&lt;li&gt;Off: The entire response is retrieved before it is made available. This may cause the FileMaker client to appear unresponsive while waiting for the complete response.&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Prompt Template Name&lt;/h2&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600185-scrtip-step-prompt.png&quot; alt=&quot;scrtip step prompt&quot; width=&quot;600&quot; height=&quot;185&quot;&gt;&lt;/p&gt;
&lt;p&gt;We will look at the prompt templates in more detail later in this article, for now, you just need to know that you can use the “Configure Prompt Template” script step to expose FileMaker&#039;s default prompt templates and name and edit these, or simply create your own prompt templates. Once the “Configure Prompt Template” script step has been called, you simply enter the Template name that you chose into this option on the “Perform SQL Query by Natural Language” Script Step.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage60028-configure-image-2.png&quot; alt=&quot;configure image 2&quot; width=&quot;600&quot; height=&quot;28&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Parameters&lt;/h2&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600185-script-step-parameters.png&quot; alt=&quot;script step parameters&quot; width=&quot;600&quot; height=&quot;185&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is a JSON object that consists of key-value pairs for additional parameters that are supported by the model provider. For example: `{&quot;temperature&quot;: 0.7, &quot;seed&quot;: 42}`. You should refer to the model provider&#039;s documentation for key names of supported parameters and their valid ranges.&lt;/p&gt;
&lt;h2&gt;Response Target&lt;/h2&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600185-script-step-response.png&quot; alt=&quot;script step response&quot; width=&quot;600&quot; height=&quot;185&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is simply the specified field or variable that you would like the response to be saved into.&lt;/p&gt;
&lt;h2&gt;Perform JavaScript in Web Viewer&lt;/h2&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600185-script-step-java.png&quot; alt=&quot;script step java&quot; width=&quot;600&quot; height=&quot;185&quot;&gt;&lt;/p&gt;
&lt;p&gt;This option allows you to specify a Web Viewer object and a function to call in that Web Viewer. This is how we displayed the conversation in a messaging window.&lt;/p&gt;
&lt;h2&gt;How it Works&lt;/h2&gt;
&lt;p&gt;The “Perform SQL Query by Natural Language” script step works a little differently from most script steps we are used to. Usually, we call a script step and expect that step to do just one thing. e.g.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Set Field&lt;/li&gt;
&lt;li&gt;Go to Layout&lt;/li&gt;
&lt;li&gt;Pause Script&lt;/li&gt;
&lt;li&gt;Etc.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; The “Perform SQL Query by Natural Language” script step has a bit of back and forth with the LLM to get a result.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Natrual-Queries/_resampled/ResizedImage600288-fm-to-llm.jpeg&quot; alt=&quot;fm to llm&quot; width=&quot;600&quot; height=&quot;288&quot;&gt;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;First, the prompt (User&#039;s question) is sent through to the LLM along with some instructions on how the LLM should answer, and the DDL (table schema in the Data Definition Language)&lt;/li&gt;
&lt;li&gt;The LLM processes this prompt and additional information and formulates an SQL statement that is sent back to FileMaker.&lt;/li&gt;
&lt;li&gt;FileMaker runs the SQL statement. &lt;/li&gt;
&lt;li&gt;FileMaker sends the result of the SQL statement back to the LLM (Even if there are errors)&lt;/li&gt;
&lt;li&gt;Steps 2-4 may be repeated several times in order to get a final result.&lt;/li&gt;
&lt;li&gt;The LLM sends back a final result that is then displayed to the user.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;You can think of the LLM as an intern or apprentice; it will do its best to produce the correct SQL statement the first time, but it may not always get it correct. This is why there is a feedback loop here, the first statement may be wrong, it may have some valid SQL that FileMaker cant process correctly, as FileMaker&#039;s ExecuteSQL function only supports a limited subset of SQL syntax. So the result is fed back to the LLM to allow for another attempt to get the answer to the &lt;strong&gt;prompt&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this first part, we’ve taken a closer look at how the “Perform SQL Query by Natural Language” script step actually works. We have broken down each of the available options, explored how FileMaker communicates with the LLM, and walked through the sequence of steps that happen behind the scenes when a query is run. What looks simple on the surface is in reality a layered process involving schema definitions, prompt handling, and multiple rounds of interaction between FileMaker and the model.&lt;/p&gt;
&lt;p&gt;In&lt;a href=&quot;https://www.teamdf.com/blogs/natural-language-queries-in-filemaker-2/&quot;&gt; &lt;strong&gt;Part 2&lt;/strong&gt;&lt;/a&gt;, coming soon, we’ll move on to the practical side — looking at how to improve the results you get from this script step using LLM comments and prompt templates to get more consistent and reliable answers.&lt;/p&gt;</description>
			<pubDate>Wed, 05 Nov 2025 12:05:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/natural-language-queries-in-filemaker-1/</guid>
		</item>
		
		<item>
			<title>Tool Calls: Giving AI Agents the Keys</title>
			<link>https://www.teamdf.com/blogs/tool-calls-giving-ai-agents-the-keys/</link>
			<description>&lt;p&gt;In a &lt;a title=&quot;ai-agents-beyond-simple-chat&quot; href=&quot;https://www.teamdf.com/blogs/ai-agents-beyond-simple-chat/&quot; target=&quot;_blank&quot;&gt;previous article &lt;/a&gt;we looked at how AI agents can plan tasks and do more than just answer questions. To perform those tasks, agents need a way to interact with other systems. This is where&lt;strong&gt; tool calls&lt;/strong&gt; come in. Think of tool calls as the verbs that let an agent take action—fetching data, running a calculation, or sending a message.&lt;/p&gt;
&lt;h2&gt;What are tool calls?&lt;/h2&gt;
&lt;p&gt;A&lt;strong&gt; tool call&lt;/strong&gt; is simply a request an agent makes to another service to get something done. This fits into the broader agent model discussed in our companion piece &lt;a title=&quot;ai-agents-beyond-simple-chat&quot; href=&quot;https://www.teamdf.com/blogs/ai-agents-beyond-simple-chat/&quot; target=&quot;_blank&quot;&gt;“From Chat to Action: Agentic AI in FileMaker”&lt;/a&gt;, where an agent isn’t limited to conversation but can plan, act and iterate. Imagine you ask a colleague to look up the weather: you give them a clear instruction and they return with the result. A tool call is the same idea, but formalised for an AI.&lt;/p&gt;
&lt;p&gt;Developers are used to writing API calls, such as `GET /weather?city=Auckland`, to make software talk to a weather service. Agents don’t know how to write code. Instead, they select from a list of tool descriptions and fill in the blanks. Each description tells the agent what the tool does, what inputs it expects and how to provide them.&lt;/p&gt;
&lt;p&gt;These descriptions are part of a growing set of AI‑native services. Unlike traditional APIs built for programmers, AI‑native services are written in plain language so that an agent can understand them. Once a tool is described in this standard way, any compliant agent can use it, no matter who wrote the tool.&lt;/p&gt;
&lt;h2&gt;How does a tool call work?&lt;/h2&gt;
&lt;p&gt;As Claris FileMaker developers, we can think of tool calls like calling a custom function or script step. You define the inputs and outputs, and the AI just plugs them together to carry out your request.&lt;/p&gt;
&lt;p&gt;Tool calls follow a straightforward cycle:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Recognising the need for help&lt;/strong&gt; – the agent reads your request and realises it doesn’t have the information or ability to answer on its own.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Picking a tool&lt;/strong&gt; – it looks through its available tools and chooses the one that fits the job, guided by the descriptions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Creating the request&lt;/strong&gt; – the agent writes down the tool name and the details it needs, such as which city to look up.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Running the tool&lt;/strong&gt; – the system running the agent executes the request. Importantly, the agent doesn’t run code itself; it hands off the work.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Getting the results&lt;/strong&gt; – the tool sends back the answer.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Using the answer&lt;/strong&gt; – the agent adds the new information to its conversation and plans what to do next.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Because the agent never runs code directly, you can set strict rules about which tools it may use and how their outputs are handled. For instance, you might only allow an agent to read data but require a human to approve any changes.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/robot-call-cycle.png&quot; alt=&quot;robot call cycle&quot; width=&quot;660&quot; height=&quot;660&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Why give AI access to tools?&lt;/h2&gt;
&lt;p&gt;Allowing an agent to call tools expands its usefulness well beyond writing sentences. In our companion article, &lt;a title=&quot;ai-agents-beyond-simple-chat&quot; href=&quot;https://www.teamdf.com/blogs/ai-agents-beyond-simple-chat/&quot; target=&quot;_blank&quot;&gt;From Chat to Action: Agentic AI in FileMaker,&lt;/a&gt; we discussed how a smart assistant can interpret your natural‑language query, plan what it needs to do, pick the right tool and iterate until it completes the task. When you marry that agentic logic with FileMaker’s new AI script steps, you get a system that understands what you mean and then works with your data in safe, predictable ways.&lt;/p&gt;
&lt;p&gt;Here’s why tool access matters – and how it plays out in FileMaker:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Understanding your intent and run the right script step.&lt;/strong&gt; The agent translates everyday language into specific actions. Using the &lt;strong&gt;Generate Response from Model&lt;/strong&gt; script step (with appropriate tool definitions), a user can ask, “What is the average invoice total for customer X over their last 10 invoices?” The agent is able to interpret this request and call the appropriate tools to complete the task and answer your question.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fetching fresh data from your own app.&lt;/strong&gt; With the Generate Response from Model step in agentic mode, the AI can call FileMaker custom functions to run SQL queries. This means the agent isn’t guessing at answers; it’s retrieving up‑to‑date information directly from your database.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chaining actions into a workflow.&lt;/strong&gt; As described in the agent article, the AI can plan its next steps and decide what to do next. In terms of our question above, this means it can execute SQL to retrieve the last 10 invoice totals. It can then call the appropriate calculation tools to work out an average.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep things grounded and controlled.&lt;/strong&gt; Tool calls rely on real data, which reduces the risk of hallucination. Because you define the tools – for example, which fields can be searched or which functions can be called – you control exactly what the agent can do. And with &lt;strong&gt;Set AI Call Logging&lt;/strong&gt;, you can record every request and response for auditing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Work seamlessly with structured data.&lt;/strong&gt; Tools return results in predictable formats, making it easy for the agent to use them in its reasoning.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;By combining natural‑language understanding with clearly defined FileMaker actions, agents become practical assistants that can interpret your queries and act on your behalf. The model isn’t free to do anything it likes – it calls only the tools you’ve described, and FileMaker’s script steps give you a high degree of control over those interactions.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/robot-tools.png&quot; alt=&quot;robot tools&quot; width=&quot;660&quot; height=&quot;660&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Cautions when using tools&lt;/h2&gt;
&lt;p&gt;Giving an agent access to tools is powerful, but it also increases the risks. The same safeguards recommended for agents apply here:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Scope&lt;/strong&gt; – define exactly which tools are available and what actions they can perform.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transparency&lt;/strong&gt; – keep logs of each call and its parameters. FileMaker’s tool call logging and other platforms’ tracing features are invaluable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Human oversight&lt;/strong&gt; – review the outputs before applying changes. Use agents to suggest actions rather than performing them automatically.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security&lt;/strong&gt; – keep API keys and credentials safe. Don’t expose them to the agent’s chat history.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;You should also consider what happens if a tool returns no results or an error. Just like with FileMaker scripts, you should build in error handling so the agent doesn’t loop endlessly or give misleading answers.&lt;/p&gt;
&lt;p&gt;Remember that tool calls are part of a bigger system. When tools are well described and access is carefully managed, they enable agents to move beyond static chat into practical assistants. Misconfigured or overly permissive tools, however, can lead to unwanted changes or security issues.&lt;/p&gt;
&lt;h2&gt;Summing up&lt;/h2&gt;
&lt;p&gt;Tool calls give AI the ability to act. By defining tools with clear descriptions and parameters, you create a safe environment where an agent can fetch fresh data, perform computations and automate tasks on your behalf. As the ecosystem of AI‑native services grows, understanding how to design and manage tool calls will help you unlock the full potential of agentic AI.&lt;/p&gt;
&lt;p&gt;With these new commands in FileMaker we can get started now — so start small: define one or two safe tools, test them with the Generate Response from Model step, and log every call. You’ll quickly see how tool calls move AI from text &quot;chat&quot; towards practical, controlled automation.&lt;/p&gt;
&lt;h2&gt;Possible use case: Post-meeting voice capture in FileMaker Go&lt;/h2&gt;
&lt;p&gt;After a client meeting, a user can open FileMaker Go on their iPhone and say something like, “Create a new note for Customer X. The contents should be…”&lt;br&gt;The agent understands the request and then uses the appropriate tools to find the contact, create a new note record, and populate it with the dictated notes.&lt;br&gt;You could even get the AI to improve/summarise the dictated notes.&lt;/p&gt;
&lt;p&gt;Tool calls turn AI from a talker into a doer. For Claris FileMaker developers, this means moving beyond chatbots into assistants that can fetch, calculate, and act inside your apps—with you always in control. Start experimenting with small, safe tools, and you’ll discover just how far agentic AI can take your FileMaker solutions.&lt;/p&gt;</description>
			<pubDate>Fri, 26 Sep 2025 16:05:12 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/tool-calls-giving-ai-agents-the-keys/</guid>
		</item>
		
		<item>
			<title>From Chat to Action: Agentic AI in FileMaker</title>
			<link>https://www.teamdf.com/blogs/ai-agents-beyond-simple-chat/</link>
			<description>&lt;p&gt;&lt;span&gt;Artificial intelligence is rapidly appearing everywhere, and new features arrive so quickly that it can be hard to separate marketing hype from genuine advances. When FileMaker 2024 added AI script steps, we explained how to harness those tools without getting lost in the hype. This article continues that mission and focuses on &lt;/span&gt;&lt;strong&gt;AI agents&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span&gt; If you’re wondering what an agent does and how it differs from a typical chat interface, read on…&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Simple Chat vs AI Agents: What’s The Difference?&lt;/h3&gt;
&lt;p&gt;A simple chat system is very good at having a conversation. You ask a question and it responds based on what it has learned from existing text. But that is all it can do. Imagine talking to a helpful librarian: they can tell you what they remember, but they aren’t allowed to leave their desk or look at any new books. They can’t go into the archive to check records, phone another library for an update or fill out a form for you.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/library-lady-smile.jpg&quot; alt=&quot;library-lady-smile&quot; width=&quot;660&quot; height=&quot;440&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Going Agentic&lt;/h3&gt;
&lt;p&gt;Making AI&lt;strong&gt; “agentic”&lt;/strong&gt; can be likened to giving that librarian the keys to the archive, a telephone (or an internet connection!) and a checklist…&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/library-lady-writing.jpg&quot; alt=&quot;library-lady-writing&quot; width=&quot;660&quot; height=&quot;440&quot;&gt;&lt;/p&gt;
&lt;p&gt;It can still talk to you, but can now also:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Plan multiple steps&lt;/strong&gt; – it breaks down a task into manageable steps rather than answering in one go.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use external tools&lt;/strong&gt; – it knows when and how to run a search, query a database or use a calculator.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decide what to do next&lt;/strong&gt; – based on what it finds, it chooses whether to keep searching, try a different approach or finish.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Work iteratively&lt;/strong&gt; – it can loop through these steps until it completes the task.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Put simply, a chat system is like a conversation that never leaves the room. An agent turns that conversation into a set of actions. It still &quot;thinks” with the same kind of language model, but by calling tools and services it can fetch fresh information and carry out tasks that the model alone could never perform.&lt;/p&gt;
&lt;h3&gt;Why Not Stay With Simple Chat?&lt;/h3&gt;
&lt;p&gt;Traditional chat interfaces are wonderful for brainstorming and summarising text, but they have some important limits. Imagine reading from a reference book that was published last year: it will never include today’s news or weather. In the same way, language models are trained on data up to a certain date and do not know about anything that has happened since. They also can’t do anything with your data — they can’t look up a record in your database, check a live stock price or move a file.&lt;/p&gt;
&lt;p&gt;Because a simple chat system cannot look up fresh information, it sometimes tries to fill the gap with a best guess. This is known as “hallucination”, when the system produces an answer that sounds plausible but isn’t correct. An agent overcomes these limits by recognising when it needs help, calling the appropriate tool and using the result to inform its answer. By tapping into live data sources and other services, the agent reduces the risk of outdated or invented answers and can actually perform tasks on your behalf.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/computer-robot.jpg&quot; alt=&quot;computer-robot&quot; width=&quot;660&quot; height=&quot;660&quot;&gt;&lt;/p&gt;
&lt;h3&gt;AI Agents In Practice&lt;/h3&gt;
&lt;p&gt;When FileMaker added the &lt;a title=&quot;Link to article on FileMaker&amp;#039;s new Generate Response From Model script step&quot; href=&quot;https://www.teamdf.com/blogs/generate-response-from-model/&quot;&gt;Generate Response from Model&lt;/a&gt; script step, it included an Agentic Mode that behaves like an AI agent. In this mode, your script can send instructions that describe what the agent should do and which tools are available. The agent plans its workflow, calls the appropriate tool (e.g. `execute_sql` or a custom function) and returns the result. You can even inspect the order of tool calls for debugging purposes.&lt;/p&gt;
&lt;p&gt;Similarly, the wider AI ecosystem is moving towards AI‑native services. Anthropic’s &lt;strong&gt;Model Context Protocol&lt;/strong&gt; (MCP), introduced in late 2024, created a standard language for agents to talk to all sorts of services.&lt;/p&gt;
&lt;p&gt;Software providers are building AI‑native interfaces that expose human‑readable descriptions and parameter schemas, making it easier for agents to understand how to interact. Within months of the protocol’s launch, thousands of tools appeared, allowing agents to access databases, browse the web, manipulate files and send emails.&lt;/p&gt;
&lt;p&gt;For example, &lt;a title=&quot;Xero introduced an MCP&quot; href=&quot;https://medium.com/xerodevblog/xero-introduces-new-model-context-protocol-server-for-smarter-accounting-4d195ccaeda5&quot; target=&quot;_blank&quot;&gt;Xero introduced an MCP&lt;/a&gt; back in March this year, and other services such as Stripe, Paypal and Slack have MCP options.&lt;/p&gt;
&lt;h3&gt;What Should You Watch Out For?&lt;/h3&gt;
&lt;p&gt;Giving an agent access to tools is powerful, but it also increases the risks. Our earlier advice about not letting AI modify your data still applies. Keep these cautions in mind:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Scope&lt;/strong&gt; – define exactly which tools the agent can use. For example, expose a read‑only SQL query function but not a function that updates invoices.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transparency&lt;/strong&gt; – log each tool call and its parameters. FileMaker’s tool call logging and other platforms’ tracing features are invaluable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Human oversight&lt;/strong&gt; – review tool outputs before applying changes. Use agents to suggest actions rather than performing them automatically.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security&lt;/strong&gt; – ensure that API keys or database credentials are stored securely and not exposed to the agent’s chat history.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Agents are also subject to the usual AI limitations: they inherit biases from their training data, can misinterpret instructions and may need careful prompting. While tool calls reduce hallucinations, they don’t eliminate them entirely.&lt;/p&gt;
&lt;h3&gt;Summing Up&lt;/h3&gt;
&lt;p&gt;An AI agent combines the conversational strengths of a language model with the ability to act. By defining what it can do and placing guardrails around those actions, you create a safe and structured environment where the agent can plan, call tools and iterate. This turns a chat‑style exchange into a workflow capable of retrieving real‑time information, performing computations reliably, and automating routine tasks.&lt;/p&gt;
&lt;p&gt;With thoughtful design and human oversight, AI agents can move beyond simple chat into genuinely useful assistants that save time and reduce manual work. &lt;/p&gt;
&lt;h3&gt;Example Use&lt;/h3&gt;
&lt;p&gt;Let&#039;s say you&#039;ve come out of a meeting and want to capture your thoughts and actions&lt;/p&gt;
&lt;p&gt;Using an AI agent you&#039;d be able to open FileMaker Go and say something like: “Create a new note for Customer X. The contents should be…”&lt;br&gt;The agent understands the request, and then uses the appropriate tools to find the contact, create a new note record, and populate it with the dictated notes.&lt;br&gt;You could even get the AI to schedule the next action reminder or extract key points from what you&#039;ve said.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 02 Sep 2025 03:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/ai-agents-beyond-simple-chat/</guid>
		</item>
		
		<item>
			<title>Generate Response from Model</title>
			<link>https://www.teamdf.com/blogs/generate-response-from-model/</link>
			<description>&lt;p&gt;FileMaker 22 (also referred to as FileMaker 2025) introduces a range of new tools for integrating AI into your solutions. In this post, we’ll be focusing on the &lt;strong&gt;Generate Response from Model&lt;/strong&gt; script step, which allows scripts to send prompts to an AI model and get a response. At its simplest, it drops a ChatGPT-style chat straight into your solution; type a prompt, and get an answer. This is similar to using ChatGPT in a browser, but switch on &lt;strong&gt;Agentic Mode&lt;/strong&gt;, and that same step can plan tasks, invoke tools such as SQL queries or own custom functions, and iterate until it gets the result you need.&lt;/p&gt;
&lt;p&gt;Just like previous AI features, you’ll need to run the &lt;strong&gt;Configure AI Account&lt;/strong&gt; script step first. This sets up the AI account by name, specifying the model provider (or endpoint) along with an API key. In this example, we’re using OpenAI, but the script steps also support Anthropic, Cohere, and even custom endpoints.&lt;/p&gt;
&lt;p&gt;Once your AI account is configured, you can use &lt;strong&gt;Generate Response from Model&lt;/strong&gt; to interact with the model of your choice.&lt;/p&gt;
&lt;p&gt;At its simplest, this script step works just like ChatGPT in a browser: you send a prompt, and the model replies. It doesn’t know anything about your FileMaker file or its data; it’s just a general-purpose LLM chatbot. The real power of the Generate Response from Model script step comes when you enable Agentic mode. So what is agentic mode?&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage66050-configure-ai.png&quot; alt=&quot;configure ai&quot; width=&quot;660&quot; height=&quot;50&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/agnetic-response-1.png&quot; alt=&quot;agnetic response 1&quot; width=&quot;660&quot; height=&quot;588&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Agentic Mode&lt;/h2&gt;
&lt;p&gt;Agentic mode is where the AI behaves more like an agent, meaning it can:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Plan its next steps&lt;/li&gt;
&lt;li&gt;Use tools or external functions to carry out tasks&lt;/li&gt;
&lt;li&gt;Make decisions based on the outcomes of those actions&lt;/li&gt;
&lt;li&gt;Work iteratively, evaluating results before continuing&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This is quite different from the usual prompt-and-response setup, where the AI just replies to what it’s given. In agentic mode, the AI can reason through a problem step-by-step and call tools as needed.&lt;/p&gt;
&lt;p&gt;LLMs are inherently probabilistic, meaning their responses can vary each time. But in agentic mode the LLM can use tools, which adds a layer of determinism, allowing the AI to produce more consistent and reliable results.&lt;/p&gt;
&lt;h2&gt;Generate Response from Model - Tools&lt;/h2&gt;
&lt;p&gt;When &lt;strong&gt;Agentic mode&lt;/strong&gt; is enabled on the &lt;strong&gt;Generate Response from Model&lt;/strong&gt; script step, the AI is given access to two built-in tools provided by Claris: `execute_sql` and `retrieve_image`. You’ll find more detail on both in the &lt;a title=&quot;Claris Help&quot; href=&quot;https://help.claris.com/en/pro-help/content/generate-response-from-model.html&quot; target=&quot;_blank&quot;&gt;Claris Help documentation.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In addition to those, you can expose any &lt;strong&gt;Custom Functions&lt;/strong&gt; in your file as tools for the AI to use. All tools must be defined in a JSON structure that’s passed to the AI agent. The exact structure can vary depending on your model provider, so it’s important to check their documentation. OpenAI’s guide for tool usage can be found &lt;a title=&quot;AI Function calling&quot; href=&quot;https://platform.openai.com/docs/guides/function-calling?api-mode=responses&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In general, each tool definition will need to include:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;the name of the tool&lt;/li&gt;
&lt;li&gt; a description of what it does&lt;/li&gt;
&lt;li&gt;a list of parameters it accepts&lt;/li&gt;
&lt;li&gt;a description for each parameter, including whether it’s required or optional&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage660632-tools-1.png&quot; alt=&quot;tools 1&quot; width=&quot;660&quot; height=&quot;632&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Generate Response from Model - Agentic Setup&lt;/h2&gt;
&lt;p&gt;To get started with Agentic mode, there are only a few key fields you need to set:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Agentic Mode &lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Enables agentic behaviour, which allows the model to plan and take actions using tools.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Tool Calls From Model &lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;This is a response field. When the model uses tools, the results will be returned here in the order they were called.&lt;/li&gt;
&lt;li&gt;This is mostly used for debugging, as it shows which tools the model called and in what order.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Instructions&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;This is where you describe the agent’s role using plain language. For example, what it&#039;s meant to do, what tools it should use, and what kind of output you expect.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Tool Definitions&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt; This is where you enter the JSON that defines which tools the AI can access. This might include the built-in Claris tools or any custom functions in your file.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage660588-agnetic-response-2.png&quot; alt=&quot;agnetic response 2&quot; width=&quot;660&quot; height=&quot;588&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Generate Response from Model - Demo&lt;/h2&gt;
&lt;p&gt;We’ve included a simple demo file that shows how to use this script step to build an AI-powered calculator.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/generate-response-from-model/ai-maths-agent.zip&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Download The Demo!&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The file defines four custom functions:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;CF_Add&lt;/li&gt;
&lt;li&gt;CF_Subtract&lt;/li&gt;
&lt;li&gt;CF_Multiply&lt;/li&gt;
&lt;li&gt;CF_Divide&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Alongside these, we’ve added three tables: &lt;strong&gt;Agents, CustomFunctions, &lt;/strong&gt;and&lt;strong&gt; CustomFunctionParameters.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;These tables use calculation fields to generate the JSON tool definitions that get passed to the model.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;CustomFunctionParameters&lt;/strong&gt; table generates the JSON for each tool’s parameters (the properties block), e.g.,&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage660204-num1.png&quot; alt=&quot;num1&quot; width=&quot;660&quot; height=&quot;204&quot;&gt;&lt;/p&gt;
&lt;p&gt;This parameter JSON is combined in the &lt;strong&gt;CustomFunctions&lt;/strong&gt; table to create the full JSON definition for each tool, e.g.,&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tools-2.png&quot; alt=&quot;tools 2&quot; width=&quot;660&quot; height=&quot;552&quot;&gt;&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Agent&lt;/strong&gt; table pulls all the individual tool JSON objects together into a single JSON array, which is passed to the model as the Tool Definitions.&lt;/p&gt;
&lt;p&gt;A simple way to confirm that the AI agent is working and actually using the tools is to modify one of the custom functions to return an obviously wrong result. For example, change CF_Add to always return 99, then ask the agent, “What is 2 plus 2?” The response should come back as 99, showing that the model used the tool rather than calculating the answer itself.&lt;/p&gt;</description>
			<pubDate>Wed, 06 Aug 2025 12:39:56 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/generate-response-from-model/</guid>
		</item>
		
		<item>
			<title>DF Con 2025</title>
			<link>https://www.teamdf.com/blogs/df-con-2025/</link>
			<description>&lt;p&gt;While not the most exciting name, “DF Con” is our own, internal-only, Digital Fusion Conference and we had our 5th one back in June — once again, it was a huge success so I&#039;ll share some insights in to how we do this and what we get out of it all.&lt;/p&gt;
&lt;p&gt;Born out of the pandemic to avert &lt;em&gt;cabin fever&lt;/em&gt; (i.e. being stuck in NZ!), we created our own event. It’s proven to be a winner in terms of knowledge sharing, team building, and just plain geek-out fun.&lt;/p&gt;
&lt;h3&gt;Theme&lt;/h3&gt;
&lt;p&gt;The moniker “DF Con” is rather generic so we spice it up with a unique theme each year: our destination this year endured a rather large tectonic event not so long ago, and of course a &lt;em&gt;tonic&lt;/em&gt; is good for reinvigoration, so combining those two ideas gave us:&lt;/p&gt;
&lt;h4 style=&quot;padding-left: 120px;&quot;&gt;TECH TONIC&lt;/h4&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;And with that we created a “logo”, printed some posters and some merch (thanks to our wonderful, &lt;a title=&quot;Website of The Queensland Tee Shirt Company&quot; href=&quot;https://qtco.com.au&quot; target=&quot;_blank&quot;&gt;long time client QTCo&lt;/a&gt;!)…&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/DFCON-2025/dfcon25-merch.jpg&quot; alt=&quot;dfcon25 merch screenshot&quot; width=&quot;647&quot; height=&quot;346&quot;&gt;&lt;/p&gt;
&lt;p&gt;…and of course, developed a Tech Tonic cocktail — “&lt;em&gt;Hex on the Beach&lt;/em&gt;”&lt;/p&gt;
&lt;p&gt;(er, as in hexidecimal numbering system used in coding... not casting spells!)&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/DFCON-2025/cocktail-v2.jpg&quot; alt=&quot;cocktail screenshot v2&quot; width=&quot;300&quot; height=&quot;473&quot;&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Kaikōura&lt;/h2&gt;
&lt;p&gt;This year we headed to &lt;a title=&quot;Office website for Kaikoura &quot; href=&quot;https://www.kaikoura.co.nz&quot; target=&quot;_blank&quot;&gt;Kaikōura&lt;/a&gt;, a small coastal village 2.5 hours north of Christchurch New Zealand. &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/DFCON-2025/_resampled/ResizedImage660370-kaikoura.jpeg&quot; alt=&quot;Kaikoura Sign&quot; width=&quot;660&quot; height=&quot;370&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;The Sudima Hotel&lt;/h3&gt;
&lt;p&gt;One thing we&#039;ve learned from doing these events is that the venue makes a big difference because it shapes the dynamics of the conference, from the mixing and mingling, to the smooth running, quality of food and of course, the service. &lt;/p&gt;
&lt;p&gt;And that&#039;s why we returned to the superb &lt;a title=&quot;Sudima Hotels website&quot; href=&quot;https://www.sudimahotels.com/en/&quot; target=&quot;_blank&quot;&gt;Sudima Hotel&lt;/a&gt; for a second time. It&#039;s luxurious, great value, all under one roof, and with staff and organisation second to none. It&#039;s ideal for us and we&#039;d highly recommend it for either a personal trip away or a company conference.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/DFCON-2025/sudima.jpeg&quot; alt=&quot;Sudima Kaikoura&quot; width=&quot;660&quot; height=&quot;452&quot;&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Mixed Agenda&lt;/h2&gt;
&lt;p&gt;So, what did we do exactly? And was it beneficial?&lt;/p&gt;
&lt;p&gt;Well, we’ve honed the formula over the years, and each year it seems to get better… needless to say, DFCon 2025 was the best yet!&lt;/p&gt;
&lt;p&gt;So here&#039;s what we did exaclty:&lt;/p&gt;
&lt;p&gt;There were 7 presentations and 3 panel discussions over the two days:&lt;br&gt;&lt;br&gt;&lt;strong&gt;Autonomy and Alignment&lt;/strong&gt; — factors as we grow the team, by Craig and Kris&lt;br&gt;&lt;br&gt;&lt;strong&gt;Designing and Tuning Large Databases&lt;/strong&gt; — tuning for performance, storage and manageability, by Daniel (aka &lt;a href=&quot;https://www.teamdf.com/blogs/&quot;&gt;Weetbicks&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FileMaker Upgrade Tool — &lt;/strong&gt;A deep dive into the &quot;Claris Upgrade Tool&quot; for patching FileMaker databases, by James&lt;br&gt;&lt;br&gt;&lt;strong&gt;A Day In The Life of Running The Office&lt;/strong&gt; — a highly entertaining look at the administrative side of DF, all represented in The Sims 2, by Karesha and Cindy&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/DFCON-2025/cindy-karesha.jpg&quot; alt=&quot;cindy karesha&quot; width=&quot;660&quot; height=&quot;311&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/DFCON-2025/_resampled/ResizedImage659303-sims2.jpeg&quot; alt=&quot;SIMs DF&quot; width=&quot;659&quot; height=&quot;303&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;strong&gt;Everyone&#039;s In Sales&lt;/strong&gt; — at least that&#039;s according to Stu who ran us all through a sales 101 course in 15 mins flat!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mental Models In UI Design&lt;/strong&gt; — presented by one of our in house interface designers, Paul Baker&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Claris Studio — &lt;/strong&gt;What&#039;s happening with this new product from Claris and how does it complement FileMaker, by Sam&lt;/p&gt;
&lt;p&gt;The sessions were interleaved with group panels where 3-4 people were selected to discuss certain topics of interest:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FileMaker ETS — &lt;/strong&gt;What’s coming in the next version of FileMaker and specifically, how will these new capabilities be useful in the solutions we build.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SysAdmin&lt;/strong&gt; — everything to do with hosting, networks, software setups and information security.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AI and FileMaker — &lt;/strong&gt; discussing when and how we should be using the new generative AI tools.&lt;/p&gt;
&lt;h3&gt;But Wait… That’s Not All!&lt;/h3&gt;
&lt;p&gt;We also had 2 Hands-on Workshops&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1 Working with OData&lt;/strong&gt; — a pivotal integration technology for the platform going forward, run by Paul Hutton.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#2 Working with AI&lt;/strong&gt; — we added and tuned an &quot;App Assistant&quot; agent to an existing CRM database solution, run by Oscar Frith-Macdonald&lt;/p&gt;
&lt;p&gt;Both were immense fun due to the gamified way the guys put the workshops together, making for extraordinarily engaging learning exercises.&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/DFCON-2025/_resampled/ResizedImage659328-dfcon25-workshop.jpeg&quot; alt=&quot;DF Con 2025 workshop&quot; width=&quot;659&quot; height=&quot;328&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;And then there was the Bonus Session:&lt;/p&gt;
&lt;p&gt;“&lt;strong&gt;Ask Me Anything&lt;/strong&gt;” a sort of fireside chat with the boss…&lt;/p&gt;
&lt;p&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/DFCON-2025/_resampled/ResizedImage660489-ama-25.jpg&quot; alt=&quot;Ask Me Anything&quot; width=&quot;660&quot; height=&quot;489&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;AND… there was a quiz and a scavenger hunt interleaved, some nice meals and a few beverages to help quench the inevitable thirst (for knowledge of course)!&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/DFCON-2025/_resampled/ResizedImage659370-dfcon25-group-photo.jpeg&quot; alt=&quot;DF Con 2025 Group Photo&quot; width=&quot;659&quot; height=&quot;370&quot;&gt;&lt;/p&gt;
&lt;p&gt;Afterwards, we surveyed attendees (which was everyone in the company) and the feedback was overwhelmingly positive with accolades and thanks to the organising team (Stu, Cath, Karesha), the presenters, the activity organisers, and the destination!&lt;/p&gt;
&lt;p&gt;It&#039;s a big call to close up shop for a couple of days, and we thank our patient clients for bearing with us if your support was affected, but the overall impact on team building, collaboration and professional development is huge: we will keep doing this as it helps us be better developers and a better team.&lt;/p&gt;</description>
			<pubDate>Wed, 23 Jul 2025 12:13:07 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/df-con-2025/</guid>
		</item>
		
		<item>
			<title>FileMaker 2025</title>
			<link>https://www.teamdf.com/blogs/filemaker-2025/</link>
			<description>&lt;h2&gt;FileMaker 2025 Arrives!&lt;/h2&gt;
&lt;p&gt;FileMaker 2025 was recently released, and we are pleased to say that there are a number of features that are quite &lt;em&gt;user-oriented&lt;/em&gt; which I&#039;d like to highlight.&lt;/p&gt;
&lt;p&gt;(There are plenty of others talking about the developer oriented stuff too of course such a &lt;a href=&quot;https://www.soliantconsulting.com/blog/filemaker-2025-executive-summary/&quot; target=&quot;_blank&quot;&gt;Soliant&#039;s very thorough piece&lt;/a&gt; on this new version.)&lt;/p&gt;
&lt;p&gt;The following features are ones that we think that you as our clients will find interesting and hopefully result in either a better experience or discussions about how they can be used better in your business/organisation.&lt;/p&gt;
&lt;h4&gt;FileMaker 2025 = FileMaker v22.0&lt;/h4&gt;
&lt;p&gt;We will start with a quick side note. As with the last two releases of FileMaker, Claris has done a good job of confusing everybody with their release numbering. As much as this article is on FileMaker 2025, the technical version number is FileMaker v22, and that’s likely the numbering you will hear from your developer. It seems the marketing and tech departments at Claris can’t get together to decide on a less confusing path. For the remainder of this post, we will refer to things as v22, v21, etc.&lt;/p&gt;
&lt;h4&gt;Upgrade Now?&lt;/h4&gt;
&lt;p&gt;Next up, the question we get a lot when new versions are released: when should we upgrade? Our suggestion is that you hold off for a month or two, let the dust settle, and let them get any bugs ironed out. We typically see Claris release one or two point updates (e.g., FileMaker v22.0.1) in the first month or two post-release, taking into account anything that needs fixing.&lt;/p&gt;
&lt;p&gt;Saying that, if you are one of those people who feels the urge, if you do upgrade FileMaker Pro to v22, you can still connect to FileMaker Server v21.0&lt;strong&gt; but not older versions of FileMaker Server.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Keep in touch with your developer; they can give you guidance on when it’s right to upgrade.&lt;/p&gt;
&lt;p&gt;Onto the features that might appeal or be of interest…&lt;/p&gt;
&lt;h3&gt;AI Capabilities&lt;/h3&gt;
&lt;p&gt;AI is the big news in this new release of FileMaker. There have been AI features in v20 and v21, but with v22 we are taking the next big leap. The three major improvements are:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;LLM integration &lt;/strong&gt;— the ability to use AI language models (LLMs) directly in FileMaker scripts&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vector search &lt;/strong&gt;— this gives us the ability to search on “meaning” from both data and images.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Natural Language Query &lt;/strong&gt;— the ability to ask questions of your database in plain language&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;To help understand the value of these, here are some very simple use cases where you can imagine things in action in your own solution:&lt;/p&gt;
&lt;h4&gt;Extract meaning from PDFs.&lt;/h4&gt;
&lt;p&gt;Let’s say you have PDFs in your database, such as meeting notes, documentation, contracts, invoices, purchase orders, etc. We can now feed these to a language model, which in turn allows you to ask questions about the information and data in the PDFs.&lt;/p&gt;
&lt;h4&gt;Searching images by description&lt;/h4&gt;
&lt;p&gt;You spend a lot of time out in the field collecting data and taking photos via FileMaker Go on your iPhone or iPad. You may visit the same site 6-7 times over the space of a year, and you want to be able to search for all images taken over those 6-7 visits.&lt;/p&gt;
&lt;p&gt;As with PDFs, FileMaker can now catalogue the “meaning” of those images—i.e., extract a description of the image. This means you can search through the images based on descriptions of what you’re looking for.&lt;/p&gt;
&lt;h4&gt;Automate customer support&lt;/h4&gt;
&lt;p&gt;One of your clients has a question; they send it to you via email, where it gets parsed into your FileMaker solution as a query. With the use of AI, we can identify that client and potentially answer that question without the need for human input.&lt;/p&gt;
&lt;p&gt;For example, a client wants to know what stage their job is at. They email in, FileMaker picks this up, identifies the customer, looks into their job tracking area, identifies where the job is at, creates an email, and sends this back to the client. This is a very simplistic example, and there are likely to be ‘checks and balances’ along the way, but it demonstrates where you can get better efficiency.&lt;/p&gt;
&lt;h4&gt;Let&#039;s conclude our discussion about AI and FileMaker&lt;/h4&gt;
&lt;p&gt;Security around the use of AI is paramount both for yourselves, Digital Fusion, and FileMaker. With the current release of FileMaker, we now have more options from both the commercial providers such as OpenAI, Cohere, and Anthropic, but if they don’t suit, then we can use a local LLM on a server of your own so that data isn’t being shared out in any shape or form.&lt;/p&gt;
&lt;h3&gt;Enhancements&lt;/h3&gt;
&lt;p&gt;As much as AI is the hot topic, there are some other points that we think might be of interest:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FileMaker WebDirect &lt;/strong&gt;— For those users of WebDirect, we are now pleased to say that Claris has somewhat resolved the issue of using the back button. Now when you click the back button, you will get a warning box that asks if you want to leave the site. This is a great addition, as we have been putting ‘workarounds’ into our solutions for the last few years.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New look on Mac &lt;/strong&gt;— If you are a Mac user, you will notice that there is a new look when you upgrade to FileMaker Pro 22. For Windows users, don’t fret; this is really just a reshuffle of how a few things look. We are hoping they will include this same look for you shortly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OData API &lt;/strong&gt;— Everyone now should know what an API is and what it does, but for those that are still a little confused, it’s the ‘pipe’ that runs between two pieces of software to allow for sharing of data. Not all APIs are created equal; sometimes the ‘pipe’ is very thin and restricts the flow of data.&lt;/p&gt;
&lt;p&gt;The good news is Claris is now moving ahead with the OData API being its preferred. This means we can connect to more pieces of software and do it better. Connected software/applications are the future, so we are excited by what&#039;s possible.&lt;/p&gt;
&lt;p&gt;One side note: Claris will deprecate the Data API at some point (we expect it to be a few years off). This will mean that at some point we may need to get into your solution and do a bit of switching about, but we will be in touch if/when that happens.&lt;/p&gt;</description>
			<pubDate>Thu, 10 Jul 2025 12:14:15 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-2025/</guid>
		</item>
		
		<item>
			<title>Harnessing AI In FileMaker</title>
			<link>https://www.teamdf.com/blogs/harnessing-ai-in-filemaker/</link>
			<description>&lt;p&gt;Let’s face it, the tech world is going crazy over “AI” with promises of exciting and seemingly unlimited potential on offer. There’s a lot of hype, and it’s hard to determine the reality of what ’ve got now, where it’s going, and what we can and should be doing with it all.&lt;/p&gt;
&lt;p&gt;So our aim here is to “keep it real” and take a close and practical look at the ways we can use AI tools now to enhance FileMaker solutions. Our plan is to keep experimenting with the new stuff and to share here in our blog what we’re learning and what we’re thinking can be achieved.&lt;/p&gt;
&lt;p&gt;As an example, the new Semantic Search capabilities mean we can provide the ability to search textual data stored in the database based on “meaning”. The implications of that are that maybe we could be capturing and storing more descriptive text in our solutions.&lt;/p&gt;
&lt;h2&gt;Let&#039;s Get It Started&lt;/h2&gt;
&lt;p&gt;To begin with, Oscar&#039;s written a great foundational piece looking at the way AI technologies are built. If you’re a developer, it really helps to have that stuff in mind, so we recommend starting there: &lt;/p&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 399px; text-align: center; padding-left: 30px;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/blogs/an-ai-overview/&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Link to article &amp;quot;An AI Overview&amp;quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/An-AI-Overview/_resampled/ResizedImage399174-ai-overview-banner-2.jpg&quot; alt=&quot;AI Overview&quot; width=&quot;399&quot; height=&quot;174&quot;&gt;&lt;/a&gt;
&lt;p class=&quot;caption center&quot; style=&quot;text-align: left;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/blogs/an-ai-overview/&quot;&gt;An AI Overview&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Semantic Search&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Our first &quot;deep dive&quot; is into semantic search with FileMaker: &lt;/p&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 399px; padding-left: 30px;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/blogs/semantic-search/&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/diving-into-semantic-search/_resampled/ResizedImage399174-0-semantic-search-teaser-1.jpg&quot; alt=&quot;Semantic Search&quot; width=&quot;399&quot; height=&quot;174&quot;&gt;&lt;/a&gt;
&lt;p class=&quot;caption center&quot; style=&quot;text-align: left;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/blogs/semantic-search/&quot;&gt;Diving Into Semantic Search&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;But as part of this intro, let’s first take stock…&lt;/p&gt;
&lt;h2&gt;What Have We Got Now?&lt;/h2&gt;
&lt;p&gt;The standard API capabilities already in FileMaker have allowed us to integrate external AI services but there are now new features coming to FileMaker which open doors for how we use AI right within the database. FileMaker also has had the ability to use machine learning (great for pattern recognition) for a long time.&lt;/p&gt;
&lt;p&gt;But as of latest version of FileMaker 2024, we’re seeing the first specific tools for LLM and generative AI being added to the platform — Claris are rolling these new features out progressively with each new update. Here’s what the state of play is now:&lt;/p&gt;
&lt;h4&gt;Claris FileMaker Pro 2024 brings:&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;New AI script steps:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a title=&quot;configure-ai-account&quot; href=&quot;https://help.claris.com/en/pro-help/content/configure-ai-account.html&quot; target=&quot;_blank&quot;&gt;Configure AI Account:&lt;/a&gt; Simplifies setting up an AI account by name, integrated with providers like OpenAI. Custom models can be configured by entering the endpoint.&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;insert embedding&quot; href=&quot;https://help.claris.com/en/pro-help/content/insert-embedding.html&quot; target=&quot;_blank&quot;&gt;Insert Embedding:&lt;/a&gt; Embeds vector representations of input text into fields or variables within FileMaker Pro.&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;insert-embedding-in-found-set&quot; href=&quot;https://help.claris.com/en/pro-help/content/insert-embedding-in-found-set.html&quot; target=&quot;_blank&quot;&gt;Insert Embedding in Found Set:&lt;/a&gt; Extends embedding insertion to all records within a found set, enhancing bulk data processing capabilities.&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;perform-semantic-find&quot; href=&quot;https://help.claris.com/en/pro-help/content/perform-semantic-find.html&quot; target=&quot;_blank&quot;&gt;Perform Semantic Find:&lt;/a&gt; Executes semantic searches within specified fields, refining search results based on contextual meaning rather than exact keywords.&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;set-ai-call-logging&quot; href=&quot;https://help.claris.com/en/pro-help/content/set-ai-call-logging.html&quot; target=&quot;_blank&quot;&gt;Set AI Call Logging:&lt;/a&gt; Controls the logging of AI calls for enhanced traceability and debugging.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;New AI functions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a title=&quot;cosinesimilarity&quot; href=&quot;https://help.claris.com/en/pro-help/content/cosinesimilarity.html&quot; target=&quot;_blank&quot;&gt;CosineSimilarity:&lt;/a&gt; Calculates similarity between two embedding vectors, aiding in data comparison and analysis. It returns the similarity as a number between -1 (opposite) and 1 (similar).&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;getembedding&quot; href=&quot;https://help.claris.com/en/pro-help/content/getembedding.html&quot; target=&quot;_blank&quot;&gt;GetEmbedding:&lt;/a&gt; Retrieves vector representations of input text as container data using designated embedding models.&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;getembeddingasfile&quot; href=&quot;https://help.claris.com/en/pro-help/content/getembeddingasfile.html&quot; target=&quot;_blank&quot;&gt;GetEmbeddingAsFile:&lt;/a&gt; Converts embedding vectors from text to binary container data format.&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;getembeddingastext&quot; href=&quot;https://help.claris.com/en/pro-help/content/getembeddingastext.html&quot; target=&quot;_blank&quot;&gt;GetEmbeddingAsText:&lt;/a&gt; Converts embedding vectors from binary container data back to text format for easier manipulation and analysis.&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;gettableddl&quot; href=&quot;https://help.claris.com/en/pro-help/content/gettableddl.html&quot; target=&quot;_blank&quot;&gt;GetTableDDL:&lt;/a&gt; provides table information in Data Definition Language (DDL) format, facilitating schema management and integration tasks.&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;gettokencount&quot; href=&quot;https://help.claris.com/en/pro-help/content/gettokencount.html&quot; target=&quot;_blank&quot;&gt;GetTokenCount:&lt;/a&gt; Estimates token counts for specified text inputs, useful for AI model training and validation.&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;get-laststeptokensused&quot; href=&quot;https://help.claris.com/en/pro-help/content/get-laststeptokensused.html&quot; target=&quot;_blank&quot;&gt;Get(LastStepTokensUsed):&lt;/a&gt; Retrieves details on tokens utilised in the last AI script step executed, aiding in script debugging and optimisation.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;As you can see from this list, FileMaker is currently geared towards embedding vectorized LLM data and using that to perform semantic searches, so that’s what we’ll start with.&lt;/p&gt;
&lt;p&gt;Before you dive in, here are a few considerations to keep in mind:&lt;/p&gt;
&lt;h2&gt;Cautions!&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;A general rule of thumb: Don&#039;t use AI to modify actual data in your systems.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As discussed in our previous article, it’s crucial not to allow AI to directly modify your FileMaker data due to the potential pitfalls. For instance, you should avoid letting an AI model calculate your average invoice amount or handle anything related to numerical data—tasks better suited to traditional tools in FileMaker. Remember, the AI models we’re working with are large &lt;strong&gt;language&lt;/strong&gt; models, not mathematical models.&lt;/p&gt;
&lt;p&gt;Instead, use AI to provide recommendations and insights, which you can then review and implement manually. AI can also be a great tool for summarising large blocks of text, though you may want to add an extra line at the end to state that this summary was produced by an AI model, similar to OpenAI’s DALL_E 3 adding an &lt;a title=&quot;ai watermark&quot; href=&quot;https://www.theverge.com/2024/2/6/24063954/ai-watermarks-dalle3-openai-content-credentials&quot; target=&quot;_blank&quot;&gt;AI watermark&lt;/a&gt; in the metadata.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This approach ensures:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Accuracy&lt;/strong&gt;: By reviewing AI recommendations, you can verify their accuracy before applying changes to your data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Control&lt;/strong&gt;: Maintaining manual control over data modifications prevents unintended consequences from AI errors or biases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transparency&lt;/strong&gt;: Understanding and documenting the decision-making process ensures that changes to your data are transparent and justifiable.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;If you are going to allow an AI to modify your data, it is important to keep an unmodified version of that data and have a human verify any modifications the AI makes.&lt;/p&gt;
&lt;h2&gt;Some Uses For AI In FileMaker&lt;/h2&gt;
&lt;p&gt;Now with the warning out of the way, what are some good uses of AI in your FileMaker solution?&lt;/p&gt;
&lt;h4&gt;1. Data Analysis and Reporting&lt;/h4&gt;
&lt;p&gt;AI can quickly analyse large datasets to identify patterns, trends, and anomalies that might not be immediately obvious to a user.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Generate Insights:&lt;/strong&gt; Automatically produce comprehensive reports that highlight key performance indicators, trends, and forecasts within your FileMaker databases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Anomaly Detection:&lt;/strong&gt; Identify outliers and anomalies in your FileMaker data that could indicate errors or opportunities for further investigation.&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;2. Predictive Analytics&lt;/h4&gt;
&lt;p&gt;By using historical data, AI can make predictions about future outcomes. In FileMaker, predictive analytics can be applied to:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Sales Forecasting:&lt;/strong&gt; Predict future sales based on past performance and current market trends within your FileMaker solutions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inventory Management:&lt;/strong&gt; Forecast inventory needs to prevent overstocking or stockouts using your FileMaker data.&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;3. Enhanced Search and Retrieval&lt;/h4&gt;
&lt;p&gt;AI can improve the search capabilities of your FileMaker databases by understanding context and relevance, leading to more accurate and relevant results. In FileMaker, enhanced search functionalities can:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Semantic Search:&lt;/strong&gt; Go beyond keyword matching to understand the intent behind a search query, providing a more accessible way to query the data in your solution.&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;4. Natural Language Interfaces&lt;/h4&gt;
&lt;p&gt;AI-powered natural language interfaces enable users to interact with FileMaker using everyday language. In FileMaker, natural language capabilities can:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Simplify Queries:&lt;/strong&gt; Allow users to ask questions or make requests in plain language, which FileMaker can interpret and execute.&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Where Can You Start?&lt;/h2&gt;
&lt;p&gt;While we did mention that AI can be used for data analysis, reporting, and predictive analytics, These are tasks more suited to the &lt;strong&gt;machine learning&lt;/strong&gt; side of AI, and these tools have already existed in FileMaker for a long time. &lt;/p&gt;
&lt;p&gt;As previously mentioned, the new script steps introduced with FileMaker 2024 are geared towards embedding (or vectorizing) your data through a language model (LLM) and using that approach to perform semantic searches on it. So let’s dive into adding a semantic search to a FileMaker solution:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;Harnessing AI in FileMaker: Diving Into Semantic Search&quot; href=&quot;https://www.teamdf.com/blogs/semantic-search/#Harnessing%20AI in FileMaker: Diving Into Semantic Search&quot; target=&quot;_blank&quot;&gt;Diving into Semantic Search&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;</description>
			<pubDate>Wed, 28 Aug 2024 10:59:11 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/harnessing-ai-in-filemaker/</guid>
		</item>
		
		<item>
			<title>Diving Into Semantic Search</title>
			<link>https://www.teamdf.com/blogs/semantic-search/</link>
			<description>&lt;p&gt;In this article, we’ll take a deeper dive into semantic searches—what they are, how they work, and when to use them. I&#039;ll start by answering some fundamental questions:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;What is semantic search?&lt;/li&gt;
&lt;li&gt;What is embedding?&lt;/li&gt;
&lt;li&gt;How does embedding enable semantic search?&lt;/li&gt;
&lt;li&gt;When should we use semantic search?&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Next, we will share our journey of implementing AI in a FileMaker solution, including the step-by-step process of setting up a semantic search. And finally, there is a demo file provided so you can play with semantic searches yourself and see how different models perform. &lt;/p&gt;
&lt;h3&gt;So, What Is Semantic Search?&lt;/h3&gt;
&lt;p&gt;A semantic search is a search technique that aims to improve search accuracy by understanding the context of terms within a search. &lt;/p&gt;
&lt;p&gt;Unlike traditional keyword-based searches, which match exact words, semantic searches consider the intent behind the search and the contextual relationships between words. &lt;/p&gt;
&lt;h3&gt;What Is Embedding?&lt;/h3&gt;
&lt;p&gt;Embedding is the process of taking your complex data and converting it to a string of numbers, where each number represents some “attribute” of the original complex data. In natural language processing, embeddings convert words, phrases, or sentences into vectors of real numbers, capturing semantic meanings and similarities.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/diving-into-semantic-search/1-Cat-kitten.png&quot; alt=&quot;cat kitten&quot; width=&quot;660&quot; height=&quot;264&quot;&gt;&lt;/p&gt;
&lt;p&gt;For a more detailed explanation of embedding, please refer back to our last &lt;a title=&quot;An AI Overview&quot; href=&quot;https://www.teamdf.com/blogs/an-ai-overview/#An%20AI Overview&quot; target=&quot;_blank&quot;&gt;AI article.&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;How Does Embedding Enable Semantic Search?&lt;/h3&gt;
&lt;p&gt;Embedding allows the semantic meaning of words or phrases to be given a set of numerical values. We can then compare these values to find data with a similar &lt;strong&gt;meaning&lt;/strong&gt; rather than being an &lt;strong&gt;exact match&lt;/strong&gt; of words or phrases.&lt;/p&gt;
&lt;h3&gt;When Should We Use Semantic Search?&lt;/h3&gt;
&lt;p&gt;The first thing you will need to consider is the type of data you want to work with. It&#039;s likely that a lot of the data in your FileMaker solution is actually too structured for semantic searches. For example, there is little point in doing a semantic search on invoice totals; this is very clear and structured data and best suited to traditional search methods. &lt;/p&gt;
&lt;p&gt;Semantic searches are much better used for searching blocks of text for meaning and context. So if you have all of your client meeting notes in a database, this would be far better suited to a semantic search.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Traditional Keyword Search:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Query: &quot;project deadlines&quot;&lt;/li&gt;
&lt;li&gt;Results: Returns notes that explicitly contain the exact phrase &quot;project deadlines.&quot;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Semantic Search:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Query: &quot;project deadlines&quot;&lt;/li&gt;
&lt;li&gt;Results: Returns notes that discuss topics related to project deadlines, even if they use different phrases or terminology. For instance:&lt;/li&gt;
&lt;/ul&gt;&lt;ol&gt;&lt;li&gt;&quot;We need to finalise the timeline for project completion.&quot;&lt;/li&gt;
&lt;li&gt;&quot;The client is concerned about the due dates for deliverables.&quot;&lt;/li&gt;
&lt;li&gt;&quot;Ensure the milestones are met within the agreed schedule.&quot;&lt;/li&gt;
&lt;li&gt;&quot;Deadlines for the project phases were reviewed and adjusted.&quot;&lt;/li&gt;
&lt;/ol&gt;&lt;h2&gt;Embedding Your Data and Using Semantic Search&lt;/h2&gt;
&lt;p&gt;The first step in using AI is to configure your AI account. This is done with the &lt;strong&gt;Configure AI&lt;/strong&gt; &lt;strong&gt;Account&lt;/strong&gt; script step. This allows you to either select OpenAI or set a custom endpoint. You will likely want to incorporate this script step into your startup script to ensure that an AI session is started for a user when they open the system.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/diving-into-semantic-search/2-configure-ai-account.png&quot; alt=&quot;configure ai account&quot; width=&quot;660&quot; height=&quot;157&quot;&gt;.&lt;/p&gt;
&lt;p&gt;Next, you will want to embed your data. As discussed, a lot of your data will not be suitable for a semantic search, and it&#039;s probable that even the data that is suitable could be improved. Given the previous example of client meeting notes, we can actually improve the context of those notes very simply by creating a field containing all the data you want to embed. The easiest way we found to do this is to create a calculation field that is a list that includes all the data you want to embed, in this case the client name and a brief description of what the notes are.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/diving-into-semantic-search/3-client-meeting-notes.png&quot; alt=&quot;client meeting notes&quot; width=&quot;660&quot; height=&quot;124&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Selecting a Model &lt;/h2&gt;
&lt;p&gt;You may need to be careful with the model you use when embedding your data. Models have limits on the number of tokens sent per minute (TPM), the number of requests per day (RPD), and the number of requests per minute (RPM). Unfortunately, it&#039;s not really possible to say how big a token is; a token could be a whole word or just a single character, depending on how frequently the model has seen that word. More common words are likely to be tokens in themselves, whereas less common words could be split up as individual tokens for each character. OpenAI does offer some general rule-of-thumb calculations to make a good estimate of how many tokens a block of text is likely to have; these can be found &lt;a title=&quot;What are tokens?&quot; href=&quot;https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;. Below are OpenAI’s free &lt;a title=&quot;AI Rate Limits &quot; href=&quot;https://platform.openai.com/docs/guides/rate-limits/usage-tiers?context=tier-free&quot; target=&quot;_blank&quot;&gt;limits&lt;/a&gt;, though these can be increased if you pay. So if your meeting notes are pretty long and you don&#039;t want the end of your notes to be cut off, you may need to pay for higher limits, or another option may be to chunk your data and have smaller embeddings.&lt;/p&gt;
&lt;p&gt;One thing to be aware of is that a request is made up of tokens, and with the limits, the token is king. For a very extreme example, say you are using the gpt-4o model and you have a request that is 30,000 tokens. While you technically have 500 requests per minute, you have used up all your tokens for that minute in one go, so you now can&#039;t make any more requests. This is a very unlikely scenario, but definitely something to keep in mind.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/diving-into-semantic-search/4-text-embedding.png&quot; alt=&quot;text embedding&quot; width=&quot;660&quot; height=&quot;367&quot;&gt;&lt;/p&gt;
&lt;p&gt;Another consideration when selecting a model could be the size of your database. Different models will embed your data differently; some may create a vector of 500 dimensions, others could create a vector with 2000+ dimensions, and the more dimensions, the larger the size. &lt;/p&gt;
&lt;p&gt;When embedding data, the number of dimensions is constant, regardless of the data you are embedding. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Single Word Input:&lt;/strong&gt; &quot;cat&quot;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Vector Size: 1,536 dimensions (if the model&#039;s output is 1,536-dimensional)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Paragraph Input:&lt;/strong&gt; &quot;The cat sat on the mat.&quot;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Vector Size: 1,536 dimensions&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Usually you will be embedding large blocks of text, so the size is likely to reduce, but if you are embedding small bits of data with a large model, you may actually create an embedding that is larger than the original data. In FileMaker, it is also important to embed your data into a container field to help reduce the size. You can embed directly into a text field, but in this case every character will be 2 bytes, and when one dimension is something like 0.003164375, that can add up to a lot of bytes (22 in this case, or 88 bits), whereas if you store the embedding in a container, this is saved as a binary number (0.0000000011001111011) and would take just 20 bits. Another good reason to embed into a container is that container fields can&#039;t be indexed, so if, for some reason, you do embed into a text field, you will need to make sure to turn off indexing for that field, or your file size could grow very quickly.&lt;/p&gt;
&lt;p&gt;Open AI offers more generic models, but you will likely get better results by using a model trained on your data. For example, a generic model working with data about rocks is likely to group all the different rock types together because they are all just rocks. Whereas a model trained on data about rocks will do a far better job of distinguishing between different types of rocks. Think of it like asking your average Joe on the street about your data vs. asking a specialist in the field. &lt;/p&gt;
&lt;h2&gt;Embedding your data&lt;/h2&gt;
&lt;p&gt;Before we get onto embedding your data, there are a few key things to remember and consider. To do a semantic search, you will need to embed your question and then compare that embedding to your embedded data to find the closest match. The important thing to remember here is that your question will need to be embedded with the same model that your data was embedded with. If that doesn&#039;t make much sense, don&#039;t worry; this will be explained in more detail further on; you just need to remember to use the same model.&lt;/p&gt;
&lt;p&gt;Once you have selected your model, you will need to embed your data. We recommend at least keeping your embedded data in a separate table and potentially even a separate file. This will allow you to easily store and manage different embeddings. (Yes, I know we said you should use the same model for everything, but when getting started, you may want to test different models and see which works best for you.)&lt;/p&gt;
&lt;p&gt;Another size issue to consider is that, though FileMaker allows you to save your embedded data into a text field, the recommended method is to use a container field. The reason for this is that a container field will be smaller than using a text field, and FileMaker can search faster on the container.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/diving-into-semantic-search/_resampled/ResizedImage657104-5-client-notes-embedded.png&quot; alt=&quot;client notes embedded&quot; width=&quot;657&quot; height=&quot;104&quot;&gt;&lt;/p&gt;
&lt;p&gt;The easiest way to embed your data is by using a found set, so first find your data. Once you have the data you want to embed, simply use the &lt;strong&gt;Insert Embedding in Found Set&lt;/strong&gt; and select the field in your base table as the source and the container field in your embedded table as the target. This can be quite time-consuming, so it is probably best done server-side.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/diving-into-semantic-search/_resampled/ResizedImage657105-6-embedding-found-set.png&quot; alt=&quot;embedding found set&quot; width=&quot;657&quot; height=&quot;105&quot;&gt;&lt;/p&gt;
&lt;h2&gt;A Note on Embedding Your Data&lt;/h2&gt;
&lt;p&gt;As mentioned in the section on selecting your model, the number of dimensions remains constant, whether you embed a single word or an entire paragraph. This is an important consideration when embedding your data, as you may want to think about breaking down your data into smaller chunks before embedding. When performing a semantic search, the results reflect the context or meaning of the embedded content. For instance, if your meeting notes cover various topics across different paragraphs, embedding them as a whole might generalise the context of the entire meeting, leading to a loss of specific details. By chunking your data into smaller, more focused segments, you can preserve a clearer context for each part.&lt;/p&gt;
&lt;p&gt;The need to chunk your data can also depend on the model you are using and the data you want to embed. A larger model with more dimensions is likely to capture and retain the context of a lengthy text block better than a smaller model, which might lose some nuances. Therefore, when using a smaller model, you might want to invest more time in carefully chunking your data before embedding. Unfortunately, there’s no one-size-fits-all approach here; it largely depends on the nature of your data, your budget, and the time you’re willing to spend on the process.&lt;/p&gt;
&lt;h2&gt;Adding a Semantic Search&lt;/h2&gt;
&lt;p&gt;The next step is to add a semantic search. To start with, we just added a text field for the search input. We then used the Perform Semantic Find script step to both embed the search entry and compare it to the embedded client notes. This script step also lets you choose how many results are returned, and the cosine similarity (a cosine similarity of 1) means identical data. (A cosine similarity of -1 means opposite data.)&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/diving-into-semantic-search/7-preform-sematic-find.png&quot; alt=&quot;preform sematic find&quot; width=&quot;660&quot; height=&quot;123&quot;&gt;&lt;/p&gt;
&lt;p&gt;This did produce reasonably good results, but due to how embedding data and using cosine similarity work, we found that slightly modifying the search input did help to improve the results. A semantic search is able to determine meaning and context, but to an extent, this is just how similar your search input is to the result without being an exact match. This means that if we can make our search look more like the embedded data, we will get better results.&lt;/p&gt;
&lt;p&gt;The way we made the search entry more like the already embedded client notes was to add a pop-up entry for the client name and then convert the search input into a list before performing the semantic search. This should improve the semantic search as the cosine similarity for ClientName in the already embedded data and the SearchClientName should be 1.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/diving-into-semantic-search/8-pioneer-solutions.png&quot; alt=&quot;pioneer solutions&quot; width=&quot;660&quot; height=&quot;245&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/diving-into-semantic-search/9-client-name-search.png&quot; alt=&quot;client name search&quot; width=&quot;660&quot; height=&quot;147&quot;&gt;&lt;/p&gt;
&lt;h2&gt;A note on where to preform your searches&lt;/h2&gt;
&lt;p&gt;As we suggested, your data should be in a separate table or file, so when performing your search, you should go to the table the embedded data is in to perform the search rather than trying to search through a relationship. Better still would be to perform your search server side and then just return the relevant records. Otherwise, you are trying to search through all the embedded data locally, and those embeddings can be a lot of data to transfer to the client.&lt;/p&gt;
&lt;p&gt;This is also an argument for trying to perform some standard FileMaker searches to reduce your found set before performing a semantic search. This will greatly increase the performance of the semantic search.&lt;/p&gt;
&lt;h2&gt;Sorting your results&lt;/h2&gt;
&lt;p&gt;A nice feature of the Perform Semantic Find script step is that it returns your results sorted by cosine similarity, which is great if your embeddings are in the same table as the unembedded data. However, we suggested keeping your embedded data in a separate table, which likely means you will be using a Go To Related Record script step to display the found records, and you will lose the sort order. &lt;/p&gt;
&lt;p&gt;To get around this, we added an unstored calculation field on the Client Meeting Notes table, which is the cosine similarity. This also requires embedding your search input into a global variable before doing the semantic search.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/diving-into-semantic-search/10-cosine-similarity.png&quot; alt=&quot;cosine similarity&quot; width=&quot;660&quot; height=&quot;190&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;CosineSimilarity Calculation Unstored, = CosineSimilarity($$EmbeddedSearchinput; ClientNotes_Embedded::ClientNotesEmbedded_Small)&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Once the Go To Related Record script step is complete, you can sort by the cosine similarity field. At least working locally, the performance on this is pretty good, as you are likely only returning a small number of records. However, if your solution is not local or you are retuning lots or records, then you will likely see a hit to performance. &lt;/p&gt;
&lt;h2&gt;Improving your results&lt;/h2&gt;
&lt;p&gt;We found that the semantic search did a great job at finding relevant records but wondered if it could be improved. We sometimes found that the most relevant result for our search was not actually the most useful result. So one method to improve the search would be to make it a two-part search.&lt;/p&gt;
&lt;p&gt;For example, you let the user do a semantic search with natural language and return the results for that. The user can select the result they think is best and use that result for another semantic search, this time using the embedded data for that record as the search input. The chances are this will contain a lot more information than the user&#039;s natural language search, so it may produce better results.&lt;/p&gt;
&lt;p&gt;Another thing you may want to test is making that two-part search a behind-the-scenes search. So you take the top result from the natural language search, use that record for the second semantic search, and only present the results from the second search to the user. If you are doing this, then you want to be very sure the first result is a good result; otherwise, you might be searching for a bad result for similar bad results. One way to mitigate this would be that you only perform the second search on the record if the cosine similarity is greater than 0.8 (or whatever value you find works best for you).&lt;/p&gt;
&lt;p&gt;Finally, you may want to do an initial standard FileMaker search to get a reduced found set, then perform your semantic search on that found set. &lt;/p&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;Semantic search tools can be really helpful and powerful tools, but only when the data suits that kind of search. So going forward with FileMaker solutions, you will want to be aware of what data might suit a semantic search and then make sure that data is in a good structure for a semantic search.&lt;/p&gt;
&lt;p&gt;Ultimately, it&#039;s likely you will have to do quite a bit of testing around the semantic search to find the best option for your data. But once setup, you will have a very powerful search built into your solution.&lt;/p&gt;
&lt;h2&gt;Demo&lt;/h2&gt;
&lt;p&gt;Now wouldn&#039;t you like to see firsthand how different models and query formatting can affect your semantic search? Well, fear not, &lt;a title=&quot;Semantic Search demo file&quot; href=&quot;https://www.teamdf.com/assets/blog-images/diving-into-semantic-search/filemaker-semantic-search.zip&quot; target=&quot;_blank&quot;&gt;we have a demo file&lt;/a&gt; where you can have a play yourself, look under the hood and see the data structure, try and enter some really obscure prompts, and see if you can get a result you just wouldn&#039;t be able to with a standard FileMaker search. This demo file contains around 4000 book summary records with large and small embeddings for each book.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;Semantic Search demo file&quot; href=&quot;https://www.teamdf.com/assets/blog-images/diving-into-semantic-search/filemaker-semantic-search.zip&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/diving-into-semantic-search/12-search-options.png&quot; alt=&quot;search options&quot; width=&quot;660&quot; height=&quot;399&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Some Interesting Stats About The Demo File&lt;/h3&gt;
&lt;p&gt;When it came to providing this demo we came up against a couple of hurdles with the size of the file, so we dug down into what exactly was causing this demo to be so much larger than our other demos — over 200 MB in fact:&lt;/p&gt;
&lt;p&gt;For starters the demo admittedly has many more records than we normally include as we wanted to provide a good selection of sample data for you to play with.&lt;/p&gt;
&lt;p&gt;But the raw data is not what is causing the size issue, in fact the raw book data, all the images and text in the demo file, scripts, etc came to just 38MB.&lt;/p&gt;
&lt;p&gt;The bulk of the file size comes from the large embeddings at 100.6MB which is double the size of the small embeddings at 50.3MB.&lt;/p&gt;
&lt;p&gt;Again this highlights the importance of testing and finding the best solution for you. If size is a consideration for you, then you may want to opt to use an embedding model with fewer dimensions.&lt;/p&gt;</description>
			<pubDate>Wed, 28 Aug 2024 10:32:08 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/semantic-search/</guid>
		</item>
		
		<item>
			<title>An AI Overview</title>
			<link>https://www.teamdf.com/blogs/an-ai-overview/</link>
			<description>&lt;p&gt;&lt;strong&gt;Before we launch into this...&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Allow me to introduce Oscar Frith-Macdonald, one of our distinguished developers at DF. Oscar has studied the use of Machine Learning to facilitate image content searching for the UK National Archives. Who better to educate our team on the inner workings of artificial intelligence? His explanations are so excellent that we’ve invited him to write for the esteemed Weetbicks blog.&lt;/p&gt;
&lt;p&gt;Take it away Oscar...&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;FileMaker &lt;strong&gt;— N&lt;/strong&gt;ow With AI!&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;For a while now, you have been able to access AI through the insert from URL script step and standard API calls (see Cath’s blog article). But FM 2024 is integrating a lot more of this directly into FileMaker, making it easier than ever to use AI in your solutions.&lt;/p&gt;
&lt;p&gt;Now, there is a lot of great information on the cool things AI can do and also on the rather funny times it gets things wrong. However, we feel there is a lack of information on exactly what AI is. So this article is to help give you an understanding of how AI works, and this should help prevent you from falling into some of the pitfalls:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/An-AI-Overview/leovaradkar-screenshot-400.png&quot; alt=&quot;Leo Varadkar&quot; width=&quot;400&quot; height=&quot;274&quot;&gt;&lt;/p&gt;
&lt;p&gt;We will cover what AI is, some of the dangers of using AI, and how it can be useful. Hopefully, this will give you an idea of how best to use the new features safely.&lt;/p&gt;
&lt;h2&gt;So what is AI?&lt;/h2&gt;
&lt;p&gt;The best way to think of AI is as the outer shell of a Russian doll made up of deep learning (deep neural networks), artificial neural networks, and machine learning.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To break it down:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Machine learning (ML)&lt;/strong&gt; is a subset of AI that involves training algorithms to learn from and make predictions based on data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Artificial neural networks (ANN)&lt;/strong&gt; are a subset of ML that mimic the human brain&#039;s interconnected neuronal structure to process information in layers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deep learning&lt;/strong&gt; is a further specialisation within ANNs, utilising multiple layers (deep networks) to analyse complex patterns in large datasets.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;In essence, each layer builds on the previous one, advancing the capabilities and complexity of AI.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/An-AI-Overview/_resampled/ResizedImage660669-russian-doll-screenshot.png&quot; alt=&quot;russian doll screenshot&quot; width=&quot;660&quot; height=&quot;669&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Artificial Neural Networks&lt;/h2&gt;
&lt;p&gt;An artificial neural network (ANN) is an interconnected group of nodes, similar to the vast network of neurones in a brain.&lt;/p&gt;
&lt;p&gt;Here, each circular node represents an artificial neurone, and an arrow represents a connection from the output of one artificial neurone to the input of another.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/An-AI-Overview/ann-screenshot.png&quot; alt=&quot;ann screenshot&quot; width=&quot;660&quot; height=&quot;794&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;An ANN is composed of layers of interconnected nodes, or neurones.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;These layers are typically organised as follows:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Input Layer:&lt;/strong&gt; This layer receives the raw data. Each neurone in the input layer represents a feature or attribute of the data. For instance, in image recognition, each neurone might represent a pixel value.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hidden Layers:&lt;/strong&gt; These layers process the input data through a series of transformations. An ANN can have one or more hidden layers, where each layer consists of neurones that apply a mathematical function to the inputs and pass the results to the next layer. The term &quot;hidden&quot; refers to the fact that these layers do not directly interact with the external environment; they only communicate with other layers within the network.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Output Layer:&lt;/strong&gt; This layer produces the final output of the network. The output can be a single value (e.g., a prediction or classification) or a set of values (e.g., probabilities for different classes).&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Each connection between nodes has a “weight” to it, which is adjusted during the training process to minimise errors in the output. This process is similar to learning in biological brains, where synaptic strengths change to improve performance.&lt;/p&gt;
&lt;h2&gt;Deep Neural Networks&lt;/h2&gt;
&lt;p&gt;Deep Neural Networks (DNN) are a specific type of artificial neural network, with multiple layers in between the input and output layers.&lt;/p&gt;
&lt;p&gt;A simple ANN may have just one hidden layer (shown in the diagram above), and a DNN adds many more of those hidden layers.&lt;/p&gt;
&lt;p&gt;These additional layers enable DNNs to model intricate patterns and representations, making them highly effective for a wide range of tasks, particularly those involving large and complex datasets.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So what&#039;s happening in these hidden layers?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Each hidden layer transforms the input features into increasingly higher-level abstractions. Initially, the network might extract simple features (e.g., edges in an image). As the data passes through more layers, the network can recognise more complex patterns and structures (e.g., shapes and objects).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For instance, in image processing:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;First Hidden Layer:&lt;/strong&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt; Might detect edges and basic textures.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Intermediate Hidden Layers:&lt;/strong&gt; Might detect patterns and shapes, such as corners or circles.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deeper Hidden Layers:&lt;/strong&gt; They might detect more complex structures, such as faces or objects.&lt;/li&gt;
&lt;/ol&gt;&lt;h2&gt;Machine Learning&lt;/h2&gt;
&lt;p&gt;Machine learning (ML) focuses on developing algorithms that enable computers to learn from and make predictions or decisions based on data.&lt;/p&gt;
&lt;p&gt;Unlike traditional programming, where explicit instructions are given to perform a task, machine learning allows systems to learn and improve from experience without being explicitly programmed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Machine learning consists of three main points:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;A Decision Process:&lt;/strong&gt; Machine learning algorithms predict or classify based on input data, whether labelled or unlabelled, to identify patterns within the data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;An Error Function:&lt;/strong&gt; This function assesses the model&#039;s predictions by comparing them to known examples, thereby determining the model&#039;s accuracy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A Model Optimisation Process:&lt;/strong&gt; To improve the model&#039;s fit to the training data, the algorithm adjusts weights to minimise the difference between actual examples and predictions. This iterative process of evaluation and optimisation continues until the desired accuracy is achieved.&lt;/li&gt;
&lt;/ol&gt;&lt;h2&gt;Data Vectorisation&lt;/h2&gt;
&lt;p&gt;Data vectorisation is a key component of many AI models, though not all, which is why it wasn&#039;t included in the earlier Russian doll analogy.&lt;/p&gt;
&lt;p&gt;Data vectorisation involves transforming raw data into a numerical format suitable for machine learning algorithms. Essentially, it converts data into numerical vectors, which are arrays of numerical values representing various features or attributes of the data. This numerical representation allows qualitative information, such as meaning to be quantified and compared to find similarities.&lt;/p&gt;
&lt;p&gt;When data is vectorised, the numerical values generated are referred to as &quot;dimensions.&quot; The more dimensions a vector has, the more accurately it can represent the data and facilitate comparisons.&lt;/p&gt;
&lt;p&gt;Consider a simple example where the only two words in your vocabulary are &quot;door&quot; and &quot;wall.&quot; In this case, the vectors might only have two dimensions:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;&quot;door&quot; : [1, 0]&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&quot;wall&quot;  :  [0, 1]&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;In other words, this limited vocabulary would be represented as [0, 0]. Comparing &quot;door&quot; and &quot;wall,&quot; we see they are distinctly different in this simple two-dimensional space. If we introduce the word &quot;window,&quot; its vector might look like this: &quot;window&quot;: [0.6, 0]. Comparing &quot;window&quot; to &quot;door&quot; and &quot;wall,&quot; we can see that &quot;window&quot; is more similar to &quot;door&quot; than &quot;wall.&quot;&lt;/p&gt;
&lt;p&gt;In reality, vectors typically have many dimensions, representing various attributes or features. These dimensions can be imagined in a virtual space, where the vector indicates a position within this space.&lt;/p&gt;
&lt;p&gt;Cosine similarity is then used to determine how close two vectors are within this multi-dimensional space. By measuring the cosine of the angle between two vectors, we can quantify their similarity, ranging from -1 (completely opposite) to 1 (identical).&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/An-AI-Overview/_resampled/ResizedImage399174-cosine-angle-sreenshot.png&quot; alt=&quot;Cosine angle&quot; width=&quot;399&quot; height=&quot;174&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/An-AI-Overview/_resampled/ResizedImage400261-angle-screenshot.png&quot; alt=&quot;Angle&quot; width=&quot;400&quot; height=&quot;261&quot;&gt;&lt;/p&gt;
&lt;h2&gt;So, really, what is AI?&lt;/h2&gt;
&lt;p&gt;Now that you have an understanding of the different components that make up AI, let’s dive deeper into what AI truly is.&lt;/p&gt;
&lt;p&gt;Knowing that a house is made of bricks and cement doesn&#039;t fully convey what a house is; it’s the same with AI.&lt;/p&gt;
&lt;p&gt;When you hear the term ‘AI,’ you might think of iconic characters like HAL 9000 from 2001: A Space Odyssey or Data from Star Trek. These examples represent machines with the capacity for reason and autonomy, known as artificial general intelligence (AGI). However, this is not what most modern AI refers to. Today, when we talk about AI, we&#039;re actually discussing Narrow Artificial Intelligence (NAI).&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/An-AI-Overview/_resampled/ResizedImage660601-ai-computer.jpg&quot; alt=&quot;ai computer&quot; width=&quot;660&quot; height=&quot;601&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Narrow Artificial Intelligence (NAI)&lt;/h2&gt;
&lt;p&gt;NAI is essentially an excellent piece of prediction software designed to perform specific tasks. Unlike AGI, which has the ability to understand, learn, and apply knowledge across a wide range of tasks at a human level, NAI is specialised. It&#039;s important to remember that it will only be an excellent piece of prediction software for the inputs it was trained for.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Here are some key points to understand NAI better:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Task-Specific:&lt;/strong&gt; NAI is designed to perform a specific task or a set of closely related tasks. For instance, a language model like ChatGPT is trained to process and generate text but cannot create images.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data-Driven:&lt;/strong&gt; The effectiveness of NAI depends heavily on the quality and quantity of data it has been trained on. It makes predictions and decisions based on patterns found in this data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prediction-Oriented&lt;/strong&gt;: At its core, NAI is about making accurate predictions. Whether it’s forecasting sales, recognising speech, or recommending products, NAI’s strength lies in its ability to predict outcomes based on input data.&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;The importance of training data&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;The performance of NAI systems is tightly linked to the data they are trained on:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Relevance:&lt;/strong&gt; The training data must be relevant to the task. A language model trained on diverse and extensive text data will perform well in text-related tasks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Volume:&lt;/strong&gt; Larger datasets typically result in better performance, as they provide more examples for the model to learn from.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quality:&lt;/strong&gt; High-quality data, which is accurate and well-labelled, leads to better predictions.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;There are three main forms of training, and all are used within the AI space.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;strong&gt;&lt;strong&gt;1. Supervised Learning:&lt;/strong&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Supervised learning plays a significant role in training models like GPT. During the initial pre-training phase, the model learns from a large corpus of text data that includes pairs of input (e.g., text snippets) and output (e.g., the next word or sequence of words). This helps the model understand language patterns, grammar, and context. Key points include:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Pre-training Phase:&lt;/strong&gt; The model is trained on vast amounts of text data from the internet in a supervised manner to predict the next word in a sentence.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fine-tuning:&lt;/strong&gt; After the initial pre-training, the model can be fine-tuned on specific datasets with labelled data for particular tasks, further enhancing its performance.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;strong&gt;2. Unsupervised Learning:&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;While the initial phase of pre-training can be considered supervised learning due to the nature of the task (predicting the next word), it also has aspects of unsupervised learning:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Learning from Unlabelled Data:&lt;/strong&gt; The massive text data used in pre-training is not explicitly labelled with specific tasks but consists of raw text. The model learns patterns, structures, and relationships in this data without specific labels guiding the learning process.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;strong&gt;3. Reinforcement Learning:&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Reinforcement learning has been notably applied in models like ChatGPT for specific aspects of training, such as fine-tuning the model&#039;s responses to be more aligned with human preferences.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Reinforcement Learning from Human Feedback (RLHF):&lt;/strong&gt; In the case of ChatGPT, after the initial supervised learning phase, the model undergoes reinforcement learning, where human feedback is used to reward desirable responses and penalise undesirable ones. This process involves:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Human Labellers:&lt;/strong&gt; Provide feedback on model outputs, ranking them based on quality, which is then used to further fine-tune the model.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Policy Optimisation:&lt;/strong&gt; Adjusting the model&#039;s parameters to maximise the reward signals obtained from human feedback.&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;&lt;strong&gt;While NAI is powerful, it comes with limitations:&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Lack of Generalisation:&lt;/strong&gt; NAI cannot generalise knowledge beyond its training. A language model won&#039;t understand visual data unless it has been specifically trained to do so.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dependence on Data:&lt;/strong&gt; NAI’s accuracy is limited by the data it was trained on. If the data is biassed or incomplete, the AI’s predictions will reflect these issues.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Absence of Understanding:&lt;/strong&gt; NAI does not possess true understanding or consciousness. It operates purely based on learned patterns, without any comprehension of the content.&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;&lt;strong&gt;NAI and GPT&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;It&#039;s pretty difficult to talk about AI and not mention OpenAI and GPT at all, so how does GPT fit into the world of NAI? Let&#039;s start with what GPT stands for:&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;strong&gt;Generative Pre-trained Transformer&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Generative: &lt;/strong&gt;This refers to the model&#039;s ability to generate text or other forms of output. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pre-trained:&lt;/strong&gt; Before fine-tuning for specific tasks, the model undergoes extensive training on a diverse dataset to learn language patterns, grammar, and general knowledge. This pre-training allows the model to perform well on various tasks with minimal additional training.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transformer:&lt;/strong&gt; This is the underlying architecture of the model. Transformers are a type of neural network designed to handle sequential data and have become the standard for natural language processing tasks due to their efficiency and effectiveness in understanding context and relationships within the data.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;GPT is actually an excellent example of NAI, as it&#039;s very obvious that none of the GPT models can do everything. They have had to be narrowed down to specific tasks such as ChatGPT, ImageGPT, etc. As their names suggest, they have similar base GPT models but have then been trained for specific tasks.&lt;/p&gt;
&lt;p&gt;These different models can work in conjunction with each other to provide a “wider” AI experience. This is why ImageGPT can generate an image from a text input.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example Workflow&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. User Input:&lt;/strong&gt; The user provides a text prompt, e.g., &quot;a two-story pink house shaped like a shoe with a small garden in front.&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Text Processing: &lt;/strong&gt;A language model (like ChatGPT) processes the text to ensure it is clear and extract essential elements, e.g., &quot;two-story pink house,&quot; &quot;shoe shape,&quot; &quot;small garden in front.&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Image Generation: &lt;/strong&gt;The processed text is fed into a text-to-image model (like ImageGPT), which then generates an image based on the description.&lt;/p&gt;
&lt;h2&gt;AI Considerations and Mitigations&lt;/h2&gt;
&lt;p&gt;While AI is a powerful tool, there are important considerations and potential pitfalls to be aware of. Understanding these can help you better navigate the challenges and maximise the benefits of AI.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pitfalls and Issues:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Bias in AI:&lt;/strong&gt; AI systems learn from the data they are trained on. If this data contains biases, the AI will likely reproduce and even amplify these biases. For instance, an AI trained on biased hiring data might favour certain demographics over others. It&#039;s crucial to ensure that training data is as unbiased and representative as possible. One of Google&#039;s issues with the AI summary was pulling information from places like Reddit and presenting it as fact.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI Hallucinations:&lt;/strong&gt; AI models, especially those dealing with language, can sometimes generate outputs that seem plausible but are completely incorrect or fabricated. This is known as AI hallucinations and occurs because the AI predicts text based on patterns it has seen, even if those patterns lead to false information.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Overfitting:&lt;/strong&gt; An AI model might perform exceptionally well on training data but fail to generalise to new, unseen data. This issue, known as overfitting, can lead to poor performance in real-world applications.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data Privacy:&lt;/strong&gt; AI systems often require large amounts of data, which can raise concerns about data privacy and security. It&#039;s important to handle personal and sensitive information responsibly, ensuring compliance with data protection regulations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Complexity and visibility:&lt;/strong&gt; Many AI models, particularly deep learning models, are complex and operate as &quot;black boxes,&quot; making it difficult to understand how they arrive at specific decisions. This lack of transparency can be problematic, especially in critical applications like healthcare or finance.&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;AI Hallucinations and Incorrect Results&lt;/h2&gt;
&lt;p&gt;Hallucinations are probably one of the biggest issues with AI, especially when the AI will provide an answer that seems plausible and will also present it as fact.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hallucinations can happen for several reasons:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Incomplete Data:&lt;/strong&gt; The AI might fill in gaps with fabricated information if the training data is incomplete or lacks context.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pattern Recognition:&lt;/strong&gt; The AI tries to predict the next piece of information based on patterns, which might lead to incorrect associations and results.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ambiguous Queries:&lt;/strong&gt; Vague or poorly defined inputs can cause the AI to generate misleading or incorrect outputs.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;To mitigate these issues, it’s important to:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Validate Outputs:&lt;/strong&gt; Always cross-check the AI’s outputs with reliable sources or experts in the field. N.B. As it is a well-known issue that these generative models can generate false information, many AI models have now been designed to return links to their source so that it is easier for a user to verify the information the model has returned.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Provide Clear Context:&lt;/strong&gt; Ensure that queries are specific and provide enough context for the AI to generate accurate responses.&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Improving AI responses and ensuring correct information&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;To enhance the reliability and accuracy of AI responses, consider the following strategies:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Use High-Quality Data:&lt;/strong&gt; Ensure the training data is high-quality, representative, and as free from biases as possible. Regularly update the data to keep the AI model current. Use your own existing data and examples when asking a question about AI; this will help to ensure it&#039;s only using information you consider to be true.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Implement Human Oversight:&lt;/strong&gt; Use AI as a tool to speed up human decision-making rather than replacing it entirely. Always have a human look over the result to ensure it is correct.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Clarify Queries:&lt;/strong&gt; When interacting with AI, especially language models, frame your queries clearly and precisely. The more specific the input, the more accurate the output is likely to be. Don&#039;t be afraid to send pages of information in your prompt to the AI, but be aware there is usually a cost for this.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Employ Ensemble Methods:&lt;/strong&gt; Combine multiple models or methods to cross-verify results. Ensemble techniques can help improve accuracy and reduce the likelihood of errors. It&#039;s also important to use the correct model for your task.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Educate Users:&lt;/strong&gt; Ensure that users understand the capabilities and limitations of AI. Providing training on how to interact with AI systems and interpret their outputs can significantly improve outcomes. One of the most important points is to ensure your users are aware that the AI could be wrong.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 30 Jul 2024 07:48:26 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/an-ai-overview/</guid>
		</item>
		
		<item>
			<title>Welcome Karesha</title>
			<link>https://www.teamdf.com/blogs/welcome-karesha/</link>
			<description>&lt;p&gt;We are a bit late to the party with this post, but as they say, better late than never.&lt;/p&gt;
&lt;p&gt;We would like to welcome Karesha Walker to the team as our ‘new’ Office Administrator. She’s been with us nearly six months to date, and has made a massive impact on the business, notably her love of pot plants has infected the DF office in Christchurch. &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;Karesha&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage660467-Karesha.png&quot; alt=&quot;Karesha&quot; width=&quot;660&quot; height=&quot;467&quot;&gt;&lt;/p&gt;
&lt;p&gt;Digital Fusion were very lucky to nab Karesha, her previous job was CEO of her household, having raised two young boys and two Chihuahuas over the last five years. After escaping that job it should be a cinch to help manage 16 developers and a few account managers (plus all those pot plants). It could be a few years before she whips the CEO into shape, but the money is on this happening.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;kareshas kids&quot; src=&quot;https://www.teamdf.com/assets/Uploads/kareshas-kids.jpeg&quot; alt=&quot;kareshas kids&quot; width=&quot;660&quot; height=&quot;440&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;kareshas chihuahuas&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage660647-kareshas-chihuahuas.jpeg&quot; alt=&quot;kareshas chihuahuas&quot; width=&quot;660&quot; height=&quot;647&quot;&gt;&lt;/p&gt;
&lt;p&gt;We asked Karesha to give us a few interesting facts about herself, and she turned up the following…&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Her favourite animal is a bison&lt;/li&gt;
&lt;li&gt;When she was a child she was a severe sleep walker and would do weird and wonderful things like bathing her dolls and making food&lt;/li&gt;
&lt;li&gt;In her earlier years she attained a Teaching Degree&lt;/li&gt;
&lt;li&gt;She&#039;s had the same friends since primary school&lt;/li&gt;
&lt;li&gt;She project managed the build and did the interior design of her new home after living in a 30 square foot tiny home for 2 years… &lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;kareshas tiny home&quot; src=&quot;https://www.teamdf.com/assets/Uploads/kareshas-tiny-home.jpeg&quot; alt=&quot;kareshas tiny home&quot; width=&quot;660&quot; height=&quot;495&quot;&gt;That certainly turned up a few things we didn’t know.&lt;/p&gt;
&lt;p&gt;Welcome Karesha to the team, if the first six months are anything to go by, you will have us all in tip top shape (and working in a jungle) in no time.&lt;/p&gt;</description>
			<pubDate>Mon, 29 Apr 2024 13:52:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/welcome-karesha/</guid>
		</item>
		
		<item>
			<title>Reconnect Experience</title>
			<link>https://www.teamdf.com/blogs/reconnect-experience/</link>
			<description>&lt;p&gt;Having attended only one other FileMaker Conference, (An in-house event just three weeks after joining Digital Fusion), I was excited at the opportunity to meet the broader FileMaker community in Sydney at the Reconnect Conference.&lt;/p&gt;
&lt;p&gt;Despite my excitement, there was an underlying nervousness about what to expect from the sessions. Would they delve into highly technical topics beyond my understanding? Could I follow sessions led by developers using different data structures? And, would the warmth and support I experience at Digital Fusion extend to the wider FileMaker developer community?&lt;/p&gt;
&lt;p&gt;I must admit, as a newcomer to development, I thoroughly enjoyed every aspect of Reconnect.&lt;/p&gt;
&lt;p&gt;The conference struck a perfect balance between social interactions and informative sessions. The evening before the conference kicked off, we visited the Apple offices for a Q&amp;amp;A session with the Claris team. This provided insights into the relationships between Claris and other FileMaker developers.&lt;/p&gt;
&lt;p&gt;The social aspect of the conference was an eye-opener for me. The first night was nothing short of fantastic! After a few drinks at a stunning rooftop bar, I summoned the courage to mingle with the FileMaker community, and what a community it is! Everyone was incredibly friendly and genuinely interested in each other&#039;s backgrounds. The atmosphere was electric, with attendees eager to reconnect and engage in meaningful conversations.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/reconnect-experience/_resampled/ResizedImage660325-recconnect-drinks.png&quot; alt=&quot;Drinks at Reconnect 2023&quot; width=&quot;660&quot; height=&quot;325&quot;&gt;&lt;/p&gt;
&lt;p&gt;I found the topics covered a wide spectrum, and even the technical sessions were accessible, thanks to well-demonstrated workflows, such as Andrew McCallum&#039;s transactions presentation.&lt;/p&gt;
&lt;p&gt;Charmaine and Salvatore&#039;s discussion on Business Analysis was particularly enlightening. Having just completed my first System Design, I found their insights invaluable, especially regarding identifying business needs and engaging with the right Stakeholders to gather project requirements effectively. Their modular approach provided a structured framework that I can apply to future analysis and design phases.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;Charmaine Salvatore&amp;#039;s presentation&quot; src=&quot;https://www.teamdf.com/assets/blog-images/reconnect-experience/charmaine-salvatores-presentation.png&quot; alt=&quot;Charmaine Salvatore&amp;#039;s presentation&quot; width=&quot;660&quot; height=&quot;339&quot;&gt;&lt;/p&gt;
&lt;p&gt;Of course I cannot overlook Cath and Jamie&#039;s sessions (not that I&#039;m biased) on the development of “MTS Connect” for the Mobile Tyre Shop.&lt;/p&gt;
&lt;p&gt;As a Developer, hearing a Client perspective on how FileMaker transformed their business by streamlining processes was incredibly inspiring. Seeing how the MTS solution was developed and used has highlighted the effectiveness of Cath&#039;s modular approach in building the MTS solution. Their collaborative relationship serves as a testament to Cath&#039;s exceptional skills and dedication to pushing boundaries to achieve remarkable results with the MTS solution.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;Cath Presenting&quot; src=&quot;https://www.teamdf.com/assets/blog-images/reconnect-experience/cath-presenting.png&quot; alt=&quot;Cath Presenting&quot; width=&quot;660&quot; height=&quot;466&quot;&gt;&lt;/p&gt;
&lt;p&gt;I could not have wished for a better experience at Reconnect, and can’t wait to go along to another…&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;PS: We figured Maddy enjoyed the experience so much she might like to talk some more about it… &lt;/p&gt;
&lt;p&gt;&lt;iframe src=&quot;https://player.vimeo.com/video/935433550?h=1908f10ccc&quot; width=&quot;640&quot; height=&quot;361&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Mon, 22 Apr 2024 08:52:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/reconnect-experience/</guid>
		</item>
		
		<item>
			<title>FileMaker ChatGPT Integration</title>
			<link>https://www.teamdf.com/blogs/filemaker-chatgpt-integration/</link>
			<description>&lt;p&gt;Simple integration using ChatGPT and FileMaker Pro solving two business problems.&lt;/p&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;By now, almost everyone has heard of ChatGPT, marvelling at its ability to write poetry, tell jokes, and entertain. But what about its practical applications in business?&lt;/p&gt;
&lt;p&gt;Are there any? We think so, and have started to solve some real world problems with the technology. These simple use cases will focus on how to use ChatGPT to improve or provide substitutes for the text we give it.&lt;/p&gt;
&lt;h2&gt;TLTR?&lt;/h2&gt;
&lt;p&gt;We explored three methods for generating text, experimenting with different prompts and requests. We landed on the last method as the most feasible option for our purposes. This method involves using functions included in the request to return predicable JSON formatted results.&lt;/p&gt;
&lt;p&gt;&lt;a title=&quot;FileMaker ChatCPT Integration File &quot; href=&quot;https://www.teamdf.com/assets/blog-images/filemaker-chatgpt-integration/filemaker-chatgpt-integration.zip&quot; target=&quot;_blank&quot;&gt;Download the Example file here&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;FileMaker ChatGPT Demo Screenshot&quot; src=&quot;https://www.teamdf.com/assets/blog-images/filemaker-chatgpt-integration/_resampled/ResizedImage660401-fm-chatgpt-screenshot.png&quot; alt=&quot;FileMaker ChatGPT Demo Screenshot&quot; width=&quot;660&quot; height=&quot;401&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Problem 1: Unprofessional Texts (SMS)&lt;/h2&gt;
&lt;p&gt;Have you ever received an unprofessional text from a business? Maintaining a consistent company style in custom messages can be challenging. ChatGPT can take the original message and provide alternative options in the writing styles of your choice.&lt;/p&gt;
&lt;p&gt;By using a variety of writing style (tones), we can craft appropriate responses to align with the impression the business wants to give.&lt;/p&gt;
&lt;p&gt;Here are some common styles or tones you could use to covert the original message. The prompt might include key words like; formal, casual, serious, friendly, optimistic, pessimistic, scientific, concise, descriptive, persuasive, professional, trustworthy or informative. Combinations of them work well too for example:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Friendly and professional&lt;/li&gt;
&lt;li&gt;Authoritative and informative&lt;/li&gt;
&lt;li&gt;Urgent and persuasive&lt;/li&gt;
&lt;li&gt;Casual and conversational&lt;/li&gt;
&lt;li&gt;Professional and trustworthy&lt;/li&gt;
&lt;/ul&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;SMS Demo Screenshot&quot; src=&quot;https://www.teamdf.com/assets/blog-images/filemaker-chatgpt-integration/_resampled/ResizedImage660880-sms-screenshot.png&quot; alt=&quot;SMS Demo Screenshot&quot; width=&quot;660&quot; height=&quot;880&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Problem 2: Poor SEO&lt;/h2&gt;
&lt;p&gt;When generating website content it can be common to use a FileMaker database to generate content. In this case we want to create a description for multiple suppliers. We will customise each entry by incorporation details such as their establishment date, the brands they represent and their location. Using these variables we can create a block of text which nicely summarises a unique description for each supplier&lt;/p&gt;
&lt;p&gt;However, an issue arises when the content, while unique, follows a repetitive structure, potentially harming SEO performance. It would be better to have the ability to quickly generate high-quality content without having to spend hours brainstorming or writing drafts.&lt;/p&gt;
&lt;p&gt;In this case we can use our FileMaker description as the input and generate multiple options in the tones of our choice. Each of which will have unique content and now unique structure too.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;MTS Connect Demo Screenshot&quot; src=&quot;https://www.teamdf.com/assets/blog-images/filemaker-chatgpt-integration/_resampled/ResizedImage660524-mts-connect-screenshot.png&quot; alt=&quot;MTS Connect Demo Screenshot&quot; width=&quot;660&quot; height=&quot;524&quot;&gt;&lt;/p&gt;
&lt;h2&gt;How Much Will It Cost?&lt;/h2&gt;
&lt;p&gt;Charging is approximately 0.03 cent per request (for around 750 words or 1K of data). The pricing model is complex, depending on the number of tokens exchanged and the request processing time.&lt;/p&gt;
&lt;p&gt;The model you use also has different pricing structures. Using GPT-3.5 Turbo models are far more cost-effective than GPT-4. The same request as above using GPT-4 would cost 9 cents per request.&lt;/p&gt;
&lt;p&gt;One thing we know about AI is that this is a very dynamic landscape. This article was written in March 2024, but to view the most current pricing, please refer to Open AI’s &lt;a title=&quot;Open AI&amp;#039;s Pricing Page &quot; href=&quot;https://openai.com/pricing&quot; target=&quot;_blank&quot;&gt;pricing page&lt;/a&gt; for further information.&lt;/p&gt;
&lt;h2&gt;What Is A Token?&lt;/h2&gt;
&lt;p&gt;Language models perceive text as a series of numbers, known as tokens, rather than in the same way that humans do. There are many advantages to Tokenising the data including reduced request transfer size and search ability. It does make it more difficult to know exactly how big your request is and therefore how much it is going to cost but there are tools for measuring request size in tokens.&lt;/p&gt;
&lt;p&gt;To find out more about what a token consist of refer to the help document on &lt;a title=&quot;Managing Tokens Document &quot; href=&quot;https://platform.openai.com/docs/guides/text-generation/managing-tokens&quot; target=&quot;_blank&quot;&gt;Managing tokens&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Privacy And Security&lt;/h2&gt;
&lt;p&gt;OpenAI will store your data for 30 days. Do not send any information you do not want to share. In our cases there is no private information contained in the posts, but we will look at how to use local Large Language Models to reduce privacy concerns in the future.&lt;/p&gt;
&lt;h2&gt;Creating The Right Prompt.&lt;/h2&gt;
&lt;p&gt;This is the number one tool for managing your response. In the demo file you will see that by changing the language code in the prompt (one word) we will receive an entirely different message. These models can’t read your mind. If outputs are too long, ask for brief replies. &lt;br&gt;Set the right tone by suggesting how you want the response to be returned for example, casual but informative. State the audience and the goal and any know constrains.&lt;/p&gt;
&lt;p&gt;Models are known to return wild responses so much so that the term Model hallucinations is used. You can reduce this by improving your prompt or by adding a mock conversation sequence to your request. The model will look at the mock conversation as a prototype on how to respond more appropriately&lt;/p&gt;
&lt;p&gt;Prompt engineering is bound to become a specific skill. One which is certain to have an impact on the usefulness of the responses you receive. To learn more, read the Open AI guide on &lt;a title=&quot;Guide On Prompt Engineering &quot; href=&quot;https://platform.openai.com/docs/guides/prompt-engineering&quot; target=&quot;_blank&quot;&gt;prompt engineering.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Which Model To Choose?&lt;/h2&gt;
&lt;p&gt;Change is happening fast. On the 4th January 2024 GPT3 and GPT 3.5 were depreciated. This article was written in March 2024 so currently we recommend that you use either GPT-4 Turbo Preview or GPT-3.5 Turbo.&lt;/p&gt;
&lt;p&gt;GPT-4 Turbo Preview&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;has improved language understanding and generation capabilities compared to GPT-3.5 Turbo.&lt;/li&gt;
&lt;li&gt;offer better accuracy in generating text and evaluation&lt;/li&gt;
&lt;li&gt;has a larger context window with a maximum size of 128,000 tokens compared to 4,096 tokens for GPT-3.5 Turbo.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;GPT-3.5 Turbo&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;is generally faster than GPT-4 Turbo Preview &lt;/li&gt;
&lt;li&gt;costs much less per token&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;You can use both, as you reference the Model as part of your cURL request. For our purposes we chose GPT-3.5 Turbo generally because the queries are simple and non computational and would be more cost effective using the cheaper model.&lt;/p&gt;
&lt;p&gt;As &lt;a title=&quot;ChatGPT And Whisper API&amp;#039;s&quot; href=&quot;https://openai.com/blog/introducing-chatgpt-and-whisper-apis#:~:text=Chat%20guide.-,ChatGPT%20upgrades,-We%20are%20constantly&quot; target=&quot;_blank&quot;&gt;announced&lt;/a&gt; in March 2023, OpenAI regularly release new versions of `gpt-4` and `gpt-3.5-turbo`. &lt;/p&gt;
&lt;p&gt;Each model version is dated with a month and date suffix; e.g., `gpt-4-0613`. The undated model name, e.g., `gpt-4`, will typically point to the latest version (e.g. `gpt-4` points to `&lt;/p&gt;
&lt;p&gt;After a new version is launched, older versions will typically be deprecated 3 months later.&lt;/p&gt;
&lt;p&gt;If you want to use a specific model you would reference it as [&quot;model&quot;: &quot;gpt-3.5-turbo-1106&quot;], for our purposes we used the undated model which is simply referred to as [&quot;model&quot;: &quot;gpt-3.5-turbo&quot;]&lt;/p&gt;
&lt;p&gt;Recent enhancements to models include: improved accuracy, improved function calling support, understanding images, reduce cases of “laziness” where the model doesn’t complete a task.&lt;/p&gt;
&lt;h2&gt;Setting The Temperature Parameter&lt;/h2&gt;
&lt;p&gt;Lower values for temperature result in more consistent outputs (e.g. 0.2), while higher values generate more diverse and creative results (e.g. 1.0). Select a temperature value based on the desired trade-off between coherence and creativity for your specific application. The temperature can range is from 0 to 2.&lt;/p&gt;
&lt;p&gt;We didn’t use temperature in this example but it is another useful tool in shaping the model responses.&lt;/p&gt;
&lt;h2&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;In the demo file we will query the API to receive 3 variations of the input text, giving each of them a slightly different tone. We will look at 3 ways you can change the response received by those queries and which method is the most reliable.&lt;/p&gt;
&lt;p&gt;&lt;a title=&quot;FileMaker ChatGPT Integration&quot; href=&quot;https://www.teamdf.com/assets/blog-images/filemaker-chatgpt-integration/filemaker-chatgpt-integration.zip&quot; target=&quot;_blank&quot;&gt;Download the Example file here&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Setting Up An OpenAI API Key&lt;/h2&gt;
&lt;p&gt;If you already have one of these, then you can skip this whole section! If not then read on…&lt;/p&gt;
&lt;p&gt;First, create an OpenAI account by signing up at &lt;a title=&quot;Link to Open AI website&quot; href=&quot;https://openai.com&quot; target=&quot;_blank&quot;&gt;https://openai.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Choose the API platform. Click on the API Key link. Accounts need to be verified with a mobile phone number before you can add a new API key.&lt;/p&gt;
&lt;p&gt;The introductory offer gives your account $18 free credit and this can be used against any API key you generate. We were allocated $5 credit when setting up a second account which shared the supplied phone number with a previous account. The tip here is that you do get a small amount of credit to get started, and a little goes a long way.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Open AI Platform Demo Screenshot&quot; src=&quot;https://www.teamdf.com/assets/Uploads/open-aiplatform-screenshot.png&quot; alt=&quot;Open AI Platform Demo Screenshot&quot; width=&quot;660&quot; height=&quot;529&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Create Account Demo Screenshot&quot; src=&quot;https://www.teamdf.com/assets/Uploads/create-account-screenshot.png&quot; alt=&quot;Create Account Demo Screenshot&quot; width=&quot;660&quot; height=&quot;529&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;API Keys Demo Screenshot&quot; src=&quot;https://www.teamdf.com/assets/Uploads/api-keys-screenshot.png&quot; alt=&quot;API Keys Demo Screenshot&quot; width=&quot;660&quot; height=&quot;528&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Connecting To The API&lt;/h2&gt;
&lt;p&gt;Use the following URL:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Endpoint: &lt;a title=&quot;Endpoint API Connection&quot; href=&quot;https://api.openai.com/v1/chat/completions&quot; target=&quot;_blank&quot;&gt;https://api.openai.com/v1/chat/completions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Below lists the main elements of the cURL request:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;-X POST&lt;/li&gt;
&lt;li&gt;-H &quot;Content-Type: application/json&quot;&lt;/li&gt;
&lt;li&gt;-H &quot;Authorization: Bearer XX-KXXXXXXXXXXX&quot; (where XX-KXXXXXXXXXXX is your API key)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The data portion of the post will specify:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The Language model you want to use&lt;/li&gt;
&lt;li&gt;The Prompt and any input text&lt;/li&gt;
&lt;li&gt;[Optional] Mock conversations used to pre prime the language model into sculpting your response&lt;/li&gt;
&lt;li&gt;[Optional] Temperature&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;For example:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;ChatGPT Integration - setting variables&quot; src=&quot;https://www.teamdf.com/assets/blog-images/filemaker-chatgpt-integration/set-variable-options-screenshot-3.jpg&quot; alt=&quot;ChatGPT Integration - setting variables&quot; width=&quot;660&quot; height=&quot;266&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Set Variable Options Demo Screenshot 1&quot; src=&quot;https://www.teamdf.com/assets/Uploads/set-variable-options-screenshot-1.png&quot; alt=&quot;Set Variable Options Demo Screenshot 1&quot; width=&quot;660&quot; height=&quot;541&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Set Variable Options Demo Screenshot 2&quot; src=&quot;https://www.teamdf.com/assets/Uploads/set-variable-options-screenshot-2.png&quot; alt=&quot; Set Variable Options Demo Screenshot 2&quot; width=&quot;660&quot; height=&quot;541&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Option 1: Basic&lt;/h2&gt;
&lt;p&gt;For this example we used the following prompt:&lt;/p&gt;
&lt;p&gt;“Provide three variations for this message using en_GB language. option1 Friendly and professional. option2 Authoritative and informative. option3 Casual and conversational. where the message is: Hi Cath your order has arrive. book in a fitting time which suit on 1800 0222 233 or visting www.teamdf.com”&lt;/p&gt;
&lt;p&gt;The incorrect spelling and bad grammar is deliberate as we want the API to improve on our submissions :)&lt;/p&gt;
&lt;p&gt;The response is returned as JSON (always) but will typically be dumped into one element &lt;br&gt;choices[0].message.content&lt;/p&gt;
&lt;p&gt;The variations are separated by a double line break.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Double Line Break Variable Demo Screenshot&quot; src=&quot;https://www.teamdf.com/assets/Uploads/double-line-break-variable-screenshot.png&quot; alt=&quot;Double Line Break Variable Demo Screenshot&quot; width=&quot;660&quot; height=&quot;474&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Problems With This?&lt;/h2&gt;
&lt;p&gt;The API will return inconsistent results, which makes parsing the result difficult. For example the way the variations were presented inside the content could change from call to call.&lt;/p&gt;
&lt;p&gt;The following had been observed…&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Option 1:\nHi Cath, your&lt;/li&gt;
&lt;li&gt;Option 1:Hi Cath, your&lt;/li&gt;
&lt;li&gt;Option1:Hi Cath, your&lt;/li&gt;
&lt;li&gt;Option1: (Friendly and professional)Hi Cath, your&lt;/li&gt;
&lt;li&gt;Variation 1:Hi Cath, your&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This could likely be improved with a more detailed prompt but its still not reliable to parse, which makes this method a bit too basic for practical use. However this would be more practical if you are asking for one answer at a time rather than 3 like this example.&lt;/p&gt;
&lt;h2&gt;Options 2: JSON&lt;/h2&gt;
&lt;p&gt;You can specify to have a JSON object returned. This showed more promise.&lt;/p&gt;
&lt;p&gt;For this example we used the following prompt:&lt;/p&gt;
&lt;p&gt;“Provide json three variations for this message using en_GB language. option1 Friendly and professional. option2 Authoritative and informative. option3 Casual and conversational. where the message is: Hi Cath your stuff has arrive. book in a fitting time which suit on 1800 0222 233 or visting www.teamdf.com”&lt;/p&gt;
&lt;p&gt;It was important to including the word JSON at the start of our prompt and to add response_format:{ &quot;type&quot; :&quot;json_object&quot;}, to the data portion of the post.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;full result screenshot&quot; src=&quot;https://www.teamdf.com/assets/blog-images/filemaker-chatgpt-integration/full-result-screenshot.png&quot; alt=&quot;full result screenshot&quot; width=&quot;660&quot; height=&quot;505&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;This worked better. By returning the result as JSON elements, removed the issue of manually parsing the result of the first method.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;JSON Message Options 1 Demo Screenshot&quot; src=&quot;https://www.teamdf.com/assets/Uploads/json-message-options-1-screenshot.png&quot; alt=&quot;JSON Message Options 1 Demo Screenshot&quot; width=&quot;660&quot; height=&quot;264&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;However, the elements returned were not 100% reliable either.  With this method you will always receive valid json however the number of elements and naming convention is not guaranteed. We noticed that if the input text was crafted more like an email, elements such at Attention, Action and Signature may be returned as would Tone on occasion.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;JSON Message Options 2 Demo Screenshot&quot; src=&quot;https://www.teamdf.com/assets/blog-images/filemaker-chatgpt-integration/json-message-options-2-screenshot.png&quot; alt=&quot;JSON Message Options 2 Demo Screenshot&quot; width=&quot;660&quot; height=&quot;329&quot;&gt;&lt;/p&gt;
&lt;p&gt;An improvement on the Basic technique but still too unreliable to work with. No doubt this could also be improved by a more specific prompt.&lt;/p&gt;
&lt;h2&gt;Options 3 Standardised JSON&lt;/h2&gt;
&lt;p&gt;The last method we settled on was to use a function in our request to specify the JSON we wanted returned.&lt;/p&gt;
&lt;p&gt;Functions are a way to force the model to return the response in a standardised format. &lt;br&gt;They are named and declared as part of your call. Meaning you now have control over the format of the response. You can also set data rules on the elements including length and the accepted values.&lt;/p&gt;
&lt;p&gt;cURL request including the function&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Curl Request Function Demo Screenshot&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage660513-curl-request-function-screenshot.png&quot; alt=&quot;Curl Request Function Demo Screenshot&quot; width=&quot;660&quot; height=&quot;513&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;Instead of the response returned in the location choices[0].message.content it will now be returned referencing the function like so: choices[0].message.function_call.arguments&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Message Function Call ArgumentsDemo Screenshot&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage660557-message-function-call-arguments-screenshot.png&quot; alt=&quot;Message Function Call ArgumentsDemo Screenshot&quot; width=&quot;660&quot; height=&quot;557&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Lessons Learnt&lt;/h2&gt;
&lt;p&gt;Along with the variation in responses, there were other issues we overcame on our journey.&lt;/p&gt;
&lt;h2&gt;Language Variations&lt;/h2&gt;
&lt;p&gt;The responses received were in American english. This wasn’t ideal for our audience and the answer was to be more specific in our prompt. Adding the term en-GB to our prompt translated the response.&lt;/p&gt;
&lt;p&gt;When specifying the prompt using ISO 639-1 language code is best That’s en-GB for British (not en-UK), and en-AU, en-NZ, en-CA, en-IE etc.&lt;/p&gt;
&lt;p&gt;Using en-GB spelling is generally a safe bet for all non-US countries unless you are very particularly about some of the language differences. If you use Australian English, it starts to overdo it, saying things like “G’day mate!” Unless of course, that’s what you want…&lt;/p&gt;
&lt;h2&gt;Saying The Right Thing&lt;/h2&gt;
&lt;p&gt;We had to tweak our prompt a fair bit. It seems like this is really important and there will be a lot of information around tips for crafting the perfect prompts.&lt;/p&gt;
&lt;p&gt;Despite carefully crafting our prompts, the language model occasionally overlooked parts of our requests. For example, most of the time our responses were in en-GB, but not every time! Occasionally they would be returned using American spelling. These are the kind of improvements we can expect to see as the Language Models mature and the reason why eye - balling the responses is so important.&lt;/p&gt;
&lt;h2&gt;Stripping Links&lt;/h2&gt;
&lt;p&gt;In some cases we wanted to include a specific URL. No matter how we changed the prompt we could not guarantee that the URL would be included in the variations. There is bound to be a way to enforce this but we changed our workflow to not need that and stopped looking to solve this problem. If you know a way then please leave a comment, we would be interested to learn.&lt;/p&gt;
&lt;h2&gt;Exceeding Rate Limit:&lt;/h2&gt;
&lt;p&gt;We hit rate limits while using an OpenAI account without a credit card.&lt;br&gt;&quot;message&quot;: &quot;Rate limit reached for gpt-3.5-turbo-0613 in organization org-XXXXXXXXXXX on requests per min (RPM): Limit 3, Used 3, Requested 1. Please try again in 20s. Visit &lt;a title=&quot;Open AI Account Rate Limits &quot; href=&quot;https://platform.openai.com/account/rate-limits&quot; target=&quot;_blank&quot;&gt;https://platform.openai.com/account/rate-limits&lt;/a&gt; to learn more. You can increase your rate limit by adding a payment method to your account at &lt;a title=&quot;Open AI Account Billing &quot; href=&quot;https://platform.openai.com/account/billing&quot; target=&quot;_blank&quot;&gt;https://platform.openai.com/account/billing&lt;/a&gt;.&quot;,&lt;/p&gt;
&lt;h2&gt;Final Comments&lt;/h2&gt;
&lt;p&gt;This is a simple integration but was very useful from a business standpoint. We would love to know what business problems you are solving with AI.&lt;/p&gt;
&lt;p&gt;Hope you found this interesting. &lt;a title=&quot;FileMaker ChatGPT Integration Download&quot; href=&quot;https://www.teamdf.com/assets/blog-images/filemaker-chatgpt-integration/filemaker-chatgpt-integration.zip&quot; target=&quot;_blank&quot;&gt;Download our file and have a play.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 19 Mar 2024 12:12:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-chatgpt-integration/</guid>
		</item>
		
		<item>
			<title>Development Excellence!</title>
			<link>https://www.teamdf.com/blogs/excellence/</link>
			<description>&lt;h2 style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/excellence-award-2023/_resampled/ResizedImage300339-5-award-claris-dev-partner.png&quot; alt=&quot;5 award claris dev partner&quot; width=&quot;300&quot; height=&quot;339&quot;&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;strong&gt;&lt;em&gt;We won!&lt;/em&gt;&lt;/strong&gt; And of course we absolutely deserved to win — the solution built by Cath Kirkland for our client Mobile Tyre Shop, is a &lt;em&gt;&lt;strong&gt;tour de force&lt;/strong&gt;&lt;/em&gt; of what can be accomplished with FileMaker, a top notch development team, and a client on a mission…&lt;/p&gt;
&lt;h4&gt;The Client&lt;/h4&gt;
&lt;p&gt;Mobile Tyre Shop (MTS) is a unique and extraordinarily innovative business, disrupting the tyre industry in Australia with the “tyre shop that comes to you.”&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;media center&quot;&gt;&lt;iframe width=&quot;659&quot; height=&quot;371&quot; src=&quot;https://www.youtube.com/embed/76nYfUDA47o?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; title=&quot;The tyre shop that comes to you - 30 sec commercial&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;p&gt; &lt;/p&gt;
&lt;h4&gt;Tailor Made&lt;/h4&gt;
&lt;p&gt;After trying a standard ERP software product, MTS recognised they needed a bespoke approach to their business systems:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/excellence-award-2023/out-of-the-box.png&quot; alt=&quot;out of the box&quot; width=&quot;500&quot; height=&quot;193&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p&gt;To meet their needs a whole new “operating system” was needed that would integrate a myriad of different services, from tyre suppliers, to car registration details, to phone systems and of course their website.&lt;/p&gt;
&lt;p&gt;To do that, in fact to build any bespoke software project, you need to align some major elements:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;A committed &lt;strong&gt;Product Owner&lt;/strong&gt; who knows what’s needed&lt;/li&gt;
&lt;li&gt;The right &lt;strong&gt;Platform&lt;/strong&gt; with flexibility and rapid development&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Developers&lt;/strong&gt; with the skills, experience and knowhow to deliver&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;And perhaps the single most important and overarching characteristic:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;An &lt;strong&gt;exceptional collaboration&lt;/strong&gt; between the Product Owner and the development team.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Much of the success here can be attributed to Cath, who spearheaded the development efforts, along with Jamie Cartwright, the Chief Operating Officer at MTS, for his vision and determination.&lt;/p&gt;
&lt;p&gt;Together they formed a dynamic duo and carved their way through challenges and complexities to deliver an extensive software solution with quantifiable benefits to the business such as —&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;40% reduction in sales staff&lt;/li&gt;
&lt;li&gt;70% reduction in the number of staff now needed to do scheduling&lt;/li&gt;
&lt;li&gt;Fleet customers are managed by a single person&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;…and the company is now positioned to double the number of jobs per day, without needing more administrative staff.&lt;/p&gt;
&lt;h4&gt;Customer Service&lt;/h4&gt;
&lt;p&gt;It’s also about improving customer service: there’s a raft of client interactions facilitated by the software — for example, when a tyre is scanned into the warehouse, the system automatically messages the client telling them their tyres have arrived, and provides a link to schedule the fitting at their convenience.&lt;/p&gt;
&lt;p&gt;MTS have also levelled the playing field in their industry by integrating with all the major brands, and many not so major brands, plus Amazon and eBay. By bringing all this data together in one place they’ve made the market more accessible and transparent so that the customer gets the best deal and chooses the right tyre for their needs.&lt;/p&gt;
&lt;p&gt;As a testament to how successful this approach is, MTS are now seeking a smaller office space with a bigger warehouse — that’s a wonderful outcome because it means they&#039;re doing more of what they actually do, with less administration and management, and in the process providing better customer service for the win!&lt;/p&gt;
&lt;p&gt;There’s a lot more we could say about the system — it’s an exciting project and we continue to build upon it even though it’s well and truly earning it’s keep already. We’ll do more in depth looks at the system itself in the future. For now though we’re celebrating…&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/excellence-award-2023/award-cake.jpeg&quot; alt=&quot;award cake&quot; width=&quot;500&quot; height=&quot;509&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;h2&gt;&lt;br&gt;Congratulations To Our Team&lt;/h2&gt;
&lt;p&gt;To Cath for the incredible commitment and hard work it’s taken, for the relationship and collaboration you foster so very well with your clients.&lt;/p&gt;
&lt;p&gt;To our entire team of 16 developers, because we all benefit from the support, knowledge and combined expertise of the entire team.&lt;/p&gt;
&lt;p&gt;And two particular giants at DF: Steve and Daniel.&lt;/p&gt;
&lt;p&gt;To you all — Well Done!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/excellence-award-2023/cath-award.png&quot; alt=&quot;cath award&quot; width=&quot;660&quot; height=&quot;682&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;&lt;br&gt;And A Huge Thanks to MTS!&lt;/h2&gt;
&lt;p&gt;Travis Osborne, founder and CEO, for the vision to bring the business to life, for selling the dream and for empowering his team, particularly Jamie, to find the best solutions…&lt;/p&gt;
&lt;p&gt;Jamie, for being an incredible product owner and evangelist, and for being articulate and forthright enough to shout about it from the rooftops!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;em&gt;&lt;strong&gt;Thank You All!&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;</description>
			<pubDate>Fri, 01 Mar 2024 10:19:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/excellence/</guid>
		</item>
		
		<item>
			<title>Welcome Oscar</title>
			<link>https://www.teamdf.com/blogs/welcome-oscar/</link>
			<description>&lt;p&gt;We would like to welcome a new member to the DF team, Oscar Frith-Macdonald.&lt;/p&gt;
&lt;p&gt;Oscar’s got a unique background, plus a unique dress sense, by the looks of the following photo. He likes a bit of unicycling, juggling, and stilt walking, and actually did a 240km charity cycle on a unicycle… &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/welcome-oscar/_resampled/ResizedImage330440-oscar-unicycle.jpg&quot; alt=&quot;oscar unicycle&quot; width=&quot;330&quot; height=&quot;440&quot;&gt;&lt;/p&gt;
&lt;p&gt;These highjinks aren’t entirely unique at Digital Fusion — we have one other developer that has a background with the circus (it must be a FileMaker thing)! …so if AI ever takes over our jobs we have a plan B.&lt;/p&gt;
&lt;p&gt;Oscar comes to us all the way from the UK, where he was born in London but moved to Cornwall when he was young. His connection to New Zealand started with that move to Cornwall when his parents almost decided on NZ instead, so when he got the chance to study abroad for a year he jumped at the chance to see us down here — well, Wellington specifically.&lt;/p&gt;
&lt;p&gt;The draw of NZ was too much and he returned last year, picking Christchurch as his new home this time round.&lt;/p&gt;
&lt;p&gt;Oscar has a Bachelor of Engineering in Electrical and Electronic Engineering. Those skills landed him with a very interesting first job in the UK, developing software for the conversion of old luxury cars to electric power at Lunaz Design.&lt;/p&gt;
&lt;h3&gt;Outside Work&lt;/h3&gt;
&lt;p&gt;Outside of work, Oscar and his partner are adventure nuts, which is possibly why they picked Christchurch which is on the doorstep to all sorts of outdoor activities — they’re into hiking, rock climbing, and getting out amongst the best NZ has to offer.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/welcome-oscar/_resampled/ResizedImage660469-oscar-hiking.jpg&quot; alt=&quot;oscar hiking&quot; width=&quot;660&quot; height=&quot;469&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;We welcome Oscar to the team, and look forward to plenty of banter when NZ and Australia take on the English in cricket or rugby.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 24 Oct 2023 18:24:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/welcome-oscar/</guid>
		</item>
		
		<item>
			<title>As You Were</title>
			<link>https://www.teamdf.com/blogs/as-you-were/</link>
			<description>&lt;p&gt;Over the last few years, Claris have been making changes across their platforms including introducing some new products. We&#039;ve been slow in how much we communicated about this  because on the whole the changes were not going to have a huge impact, or at least not in the short term, and we&#039;ve been uncertain on how it would all work exactly…&lt;/p&gt;
&lt;p&gt;Without going into great detail, Claris intended to have two platforms, the original FileMaker Platform that we all know and love, and a new one called the &quot;Claris Platform&quot; that would encompass the new products as well as a new version of FileMaker itself under a new name.&lt;/p&gt;
&lt;h3&gt;Claris Studio&lt;/h3&gt;
&lt;p&gt;As part of this, they released a new product, Claris Studio, which is essentially an easy-to-use, purely web-based, database and form builder. This would allow users to spin up a web form for things like conference registrations, internal forms etc etc. The data captured in these forms would then flow through into Claris Pro, the FileMaker Pro type app on the Claris Platform side the equation.&lt;/p&gt;
&lt;p&gt;Studio has the makings to be a great addition to the product range from Claris and a very useful compliment to FileMaker. As a product it’s still in its infancy, and Claris are making changes to it on a very regular basis. I think that in another six to twelve months we&#039;ll start seeing all sorts of use cases and ways that it can help expand on the capabilities of FileMaker.&lt;/p&gt;
&lt;p&gt;We recently used Studio in the organisation of the &lt;a href=&quot;http://reconnect.sydney&quot; target=&quot;_blank&quot;&gt;Reconnect.Sydney&lt;/a&gt; conference, the local APAC for FileMaker developers. It helped us build forms for speaker registrations, filter the speakers we wanted, collect their bio’s, photos etc. All this was spun up without any coding required, no need to set up a server, and zero deployment effort.&lt;/p&gt;
&lt;h3&gt;Simplification&lt;/h3&gt;
&lt;p&gt;Before we go too deep into all of this, things have changed, and we believe for the better and simpler: Claris announced last month that they are going to go with just the single platform moving forward, that being the &quot;&lt;strong&gt;Claris platform&lt;/strong&gt;&quot;, comprising of:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Claris Platform 2024&quot; src=&quot;https://www.teamdf.com/assets/blog-images/as-you-were/_resampled/ResizedImage658114-claris-platform-2024.png&quot; alt=&quot;Claris Platform 2024&quot; width=&quot;658&quot; height=&quot;114&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p&gt;In short, they are consolidating the new products with the tried and true FileMaker line, and calling it the &quot;Claris platform&quot;, but keeping the FileMaker name and product as it is (confused yet?!) &lt;/p&gt;
&lt;p&gt;The big win for you if you have FileMaker already is that Claris Studio which was limited to the new Claris Platform, will now work with the current FileMaker product line.&lt;/p&gt;
&lt;p&gt;All up we think this is a great move by Claris, they listened to feedback about the two platforms, and have made the right decision. What it has shown to us is that Claris are continuing to try things, sometimes they don’t get it right, but they are trying, and we think thats great.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;If you&#039;d like to know more, here&#039;s Claris&#039; own recent presention on their platforms:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 659px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;media center&quot;&gt;&lt;iframe width=&quot;659&quot; height=&quot;371&quot; src=&quot;https://www.youtube.com/embed/qtMos2uToBE?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; title=&quot;Claris Product Strategy Update 2023&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div class=&quot;captionImage center&quot; style=&quot;width: 659px;&quot;&gt;&lt;p class=&quot;caption&quot; style=&quot;text-align: center;&quot;&gt;Claris Product Strategy Update 2023&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Wed, 20 Sep 2023 15:33:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/as-you-were/</guid>
		</item>
		
		<item>
			<title>FileMaker OCR Integration with Veryfi</title>
			<link>https://www.teamdf.com/blogs/filemaker-veryfi-integration/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Hey there!&lt;/p&gt;
&lt;p&gt;Are you tired of spending countless hours manually entering data from documents? &lt;/p&gt;
&lt;p&gt;Check out OCR for a little slice of magic! OCR (Optical Character Recognition) is a fantastic technology that can transform printed or hand-written text into JSON format that can then be easily used to populate FileMaker records. &lt;/p&gt;
&lt;p&gt;In this example we will use the paid web service by Veryfi to read invoice documents but there are many other OCR services available.  Our choice to use Veryfi was mostly based on the standard JSON reponse they return.&lt;/p&gt;
&lt;p&gt;Are you ready to get started? Let&#039;s dive in! Download the example file below:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/veryfi/filemaker-veryfi-integration.zip&quot;&gt;Download the example file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;What You Will Need&lt;/h2&gt;
&lt;p&gt;First, you will need to create an account with Veryfi. &lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;a class=&quot;dynamiclink&quot; rel=&quot;noreferrer nofollow noopener&quot; href=&quot;https://app.veryfi.com/signup&quot; target=&quot;_blank&quot;&gt;https://app.veryfi.com/signup&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You have 14 days to use this account for free with limitations. After this point you will need to create a paid account, or add billing details to your own.&lt;/p&gt;
&lt;p&gt;Next, go to the Settings → Keys page and create a new API key&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;a class=&quot;dynamiclink&quot; rel=&quot;noreferrer nofollow noopener&quot; href=&quot;https://app.veryfi.com/api/settings/keys&quot; target=&quot;_blank&quot;&gt;https://app.veryfi.com/api/settings/keys&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/veryfi/_resampled/ResizedImage600472-veryfi-0.png&quot; alt=&quot;veryfi 0&quot; width=&quot;600&quot; height=&quot;472&quot;&gt;&lt;/p&gt;
&lt;p&gt;The information you will need to record from this page includes the following: &lt;/p&gt;
&lt;ul class=&quot;listtype-bullet listindent1 list-bullet1&quot;&gt;&lt;li&gt;
&lt;p&gt;Client ID&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Client Secret&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Username&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;API Key&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;and the URL &lt;a class=&quot;dynamiclink&quot; rel=&quot;noreferrer nofollow noopener&quot; href=&quot;https://api.veryfi.com/api/v7/partner/documents/&quot; target=&quot;_blank&quot;&gt;https://api.veryfi.com/api/v7/partner/documents/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/veryfi/_resampled/ResizedImage600363-veryfi-1.png&quot; alt=&quot;veryfi 1&quot; width=&quot;600&quot; height=&quot;363&quot;&gt;  &lt;/p&gt;
&lt;p&gt;Now you have all the tools you need, create a layout and add a container field for receiving the document you want to read.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/veryfi/_resampled/ResizedImage600363-veryfi-2.png&quot; alt=&quot;veryfi 2&quot; width=&quot;600&quot; height=&quot;363&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;The file contents will need to be Base64 encoded to include into the cURL which we will build up and send to Veryfi. &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/veryfi/_resampled/ResizedImage600202-veryfi-6.png&quot; alt=&quot;veryfi 6&quot; width=&quot;600&quot; height=&quot;202&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Now we have the contents of the file all nicely packaged up into a variable. Veryfi requires two pieces of information to be sent. The file name and the encoded file. Build up your data string like so escaping the quotes as needed.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;p&gt;JSONFormatElements (&lt;/p&gt;
&lt;p&gt;&quot;{&lt;/p&gt;
&lt;p&gt;  \&quot;file_name\&quot;: \&quot;&quot; &amp;amp; GetContainerAttribute ( HOME::fileadd_dragdrop ; &quot;filename&quot; )&amp;amp; &quot;\&quot;&quot; &amp;amp; &lt;/p&gt;
&lt;p&gt;  &quot;, \&quot;file_data\&quot;: \&quot;application/pdf;base64, &quot; &amp;amp; $file &amp;amp; &quot;\&quot;&quot; &amp;amp;&lt;/p&gt;
&lt;p&gt;&quot;}&quot; &lt;/p&gt;
&lt;p&gt;)&lt;br&gt;&lt;br&gt;&lt;br&gt;End result required: &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/veryfi/_resampled/ResizedImage600121-veryfi-5.png&quot; alt=&quot;veryfi 5&quot; width=&quot;600&quot; height=&quot;121&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Veryfi supports the following file types  .pdf, .htm, .jpeg, .avif, .heic, .gif, .webp, .txt, .html, .heif, .ofd, .png, .jpg, .zip with a maximum file size of 20mb.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;Sending the Request&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Next we want to build up the CURL request.  In this case we are using a POST and sending the authorization details of our API key and account set up earlier.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&quot;-X POST&quot; &amp;amp; ¶ &amp;amp;&quot;-H \&quot;Accept: application/json\&quot;&quot; &amp;amp; ¶ &amp;amp;&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&quot;-H \&quot;Content-Type: application/json\&quot;&quot; &amp;amp; ¶ &amp;amp;&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&quot;-H \&quot;CLIENT-ID: &quot; &amp;amp; $clientid &amp;amp; &quot;\&quot;&quot; &amp;amp; ¶ &amp;amp;&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&quot;-H \&quot;AUTHORIZATION: apikey &quot; &amp;amp; $account &amp;amp; &quot;:&quot; &amp;amp; $apikey &amp;amp; &quot;\&quot;&quot; &amp;amp; ¶ &amp;amp;&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&quot;--dump-header $responsestatus &quot;   &amp;amp; ¶ &amp;amp; //gets us a response code&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&quot;-d @$Data&quot; &amp;amp; ¶ &amp;amp;&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&quot;--trace $$trace “ [Optional; used for troubleshooting]&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;Now use Insert from URL to send the request&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/veryfi/_resampled/ResizedImage600181-veryfi-4.png&quot; alt=&quot;veryfi 4&quot; width=&quot;600&quot; height=&quot;181&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p&gt;In this case we are setting the response into the &lt;em&gt;$Response&lt;/em&gt; variable so you can check this for a valid response of 201.&lt;/p&gt;
&lt;p&gt;The document will be returned as JSON listing out elements such as but not limited to:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/veryfi/_resampled/ResizedImage600266-veryfi-3.png&quot; alt=&quot;veryfi 3&quot; width=&quot;600&quot; height=&quot;266&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;Want To Know More?&lt;/h2&gt;
&lt;p&gt;Check out Veryfi&#039;s documentation for further information on the JSON response or other details.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;dynamiclink&quot; rel=&quot;noreferrer nofollow noopener&quot; href=&quot;https://app.veryfi.com/api/docs/&quot; target=&quot;_blank&quot;&gt;https://app.veryfi.com/api/docs/&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;  &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;As mentioned, we always include an example file with our articles to help you learn and explore. We spend a lot of time on these so please do check it out.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/veryfi/filemaker-veryfi-integration.zip&quot;&gt;Click here to download the example file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 18 Jul 2023 23:08:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-veryfi-integration/</guid>
		</item>
		
		<item>
			<title>Google Maps in FileMaker</title>
			<link>https://www.teamdf.com/blogs/filemaker-googlemaps-calculating-travel-time/</link>
			<description>&lt;div&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Wow, there are endless possibilities with Google Maps! But where do we even begin? In this demo, we&#039;ll show you just how effortless it is to find and display the travel time between any two locations using Google Maps.&lt;/p&gt;
&lt;p&gt;Imagine this: you&#039;re using FileMaker Go, and in just a few clicks, you can instantly know your exact location and estimate the travel time to your next destination or important meeting.&lt;/p&gt;
&lt;p&gt;Now, here&#039;s the slightly tricky part - getting your hands on a Google API key. If you don&#039;t have one don&#039;t worry we will take you through the steps of getting one. Let&#039;s get started and discover the benefits of this integration…&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;Are you ready to get started? Let&#039;s dive in!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/google-travel/filemaker-google-maps-calculationg-travel-time.zip&quot;&gt;Download the Example File&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Setting-up A Google API Key&lt;/h2&gt;
&lt;p&gt;If you already have one of these, then you can skip this whole section! If not then read on…&lt;/p&gt;
&lt;p&gt;You will need to set up a Google API key. This involves creating a cloud.googe.com account and using a credit card. &lt;/p&gt;
&lt;p&gt;In most cases usage rates fall in the free zone, mostly because Google currently gives you a $200 recurring monthly credit. Some of their rates are here:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a class=&quot;dynamiclink&quot; rel=&quot;noreferrer nofollow noopener&quot; href=&quot;https://developers.google.com/maps/documentation/directions/usage-and-billing&quot; target=&quot;_blank&quot;&gt;https://developers.google.com/maps/documentation/directions/usage-and-billing&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Finding the right place to set up a Google API key can be a pain and you have to enable the services you want to use. But don’t worry once you have the API key it&#039;s smooth sailing from there!&lt;/p&gt;
&lt;p&gt;1. Go to the Google Cloud Console &lt;a class=&quot;dynamiclink&quot; rel=&quot;noreferrer nofollow noopener&quot; href=&quot;https://console.cloud.google.com/projectselector2&quot;&gt;https://console.cloud.google.com/projectselector2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2. Select a project, or create a new one. &lt;/p&gt;
&lt;p&gt;3. Go to the APIs &amp;amp; Services &amp;gt; Credentials page. &lt;/p&gt;
&lt;p&gt;4. Create Credential, select API key and choose the following options:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Choose Application Restriction if any.&lt;/li&gt;
&lt;li&gt;Click Restrict key.&lt;/li&gt;
&lt;li&gt;From the Selected APIs dropdown. Enable the following: &lt;/li&gt;
&lt;ul&gt;&lt;li&gt;Directions API, Geocoding API, Geolocation API, Maps JavaScript API, Places API (you wont be able to select some of these until there is billing information added.&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;p&gt; To finalise your changes, click Save.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/google-travel/_resampled/ResizedImage600641-google-travel-7.png&quot; alt=&quot;google travel 7&quot; width=&quot;600&quot; height=&quot;641&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;div&gt;
&lt;h2&gt;The Google APIs&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;When you set up your Google API key you do get the option to enable the services you want to use. If you are going to be using Google Maps integration for a multiple integrations in your FileMaker database we suggest setting up multiple keys.  In the event that you do start to get charged you then have a little more visibility as to where those charges are driven from as the charges get linked to the API key.  We didn&#039;t do this here but you know… you live and learn!&lt;/p&gt;
&lt;p&gt;For more information on the services we use look here:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Directions API&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Get directions between locations, for driving, cycling, transit, and walking:&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;a class=&quot;dynamiclink&quot; rel=&quot;noreferrer nofollow noopener&quot; href=&quot;https://developers.google.com/maps/documentation/directions&quot; target=&quot;_blank&quot;&gt;https://developers.google.com/maps/documentation/directions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Geocoding API&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Convert addresses or Place IDs to latitude/longitude coordinates and vice-versa:&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;a class=&quot;dynamiclink&quot; rel=&quot;noreferrer nofollow noopener&quot; href=&quot;https://developers.google.com/maps/documentation/geocoding&quot; target=&quot;_blank&quot;&gt;https://developers.google.com/maps/documentation/geocoding&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Geolocation API &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Uses cell phone towers to establish a gps location:&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;a class=&quot;dynamiclink&quot; rel=&quot;noreferrer nofollow noopener&quot; href=&quot;https://developers.google.com/maps/documentation/geolocation/overview&quot; target=&quot;_blank&quot;&gt;https://developers.google.com/maps/documentation/geolocation/overview&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Maps JavaScript API &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Build dynamic, interactive, deeply customized maps, location, and geospatial experiences for your web app:&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;a class=&quot;dynamiclink&quot; rel=&quot;noreferrer nofollow noopener&quot; href=&quot;https://developers.google.com/maps/documentation/javascript&quot; target=&quot;_blank&quot;&gt;https://developers.google.com/maps/documentation/javascript&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Places API &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Get location data for over 200 million places, and add place details, search, and autocomplete to your apps:&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;a class=&quot;dynamiclink&quot; rel=&quot;noreferrer nofollow noopener&quot; href=&quot;https://developers.google.com/maps/documentation/places/web-service&quot; target=&quot;_blank&quot;&gt;https://developers.google.com/maps/documentation/places/web-service&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div&gt;
&lt;h2&gt;Getting Started&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Download the demo file and enter your own API key.&lt;/p&gt;
&lt;p&gt;The main block of code contains a couple of substitutes. We have inserted tags into the code to make it simple to substitute with your own data.  The minimum data you will need is the &lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Start coordinates (longitude + latitude)&lt;/li&gt;
&lt;li&gt;Destination coordinates.  &lt;/li&gt;
&lt;li&gt;API key&lt;/li&gt;
&lt;li&gt;Mode is optional and will default to driving if not specified&lt;/li&gt;
&lt;/ul&gt;&lt;p style=&quot;text-align: center;&quot;&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/google-travel/_resampled/ResizedImage600429-google-travel-1.png&quot; alt=&quot;google travel 1&quot; width=&quot;600&quot; height=&quot;429&quot;&gt;&lt;/p&gt;
&lt;div&gt;
&lt;h2&gt;Returning The Travel Time&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;The code also contains the name of a script which will get called when the map loads in a webviewer. The time is passed as a script parameter in seconds.&lt;/p&gt;
&lt;p&gt;The script name in the example file is called:&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;em&gt;[MAP: SetTravelTime] &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You can customise this to call your script by changing the name directly in the map code.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For Example...&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In our example we demonstrate the travel time in New York City across central park. Changing the mode of transport re-calculates the optimal route and estimated travel time for the 4 modes Google allows you to select.  &lt;/p&gt;
&lt;p&gt;Note: For each mode to work there does have to be sufficient google data to revaluate the route. For instance biking mode does not work in Christchurch, NZ due to a lack of google data.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/google-travel/_resampled/ResizedImage600363-google-travel-2.png&quot; alt=&quot;google travel 2&quot; width=&quot;600&quot; height=&quot;363&quot;&gt;&lt;/p&gt;
&lt;p&gt;40 minutes to walk from The Metropolitan Museum of Art to Times Square. &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/google-travel/_resampled/ResizedImage600363-google-travel-3.png&quot; alt=&quot;google travel 3&quot; width=&quot;600&quot; height=&quot;363&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;29 minutes by public transport&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/google-travel/_resampled/ResizedImage600363-google-travel-4.png&quot; alt=&quot;google travel 4&quot; width=&quot;600&quot; height=&quot;363&quot;&gt; &lt;/p&gt;
&lt;p&gt;13 mins to drive&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/google-travel/_resampled/ResizedImage600363-google-travel-5.png&quot; alt=&quot;google travel 5&quot; width=&quot;600&quot; height=&quot;363&quot;&gt;&lt;/p&gt;
&lt;p&gt;But the winner was 12 minutes to bike between the two points.  &lt;/p&gt;
&lt;p&gt;Compare some other locations in our demo file or add your own. &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;What&#039;s Your Current Location?&lt;/h2&gt;
&lt;p&gt;Using FileMaker Go this is simple to work out as we can use the FileMaker Function &lt;/p&gt;
&lt;pre&gt;LocationValues(200;10)&lt;/pre&gt;
&lt;p&gt;Where 200 represents the accepted accuracy in meters and 10 represents the maximum acceptable time in seconds since the location was last looked up. This function returns a delimited list of location information where:&lt;/p&gt;
&lt;p&gt;1st value = latitude&lt;/p&gt;
&lt;p&gt;2nd value = longitude &lt;/p&gt;
&lt;p&gt;On non-iOS devices you could use Geolocation API which uses cell phone towers to establish a gps location.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;How To GPS Your Addresses&lt;/h2&gt;
&lt;p&gt;In reality to use this integration your contact addresses have to be GPS’ed.  There are two main ways to do this.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;At the point of data entry&lt;/li&gt;
&lt;li&gt;Retrospectively.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;That choice will be up to you. There is code in the example file which will retrospectively loop through a bunch of addresses and use the Google Places API to code them.&lt;/p&gt;
&lt;p&gt;Alternatively you can use a widget like Google address validator in a web viewer to enter and code addresses as you go.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/google-travel/_resampled/ResizedImage600446-google-travel-6.png&quot; alt=&quot;google travel 6&quot; width=&quot;600&quot; height=&quot;446&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Hope you found this interesting. Download our file and have a play.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;As mentioned, we always include an example file with our articles to help you learn and explore. We spend a lot of time on these so please do check it out.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/google-travel/filemaker-google-maps-calculationg-travel-time.zip&quot;&gt;Click here to download the example file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 18 Jul 2023 16:29:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-googlemaps-calculating-travel-time/</guid>
		</item>
		
		<item>
			<title>Server Compatible Dynamic Portal Sorting</title>
			<link>https://www.teamdf.com/blogs/server-compatible-dynamic-portal-sorting/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this article we&#039;re going to show an approach to dynamically sort a portal. By dynamically we mean allowing the end user control over which field a portal is sorted by.&lt;/p&gt;
&lt;p&gt;Traditionally this has always been difficult in FileMaker because portals are sorted using the standard sort dialog, which only allows you to hard-code one or more predetermined fields as the sort order - there simply is no ability to programatically change the field defined.&lt;/p&gt;
&lt;p&gt;There have been a number of approaches to this issue over the years and all are certainly usable and do the job.  They do however suffer from a few drawbacks which we&#039;ll also discuss.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Cut to the chase, what is your solution?&lt;/h2&gt;
&lt;p&gt;We&#039;re going to do things a little different in this article. Usually we go through a detailed explanation of a technique before getting to the final implementation. We&#039;re going to flip this on it&#039;s head and instead tell you what the approach is up-front.  &lt;/p&gt;
&lt;p&gt;The remainder of the article will then go into all that nitty gritty which we really think you will find interesting and informative.  It helps to understand why this particular approach has been taken so you can get an appreciation for the challenges involved in portal sorting.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;So here is our approach&lt;/h2&gt;
&lt;p&gt;Firstly, we&#039;re going to sort a portal by each records internal ID. This can be obtained using the &lt;strong&gt;Get ( recordID )&lt;/strong&gt; function.  We then set into a calculation field which we&#039;ll call &lt;strong&gt;rowid.&lt;/strong&gt;  &lt;/p&gt;
&lt;p&gt;When we specify the sort field used, we&#039;re going to use the additional option to use a Custom order based on a Value list.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;The Sort Dialog&quot; src=&quot;https://www.teamdf.com/assets/blog-images/dynamic-portal-sort/_resampled/ResizedImage600472-dynamicportalsort-1.png&quot; alt=&quot;Sort Dialog&quot; width=&quot;600&quot; height=&quot;472&quot;&gt;&lt;/p&gt;
&lt;p&gt;This value list lies at the core of our ability to sort dynamically. It will be a value list of &lt;strong&gt;rowid&lt;/strong&gt; values for the records in the portal but the value list will present them in an order which matches the desired sort order we want.&lt;/p&gt;
&lt;p&gt;If the value list is in the desired sort order and we&#039;re sorting the portal based on &lt;strong&gt;rowids&lt;/strong&gt; being in this order, then our records will then also be sorted in this dynamic order.&lt;/p&gt;
&lt;p&gt;SO, that&#039;s the theory anyway. Now lies all the tricky business of implementation. Time to come with us on a journey of learning!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;Now is a great time to download the example file.  We have invested a lot of time again in providing an informative and easy to follow example file that not only explains the technique but lets you explore it for yourself.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/dynamic-portal-sort/DynamicPortalSorting.zip&quot; target=&quot;_blank&quot;&gt;Please download the example file here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;And now for the nitty gritty and interesting stuff…&lt;/h2&gt;
&lt;p&gt;In a nutshell this approach seems simple but it relies on quite a few interesting techniques to get it to work. it also draws upon historical techniques  which we have had to refine for this process. We&#039;re going to go through all of these in some detail. &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;First, some history on Portal sorting&lt;/h2&gt;
&lt;p&gt;In order for a portal to be dynamically sorted, it has to allow each individual user control over how they choose to sort it. Simply sorting a portal by a predefined stored field will not allow this, because the stored value cannot change on a per-user basis.&lt;/p&gt;
&lt;p&gt;For this reason, most dynamic portal sorting solutions involve the use of an &lt;strong&gt;unstored calculation&lt;/strong&gt; field for sorting. The value of an unstored calculation can be different for each individual user because the result is not stored, and can dynamically change.&lt;/p&gt;
&lt;p&gt;If a portal is sorted by an unstored calculation, and the user can programatically change the value of this calculation, then they can affect the portal sort. This is the exact technique Digital Fusion has employed for our dynamic portal sorting for a number of years.&lt;/p&gt;
&lt;p&gt;There are some good articles on this topic.  &lt;a href=&quot;https://www.soliantconsulting.com/blog/filemaker-portal-column-techniques/&quot; target=&quot;_blank&quot;&gt;Soliant Consulting have an implementation&lt;/a&gt;, as does &lt;a href=&quot;https://gomainspring.com/filemaker-community/sorting-portals-dynamically-using-filemaker/&quot; target=&quot;_blank&quot;&gt;MainSpring here&lt;/a&gt;&lt;a href=&quot;https://www.teamdf.com/[sitetree_link,id=]#https:/gomainspring.com/filemaker-community/sorting-portals-dynamically-using-filemaker/&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Our approach of choice is a custom function provided by the developer Ugo Di Luca of DL Systems.  &lt;a href=&quot;https://www.briandunning.com/cf/368&quot; target=&quot;_blank&quot;&gt;You can find the custom function here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ugo&#039;s custom function can be used to produce a result of any number of various fields in a given table, in either ascending or descending order, for the purposes of sorting.  He does this by converting a fields value from it&#039;s default format  (e.g. numeric, date, timestamp, text) into a text string representation capable of being sorted as a text field.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;What problems does dynamic sorting face?&lt;/h2&gt;
&lt;p&gt;While Ugo&#039;s solution is ingenious and works, it does suffer from a limitation of unstored calculations.  An unstored calculation can only be one field type.  If an unstored calculation is thus used as the basis of a portal sort then any field it represents must be cast into the same format as the unstored calculation.  &lt;/p&gt;
&lt;p&gt;Take a text calculation where we want to be able to dynamically change it&#039;s value to be that of other fields. These other fields could be numbers, dates, timestamps or times. Simply putting these types of values into a text field is not going to allow them to sort correctly.&lt;/p&gt;
&lt;p&gt;The simplest example of this is the number 1 versus number 10. In number fields, 10 is greater than 1, but as text, 1 is greater than 10. This immediately breaks any sorting we would want to do on numbers.&lt;/p&gt;
&lt;p&gt;To resolve this, Ugo has to convert all fields from their base format (e.g. number) into a text string representation that can still preserve sort ordering.&lt;/p&gt;
&lt;p&gt;This adds quite an extra layer of overhead to this technique and is a drawback when sorting on lots of records.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Server sorting issue&lt;/h2&gt;
&lt;p&gt;Furthermore, in order to dynamically specify which field to use in the unstored calculation, it relies on a user specific preference, and this is often handled through a global variable or global field. The value of an unstored calculation for one user may be entirely different for another user - keep this in mind.&lt;/p&gt;
&lt;p&gt;In FileMaker Server 19, a new feature was introduced called &lt;strong&gt;Server Side Sorting&lt;/strong&gt;.  Basically this allows FileMaker Server to carry out the sorting of records where previously this was done entirely on the client machine. This greatly improves sorting performance as previously all sorting was handled client side and required the transfer of all records being sorted from server to client.&lt;/p&gt;
&lt;p&gt;BUT (and there is always a but) this feature itself suffers from some problems when it comes to sorting unstored calculations.&lt;/p&gt;
&lt;p&gt;When server sorts an unstored calculation it does not expect the value to be different for different users. It actually calculates the same value &lt;strong&gt;for all users&lt;/strong&gt; and ignores any user specific preference.&lt;/p&gt;
&lt;p&gt;As a result, this sorting technique breaks when FileMaker Server carries out the sorting.&lt;/p&gt;
&lt;p&gt;Unfortunately we have no control over this feature other than to entirely disable it. When enabled, FileMaker Server makes a determination as to whether it will sort records or whether it will defer this to the client. This decision is made on various heuristics to do with server load.&lt;/p&gt;
&lt;p&gt;In practice when FileMaker Server 19 came out, we saw our dynamic portals only sort correctly some of the time - the times where server was &lt;strong&gt;not&lt;/strong&gt; doing the sorting.&lt;/p&gt;
&lt;p&gt;This led us to the conclusion that unstored calculation based approaches are simply not that reliable from FileMaker 19 onwards.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;A &quot;Stored&quot; Solution: Value Lists&lt;/h2&gt;
&lt;p&gt;So if we can&#039;t use an unstored calculation, how on earth do we do dynamic sorting? Well let&#039;s take a look at the sort dialog again:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/dynamic-portal-sort/_resampled/ResizedImage600472-dynamicportalsort-1.png&quot; alt=&quot;dynamicportalsort 1&quot; width=&quot;600&quot; height=&quot;472&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;We have this option here to sort based on a custom order. Ha! That sounds kind of like what we&#039;re trying to achieve.  This is the option we investigated and looked to exploit.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;So let&#039;s sort our records based on something unique such as the internal record ID.  The field itself we choose is somewhat arbitrary so long as it is unique, and this internal record ID works best.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;The actual sorting is done in the value list because &lt;strong&gt;it is the order of the value list&lt;/strong&gt; which will determine the order of the records. &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;How does sorting based on Value Lists work?&lt;/h2&gt;
&lt;p&gt;Right, so all we need to do is build a value list of &lt;strong&gt;rowids&lt;/strong&gt; which are in an order that we want our records to be sorted. Simple right?  NO you fool! Nothing is simple when it comes to value lists!&lt;/p&gt;
&lt;p&gt;We have to first understand what options we have when it comes to sorting a value list.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Sort Options for a Value List&quot; src=&quot;https://www.teamdf.com/assets/blog-images/dynamic-portal-sort/dynamicportalsort-2.png&quot; alt=&quot;dynamicportalsort 2&quot; width=&quot;582&quot; height=&quot;136&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;With sorting, we really have no options for a custom order.  The order of a value list is always based upon sorting the primary field, OR by the secondary field if applicable. In the case of a text field this is always alphabetical which for us is useless - we don&#039;t want rowids sorted alphabetically, we want them in a predefined order of our choosing.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Which leads us to the next insightful breakthrough.....&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The first challenge - Sorting a value list!&lt;/h2&gt;
&lt;p&gt;This:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Sort Override&quot; src=&quot;https://www.teamdf.com/assets/blog-images/dynamic-portal-sort/dynamicportalsort-3.png&quot; alt=&quot;dynamicportalsort 3&quot; width=&quot;409&quot; height=&quot;36&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;There is an option to re-sort values based on a different language. Why would you generally want to do this? Well let&#039;s say you had values in a field that were German words. You don&#039;t want to sort these using the English alphabet which might be the file default, and so you instead choose from this drop-down the German language. So this is a language resort.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;One of the available languages however is Unicode. Unique is a language which not only includes alphabetical characters, but numeric, and many other symbols. Each character is defined by an ASCII code number, and when sorting a value list by Unicode, it is actually being sorted on its underlying ASCII code.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Why is this of any relevance here? Well it all comes down to a very special ASCII character which has opened the door for custom value list sorting…&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Enter the BOM&lt;/h2&gt;
&lt;p&gt;This character is called a Byte-Order Mark, or BOM for short. It is defined as a zero-width no break space. If you want to learn more you can read the wikipedia page &lt;a href=&quot;https://en.wikipedia.org/wiki/Byte_order_mark#:~:text=marks%20by%20encoding-,Usage,%2Dbreaking%20between%20word%2Dglyphs.&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For us, the important characteristic about this code, is that it is invisible. We can include this character in a text string. It does not appear in the string, but it does influence the sorting of that string when sorted by Unicode.&lt;/p&gt;
&lt;p&gt;The BOM character can be written in FileMaker using the &lt;em&gt;Code&lt;/em&gt; function, i.e.: Code(65279)&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;So how does BOM sorting work?&lt;/h2&gt;
&lt;p&gt;Soliant Consulting first introduced this technique in &lt;a href=&quot;https://www.soliantconsulting.com/blog/filemaker-char-function/&quot; target=&quot;_blank&quot;&gt;this seminal article from 2012&lt;/a&gt;. I encourage you to read and learn about the technique here as they do a better job of explaining it than I ever can.&lt;/p&gt;
&lt;p&gt;When a BOM is placed at the start of a string, it alters where that string appears in a Unicode sorted list. By appending more or less BOM&#039;s to the start of a string, you can alter it&#039;s position in the list when sorted by Unicode.&lt;/p&gt;
&lt;p&gt;Here&#039;s an example where X is a BOM:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;X3958&lt;/p&gt;
&lt;p&gt;XX113&lt;/p&gt;
&lt;p&gt;XXX924&lt;/p&gt;
&lt;p&gt;XXXX2281&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;These values appear in this order when sorted by Unicode. The list is sorted according to the number of prepended BOMs.&lt;/p&gt;
&lt;p&gt;This technique has been used with great success to allow record-based value lists to be ordered based on some sort order for each record. A calculation simply prepends a number of BOM items to the value based on where you want that value to appear in the value list.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Let&#039;s bring this back to our approach… &lt;/h2&gt;
&lt;p&gt;We are trying to build a value list of rowids in a specific order, so we could use this BOM technique to achieve it. This is exactly what we did – initially…&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The second challenge - BOMs bomb out at a point&lt;/h2&gt;
&lt;p&gt;So, it turns out that the BOM technique works great when the number of values in your value list is relatively low (under 100 values).&lt;/p&gt;
&lt;p&gt;Once you hit approximately 100 values things start to go haywire and the values are no longer correctly ordered, so why is this the case?&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;A problem...&quot; src=&quot;https://www.teamdf.com/assets/blog-images/dynamic-portal-sort/_resampled/ResizedImage600245-dynamicportalsort-4.png&quot; alt=&quot;dynamicportalsort 4&quot; width=&quot;600&quot; height=&quot;245&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;In the above image we have a list of numbers which are prepended with BOM characters (shown in red).  This field was used as the basis of a value list, and the above values were obtained using the &lt;strong&gt;ValueListItems&lt;/strong&gt; function. This function returns us the list of values as they appear in the value list.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Now, what you&#039;ll see here is 3 entries look drastically out of place.  These occur from line 110 onwards, however when this issue presents itself depends also on the length of the number.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Why are they so far out of the desired order?&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Turns out the issue is to do with how Value Lists order items. They do so using a fields &lt;strong&gt;Value Index&lt;/strong&gt;. In FileMaker, a value index is not the entire value.  This is the definition from FileMaker help:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;a name=&quot;1029851&quot;&gt;&lt;/a&gt;A value index is created by taking each line of text (delimited by the carriage return character) and taking up to the first 100 primary character weights that all the characters in that line generate, according to the Unicode Collation Algorithm. See &lt;span class=&quot;zh-hyper&quot;&gt;&lt;a href=&quot;https://fmhelp.filemaker.com/help/14/fmp/en/html/non_toc.43.1.html#1039132&quot;&gt;Choosing a language for indexing or sorting&lt;/a&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;In short, once we max out the size of the value index for any given field value, things just don&#039;t order correctly.  The first characters in this technique are always BOM&#039;s so at some point the value index for all records just becomes a big set of BOM&#039;s (not the actual field value we want which is the number component).&lt;/p&gt;
&lt;p&gt;In short - BOM is great for small value lists, but don&#039;t use it on larger ones!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Can we use something other than a BOM to the same effect?&lt;/h2&gt;
&lt;p&gt;So BOMs kind of bombed out (pun intended), but perhaps not all is lost. Can we salvage something from the lessons learned about BOMs and how they help to do sorting?&lt;/p&gt;
&lt;p&gt;Our main issue with them is the length of the BOMs breaking our value indexes. What if we can represent a large number of BOMs by something else which is much shorter?&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;The solution to this came from the brilliant mind of Steve Senft-Herrer (you may know him as Steve_ssh). What if we simply used a mapping of a values position to letters, and prepended the letters instead?&lt;/p&gt;
&lt;p&gt;To show you what we mean consider the below mapping:&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;0 -&amp;gt; a&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;1 -&amp;gt; b&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;2 -&amp;gt; c&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;...&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;9 -&amp;gt; i&lt;/p&gt;
&lt;p&gt;We simply map a number to a letter.  To preserve correct positioning of a number, we always pad a number out with 0&#039;s until it is of a constant length. Let&#039;s pick 10 digits, so the number 1 becomes 0000000001.&lt;/p&gt;
&lt;p&gt;Now consider the number 3,489,941.  This could be represented as &lt;strong&gt;0003489941&lt;/strong&gt; , or mapped is &lt;strong&gt;aaacdhiida&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Putting this all together, the value list from our earlier example would now look something like this:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;aaaaaaaaab3958&lt;/p&gt;
&lt;p&gt;aaaaaaaaac113&lt;/p&gt;
&lt;p&gt;aaaaaaaaad924&lt;/p&gt;
&lt;p&gt;aaaaaaaaae2281&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;This can be sorted as Unicode or Alphabetical and works the same way, it&#039;s the constant length alphabetic string at the start which determines the actual sorting of the values.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Wait, is this really going to work?&lt;/h2&gt;
&lt;p&gt;Remember, we&#039;re trying to sort a portals records by &lt;strong&gt;rowid&lt;/strong&gt;, using custom ordering based on a value list that looks like the one above. Is that actually going to work?&lt;/p&gt;
&lt;p&gt;If I want rowid &lt;strong&gt;924&lt;/strong&gt; for example to sort to the third position as above, is it going to work given that technically speaking 924 is not in the value list, it is instead represented as &lt;strong&gt;aaaaaaaaad924&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;Strangely enough, yes it will!&lt;/p&gt;
&lt;p&gt;So, as it turns out in yet another interesting quirk of Value Lists, if you sort by a number field and choose to custom order based on a value list, then FileMaker will interpret the values of that value list as being in the same format as the field you are sorting by - in other words as numbers.  FileMaker completely ignores any non-numeric character in the values and what you are left with is just the &lt;strong&gt;rowids&lt;/strong&gt; which are numbers.&lt;/p&gt;
&lt;p&gt;Why this is the case is a question for the Claris engineers.&lt;/p&gt;
&lt;p&gt;Because this value list is being created purely for sorting purposes, and is not intended as a value list to be used for value selection, we really don&#039;t care about the fact it looks like gibberish - no one is ever going to see it. All we care about is the fact that it is a successful way for us to sort our records.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Time to build the value list&lt;/h2&gt;
&lt;p&gt;At this point we know it is possible to produce a list of values that can be used to sort records. That&#039;s only half the puzzle as we need to actually generate this value list.&lt;/p&gt;
&lt;p&gt;How you do this is up to you but we found the best approach is to use a script to carry out the sorting and creation of the value list.&lt;/p&gt;
&lt;p&gt;When a user chooses to sort a portals records, a script will run that will produce a found set of those records on a target layout (this can be done off-screen OR on server).&lt;/p&gt;
&lt;p&gt;The script can then sort the found set of records by the order which the user desires.&lt;/p&gt;
&lt;p&gt;Once sorted, a &lt;strong&gt;List Of &lt;/strong&gt;summary field can be used to collate a list of values to be used in a value list.&lt;/p&gt;
&lt;p&gt;We just need a calculation field on the table that can give us this value for each record.  The calculation looks like this:&lt;/p&gt;
&lt;pre&gt;Let ( [ &lt;br&gt;_PADDING = &quot;000000000&quot; ; &lt;br&gt;~row_id = Get ( RecordID ) ; &lt;br&gt;~record_number = Get( RecordNumber ); &lt;br&gt;~prefix = Right( _PADDING &amp;amp; ~record_number ; 10 ); &lt;br&gt;~prefix_encoded = Substitute( ~prefix ; &lt;br&gt;                           [ &quot;0&quot; ; &quot;a&quot; ] ; &lt;br&gt;                           [ &quot;1&quot; ; &quot;b&quot; ] ;&lt;br&gt;                           [ &quot;2&quot; ; &quot;c&quot; ] ;&lt;br&gt;                           [ &quot;3&quot; ; &quot;d&quot; ] ; &lt;br&gt;                           [ &quot;4&quot; ; &quot;e&quot; ] ; &lt;br&gt;                           [ &quot;5&quot; ; &quot;f&quot; ] ; &lt;br&gt;                           [ &quot;6&quot; ; &quot;g&quot; ] ; &lt;br&gt;                           [ &quot;7&quot; ; &quot;h&quot; ] ; &lt;br&gt;                           [ &quot;8&quot; ; &quot;i&quot; ] ; &lt;br&gt;                           [ &quot;9&quot; ; &quot;j&quot; ]&lt;br&gt;) &lt;br&gt;] ; &lt;br&gt;~prefix_encoded &amp;amp; ~row_id&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;We begin by getting the record&#039;s position in the found set padded with zeroes. It&#039;s position in the found set is the same as it&#039;s required position in the value list. This is then mapped to our alphabetical representation. Finally this string is prepended to the internal record ID.&lt;/p&gt;
&lt;p&gt;As mentioned earlier, we summarise this value across all records for our final list. This value is then set into a field which serves as the basis of the sorting value list.&lt;/p&gt;
&lt;p&gt;It is important to note this step. In order for a value list to work it has to be indexed, meaning it cannot be based on an unstored field such as a global. We want this value list to be user-specific and so you need to think carefully about this.  The field you use has to be stored.  We prefer to put this field on a record that is unique to the user, such as their own user record in a user table. That way the value list can be based on the same field &lt;strong&gt;but from a different record&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Putting it all together&lt;/h2&gt;
&lt;p&gt;Well, it was a long journey but we got there in the end, let&#039;s now recap the overall technique knowing what we now know:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Create a field in the table to store the internal record id - &lt;strong&gt;rowid.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Sort a portal by the &lt;strong&gt;rowid&lt;/strong&gt;, choosing a custom order based on a value list, itself sorted by Unicode.&lt;/li&gt;
&lt;li&gt;The value list is set up based on a field we&#039;ll call &lt;strong&gt;ordered_values&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;ordered_values &lt;/strong&gt;are constructed from a found set of records that are sorted in the desired order.&lt;/li&gt;
&lt;li&gt;Each record calculates a special string to be used in the value list. This is a combination of an alphabetical string representing a number, and the &lt;strong&gt;rowid&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;To calculate the alphabetical string, take the position of the value in the list (it&#039;s record number), and map this number&#039;s digits to letters - being sure to pad with zeroes so that the length of the string is a constant length.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Clear as mud? Great! &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Some advantages and drawbacks to this approach&lt;/h2&gt;
&lt;p&gt;The technique itself seems solid. It can also be made to be more performant than others as each time the portal records are sorted, there is no need to do intensive unstored calculations or conversions of values from their default format into strings.&lt;/p&gt;
&lt;p&gt;Furthermore it avoids the unstored calculation issue concerning server-side sorting in FileMaker 19 as it is not based on a calculation. The sorting part is merely sorting a found set of records using a script, and so can easily be handed off to the server to carry out using &lt;strong&gt;Perform Script on Server&lt;/strong&gt;. This can make it very fast to sort large sets of records dynamically.&lt;/p&gt;
&lt;p&gt;Now for the disadvantages....&lt;/p&gt;
&lt;p&gt;When a portal is sorted by a given order, it remains sorted in that order because it&#039;s sort is based on a stored value list. In order for a portals sort to be refreshed, the value list itself must be refreshed meaning the sort script has to be re-run. The implications are that new records added into a portal are not going to be properly sorted until this is done.&lt;/p&gt;
&lt;p&gt;Sorting must also be triggered more often, such as when a layout loads or a portal is first displayed. It does add overhead in this respect.&lt;/p&gt;
&lt;p&gt;For this reason, the technique has specific cases where it is really useful. These are portals where the records do not change often. This is most portals. It works great for larger sets of records. For smaller sets I&#039;d be looking at the BOM technique as another viable approach.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;In conclusion&lt;/h2&gt;
&lt;p&gt;We hope this article has not only given you some food for thought in terms of alternative approaches to dynamic portal sorting, but that you also learned a thing or two about BOMs, value lists, sorting, indexing, and many more things along the way - this was always our intention!&lt;/p&gt;
&lt;p&gt;Dynamic portal sorting is a fascinating area because it is not something Claris has ever offered us as developers. How nice would it be if the Sort Records dialog could be dynamically programmed that would solve all our problems and remove all the need for this stupid hackery!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;Don&#039;t forget to check out the example file if you haven&#039;t already.  &lt;a href=&quot;https://www.teamdf.com/assets/blog-images/dynamic-portal-sort/DynamicPortalSorting.zip&quot; target=&quot;_blank&quot;&gt;Download it here&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;As always, please feel free to leave a comment, we appreciate all feedback.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 02 May 2023 09:17:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/server-compatible-dynamic-portal-sorting/</guid>
		</item>
		
		<item>
			<title>FileMaker 2023 Is Here!</title>
			<link>https://www.teamdf.com/blogs/filemaker-2023-is-here/</link>
			<description>&lt;p&gt;Yes, you read that right, Claris have released the next version of FileMaker and decided there will be no FileMaker 20 or 21 etc., and have headed straight to &quot;FileMaker 2023&quot;.&lt;/p&gt;
&lt;p&gt;Since the release of FileMaker 19 in 2020, Claris have made many very important improvements and released them in small doses as incremental “point” updates (19.4, 19.5 etc.)… So to help customers see that year-on-year the product moves forward quite substantially, they’ve decided to use this yearly based naming system. And it’s easy to see when you’re falling behind!&lt;/p&gt;
&lt;p&gt;Confused yet? Don’t worry because what excites us most at Digital Fusion is that Claris are continuing the evolution and releases of the FileMaker platform that we use and love. Doubling down on this, we also get a cool new logo:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/filemaker-2023/_resampled/ResizedImage49561-claris-filemaker-lockup-color.png&quot; alt=&quot;claris filemaker lockup color&quot; width=&quot;495&quot; height=&quot;61&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;h3&gt;So What’s New In FileMaker 2023?&lt;/h3&gt;
&lt;p&gt;For end users there’s not a great deal of visible difference, and that’s not a bad thing in some ways because it means you will continue to work like you always have, without any major changes to disrupt your business operation.&lt;/p&gt;
&lt;p&gt;Where it does get interesting, and in some cases relates to a better experience for you as an end user, is all the tweaks made in the “back end” of the platform. Here’re a few that’ve caught our eyes:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Performance and Stability&lt;/strong&gt;: One thing that can be said about Claris, they like to keep a stable platform, born from having been around for so long. At the same time they’ve also been steadily improving performance and this release builds on that with some more improvements in key bottleneck areas.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;500 Bugs&lt;/strong&gt;: Yes, Claris has “squashed” over 500 bugs since 19.0! That is an astounding number… we’ve encountered a few and are very glad to see them fixed, but who knew there were that many issues, even in an exceptionally well sorted platform like FileMaker.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;FileMaker WebDirect&lt;/strong&gt;: A section of the FileMaker suite that doesn’t always get the attention, but now it’s been given some major lovin’ in this update: it’s now faster, easier on the server resources, and you can have to 1000 users!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Linux Hosting&lt;/strong&gt;: A few years back Claris added Linux servers as one of the options to host your solution. The big gain with Linux Servers is that they are cheaper and leaner to run than Microsoft Windows-based servers. We’re gradually migrating many of our clients across but there are a few technical challenges when you’ve already been set up the Microsoft way.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security&lt;/strong&gt;: This is fundamental to any new release, and security is often number one on the list of things Claris FileMaker are working on. They have support for the newest security and authentication protocols shields your solutions from threats.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;That’s really just the tip of the iceberg — you can’t even see some of the most important changes like improvements to how FileMaker manages it’s caches. Rest assured Claris are working very hard to keep FileMaker the best of the low-code, high-productivity platforms available.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/filemaker-2023/_resampled/ResizedImage150150-claris-filemaker-icon-color.png&quot; alt=&quot;claris filemaker icon color&quot; width=&quot;150&quot; height=&quot;150&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;</description>
			<pubDate>Thu, 27 Apr 2023 13:30:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-2023-is-here/</guid>
		</item>
		
		<item>
			<title>Don&#039;t Get Duped When Duplicating Records</title>
			<link>https://www.teamdf.com/blogs/dont-get-duped-when-duplicating-records/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;On the surface, duplicating records in FileMaker is straightforward. We use the &lt;em&gt;&lt;strong&gt;Duplicate Record&lt;/strong&gt;&lt;/em&gt; script step to do this.&lt;/p&gt;
&lt;p&gt;However much like everything in FileMaker, what appears simple on the surface can become rather technical and complex. There&#039;s always more than one way to skin a cat, as they say.&lt;/p&gt;
&lt;p&gt;In this article we&#039;re going to explore some of the different approaches to duplicating multiple records and their relative performances.&lt;/p&gt;
&lt;p&gt;We should note at this stage that these approaches were purely born out of experimenting and playing with different approaches in an attempt to find an optimal solution with regards to performance. Some of the approaches are certainly not recommended but are still mentioned for comparison and out of interest. You may find you learn something along the way!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;You might learn something&quot; src=&quot;https://www.teamdf.com/assets/blog-images/duplicate/_resampled/ResizedImage9090-dupe-1.png&quot; alt=&quot;Learning&quot; width=&quot;90&quot; height=&quot;90&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Duplicating Parent and Child Records&lt;/h2&gt;
&lt;p&gt;Duplicating a single record is simple, but we will be duplicating many hundreds of records.  In addition, not only will these records be duplicated but they have related child records that also need to be duplicated. &lt;/p&gt;
&lt;p&gt;An important factor of parent/child duplication is the child must be reassigned to the new parent ID. This point becomes quite significant when deciding upon your approach to record duplication.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;A typical structure you may need to duplicate&quot; src=&quot;https://www.teamdf.com/assets/blog-images/duplicate/_resampled/ResizedImage600274-dupe-2.png&quot; alt=&quot;Duplicating&quot; width=&quot;600&quot; height=&quot;274&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File!&lt;/h2&gt;
&lt;p&gt;As with all our articles, a lot of time and effort goes into our example files to help explain techniques used and to allow you to explore and try for yourself.&lt;/p&gt;
&lt;p&gt;Please take time to download this as the article very closely follows the content of the example file — no email address required!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/duplicate/DuplicatingRecords.zip&quot; target=&quot;_blank&quot;&gt;Click Here to Download&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Trying some Different Approaches&lt;/h2&gt;
&lt;p&gt;The approaches taken to parent/child record duplication began with the first approach and subsequent approaches were born out of this by looking at ways to change it and potentially improve upon it by hunting out optimisations in the process.&lt;/p&gt;
&lt;p&gt;In the end we came up with 7 different approaches. We must warn you not all approaches are great. We left in the bad ones because you can still learn something from them, and hey — you may just come up with a better solution yourself — we always love feedback!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Apples and Oranges&quot; src=&quot;https://www.teamdf.com/assets/blog-images/duplicate/_resampled/ResizedImage9090-dupe-3.png&quot; alt=&quot;Duplicate&quot; width=&quot;90&quot; height=&quot;90&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Our Test Scenarios&lt;/h2&gt;
&lt;p&gt;We ran each duplication test a series of 5 times and took the average duration of each test to be our result. Taking the average means we can try to eliminate minor server performance fluctuations. Tests were performed on a Mac Mini M1 machine running FileMaker Server 19.6.3 with no connected users.&lt;/p&gt;
&lt;p&gt;The tests were run using &lt;em&gt;&lt;strong&gt;Perform Script on Server &lt;/strong&gt;&lt;/em&gt;and before each test we cleared out any previously duplicated test data.&lt;/p&gt;
&lt;p&gt;We ran ten variations per approach. We incremented the number of parent records being duplicated by 100, for a total of ten tests ranging from 100 to 1,000 parent records.&lt;/p&gt;
&lt;p&gt;Finally each parent record duplicated had about 6 child records residing in two different child tables for a total of 12 child records overall.  All child records were duplicated and assigned their new parent ID.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Approach 1: Loop From End&lt;/h2&gt;
&lt;p&gt;Our first approach is the simplest approach. It involves looping through parent records.  Looping is itself an entire subject worth delving into (&lt;a href=&quot;https://www.teamdf.com/blogs/thinking-outside-the-loop/&quot; target=&quot;_blank&quot;&gt;click here for an earlier article on this topic&lt;/a&gt;).&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Looping from End&quot; src=&quot;https://www.teamdf.com/assets/blog-images/duplicate/dupe-4.png&quot; alt=&quot;Duplicate&quot; width=&quot;414&quot; height=&quot;303&quot;&gt;&lt;/p&gt;
&lt;p&gt;The above is the loop method being used in this approach. Important is to note the following aspects:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Looping begins at the end of the found set.&lt;/li&gt;
&lt;li&gt;After we duplicate we omit both the new record (last record) and the parent record (one prior to that).&lt;/li&gt;
&lt;li&gt;We proceed to duplicate any child records&lt;/li&gt;
&lt;li&gt;The loop ends when we have no more records in the parent found set.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This approach is called looping from end because we start at the end of the found set, working backwards.&lt;/p&gt;
&lt;p&gt;For each parent record duplicated in this fashion we repeat the exact same procedure for any child records. &lt;/p&gt;
&lt;p&gt;Child records are found by first navigating to the child layout and performing a find for any child records that are related to the parent. If any records are found they are duplicated using looping from end.&lt;/p&gt;
&lt;h4&gt;Pros:&lt;/h4&gt;
&lt;p&gt;A benefit of this approach is that the script is very simple to follow and understand for other developers as well as easy to write. It is also easy to add in extra child tables for duplication if required in future.&lt;/p&gt;
&lt;h4&gt;Cons:&lt;/h4&gt;
&lt;p&gt;A downside to this approach is that the resulting duplicated records are in reverse creation order to that of the originals. When we loop from the end we are duplicating the newest record first and working back to the oldest.&lt;/p&gt;
&lt;p&gt;This may not seem like an issue but if you are duplicating records where you expect them to be present to the user in their original creation order, then this will not work unless you sort them. Sometimes you simply don&#039;t wish to sort records and so if that is the case this approach may not be for you.&lt;/p&gt;
&lt;p&gt;Another often overlooked issue with reverse looping is how FileMaker pre-fetches records from server. When you are looking at a layout that has at least one field on it, FileMaker will download from the server the next set of records in the found set. When on Form View this is the next 25 records. For List View it is the visible records plus 50 more, and the same rule applies for Table View.&lt;/p&gt;
&lt;p&gt;FileMaker does this to allow for smooth scrolling through records as it makes the assumption you will be doing just that. This only works forwards however, not backwards.&lt;/p&gt;
&lt;p&gt;Consider starting at the end of a found set. No pre-fetching occurs because there are no records ahead in the found set. Now when you navigate back 1 record FileMaker must query and download this from the server as it has not been pre-fetched. Repeating this backwards through a found set requires an individual query and download of each record to occur.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Approach 2: Loop From Start&lt;/h2&gt;
&lt;p&gt;To help combat the reverse creation order issue presented in the first approach as well as pre-fetching, a small change can be made to simply loop from the start of the found set rather than the end.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;Looping from Start&quot; src=&quot;https://www.teamdf.com/assets/blog-images/duplicate/dupe-5.png&quot; alt=&quot;Duplicate&quot; width=&quot;412&quot; height=&quot;327&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Pros:&lt;/h4&gt;
&lt;p&gt;That&#039;s it. The only real change from approach 1.  The benefit now is we do get our duplicates in the same creation order as the originals. We also utilise pre-fetching as FileMaker will give us at least the next 25 records in the found set pre-fetched to reduce the number of server queries for record data required.  This fact also means doing a loop from Start in list or table view is preferable as more records will be pre-fetched.&lt;/p&gt;
&lt;h4&gt;Cons:&lt;/h4&gt;
&lt;p&gt;Not necessarily a bad thing but it can be noted that we now require some extra record navigation to duplicate records. Duplicate records are added to the end of the found set, so after we omit the duplicate, we have to jump back to the first record to omit that. With Approach 1 this was not required. &lt;/p&gt;
&lt;p&gt;In the grand scheme of things this record navigation is probably going to have a negligible impact.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Reducing Overhead&lt;/h3&gt;
&lt;p&gt;The first two looping approaches are simple to follow and robust. However keen eyes might have spotted in the example file that there is quite a lot of finding occurring as well as layout switching.&lt;/p&gt;
&lt;p&gt;For each parent record we navigate to both child layouts and perform a find. We duplicate any found records before switching back to the parent layout and continuing.&lt;/p&gt;
&lt;p&gt;That&#039;s a lot of layout switching! If duplicating 100 parent records, this means upwards of 300 layout switches and 200 finds!&lt;/p&gt;
&lt;p&gt;With this in mind the next approaches aim to eliminate the need for these finds and switches as much as possible.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Approach 3: Go to Related Record - Per Record&lt;/h2&gt;
&lt;p&gt;Relationships can be created between parent &amp;amp; child and these relationships can be used to test whether any child records exist. By checking first we can eliminate the need to switch layout and search for child records.&lt;/p&gt;
&lt;p&gt;Furthermore, the relationship itself can act as a means to navigate to the child records for duplication rather than doing a find.&lt;/p&gt;
&lt;p&gt;This approach makes use of this fact by first testing child relationships for records and using the &lt;em&gt;&lt;strong&gt;Go to Related Record&lt;/strong&gt;&lt;/em&gt; script step to navigate to the child records for duplication.&lt;/p&gt;
&lt;p&gt;Duplication of a found set is still achieved through looping using Approach 2.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;Using Go to Related Record and Relationship Check&quot; src=&quot;https://www.teamdf.com/assets/blog-images/duplicate/_resampled/ResizedImage60077-dupe-6.png&quot; alt=&quot;Duplicate&quot; width=&quot;600&quot; height=&quot;77&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Pros:&lt;/h4&gt;
&lt;p&gt;The significant benefit is that we eliminate needless layout switching and finding by testing the relationship instead and using &lt;em&gt;&lt;strong&gt;Go to Related Record&lt;/strong&gt;&lt;/em&gt; for navigating to the child records.&lt;/p&gt;
&lt;h4&gt;Cons:&lt;/h4&gt;
&lt;p&gt;Whether this is a con or not is all in the eye of the beholder. This method does require you to establish a relationship from your parent context to your child tables.  If you&#039;ve somehow managed to build a FileMaker database without relationships (shame on you!) then you could see this as being a nuisance but realistically most solutions benefit from having parent/child relationships.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Go to Related Record…&lt;/h3&gt;
&lt;p&gt;At this point we were pretty happy with Approach 3. However there was still some potential here for improvement. So what in the approaches could still be optimised?&lt;/p&gt;
&lt;p&gt;We looked to the &lt;em&gt;&lt;strong&gt;Go to Related Record&lt;/strong&gt;&lt;/em&gt; script step. In the previous approach we used this step to duplicate child records &lt;em&gt;&lt;strong&gt;for each parent record&lt;/strong&gt;&lt;/em&gt;. If we were duplicating 1,000 parent records then at worst that means 1,000 &lt;em&gt;&lt;strong&gt;Go to Related Record&lt;/strong&gt;&lt;/em&gt; steps per child table.&lt;/p&gt;
&lt;p&gt;What if we could do the same thing but just with a single &lt;em&gt;&lt;strong&gt;Go to Related Record&lt;/strong&gt;&lt;/em&gt; step?&lt;/p&gt;
&lt;p&gt;Well the step does give us the ability to navigate to child records for all records in the found set - can we use this?&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Go to Related Record Found Set&quot; src=&quot;https://www.teamdf.com/assets/blog-images/duplicate/_resampled/ResizedImage600441-dupe-7.png&quot; alt=&quot;Duplicate&quot; width=&quot;600&quot; height=&quot;441&quot;&gt;&lt;/p&gt;
&lt;p&gt;The plan was as follows:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Loop and duplicate parents (but keep the original found set - do not omit records)&lt;/li&gt;
&lt;li&gt;Go to all related child records for all parent records in a single step&lt;/li&gt;
&lt;li&gt;Loop and duplicate all children.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Sounds great! There is however just one problem...&lt;/p&gt;
&lt;p&gt;Child records must be assigned the &lt;strong&gt;new &lt;/strong&gt;parent ID. When using Approach 1-3 this is simple because we&#039;re just storing the new parent ID into a variable, and setting it onto the children.&lt;/p&gt;
&lt;p&gt;However with this modifed approach we don&#039;t know what the new parent ID is for a given child record. In order to know this we have to create a mapping&lt;strong&gt; &lt;/strong&gt;between the original parent ID, and it&#039;s duplicate ID.&lt;/p&gt;
&lt;p&gt;If we can establish a mapping structure then when we duplicate children we can consult the mapping to derive the new parent ID by looking up the old one.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Approach 4: Go to Related Record Found Set - List&lt;/h2&gt;
&lt;p&gt;Approach 4 is the first mapping approach and uses lists to map original parent IDs to their new duplicate IDs. These lists are maintained in local variables.&lt;/p&gt;
&lt;p&gt;When it comes time to duplicate child records, we take the existing parent ID on the child record, and use it to look up it&#039;s position in the list of original parent IDs. This position can then be used to look up the corresponding parent ID from the new duplicate list.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Looping and building a Mapping&quot; src=&quot;https://www.teamdf.com/assets/blog-images/duplicate/_resampled/ResizedImage600388-dupe-8.png&quot; alt=&quot;Duplicate&quot; width=&quot;600&quot; height=&quot;388&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Pros:&lt;/h4&gt;
&lt;p&gt;A benefit of this is we only require a single &lt;em&gt;&lt;strong&gt;Go to Related Record &lt;/strong&gt;&lt;/em&gt;script step to find and duplicate children records rather than one per parent record.&lt;/p&gt;
&lt;p&gt;Creating the mapping is pretty simple and we are just using the &lt;em&gt;&lt;strong&gt;List&lt;/strong&gt;&lt;/em&gt; function to compile lists of old and duplicate IDs as we go.&lt;/p&gt;
&lt;h4&gt;Cons:&lt;/h4&gt;
&lt;p&gt;Having to maintain the mapping is itself a negative - the reasons why will become apparent later when we discuss results.&lt;/p&gt;
&lt;p&gt;The overhead required to generate the mapping and to retrieve the new parent ID from this mapping is quite expensive and at high record duplication numbers will just completely negate any performance gained by doing a single GTRR step.&lt;/p&gt;
&lt;p&gt;It&#039;s an elegant approach overall and one that does work well for low record duplication counts - but once you hit a certain point the cost outweighs the benefit.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Approach 5: Go to Related Record Found Set - JSON&lt;/h2&gt;
&lt;p&gt;Because of the list methods failed performance due to it&#039;s creation, management and retrieval of parent IDs, we looked to instead use JSON as our mapping mechanism.&lt;/p&gt;
&lt;p&gt;JSON is great at storing information and in this case we are going to use simple key/value pairs to be the mapping between old and new parent IDs.&lt;/p&gt;
&lt;p&gt;We simply add a mapping to the JSON using the following:&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;em&gt;&lt;strong&gt;JSONSetElement ( theJSON ; parentID ; duplicateID ; JSONSTRING )&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When needing to retrieve the duplicate ID we simply use:&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;em&gt;&lt;strong&gt;JSONGetElement ( thsJSON ; parentID ) &lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;Pros:&lt;/h4&gt;
&lt;p&gt;You could consider the use of JSON a more robust method of mapping parent/duplicate IDs but that&#039;s about it!&lt;/p&gt;
&lt;h4&gt;Cons:&lt;/h4&gt;
&lt;p&gt;JSON functions in FileMaker are terrible! Their performance at large sizes is just garbage. Again at low duplicate numbers it&#039;s acceptable but for anything over a couple hundred the performance of these functions just ruin any perfromance gain.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;We failed?&lt;/h3&gt;
&lt;p&gt;The mapping approaches in 4 and 5 in theory should be faster than layout switching all the time but the cost of having to establish a mapping between parent and duplicate IDs is just far too great. Until a better and much more efficient method of mapping can be found, these approaches only work well at low duplicate counts.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Fail&quot; src=&quot;https://www.teamdf.com/assets/blog-images/duplicate/_resampled/ResizedImage9090-dupe-9.png&quot; alt=&quot;Duplicate&quot; width=&quot;90&quot; height=&quot;90&quot;&gt;&lt;/p&gt;
&lt;p&gt;So what else is there to try?&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Approach 6: Export / Import&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;&lt;strong&gt;Import Records&lt;/strong&gt;&lt;/em&gt; script step is another way in which records can be created in a table. What if we exported all required records to disk and then imported them straight back in to the same table?&lt;/p&gt;
&lt;p&gt;This approach negates the need for any looping necessary for record creation.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Export / Import&quot; src=&quot;https://www.teamdf.com/assets/blog-images/duplicate/_resampled/ResizedImage600150-dupe-10.png&quot; alt=&quot;Duplicate&quot; width=&quot;600&quot; height=&quot;150&quot;&gt;&lt;/p&gt;
&lt;p&gt;We export a found set and import it back in as the new set of duplicates.&lt;/p&gt;
&lt;p&gt;However we do still suffer from the issue of having to establish a mapping and use this to assign new parent IDs to the child records. Once we establish a mapping then they can be assigned using the &quot;Replace Field Contents&quot; script step as opposed to a loop.&lt;/p&gt;
&lt;h3&gt;Pros:&lt;/h3&gt;
&lt;p&gt;There are no loops in this approach as the import is the process of creating duplicates.&lt;/p&gt;
&lt;h3&gt;Cons:&lt;/h3&gt;
&lt;p&gt;The Export Records script step is not very server friendly because it cannot be used to export a FileMaker file. Nor can you import from a FileMaker file on server.&lt;/p&gt;
&lt;p&gt;This means if the process is to be run on server then things like container fields could not be duplicated (unless you did something like base64 encode them as text for the export but that would negate performance).&lt;/p&gt;
&lt;p&gt;This technique is best suited for smaller text only record structures.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;An Idea about Improving Mapping....&lt;/h2&gt;
&lt;p&gt;The key issue with our approaches is the performance of mapping old/new IDs when it comes to using GTRR or Export/Import.&lt;/p&gt;
&lt;p&gt;Mapping performance seems to be slow at large duplication sizes for two reasons:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The cost of compiling the lists.&lt;/li&gt;
&lt;li&gt;The cost of retrieval of duplicate IDs from the list.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;In thinking about this we came up with a variation on Approach 4 which attempts to eliminate the need for using the List function at each step of duplication. Rather than add one item to the list during each iteration, we instead compile the list before and after duplication.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Approach 7: Go to Related Record Found Set - List ++&lt;/h2&gt;
&lt;p&gt;This final approach makes use of the &lt;strong&gt;&lt;em&gt;List Of&lt;/em&gt; &lt;/strong&gt;summary function type. &lt;/p&gt;
&lt;p&gt;To obtain the original list of parent IDs we just store the summary fields value into a variable.&lt;/p&gt;
&lt;p&gt;Next, we need to duplicate the parent records such that at the end of this process we are on a found set just of the new duplicate records.&lt;/p&gt;
&lt;p&gt;This is fairly easily done by a small tweak to the looping process.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;Optimised&quot; src=&quot;https://www.teamdf.com/assets/blog-images/duplicate/_resampled/ResizedImage600291-dupe-11.png&quot; alt=&quot;Duplicate&quot; width=&quot;600&quot; height=&quot;291&quot;&gt;&lt;/p&gt;
&lt;p&gt;We do this in a new window to preserve our original found set for later.  Next we store the very first duplicates ID into a variable - this will act as our stopping point in the loop.&lt;/p&gt;
&lt;p&gt;As we duplicate we omit the parent only from the start of the found set, and we stop once we reach that very first duplicate record created.&lt;/p&gt;
&lt;p&gt;Now we&#039;re on a found set of duplicates and we can again use the summary field to return the list of duplicate IDs.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;We do gain a little performance here using this method over the List function.&lt;/p&gt;
&lt;h4&gt;Cons: &lt;/h4&gt;
&lt;p&gt;Still at high record counts it&#039;s not great, most likely due to method of ID retrieval from the mapping.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;We had to stop somewhere!&lt;/h2&gt;
&lt;p&gt;This article took so long to write because at every point in the process we kept finding new ways to optimise and tweak approaches. Tests had to be rewritten and re-run and so the whole thing would just keep going forever without drawing a line in the sand.&lt;/p&gt;
&lt;p&gt;We invite any readers to attempt this approach and let us know in the comments how you go and how your performance compares to the other methods. &lt;/p&gt;
&lt;p&gt;Some other ideas explored include:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Sorting found sets by parent ID before duplication. This way we know the order of mapping, and if we sort child records by the parent ID, we can be sure their order matches the mapping. The means of retrieval of the duplicate ID from the mapping can then be changed to look up a value based on tracking a position in the list as you loop rather than always looking up from the list (where the ID could be in any random position).&lt;/li&gt;
&lt;li&gt;Combinations of techniques - can you use export/import for child duplication, and looping for parent generation?&lt;/li&gt;
&lt;li&gt;Does Replace Field Contents work better for assigning new parent IDs to child records?&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Also if you have any other ideas around optimisations we&#039;d love to hear them. &lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Overall Results&lt;/h2&gt;
&lt;p&gt;So with all that said and done here are our final results for performance of tests (times are in milliseconds)&lt;/p&gt;
&lt;table style=&quot;width: 658px; height: 202px; border: 2px solid #7c7a85;&quot; cellpadding=&quot;0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Test 1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Test 2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Test 3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Test 4&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Test 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Test 6&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Test 7&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;100&lt;/strong&gt; &lt;/td&gt;
&lt;td&gt; 711&lt;/td&gt;
&lt;td&gt; 676&lt;/td&gt;
&lt;td&gt; 645&lt;/td&gt;
&lt;td&gt; 473&lt;/td&gt;
&lt;td&gt; 482&lt;/td&gt;
&lt;td&gt; 326&lt;/td&gt;
&lt;td&gt; 468&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;200&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt; 1423&lt;/td&gt;
&lt;td&gt; 1356&lt;/td&gt;
&lt;td&gt; 1260&lt;/td&gt;
&lt;td&gt; 1022&lt;/td&gt;
&lt;td&gt; 1058&lt;/td&gt;
&lt;td&gt; 671&lt;/td&gt;
&lt;td&gt; 966&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;300&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt; 2147&lt;/td&gt;
&lt;td&gt; 2080&lt;/td&gt;
&lt;td&gt; 1871&lt;/td&gt;
&lt;td&gt;1640 &lt;/td&gt;
&lt;td&gt; 1751&lt;/td&gt;
&lt;td&gt;1098 &lt;/td&gt;
&lt;td&gt; 1513&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;400&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt; 2756&lt;/td&gt;
&lt;td&gt; 2667&lt;/td&gt;
&lt;td&gt; 2495&lt;/td&gt;
&lt;td&gt; 2320&lt;/td&gt;
&lt;td&gt; 2537&lt;/td&gt;
&lt;td&gt; 1544&lt;/td&gt;
&lt;td&gt; 2154&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;500&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt; 3619&lt;/td&gt;
&lt;td&gt; 3431&lt;/td&gt;
&lt;td&gt; 3125&lt;/td&gt;
&lt;td&gt; 3115&lt;/td&gt;
&lt;td&gt; 4167&lt;/td&gt;
&lt;td&gt; 2046&lt;/td&gt;
&lt;td&gt; 2814&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;600&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt; 4121&lt;/td&gt;
&lt;td&gt; 4211&lt;/td&gt;
&lt;td&gt; 3740&lt;/td&gt;
&lt;td&gt; 4179&lt;/td&gt;
&lt;td&gt; 5536&lt;/td&gt;
&lt;td&gt; 2630&lt;/td&gt;
&lt;td&gt; 3518&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;700&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt; 4901&lt;/td&gt;
&lt;td&gt; 4883&lt;/td&gt;
&lt;td&gt; 4360&lt;/td&gt;
&lt;td&gt; 5298&lt;/td&gt;
&lt;td&gt; 6851&lt;/td&gt;
&lt;td&gt; 3293&lt;/td&gt;
&lt;td&gt; 4441&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;800&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt; 5559&lt;/td&gt;
&lt;td&gt; 5314&lt;/td&gt;
&lt;td&gt; 4981&lt;/td&gt;
&lt;td&gt; 6501&lt;/td&gt;
&lt;td&gt; 8242&lt;/td&gt;
&lt;td&gt; 4023&lt;/td&gt;
&lt;td&gt; 5482&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;900&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt; 6181&lt;/td&gt;
&lt;td&gt; 6100&lt;/td&gt;
&lt;td&gt; 5581&lt;/td&gt;
&lt;td&gt; 7792&lt;/td&gt;
&lt;td&gt; 9771&lt;/td&gt;
&lt;td&gt; 4737&lt;/td&gt;
&lt;td&gt; 6579&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;1000&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt; 7120&lt;/td&gt;
&lt;td&gt; 6728&lt;/td&gt;
&lt;td&gt; 6299&lt;/td&gt;
&lt;td&gt; 9204&lt;/td&gt;
&lt;td&gt; 11351&lt;/td&gt;
&lt;td&gt; 5531&lt;/td&gt;
&lt;td&gt; 7448&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/duplicate/_resampled/ResizedImage1782962-dupe-chart1.png&quot; alt=&quot;dupe chart1&quot; width=&quot;1782&quot; height=&quot;962&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/duplicate/_resampled/ResizedImage19951097-dupe-chart2.png&quot; alt=&quot;dupe chart2&quot; width=&quot;1995&quot; height=&quot;1097&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;What Did We Learn?&lt;/h2&gt;
&lt;p&gt;What we learnt could be summarised as follows&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Looping is simplest and easiest for developers to write and understand and works well at low duplicate counts.&lt;/li&gt;
&lt;li&gt;GTRR and mappings is even better for lower record counts, but can suffer at higher duplicate counts.&lt;/li&gt;
&lt;li&gt;Export/Import works great and is fast so long as your conditions for using it are correct.&lt;/li&gt;
&lt;li&gt;The methods can &lt;strong&gt;always &lt;/strong&gt;be optimised further.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;   &lt;/p&gt;
&lt;h2&gt;In Conclusion&lt;/h2&gt;
&lt;p&gt;Realistically speaking the need for massive amounts of record duplication is low and infrequent. The intention of this article is more to give you an understanding of how different approaches can be employed to solve a single seemingly simple situation. Every step used can be considered and may have an impact on performance. Not all techniques are linear - some start off good but get progressively worse compared to others as record sizes increase. Never assume a technique is going to scale linearly.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;A final word – please check out our example file :)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/duplicate/DuplicatingRecords.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file if you haven&#039;t already.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 28 Mar 2023 06:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/dont-get-duped-when-duplicating-records/</guid>
		</item>
		
		<item>
			<title>It&#039;s Time To Get Together…</title>
			<link>https://www.teamdf.com/blogs/engage-sydney-2023-its-time-to-reconnect/</link>
			<description>&lt;p&gt;It&#039;s been three long years since the Claris community got together in the APAC region to share ideas, inspire each other, and network.&lt;/p&gt;
&lt;p&gt;We&#039;re rapt to announce that in 2023 we are getting back to the old ways, and have joined forces with a few of the other developers from the region to organise the first Claris/FileMaker themed conference in the region since 2019!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://reconnect.sydney&quot;&gt;Reconnect.Sydney&lt;/a&gt; will run over Thursday the 20th and Friday the 21st of July — lock in the dates! In fact if you&#039;d like to join us we highly recommend getting tickets asap.&lt;/p&gt;
&lt;p&gt;As much as it says Sydney in it&#039;s name, this is a conference for the whole Asia Pacific region... in fact it&#039;s for the whole world as we would love to welcome all to come and share in this great occasion.&lt;/p&gt;
&lt;p&gt;Details of the schedule are yet to be worked out but we&#039;re working on:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Two days of expert presentations&lt;/li&gt;
&lt;li&gt;Speakers from Claris&lt;/li&gt;
&lt;li&gt;Social events&lt;/li&gt;
&lt;li&gt;Plenty of networking time&lt;/li&gt;
&lt;li&gt;An event for Claris Partners&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Tickets are now available to purchase so head over to the &lt;a href=&quot;http://reconnect.sydney&quot;&gt;Reconnect.Sydney website&lt;/a&gt; and check it out.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/engage.sydney-announcement/cath-presenting-660.jpg&quot; alt=&quot;cath presenting 660&quot; width=&quot;660&quot; height=&quot;396&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Tue, 28 Mar 2023 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/engage-sydney-2023-its-time-to-reconnect/</guid>
		</item>
		
		<item>
			<title>My Crazy Trailwalk For Charity</title>
			<link>https://www.teamdf.com/blogs/kriss-crazy-trailwalk-for-charity/</link>
			<description>&lt;p&gt;So, sometime around July of last year, I heard from a friend of mine who lives up in Auckland... he sent me a link to a trail-walk taking place the following year and enquired if I&#039;d be keen…&lt;/p&gt;
&lt;h2&gt;100km in less than 36 hours&lt;/h2&gt;
&lt;p&gt;The venue: Taranaki, on the west coast of the North Island of New Zealand.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/kris-crazy-trailwalk/_resampled/ResizedImage500638-map.jpg&quot; alt=&quot;Trailwalk Map&quot; width=&quot;500&quot; height=&quot;638&quot;&gt;&lt;/p&gt;
&lt;p&gt;Clearly an &lt;em&gt;insane&lt;/em&gt; distance, but as I&#039;d been doing a lot of hiking at that time (albeit nothing even approaching an echo of that distance) it seemed like a relatively accessible challenge.&lt;/p&gt;
&lt;p&gt;There was another aspect to it, we were required to raise an amount in donations for Oxfam to take part...this was my main concern, but I was swiftly told &quot;she&#039;d be right&quot;. Problem solved then ;)&lt;/p&gt;
&lt;h2&gt;A Team Sport&lt;/h2&gt;
&lt;p&gt;I was in. The next thing was we needed a team of 4. And there were only 2 of us.&lt;/p&gt;
&lt;p&gt;I have a friend down Southland (where I&#039;m from) that I figured would be a 50/50 shot. I put it to him, he was interested but told me he needed to sleep on it, then I heard from him hilariously early the next morning telling me he was in.&lt;/p&gt;
&lt;p&gt;So that made three, we still needed a fourth. Thankfully, my friend from the South conscripted his brother who I knew to be a good sort. We had our team.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/kris-crazy-trailwalk/_resampled/ResizedImage660465-kris-and-co-at-hump-ridge.jpg&quot; alt=&quot;kris and co at hump ridge&quot; width=&quot;660&quot; height=&quot;465&quot;&gt;&lt;/p&gt;
&lt;p&gt;And now July of 2022 has moved on into March 2023, the event itself is less than a week away. I&#039;ve booked my leave from work, my flights, accommodation. No backing out now.&lt;/p&gt;
&lt;h2&gt;Our Fundraising Target&lt;/h2&gt;
&lt;p&gt;The training has been intense, though as I feared, we still haven&#039;t made our donation target. So please, if you&#039;re reading this, and you&#039;re inclined to give to a good cause every now and then – consider Oxfam. You could do a lot worse. Their mission is alleviating poverty across the globe. This can take several forms:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Emergency and climate change relief&lt;/li&gt;
&lt;li&gt;Developing relationships with communities to empower them in escaping poverty&lt;/li&gt;
&lt;li&gt;Fighting discrimination, and working with governments in exposing and changing unjust laws&lt;/li&gt;
&lt;/ul&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;To help me out here, head on over to my &lt;a href=&quot;https://www.oxfamtrailwalker.org.nz/kris-weyling&quot; target=&quot;_blank&quot;&gt;donation page,&lt;/a&gt; thanks!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Having said this, we would like to express unending gratitude for those who have already donated, you know who you are, and you&#039;re amazing!&lt;/p&gt;
&lt;h2&gt;&#039;naki, Here We Come!&lt;/h2&gt;
&lt;p&gt;I&#039;ve got no idea how the weekend itself will go, I had a training plan worked out but that got shunted aside due a bunch of things... covid, Christmas, complacency. That said, could you ever feel prepared for something this absurd?&lt;/p&gt;
&lt;p&gt;We&#039;ll make it to the start line, and we&#039;ll see it through to the finish line if our bodies are able.&lt;/p&gt;
&lt;p&gt;That&#039;s all for now. I&#039;ll check back in after the race and let you know how we got on. And I promise I&#039;ll take a whole heap of photos!&lt;/p&gt;
&lt;div class=&quot;captionImage leftAlone&quot; style=&quot;width: 660px;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/kris-crazy-trailwalk/_resampled/ResizedImage660350-bridge.jpg&quot; alt=&quot;bridge&quot; width=&quot;660&quot; height=&quot;350&quot;&gt;&lt;/div&gt;</description>
			<pubDate>Tue, 07 Mar 2023 16:08:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/kriss-crazy-trailwalk-for-charity/</guid>
		</item>
		
		<item>
			<title>Claris Update - January 2023</title>
			<link>https://www.teamdf.com/blogs/claris-update-january-2023/</link>
			<description>&lt;div&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m&quot;&gt;Last week, Claris hosted a webinar to share what&#039;s been happening with the Claris Platform and Claris Studio, and also to tell us what is ahead in terms of the development plans.&lt;br&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m&quot;&gt;Studio is coming on in leaps and bounds, with very frequent updates, some of which are very exciting. The puzzle is coming together, and more rapidly than we have ever seen another product come from Claris/FileMaker.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m&quot;&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m&quot;&gt;We already have the ability to create anonymous web form collection, the ability to chart this data, and something very exciting, the ability to create Kanban views of the data.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/claris-update-jan-2023/_resampled/ResizedImage660566-kanban-example.jpg&quot; alt=&quot;kanban example&quot; width=&quot;660&quot; height=&quot;566&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m&quot;&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m&quot;&gt;Along with this, they are releasing new versions of FileMaker Pro and Claris Pro &lt;/span&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m h-lparen&quot;&gt;(along&lt;/span&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m&quot;&gt; with the other products in the suites) at a rapid pace. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m&quot;&gt;One of the key changes coming soon is that the Claris platform will be able to be hosted in data centres other than the current US based servers, which has been a damper on performance from this part of the world.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m&quot;&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m&quot;&gt;2023 is shaping up to be a big year for Claris and we know the team at Digital Fusion are eagerly awaiting whats ahead.&lt;br&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m&quot;&gt;For more info on Claris Studio go to &lt;a href=&quot;https://www.claris.com/studio/&quot;&gt;https://www.claris.com/studio/&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m&quot;&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m&quot;&gt;If you are interested in finding out more and watching the webinar, check it out below...&lt;br&gt;&lt;br&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;div class=&quot;media leftAlone&quot;&gt;&lt;iframe width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://www.youtube.com/embed/avKJSEJbrOA?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; title=&quot;Claris Update Webinar - Jan 25&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/div&gt;</description>
			<pubDate>Fri, 03 Feb 2023 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/claris-update-january-2023/</guid>
		</item>
		
		<item>
			<title>Navigation that Responds on Mouse-Over</title>
			<link>https://www.teamdf.com/blogs/navigate-the-df-way-responsive-navigation-on-mouse-over/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this article, we&#039;re talking about building Navigational Controls which respond to the users Mouse when they are hovered over. We will call this a responsive navigation for the benefit of the article.&lt;/p&gt;
&lt;p&gt;Currently, buttons and controls can be responsive to the user in a variety of ways such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Transitional Effects (switching layouts on iOS)&lt;/li&gt;
&lt;li&gt;Animation (popovers and Panels)&lt;/li&gt;
&lt;li&gt;State Changes of objects (onHover, onPress, onClick etc._&lt;/li&gt;
&lt;li&gt;Formatting of an object (conditional formatting, hide conditions)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This article is going to focus on a different type of interaction a user can have with a button that will happen on the Hover state of an object. Typically a user will interact with a button or control by clicking on it. There is however a pretty simple way to turn almost any object on a layout into an object that will immediately respond to the users mouse when hovered over.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/responsive-navigation-mouseover/responsive-navigation-mouseover-1.gif&quot; alt=&quot;responsive navigation mouseover 1&quot; width=&quot;600&quot; height=&quot;338&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File Time&lt;/h2&gt;
&lt;p&gt;This is a very example-heavy article and as such we recommend downloading and looking through our example file which contains all the examples featured below.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/responsive-navigation-mouseover/responsive-navigation-mouseover.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Not Our First Time Around This Block!&lt;/h2&gt;
&lt;p&gt;This technique can be utilised in a number of ways and this is not the first time we have covered it on the Weetbicks blog.&lt;/p&gt;
&lt;p&gt;In 2014 we wrote two articles that utilised the &lt;em&gt;mouse-over&lt;/em&gt; technique.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/blogs/a-sliding-drawer-that-opens-and-closes-on-mouse-over/&quot; target=&quot;_blank&quot;&gt;The first article&lt;/a&gt; showed how you could utilise this to produce a sliding-drawer control that could automatically open and close just by the user hovering over it.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/responsive-navigation-mouseover/_resampled/ResizedImage600191-responsive-navigation-mouseover-2.png&quot; alt=&quot;A pop-over on Mouse-Over&quot; width=&quot;600&quot; height=&quot;191&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/blogs/popovers-that-open-and-close-on-mouse-over&quot; target=&quot;_blank&quot;&gt;While the second article&lt;/a&gt; dealt with opening and closing pop-over menus by hovering the mouse over a pop-over button.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/responsive-navigation-mouseover/_resampled/ResizedImage361384-responsive-navigation-mouseover-3.png&quot; alt=&quot;A sliding drawer on Mouse-Over&quot; width=&quot;361&quot; height=&quot;384&quot;&gt;&lt;/p&gt;
&lt;p&gt;This time we&#039;re presenting three further examples of how it can be utilised in a navigational sense. Note this is not just some fancy trick. This is something we use in our client solutions to great effect. It does however have to be used carefully and only in circumstances that warrant it.  Not all navigation controls benefit from having a mouse-over triggering them.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Making A Mouse-Over Trigger Possible&lt;/h2&gt;
&lt;p&gt;As a quick refresher on the technique covered in the two earlier articles, let&#039;s look at how we actually initiate a Mouse-Over event. &lt;/p&gt;
&lt;p&gt;To achieve this we require a plugin that is capable of running a script. Our plugin of choice is always &lt;a href=&quot;https://docs.baseelementsplugin.com/article/522-downloads&quot; target=&quot;_blank&quot;&gt;BaseElements&lt;/a&gt; from &lt;a href=&quot;http://www.goya.com.au&quot; target=&quot;_blank&quot;&gt;Goya&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We simply attach a tooltip to any object we wish to initiate a script.&lt;/p&gt;
&lt;p&gt;Tooltip calculations evaluate immediately when the mouse is placed over them, even if they do not immediately appear. This is good because our script is run immediately giving very responsive feedback to the users input. Here is an example showing how frequently a tooltip is evaluated. We are running a script that is incrementing a counter:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/responsive-navigation-mouseover/responsive-navigation-mouseover-4.gif&quot; alt=&quot;responsive navigation mouseover 4&quot; width=&quot;600&quot; height=&quot;117&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;We have written a custom function to accept the script name &lt;em&gt;&lt;strong&gt;_scriptName&lt;/strong&gt;&lt;/em&gt; and optional parameter &lt;em&gt;&lt;strong&gt;_parameter&lt;/strong&gt;&lt;/em&gt; for the script. It looks like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If ( not IsEmpty ( Get ( ScriptName ) ) ; &quot;&quot; ; Let ( ~run = BE_ScriptExecute ( _scriptName ; Get ( FileName ) ; _parameter ) ; &quot;&quot; ) )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You might be wondering what the first condition of the IF statement is for. Our tooltip calculation is checking whether a script is already running by looking to see if Get(ScriptName) is returning a script.&lt;/p&gt;
&lt;p&gt;This is because tooltips can also respond to the user while a script is running. Every time the user moves their mouse over an object, a new call to the script would otherwise be called, thus creating a stack of hundreds or thousands of scripts to run.&lt;/p&gt;
&lt;p&gt;To avoid this, our tooltip calculation will only ever run a script if no other script is running, thus avoiding this issue.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;An example of Portal Navigation&lt;/h2&gt;
&lt;p&gt;So that&#039;s the basic technique, there really isn&#039;t much to it. Let&#039;s look at a few examples, all of which you&#039;ll find in the example files.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/responsive-navigation-mouseover/responsive-navigation-mouseover-5.gif&quot; alt=&quot;responsive navigation mouseover 5&quot; width=&quot;600&quot; height=&quot;419&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is our example files main navigation. As the mouse moves over it, a script is initiated from within the portal to carry out navigation. This is the same control featured in our &lt;a href=&quot;https://www.teamdf.com/blogs/navigate-the-df-way-layout-sections/&quot; target=&quot;_blank&quot;&gt;first navigation article about layout-level navigation&lt;/a&gt;. All we had to do was add a tooltip to the existing button.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;An Example Of Button Bar Navigation&lt;/h2&gt;
&lt;p&gt;Here is an example of a button bar used to control navigation within a layout. Much like the portal example, we are using a hidden sliding panel as our sections of the layout, and the button segments control which panel is visible.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/responsive-navigation-mouseover/responsive-navigation-mouseover-6.gif&quot; alt=&quot;responsive navigation mouseover 6&quot; width=&quot;600&quot; height=&quot;215&quot;&gt;&lt;/p&gt;
&lt;p&gt;In addition to this, we also have two pop-over-based segments which themselves are opened via a tooltip. &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;How Do We Avoid Accidental Mouse-Over triggers?&lt;/h2&gt;
&lt;p&gt;The button bar above is a particularly nice use of this technique because the user tends to move their mouse horizontal across the button bars, and then when they have made a selection their next mouse movement is in a downward direction to either the pop-over or to the panel content.&lt;/p&gt;
&lt;p&gt;This horizontal/vertical mouse movement lowers the risk of any potential &quot;accidents&quot; that may arise due to the user inadvertently putting their mouse over a navigation element they didn&#039;t wish to select. &lt;/p&gt;
&lt;p&gt;This is a classic issue with this technique. We wish to try to eliminate accidental Mouse-Overs. In reality, this is quite hard to do, which is why using it with caution is advised, not all navigation benefits.&lt;/p&gt;
&lt;p&gt;There are a few useful tips to adhere to.&lt;/p&gt;
&lt;p&gt;Firstly, the larger the button area selectable the better, e.g. taller portal rows, and larger buttons. This gives more affordance when the user moves their mouse away from the object so that they will not touch another object.&lt;/p&gt;
&lt;p&gt;Next, consider adding a &quot;dead-zone&quot; to the navigation, particularly if using a portal. In our example above we actually make the button not quite the full width of the portal, but rather have it cover the text instead. This is usually effective because users tend to Mouse-Over text (whether they realise it or not) and second when a user leaves the portal for the panel to the right, they may head off diagonally up or down. By creating this dead-zone patch we can ensure they leave safely. Here is a dead-zone in yellow:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/responsive-navigation-mouseover/_resampled/ResizedImage307267-responsive-navigation-mouseover-8.png&quot; alt=&quot;Dead Zone&quot; width=&quot;307&quot; height=&quot;267&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;A Final Example Of Multi-record Selection In Portals&lt;/h2&gt;
&lt;p&gt;This last example is not strictly navigation but rather has to do with selecting entries in a portal. Here we have a 3-tier portal structure where the user is to select from all 3 portals. The portals may contain fixed values, or they may be conditional in that the values in the second portal change depending on the first, and the values in the third change depending on the second.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/responsive-navigation-mouseover/responsive-navigation-mouseover-7.gif&quot; alt=&quot;responsive navigation mouseover 7&quot; width=&quot;600&quot; height=&quot;241&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here the mouse movement is up/down, followed by a move to the right for the next portal. Again we run the risk of the user moving diagonally up/down from their selection and so a dead-zone could be used.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;In Conclusion&lt;/h2&gt;
&lt;p&gt;So we&#039;ve shown a few different use cases of mouse-over for navigation. As mentioned this is to be used with care – there are many situations where standard navigation involving a mouse click is preferable. However, this does have its own use-cases and you may find a good use for it. In our experience, we found the best application is menus that contain a lot of sub-item menus, be it via a panel or pop-over. The users end goal is to get to the sub-level navigation and so not having to click before they get there can often be a nice experience.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;A lot of time and care goes into our example files and we appreciate you taking the time to explore and learn.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/responsive-navigation-mouseover/responsive-navigation-mouseover.zip&quot; target=&quot;_blank&quot;&gt;You can download the example file here. &lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Fri, 04 Nov 2022 10:32:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/navigate-the-df-way-responsive-navigation-on-mouse-over/</guid>
		</item>
		
		<item>
			<title>Welcome Maddy and Andy</title>
			<link>https://www.teamdf.com/blogs/welcome-maddy-and-andy/</link>
			<description>&lt;p&gt;It seems like just yesterday that we posted that we had added to our team, and here we are again, adding to our team: this time we get to welcome two new comers, Madeleine Voice and Andrew Mills.&lt;/p&gt;
&lt;p&gt;It’s worth noting that we felt we had maxed out in our &quot;Paul&quot; brigade, now totalling three, so have moved onto the name of Andrew, hence new-Andrew is being referred to as &lt;em&gt;Andy&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Anyhow, onto welcoming Maddy and Andy to the team...&lt;/p&gt;
&lt;h2&gt;Maddy Voice&lt;/h2&gt;
&lt;p&gt;Maddy is like a lot of DF’ers, having had a previous life in a totally different career before seeing the light to become a FileMaker developer. &lt;/p&gt;
&lt;p&gt;She has Bachelor of Plant Science degree from Lincoln University here in Canterbury, and pursued a career as a &lt;a title=&quot;Everything you ever wanted to know about Triticale...&quot; href=&quot;https://link.springer.com/chapter/10.1007/978-3-030-23108-8_11&quot; target=&quot;_blank&quot;&gt;triticale breeder&lt;/a&gt;: for those who don’t know what that is (and in all honesty, that’s 99% of us), we’ve provided a very helpful link that explains.&lt;/p&gt;
&lt;p&gt;While working in the seed breeding industry Maddy could see first hand the need for solutions that would give her a smarter way of working. There had to be a better way to work with data than pen, paper, and Excel…&lt;/p&gt;
&lt;p&gt;We love it when people come to software development knowing what the “need” is because there is real understanding and purpose behind their motivation.&lt;/p&gt;
&lt;p&gt;Keeping Maddy busy outside of work, is her two year old daughter, Juniper. The backstory to Juniper&#039;s name is that there’re four generations of women all named after botanicals, i.e. Ivy, Hazel, Rose, Daisy, and Daphne.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Maddy and daughter, Juniper&quot; src=&quot;https://www.teamdf.com/assets/blog-images/welcome-maddy-and-andy/maddy-juni.jpg&quot; alt=&quot;Maddy and daughter, Juniper&quot; width=&quot;480&quot; height=&quot;485&quot;&gt;&lt;/p&gt;
&lt;p&gt;Also on the hit list of interests are yoga, maintaining her extensive house plant collection, and snowboarding.&lt;/p&gt;
&lt;p&gt;The real claim to fame that only came out in passing conversation is that Maddy once competed in Muay Thai, including four official fights, plus a broken foot. She’s one person you don’t want to mess with.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Maddy snowboarding&quot; src=&quot;https://www.teamdf.com/assets/blog-images/welcome-maddy-and-andy/_resampled/ResizedImage639426-maddy-snowboard.jpg&quot; alt=&quot;Maddy snowboarding&quot; width=&quot;639&quot; height=&quot;426&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Andy Mills&lt;/h2&gt;
&lt;p&gt;Like Maddy, Andy comes to us with an interesting career path, having spent 8 years in geotechnical instrumentation. Once again that takes some explaining, but after a quick search of what it actually means, we/you will be even more lost (inclinometers, piezometers, tilt meters, beam sensors etc etc). Let’s just say that Andy has a friend in Paul Hutton, who joined us with a previous career in geology (and now 20+ years as a FileMaker developer).&lt;/p&gt;
&lt;p&gt;Andy made the switch to IT a few years ago because, in his own words, he &quot;loves technology and achieving results that would otherwise be unobtainable.&quot; We like that too!&lt;/p&gt;
&lt;p&gt;In his spare time Andy gets up to all sorts of mischief, but one of his passions in life is his role as a volunteer firefighter. He’s currently based at the New Brighton Volunteer Fire Brigade here in Christchurch.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Andy firefighting&quot; src=&quot;https://www.teamdf.com/assets/blog-images/welcome-maddy-and-andy/andy-fire.jpg&quot; alt=&quot;Andy firefighting&quot; width=&quot;660&quot; height=&quot;454&quot;&gt;&lt;/p&gt;
&lt;p&gt;Andy is also somewhat of a water baby, in what seems like every water pursuit. This has lead to his claim to fame, that being once chased by a humpback whale. We are pleased he survived, and gets to join the team.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Andy and his dog out for a surf&quot; src=&quot;https://www.teamdf.com/assets/blog-images/welcome-maddy-and-andy/_resampled/ResizedImage660501-andy-surfboard.jpg&quot; alt=&quot;Andy and his dog out for a surf&quot; width=&quot;660&quot; height=&quot;501&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 02 Nov 2022 12:39:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/welcome-maddy-and-andy/</guid>
		</item>
		
		<item>
			<title>Avoiding Multi Window Record Locking</title>
			<link>https://www.teamdf.com/blogs/avoiding-multi-window-record-locking/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;The dreaded lock dialog&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multi-window-record-locking/_resampled/ResizedImage300274-multi-window-record-locking-1.png&quot; alt=&quot;multi window record locking 1&quot; width=&quot;300&quot; height=&quot;274&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is what we are trying to get rid of. That situation where you lock yourself out of a record because you already have it open in another window. We&#039;ve all seen it, and it can be highly frustrating.&lt;/p&gt;
&lt;p&gt;The issue is more prevalent in solutions that employ session/interface-based approaches, where the user may be editing records through a particular record that defines their session. Unless managed then spawning new windows can result in the user ending up on the same record.&lt;/p&gt;
&lt;p&gt;There is no great reason why a user should ever see this dialog - a user can only ever interact with one window at a time. It makes little sense to leave a window in an uncommitted state while they move to another window - well at least in my experience!&lt;/p&gt;
&lt;p&gt;So come with us on a journey to find a solution to this timeless problem, you may learn a thing or two along the way.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;This article is based on our example file which also includes examples of the solution you can try out, along with additional information. We highly recommend downloading and checking it out while you read. We spend a lot of time on these!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/multi-window-record-locking/avoid-multi-window-record-locking.zip&quot; target=&quot;_blank&quot;&gt;Download the example file here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Time For a History Lesson&lt;/h2&gt;
&lt;p&gt;Let&#039;s go back now. The year is 2010. The Web Viewer has been out now for a couple of years since version 8.5. It&#039;s slowly gaining traction as a tool for not just displaying google or FedEx websites, but as a way to enrich solutions with Javascript integration, helped largely in part by &lt;a href=&quot;http://www.reactorized.com&quot; target=&quot;_blank&quot;&gt;Digital Fusions Reactor plugin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Back then the Web Viewer behaved slightly differently than it does today. It had a particular quirk in how it evaluated its URL calculation. The calculation would evaluate not only when the web viewer was in focus, but also when not in focus, and even more importantly even when the window which the web viewer was in was not the active window.&lt;/p&gt;
&lt;p&gt;A young Weetbicks saw this as an opportunity to exploit and exploit he did. If a Web Viewer was evaluating a calculation when the active window changed, we could use it to write a calculation that determined if a window had just lost its focus, and if so run a script using a plugin (Reactor at the time) to commit the window.&lt;/p&gt;
&lt;p&gt;This was the code:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Let ( [&lt;/p&gt;
&lt;p&gt;~windows = WindowNames ( Get ( FileName ) ) ;&lt;/p&gt;
&lt;p&gt;~active = GetValue ( ~windows ; 1 ) ;&lt;/p&gt;
&lt;p&gt;~this = Get ( WindowName )&lt;/p&gt;
&lt;p&gt;];&lt;/p&gt;
&lt;p&gt;&quot;data:text/html,&quot; &amp;amp; &lt;/p&gt;
&lt;p&gt;If ( ~this ≠ ~active and Get ( RecordOpenState ) ; ReactorRunScript (  Get ( FileName ) ; &quot;Commit&quot; ; &quot;&quot; ) ; &quot;&quot; )&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;The beautiful thing about this code is that the calculation would evaluate from the context of the Web Viewers window - that being the one that just lost focus.&lt;/p&gt;
&lt;p&gt;Fast forward to some time in the future - perhaps around FileMaker 14 (we are not quite sure) and this technique no longer worked. The Web Viewer now only evaluated its calculation when loaded, or when it gained or lost focus.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Why Not Use an onTimer?&lt;/h2&gt;
&lt;p&gt;It&#039;s now 2022 and we were still looking for a solution. Now, there obviously has been a solution right in front of our noses for many years - an OnTimer script. Why not just install an OnTimer in every window that checks whether the window is active, and issue a commit if it is not? &lt;/p&gt;
&lt;p&gt;This does work. The issue we have however is that it is an active approach. We are forced to run a script every 1-2 seconds to do this check. This can become really annoying especially if trying to do development or debugging. &lt;/p&gt;
&lt;p&gt;We did however use this technique recently in our article on &lt;a href=&quot;https://www.teamdf.com/blogs/idle-release/&quot; target=&quot;_blank&quot;&gt;how to prevent users from becoming IDLE in a record&lt;/a&gt;, and quietly commit them. This was using an OnTimer.&lt;/p&gt;
&lt;p&gt;Here we wish to use a passive approach - something that sits in the background and only rears its head when required. This was what the Web Viewer provided us in 2010, and now we need a new solution.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Record Locking&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multi-window-record-locking/_resampled/ResizedImage600369-multi-window-record-locking-2.png&quot; alt=&quot;multi window record locking 2&quot; width=&quot;600&quot; height=&quot;369&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Shifting Our Attention to Window Focus&lt;/h2&gt;
&lt;p&gt;Our earlier Web Viewer approach was concerned with determining when a window had lost its focus. Now however we switched our attention to finding something that might evaluate on a layout when a window gained focus as this seemed more likely than the former approach.&lt;/p&gt;
&lt;p&gt;We tried most things but it seemed in this day in age no layout object would reevaluate its calculation simply by losing or regaining window focus.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Are Web Viewers the Solution? (again)&lt;/h2&gt;
&lt;p&gt;Once again we pursued the web viewer, although it proved fruitless. They seem like the best approach given their ability now to perform FileMaker scripts from within the Javascript.  Try as we might, the closest we could get was an implementation that relied on the Web Viewer being given focus in order for its code to evaluate - it simply wasn&#039;t going to cut it.&lt;/p&gt;
&lt;p&gt;Purely out of interest we included this in our example file for you to see in action. The Javascript code checks whether the document has focus or not, and is able to carry out an action accordingly, such as running a FileMaker script.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Our code for Web Viewer focus detection&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multi-window-record-locking/_resampled/ResizedImage600273-multi-window-record-locking-3.png&quot; alt=&quot;multi window record locking 3&quot; width=&quot;600&quot; height=&quot;273&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Aha! Custom Menus!&lt;/h2&gt;
&lt;p&gt;The &lt;strong&gt;only &lt;/strong&gt;element of a layout we could find that would actually evaluate a calculation when a window gained focus is that of a Custom Menu. When a window gains focus a Custom Menu can be evaluated to determine its visibility and its name. This happens &lt;strong&gt;every &lt;/strong&gt;time a window gains focus.&lt;/p&gt;
&lt;p&gt;That was the breakthrough required!  Credit must go to our friend &lt;span&gt;Steve Senft-Herrera who put us on the right track here and suggested the Custom Menu could be the way to go.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Now it seemed so simple:&lt;/span&gt;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Use a Custom Menu Set on your layouts.&lt;/li&gt;
&lt;li&gt;Attach a Custom Menu where its name contained a calculation.&lt;/li&gt;
&lt;li&gt;Have that calculation run a FileMaker Script to Commit the previously selected window.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;And that&#039;s exactly what we did.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Forcing a Commit Record&lt;/h2&gt;
&lt;p&gt;We force a commit in a calculation by using a plugin. These days we prefer &lt;a href=&quot;https://docs.baseelementsplugin.com/article/522-downloads&quot; target=&quot;_blank&quot;&gt;BaseElements Plugin&lt;/a&gt; by &lt;a href=&quot;http://www.goya.com.au&quot; target=&quot;_blank&quot;&gt;Goya&lt;/a&gt;. Note that the issue of window record locking is mostly a desktop issue hence why we are not focussing our efforts on iOS and WebDirect as both of those platforms have solutions to this issue through different design choices.&lt;/p&gt;
&lt;p&gt;The code is pretty simple:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;BE_ScriptExecute ( &quot;Commit&quot; )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We put this into a custom function so we can easily modify the code if need be.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Dealing With Other Situations That Can Load a Custom Menu&lt;/h2&gt;
&lt;p&gt;It&#039;s not just window switching that forces a custom menu to load. The following will also do this: &lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Window Changes (obviously)&lt;/li&gt;
&lt;li&gt;Switching Modes&lt;/li&gt;
&lt;li&gt;Switching Views&lt;/li&gt;
&lt;li&gt;Switching Layout&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;We only wish to run on a window change, so we needed a way to suppress all the other situations.&lt;/p&gt;
&lt;p&gt; The solution in our script is to set a global variable to the active window name but only do so if the active window name is different from that stored in the variable currently. Only when they are different can we be sure a new window has been selected.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Only running on window change&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multi-window-record-locking/_resampled/ResizedImage600184-multi-window-record-locking-5.png&quot; alt=&quot;multi window record locking 5&quot; width=&quot;600&quot; height=&quot;184&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Dealing With Runaway Scripts!&lt;/h2&gt;
&lt;p&gt;Now that we are only concerned with when the active window changes, the rest of our script can commit the previous window as follows:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Select Old Window&lt;/li&gt;
&lt;li&gt;Commit&lt;/li&gt;
&lt;li&gt;Re-select New Window &lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Uh-oh, we have a problem! We know our script will run every time a window is given focus, and steps 1 and 3 both switch windows and will trigger our script. &lt;/p&gt;
&lt;p&gt;We wish to avoid our script firing on both of these script steps.&lt;/p&gt;
&lt;p&gt;To do this, we set a global variable - &lt;strong&gt;$$SUPPRESS&lt;/strong&gt; - used to suppress our script triggering for the duration of when it is set. &lt;/p&gt;
&lt;p&gt;This &lt;strong&gt;$$SUPPRESS&lt;/strong&gt; variable is checked in our menu calculation and if it is set will not trigger our script to run again.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;Suppressing script from firing on window switches during script&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multi-window-record-locking/_resampled/ResizedImage600151-multi-window-record-locking-6.png&quot; alt=&quot;multi window record locking 6&quot; width=&quot;600&quot; height=&quot;151&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The @COMMIT Custom Function&lt;/h2&gt;
&lt;p&gt;So let&#039;s look now at the calculation that drives everything from the Custom Menu. We put this in a Custom Function simply so we can easily edit the code.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If (  $$SUPPRESS ; &quot;&quot; ;  Let ( ~commit = BE_ScriptExecute ( &quot;Commit&quot; ) ; &quot;&quot; ) )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;First, if the suppress variable is set we do nothing and return an empty string.&lt;/p&gt;
&lt;p&gt;If it is not set then we wish to initiate our Commit script which we do using a Let statement. We return an empty string.&lt;/p&gt;
&lt;p&gt;This custom function can be placed in any calculation in a Custom Menu, such as its name or visibility. We prefer to place it in an existing common Custom Menu that would appear in any Menu Set, such as within the File menu. Because the function returns an empty string we do not need to worry about it impacting the rest of a calculation for name or visibility.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Attaching to a Custom Menu&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multi-window-record-locking/_resampled/ResizedImage600442-multi-window-record-locking-7.png&quot; alt=&quot;multi window record locking 7&quot; width=&quot;600&quot; height=&quot;442&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;In Conclusion&lt;/h2&gt;
&lt;p&gt;We have come a long way since 2010 and while the Web Viewer technique back then was actually a bit nicer (and if it worked today would be even nicer with FileMaker.PerformScript instead of a plugin required) we have adapted and found a viable solution to this issue.&lt;/p&gt;
&lt;p&gt;Can you improve on this technique or offer any valuable insight or feedback? We&#039;d love to hear from you in the comments.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;As mentioned above, we always include an example file with our articles to help you learn and explore. We spend a lot of time on these so please do check it out.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/multi-window-record-locking/avoid-multi-window-record-locking.zip&quot; target=&quot;_blank&quot;&gt;Download the example file here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Thu, 22 Sep 2022 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/avoiding-multi-window-record-locking/</guid>
		</item>
		
		<item>
			<title>Three (New) Amigos</title>
			<link>https://www.teamdf.com/blogs/3-new-amigos/</link>
			<description>&lt;p&gt;Over the last year, Digital Fusion have taken on three new developers, to bring our wonderful team up to now total 19.&lt;/p&gt;
&lt;p&gt;All three of the ‘newbies’ came to us with varying backgrounds, both in terms of their careers to date but also their previous exposure to FileMaker.&lt;/p&gt;
&lt;p&gt;We are proud to have them on our team, and to follow is a little bit about each of them…&lt;/p&gt;
&lt;h3&gt;Reis Adamson&lt;/h3&gt;
&lt;p&gt;Reis is unique amongst the three of them, in that he’s joined as a ‘remotie’, but he also came to us with a huge amount of experience in FileMaker.&lt;/p&gt;
&lt;p&gt;He’s based out of &lt;a title=&quot;Lismore on the map&quot; href=&quot;https://maps.apple.com/?address=Lismore%20NSW 2480, Australia&amp;amp;auid=17105506915267088071&amp;amp;ll=-28.812688,153.273911&amp;amp;lsp=6489&amp;amp;q=Lismore&amp;amp;_ext=Ch4KBAgEEBYKBAgFEAMKBAgGEAMKBAgKEAsKBAhVEA4SJimcYbTYN9E8wDHbpZTimShjQDkEmVO41Ms8wEF+USdF0CljQFAD&quot; target=&quot;_blank&quot;&gt;Lismore&lt;/a&gt;, which is in the northern section of NSW, around a three hour drive from Brisbane. This means he’s not too remote, and he gets to catch up with Morgan and Sam from time to time.&lt;/p&gt;
&lt;p&gt;Although Reis was a promising orchestral percussionist in the Sydney Youth Orchestra, he went on to study and work in graphic design before eventually finding FileMaker as the ultimate creative platform.&lt;/p&gt;
&lt;p&gt;Reis comes to us with a wealth of experience in FileMaker but one of the appeals of joining Digital Fusion was to extend his knowledge, and learn from our team, so we are stoked we can help him out there.&lt;/p&gt;
&lt;p&gt;In his time away from work, Reis is active with his partner and two dogs, with the dogs taking a starring role in many a Zoom catchup. Reis is also into cross fit and running, so keeps an active life away. One of his life goals is to buy a property in the Northern Rivers region and have horses on it.&lt;/p&gt;
&lt;p&gt;The claim to fame for Reis when he joined DF was that he had never seen or touched snow. In his recent trip over to Christchurch, he held great concerns that he would be very cold, so had to borrow ‘winter clothes’ from his brother in law. It was pointed out that he was a month or two away from our coldest days, and he was pleasantly surprised how mild it was. He has yet to see or touch snow.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/3amigos/reis.jpg&quot; alt=&quot;reis&quot; width=&quot;303&quot; height=&quot;287&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Andrew Close&lt;/h3&gt;
&lt;p&gt;Andrew is the ‘young one’ of the three, but where he lacks in age, he makes up for in height, topping out at an impressive six foot six inches (1.98m). This has made him very handy as the architect who designed our offices, installed windows that nobody else can reach.&lt;/p&gt;
&lt;p&gt;Coming to us with a Mechanical Engineering degree plus a number of years working for a company that designed and inspected ceilings, Andrew understands what makes FileMaker such a valuable asset to a business. Although not having used FileMaker previously, he’s taken to it quickly, and has already seen how we transform clients efficiency.&lt;/p&gt;
&lt;p&gt;Andrew is very active in the church, playing in the band, and getting roped into all different sports teams. He’s also a regular bike rider, commuting to work each day is 30km plus round trip.&lt;/p&gt;
&lt;p&gt;Andrew’s claim to fame, he is the first ever employee of DF that is younger than the company itself.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/3amigos/andrew.jpg&quot; alt=&quot;andrew&quot; width=&quot;359&quot; height=&quot;287&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Glen Naysmith&lt;/h3&gt;
&lt;p&gt;Glen’s our ‘newbie’ in terms of his time with Digital Fusion, but he comes to us with a wealth of experience, both in terms of IT, but also understanding what makes businesses tick.&lt;br&gt;&lt;br&gt;Having been in Auckland for the last few years, he’s relocated to the beautiful Cass Bay in Christchurch, and is loving the 15 minute commute to work each day. He’s also loved getting his teeth into FileMaker, and working with clients.&lt;/p&gt;
&lt;p&gt;Having spent his early years studying and then being a builder, he now has a vast array of tools in his garage that are gathering dust.&lt;/p&gt;
&lt;p&gt;Glen’s claim to fame is that he was once an avid reader (before having kids) but had never read a Jack Reacher novel before winning a competition to meet the author when he was touring NZ. Awkward.&lt;/p&gt;
&lt;p&gt;And he may, or may not, have played THE starring role in a traditional fairy tale…&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/3amigos/glen.jpg&quot; alt=&quot;glen&quot; width=&quot;305&quot; height=&quot;287&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Wed, 06 Jul 2022 06:48:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/3-new-amigos/</guid>
		</item>
		
		<item>
			<title>Claris Problem Solvers Circle</title>
			<link>https://www.teamdf.com/blogs/claris-problem-solvers-circle/</link>
			<description>&lt;p&gt;We recently had two big announcements from Claris that we&#039;d like to share—&lt;/p&gt;
&lt;p&gt;Firstly we had the release of a new product, Claris Studio. We will tackle this one in another blog post, but in short, it’s a product that will start to fill in the gaps of what Claris/FileMaker can offer.&lt;/p&gt;
&lt;p&gt;The other announcement was of a new licensing promotion, the &lt;strong&gt;Problem Solvers Circle:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Claris are super aware that once FileMaker is embedded into businesses and organisations, it can lead to massive improvements. While you might start with one app, Claris want to encourage organisations to take advantage of the platform solve more problems and build multiple apps.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Tech is core to differentiation in business&quot; src=&quot;https://www.teamdf.com/assets/blog-images/claris-problem-solvers-circle/_resampled/ResizedImage659369-tech-differentiation.jpg&quot; alt=&quot;Tech is core to differentiation in business&quot; width=&quot;659&quot; height=&quot;369&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Problem Solvers Circle allows you to embed FileMaker into all four corners of your organisation by giving you a license for 100% of your staff.&lt;/p&gt;
&lt;p&gt;Before getting into the nitty gritty of how this works, it’s worth pointing out a few gotchas:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Clients who have Site Licenses (ASLA) are not eligible*&lt;/li&gt;
&lt;li&gt;It’s not for new licensing, you need to be an existing FileMaker user&lt;/li&gt;
&lt;li&gt;It’s only for annual license holders, if you hold perpetual licenses, you can’t join.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;* A lot of our clients fall into this category already, and are using FileMaker extensively with an Annual Site License.&lt;/p&gt;
&lt;p&gt;So what is it and what does it cost? The best way of describing this is to use an example company and actual license costs (based on an Australian business in AUD)…&lt;/p&gt;
&lt;p&gt;Let&#039;s say ABC is a company of 50 staff, but only 10 staff currently use an app built with FileMaker. For the last few years they&#039;ve purchased 10 User Licenses which costs them $2072.40 + GST per year.&lt;/p&gt;
&lt;p&gt;Under the Problem Solvers Circle, you commit to two years of licensing based on the previous year of licensing (as above), add a 30% premium, and in return you get licensing for the whole company (i.e. 50 staff in our example).&lt;/p&gt;
&lt;p&gt;So for ABC, to join the PSC for the next two years would cost them $5388.24 + GST (remember this is for two years, so that’s only $1300 extra for the 2 years)&lt;/p&gt;
&lt;p&gt;To show the value of this, if they didn’t join the PSC, to license all 50 staff would normally cost $9050 + GST for the two years.&lt;/p&gt;
&lt;p&gt;We think the Problem Solvers Club is a great option for a number of our clients and we will be discussing this with them over the coming weeks. It’s particulary useful if you want to expand FileMaker into all areas of your business, and potentially the cost of licensing has been a little high.&lt;/p&gt;
&lt;p&gt;Do &lt;a title=&quot;Email enquiries at Team DF about the Problem Solvers Circle licensing programme&quot; href=&quot;mailto:enquiries@teamdf.com&quot;&gt;get in touch&lt;/a&gt; if this is of interest, we are always keen to walk you through what it might look like for you.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Fri, 27 May 2022 08:21:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/claris-problem-solvers-circle/</guid>
		</item>
		
		<item>
			<title>Navigate the DF Way - Solution Navigation Bar</title>
			<link>https://www.teamdf.com/blogs/navigate-the-df-way-solution-navigation-bar/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://www.teamdf.com/blogs/navigate-the-df-way-layout-sections/&quot; target=&quot;_blank&quot;&gt;Part One&lt;/a&gt; of our Navigation series we talked about how to implement navigation within a single screen by building a portal of Navigation records. This utilised a table called &lt;em&gt;NavigationItems&lt;/em&gt; where each record was an element in the navigation portal - be it a screen, a header, or a separator.&lt;/p&gt;
&lt;p&gt;In this article we extend this table further to build a Navigation Bar used for solution-wide navigation. We introduce a new &lt;em&gt;NavigationSets&lt;/em&gt; table and talk about it&#039;s purpose for allowing multiple different types of Navigation Bars.&lt;/p&gt;
&lt;p&gt;We also talk a bit about Dashboards and how these can be customised to suit each individual user within a Navigation Bar.&lt;/p&gt;
&lt;p&gt;So, let&#039;s jump right in!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;This is the type of article where it will really help if you follow along using the example file because a lot of the examples given have come direct from our example file.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/navigation-bar/solution-navigation-bar.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file. &lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;What is a Navigation Bar?&lt;/h2&gt;
&lt;p&gt;A Navigation Bar is a horizontal (or vertical) object that contains buttons the user can interact with the navigate to different screens within a solution.  Below is an example of the Navigation Bar you&#039;ll find in our example file:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Our Navigation Bar&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigation-bar/_resampled/ResizedImage60089-navigation-bar-1.png&quot; alt=&quot;navigation bar 1&quot; width=&quot;600&quot; height=&quot;89&quot;&gt;&lt;/p&gt;
&lt;p&gt;They can be built in a number of ways using different FileMaker techniques.&lt;/p&gt;
&lt;p&gt;Historically at Digital Fusion our Navigation Bar for years was a series of repeating fields placed across the top of each layout. We would have a repeating field for an icon, another for the label, and more for the buttons that the user interacts with. &lt;/p&gt;
&lt;p&gt;One of the disadvantages we had with this approach was that our Navigation Bars were context dependent. Every time we wished to place it on a new layout of a different context we would have to re-point all the fields to the parent context.  The fact that it was comprised of multiple fields and objects also made it a pain to work with.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;A Button-Bar Based JSON Approach&lt;/h2&gt;
&lt;p&gt;These days we have abandoned repeating fields in favour of utilising button bars in conjunction with JSON.  We construct a JSON object which is a complete representation of each Navigation Bar, and then load the JSON into a global variable for the user.  This is used by the Navigation Bar for both its display, and for determining which action is to be carried out when a button is pressed.&lt;/p&gt;
&lt;p&gt;With the information stored within a JSON object we have everything we need to build our Navigation Bar object. However that is only half the story. The basis of the JSON is a couple of navigation based tables. Think of these as our underlying navigational structure. We have already seen one of these tables in our first article - &lt;em&gt;NavigationItems&lt;/em&gt; - and now we&#039;ll talk a bit more about the structure for our Navigation Bar.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;JSON representation of Navigation Bar&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigation-bar/_resampled/ResizedImage600659-navigation-bar-3.png&quot; alt=&quot;navigation bar 3&quot; width=&quot;600&quot; height=&quot;659&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;The &lt;em&gt;NavigationItems&lt;/em&gt; Table&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;NavigationItems&lt;/em&gt; table stores information about each individual item in our navigation object. In &lt;a href=&quot;https://www.teamdf.com/blogs/navigate-the-df-way-layout-sections/&quot; target=&quot;_blank&quot;&gt;part one&lt;/a&gt; we saw it used for items in a portal based control we built for navigation within a single screen.  We are now going to use it as a store of information about each item represented in our Navigation Bar.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;NavigationItems&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigation-bar/_resampled/ResizedImage600463-navigation-bar-4.png&quot; alt=&quot;navigation bar 4&quot; width=&quot;600&quot; height=&quot;463&quot;&gt;&lt;/p&gt;
&lt;p&gt;The majority of fields we utilised for the portal navigation will be reused for our navigation bar. The main exception however is the icon. Because we will be using a button bar object, we have no control over dynamic display. Any icons in a button bar would have to be hard-coded into each individual segment, and this defeats our goal of building a Navigation Bar that is entirely soft-coded.  For this reason we will not be using icons.&lt;/p&gt;
&lt;p&gt;We also won&#039;t be using separators or titles in our Navigation Bar - each item in the button bar will be clickable.&lt;/p&gt;
&lt;p&gt;We have however introduced two new fields into our table:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigation-bar/navigation-bar-5.png&quot; alt=&quot;navigation bar 5&quot; width=&quot;588&quot; height=&quot;42&quot;&gt;&lt;/p&gt;
&lt;p&gt;The first is &lt;em&gt;id_dashboard&lt;/em&gt;. This will serve as a foreign key, pointing to another special &lt;em&gt;NavigationItem&lt;/em&gt; record. We&#039;ll talk more about how this works later.&lt;/p&gt;
&lt;p&gt;The second is &lt;em&gt;id_navigationSet&lt;/em&gt;. This is a foreign key also and links each &lt;em&gt;NavigationItem&lt;/em&gt; record to a parent &lt;em&gt;NavigationSet&lt;/em&gt; record.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The &lt;em&gt;NavigationSets&lt;/em&gt; Table&lt;/h2&gt;
&lt;p&gt;Think of this as a parent table for a collection of &lt;em&gt;NavigationItems&lt;/em&gt;.  Each record in this table serves as a single Navigation Bar.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigation-bar/navigation-bar-6.png&quot; alt=&quot;navigation bar 6&quot; width=&quot;459&quot; height=&quot;160&quot;&gt;&lt;/p&gt;
&lt;p&gt;The table comprises of the fields:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;flag_default:  Indicates which Navigation Set is the system default for users.&lt;/li&gt;
&lt;li&gt;id_dashboard: A calculation that determines the id of the special dashboard &lt;em&gt;NavigationItem&lt;/em&gt; record. More on this later.&lt;/li&gt;
&lt;li&gt;name: We give each set a name, obviously.&lt;/li&gt;
&lt;li&gt;zzrec_id:  The primary key.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;That&#039;s about it, not much to it really. &lt;/p&gt;
&lt;p&gt;If you want 10 different navigation bars in your solution then you would create 10 different records in this table each with its own set of &lt;em&gt;NavigationItems&lt;/em&gt;. Once you have your Navigation Sets created with items, then it becomes a case of deciding which one to use for any given user.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Types of Navigation Items&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://www.teamdf.com/blogs/navigate-the-df-way-layout-sections/&quot; target=&quot;_blank&quot;&gt;part one&lt;/a&gt; we saw 3 different types of &lt;em&gt;NavigationItem&lt;/em&gt; records. We had one for a screen, a separator, or a header. These were defined using the &lt;em&gt;type &lt;/em&gt;field.&lt;/p&gt;
&lt;p&gt;However in our Navigation Bar implementation we won&#039;t be using types. All &lt;em&gt;NavigationItem&lt;/em&gt; records will represent an item in the Navigation Bar that can be clicked upon to initiate an action.&lt;/p&gt;
&lt;p&gt;We do however have one special type of &lt;em&gt;NavigationItem&lt;/em&gt; record which we call the Dashboard record&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Dealing with Dashboards&lt;/h2&gt;
&lt;p&gt;We always assign a value of &quot;0&quot; for the &lt;em&gt;sort &lt;/em&gt;field on this special record, and this is how we identify the dashboard record from all other &lt;em&gt;NavigationItem&lt;/em&gt; records. This is because our Dashboard navigation will always be the left-most button in our navigation bar - no exceptions.&lt;/p&gt;
&lt;p&gt;The other difference between this record and other &lt;em&gt;NavigationItem&lt;/em&gt; records is that on this record the only other field value we need provide is that of &lt;em&gt;id_dashboard. &lt;/em&gt;As mentioned earlier this is a foreign key to a dashboard record.  We are effectively telling the &lt;em&gt;NavigationSet&lt;/em&gt; what the default dashboard screen will be for this navigation bar.&lt;/p&gt;
&lt;p&gt;The key here is &lt;strong&gt;default&lt;/strong&gt;. The Dashboard is able to be changed on any given navigation bar when initialised based on whatever criteria you wish. Some systems assign dashboards to specific users, while others assign based on the role a user might be undertaking.&lt;/p&gt;
&lt;p&gt;We want our navigation to be flexible such that we can easily change what happens when this left-most button to access the dashboard is clicked.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;How do we define Dashboards?&lt;/h2&gt;
&lt;p&gt;A dashboard record is just a &lt;em&gt;NavigationItem&lt;/em&gt; record whose &lt;em&gt;type&lt;/em&gt; field value is equal to &quot;dashboard&quot;. They have no direct relationship to any specific &lt;em&gt;NavigationSet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;You create one record for each different dashboard in your solution.  These are configured in the same way as a normal &lt;em&gt;NavigationItem&lt;/em&gt; record where you specify:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;A name&lt;/li&gt;
&lt;li&gt;A target layout&lt;/li&gt;
&lt;li&gt;A script to run either immediately, or after layout navigation if a target was specified.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;You don&#039;t need to define a sort order for these records - when they are linked up to a &lt;em&gt;NavigationSet&lt;/em&gt; they&#039;ll always have a sort order of 0.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Dashboard Configuration&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigation-bar/_resampled/ResizedImage600160-navigation-bar-7.png&quot; alt=&quot;navigation bar 7&quot; width=&quot;600&quot; height=&quot;160&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Assigning Dashboards to Navigation Sets&lt;/h2&gt;
&lt;p&gt;Recall earlier we created a special &lt;em&gt;NavigationItem&lt;/em&gt; record in each &lt;em&gt;NavigationSet&lt;/em&gt; to act as the dashboard position with a sort order of 0.&lt;/p&gt;
&lt;p&gt;We said that each item only needs to be related to a dashboard record. Now that we have set up a number of dashboard records as shown above, we can now set the &lt;em&gt;id_dashboard&lt;/em&gt; field value our dashboard &lt;em&gt;NavigationItems &lt;/em&gt;records.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Setting up your Sets &lt;em&gt;NavigationItems&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;Next step is to configure your regular &lt;em&gt;NavigationItem&lt;/em&gt; records in your Navigation Set.  These are set up in a very similar way to the &lt;em&gt;NavigationItems&lt;/em&gt; we saw in &lt;a href=&quot;https://www.teamdf.com/blogs/navigate-the-df-way-layout-sections/&quot; target=&quot;_blank&quot;&gt;part one&lt;/a&gt; for our portal based navigation. &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Defining Navigation Items&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigation-bar/_resampled/ResizedImage600207-navigation-bar-8.png&quot; alt=&quot;navigation bar 8&quot; width=&quot;600&quot; height=&quot;207&quot;&gt;&lt;/p&gt;
&lt;p&gt;One difference here from &lt;a href=&quot;https://www.teamdf.com/blogs/navigate-the-df-way-layout-sections/&quot; target=&quot;_blank&quot;&gt;part one&lt;/a&gt; is that our target will be a layout name instead of layout object name. We also have introduced an Alternative layout name as an option. This is such that we can hold a modifier key while pressing a button in our Navigation Bar to access a secondary layout. It is useful where you may have both a form and list view version of a screen and wish for a quick and simple way for a user to choose which of the two varieties they want to navigate to.&lt;/p&gt;
&lt;p&gt;Lastly we have an option to run a script as part of the button click. You can either use this on its own or in conjunction with a specified layout. If you specify both then the script will run after the layout is navigated to.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Building a JSON Representation of a Navigation Set&lt;/h2&gt;
&lt;p&gt;At this point if you&#039;re following along we should have the following records defined in order to build a Navigation Bar:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;At least one &lt;em&gt;NavigationSet&lt;/em&gt; record&lt;/li&gt;
&lt;li&gt;At least one Dashboard &lt;em&gt;NavigationItem&lt;/em&gt; record.&lt;/li&gt;
&lt;li&gt;A special dashboard &lt;em&gt;NavigationItem&lt;/em&gt; record for our NavigationSet (sort order 0) which is linked to a Dashboard &lt;em&gt;NavigationItem&lt;/em&gt; record.&lt;/li&gt;
&lt;li&gt;One or more additional &lt;em&gt;NavigationItem&lt;/em&gt; records associated with the &lt;em&gt;NavigationSet&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;With all this information we have everything we need to now construct a JSON representation of a &lt;em&gt;NavigationSet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The JSON object will contain the following:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The ID of the &lt;em&gt;NavigationSet&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;An array of &lt;em&gt;NavigationItem&lt;/em&gt; objects, ordered by how they are to appear in the Navigation Bar (sort order). &lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Here is an example of a basic navigation Set with a dashboard and 2 screens:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;A Navigation Bar with 3 items&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigation-bar/_resampled/ResizedImage600717-navigation-bar-9.png&quot; alt=&quot;navigation bar 9&quot; width=&quot;600&quot; height=&quot;717&quot;&gt;&lt;/p&gt;
&lt;p&gt;The JSON is constructed using a script called &quot;NAV: Initialise&quot;. This script is responsible for taking a &lt;em&gt;NavigationSet&lt;/em&gt; record as its parameter and constructing the JSON representation.&lt;/p&gt;
&lt;p&gt;Now, we won&#039;t go into fine detail about each line of code in this script because you&#039;ll find it well commented in our example file to dissect, however let&#039;s give a high level overview of what it does...&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Determine Navigation Bar&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While a &lt;em&gt;NavigationSet&lt;/em&gt; id can be passed to this script, if the user does not specify one then there are some fall-backs.  The first is trying to use the value in the global variable &lt;em&gt;$$USER_NAVIGATION_ID&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Now, this is purely an arbitrary name and depends on your own solution, but effectively think of this as a &lt;em&gt;NavigationSet&lt;/em&gt; that has been assigned to the logged in user. This can sometimes be done on startup of a solution or when a user defines their role, or some other criteria. &lt;/p&gt;
&lt;p&gt;Whatever the case may be, it may transpire users have their own Navigation Bars, and in our example that ID gets stored in this global variable.&lt;/p&gt;
&lt;p&gt;Now, failing there being one, the script will do a second fall-back to look for the system default Navigation Set. If no default has been defined, then we are unable to proceed.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Obtain &lt;em&gt;NavigationItem&lt;/em&gt; data.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We next run an ExecuteSQL query to obtain the required information from each &lt;em&gt;NavigationItem&lt;/em&gt; record associated with the &lt;em&gt;NavigationSet&lt;/em&gt;. We then separate the left-most (dashboard) entry from the rest (regular items).&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Determine Dashboard to use.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We handle the dashboard item differently because within this item is the &lt;em&gt;id_dashboard &lt;/em&gt;value which we now need to look up to obtain the required information from this Dashboard &lt;em&gt;NavigationItem&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;There is also a part in the script here where you have the ability to determine a user-specific overriding dashboard. Remember we&#039;re dealing up to this point with the default Dashboard for the Navigation Set. However in your own implementation you may wish to define dashboards at the user level meaning dashboard records are actually assigned to individual users. If this is the case then this part of the script is where you would check if the user has a specified dashboard, and override the dashboard record to use with the user specified one. &lt;/p&gt;
&lt;p&gt;We again run an executeSQL query to now obtain the required information from the chosen Dashboard &lt;em&gt;NavigationItem&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Build the JSON&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The last part is pretty simple, we now just construct the JSON and build the array of items. The first position in the array is always for that of the dashboard, with the remainder of the items going into the subsequent array positions.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Loading a Navigation Bar using a Set&lt;/h2&gt;
&lt;p&gt;The actual loading is a piece of cake and is a single line of code. We simply set the resulting JSON into the &lt;em&gt;$$USER_NAVIGATION_DATA&lt;/em&gt; global variable. Everything else is now handled by the Navigation Bar object, and the script that runs when an item is clicked.&lt;/p&gt;
&lt;p&gt;To change the navigation bar for a user, just simply re-run the &lt;em&gt;Nav:Initialise &lt;/em&gt;script, passing it the id of a new &lt;em&gt;NavigationSet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Navigation Bar Object&lt;/h2&gt;
&lt;p&gt;The Navigation Bar as previously mentioned is a button bar object. Each element is soft-coded based on the JSON in &lt;em&gt;$$USER_NAVIGATION_DATA&lt;/em&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Navigation Bar in Layout Mode&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigation-bar/_resampled/ResizedImage60060-navigation-bar-10.png&quot; alt=&quot;navigation bar 10&quot; width=&quot;600&quot; height=&quot;60&quot;&gt;&lt;/p&gt;
&lt;p&gt;Taking an initial look we can learn the following:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;First item is always called &quot;Home&quot; - it&#039;s hard coded.&lt;/li&gt;
&lt;li&gt;Item names are defined via calculation&lt;/li&gt;
&lt;li&gt;The number of possible items in the horizontal navigation bar is predefined to be 8&lt;/li&gt;
&lt;li&gt;We have a special 9th item labelled &quot;More…&quot;  - more on this later!&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Firstly let&#039;s look at the calculation for each regular item in the nav bar:&lt;/p&gt;
&lt;pre&gt;@NAV_Get ( &quot;name&quot; ; 1 )&lt;/pre&gt;
&lt;p&gt;This is a custom function which we use in our implementation to help obscure some of the more lengthy calculations and simply allow us to query our JSON for a specific value based on item index.  In this case we&#039;re asking for the name value for the item at array position 1. This is what we use to show the name of the second item in the navigation bar (remember arrays in JSON begin at index 0).&lt;/p&gt;
&lt;p&gt;Each item has an action assigned which will run the &lt;em&gt;Nav:Select&lt;/em&gt; script. This script accepts the following parameter:&lt;/p&gt;
&lt;pre&gt;JSONSetElement ( &quot;&quot; ; &quot;target_number&quot; ; 1 ; JSONNumber )&lt;/pre&gt;
&lt;p&gt;Which is just a JSON object containing the index of the item.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Highlighting the Current Navigation Item&lt;/h2&gt;
&lt;p&gt;We want to use the active button bar state to indicate which layout the user is currently on. To do this we first give each segment an object name containing its index, e.g.:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;nav_0 (dashboard)&lt;/li&gt;
&lt;li&gt;nav_1&lt;/li&gt;
&lt;li&gt;nav_2&lt;/li&gt;
&lt;li&gt;... and so on.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Next, we define the active segment to be:&lt;/p&gt;
&lt;pre&gt;&quot;nav_&quot; &amp;amp; @NAV_Get ( &quot;Position&quot; ; &quot;&quot; )&lt;/pre&gt;
&lt;p&gt;You&#039;ll see we have again utilised our custom function, but this time we are passing it a special parameter &quot;position&quot;. We are requesting the function to tell us at which position in the list of items our current layout name resides. The function will check each navigation Item for both its primary layout and alternate layout name, returning the first index position in the array it finds.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigation-bar/_resampled/ResizedImage600688-navigation-bar-11.png&quot; alt=&quot;navigation bar 11&quot; width=&quot;600&quot; height=&quot;688&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the example pictured above, if we were on the highlighted layout then this custom function call would return &quot;2&quot; and thus the active segment object name would be &quot;nav_2&quot;.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;The &lt;em&gt;Nav:Select&lt;/em&gt; Script&lt;/h2&gt;
&lt;p&gt;Again there is nothing really technical here. This script accepts as parameter an index position. It then looks up our JSON objects array of Navigation Items for the corresponding position, from which it can then obtain the layout name, alternate layout name and script.  It then is responsible for carrying out the correct navigation and execution of a nominated script.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigation-bar/navigation-bar-12.png&quot; alt=&quot;navigation bar 12&quot; width=&quot;326&quot; height=&quot;582&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Showing More Items in the Bar&lt;/h2&gt;
&lt;p&gt;Unlike portal based navigation that can be scrolled, we do not have that luxury with a horizontal Navigation Bar. Now, to be honest if you are building Navigation Bars where you want to employ horizontal scrolling then you&#039;re doing it wrong - you have too many items in your nav bar and need to rethink your solutions Navigation.&lt;/p&gt;
&lt;p&gt;However being the hypocrites we are, we added into our Navigation Bar object the means to allow a small number of additional screens that will open in a vertical popover if there are more than can be displayed horizontally.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigation-bar/navigation-bar-13.png&quot; alt=&quot;navigation bar 13&quot; width=&quot;480&quot; height=&quot;408&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here you&#039;ll see the last item in the bar is a special item labelled &quot;More…&quot; which is a popover, containing further Navigation Bar items. These additional items are basically set up in the same way as the horizontal items.&lt;/p&gt;
&lt;p&gt;In our solution setup we first define a special global variable &lt;em&gt;$$SOLUTION_NAV_SIZE&lt;/em&gt;. This is set to a number which is how many actual items we can display horizontally. In the case of our example file this number is 8 (we exclude the &quot;more&quot; segment).&lt;/p&gt;
&lt;p&gt;In situations where our Navigation Bar has 8 or less items we will hide this &quot;More…&quot; popover, and simply show our 8 regular segments.&lt;/p&gt;
&lt;p&gt;However if we have over 8 items in the Navigation Bar then we hide the last regular segment and instead replace it with the &quot;More…&quot; popover. Thus the last segment in the Navigation Bar will always either be the last normal item or the &quot;More…&quot; popover.&lt;/p&gt;
&lt;p&gt;Inside the popover our segments will begin at position 8. This is because in order to show the &quot;More…&quot; popover, we hid the 8th segment in the horizontal view, and so we now require it to be the staring segment in the vertical view.&lt;/p&gt;
&lt;p&gt;Because you cannot use the same layout object name twice, these vertical object names are suffixed with &quot;_alt&quot; to differentiate them from their horizontal counterparts. We just make a small adjustment to the active segment calculation here to accommodate.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;As always we have crafted an example file to help you follow along with the article and so you can explore and implement this in your own solutions.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/navigation-bar/solution-navigation-bar.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file. &lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Thu, 26 May 2022 06:46:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/navigate-the-df-way-solution-navigation-bar/</guid>
		</item>
		
		<item>
			<title>Navigate the DF Way - Layout Sections</title>
			<link>https://www.teamdf.com/blogs/navigate-the-df-way-layout-sections/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;At Digital Fusion we have spent years implementing solutions using all manner of navigational techniques.&lt;/p&gt;
&lt;p&gt;Over that time we have refined and settled on our own methods for managing navigation within a solution - be it solution-wide, within a layout, or within within parts of a layout.&lt;/p&gt;
&lt;p&gt;In this and upcoming articles we will share some of these techniques and frameworks, beginning with a simple framework used for layout section navigation.&lt;/p&gt;
&lt;p&gt;This portal-based approach allows us to produce a vertical navigation control that lets the user navigate to a nominated tab control, or panel control.&lt;/p&gt;
&lt;p&gt;We use it in situations where a tab control would simply have too many tabs to be a usable means of navigation, or where other controls such as button bars would just end up with far too many segments.&lt;/p&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 600px;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;example file&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigate-layout-sections/_resampled/ResizedImage600363-navigate-layout-sections-1.png&quot; alt=&quot;navigate layout sections 1&quot; width=&quot;600&quot; height=&quot;363&quot;&gt;&lt;p class=&quot;caption center&quot; style=&quot;text-align: center;&quot;&gt;our example file &lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;What is a Layout Section?&lt;/h2&gt;
&lt;p&gt;Simply put, a section is a specific tab control section or panel section within their respective objects. A common layout structure we have is to create a hidden sliding panel object and make it the size of the content area of a layout.  Each panel will contain a different set of fields or functionality for that layout.&lt;/p&gt;
&lt;p&gt;In fact this is no different than simply putting a tab control/panel on a layout and using their built in navigational controls. What we are doing instead is hiding those controls and building our own portal based control to navigate them.&lt;/p&gt;
&lt;p&gt;You may have come across other approaches such as using a button bar control to handle tab/panel navigation. While being a perfectly reasonable approach, it does suffer a few setbacks:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;No icon customisation - they must be hard-coded into the bar.&lt;/li&gt;
&lt;li&gt;The active button bar state must be handled &amp;amp; refreshed - this can be very annoying.&lt;/li&gt;
&lt;li&gt;Hiding disabled items in the bar will result in the other segments becoming wider - can be jarring for a user and can make the UI look really bad.&lt;/li&gt;
&lt;li&gt;Styling of button bars is a total PITA!&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Based on these factors and our own desire to make a far more dynamic and reusable control that can cater to larger navigational structures we opted instead for a portal approach.&lt;/p&gt;
&lt;p&gt;Note however that this does not mean other approaches are invalid - it all depends on your scenario. We still use tab controls all the time because they are perfect for smaller layout section navigation.  Our portal approach is for times when a tab is not the best suited control for the job.&lt;/p&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 600px;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;showing the layout sections as a panel control.&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigate-layout-sections/_resampled/ResizedImage600363-navigate-layout-sections-2.png&quot; alt=&quot;navigate layout sections 2&quot; width=&quot;600&quot; height=&quot;363&quot;&gt;&lt;p class=&quot;caption center&quot; style=&quot;text-align: center;&quot;&gt;layout sections identified - it&#039;s a panel! &lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Taking a Portal Based Approach&lt;/h2&gt;
&lt;p&gt;By building a navigation control using a portal, each item in our navigation control is a record in a table. We call this the &lt;em&gt;&lt;strong&gt;NavigationItems&lt;/strong&gt;&lt;/em&gt; table (more on this later).&lt;/p&gt;
&lt;p&gt;With this approach our records can be setup to contain any number of different properties to aid us in navigation and display such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;A type (header, separator, navigation item etc).&lt;/li&gt;
&lt;li&gt;An icon (either singular or one for selected vs non-selected).&lt;/li&gt;
&lt;li&gt;A display name.&lt;/li&gt;
&lt;li&gt;Target object on the layout to navigate to.&lt;/li&gt;
&lt;li&gt;The name of a script to run post (or pre) navigation.&lt;/li&gt;
&lt;li&gt;A prefix for the display name, e.g. bullet point.&lt;/li&gt;
&lt;li&gt;Indenting of the display name using tabs.&lt;/li&gt;
&lt;li&gt;... and whatever else you can think up.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The portal can then have a script run from within such that depending on the row you select the script can obtain the relevant information needed to navigate, and do so.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;The NavigationItems Table&lt;/h2&gt;
&lt;p&gt;The underlying table that our Navigation control is based on is the &lt;em&gt;&lt;strong&gt;NavigationItems&lt;/strong&gt;&lt;/em&gt; table. As mentioned above it contains a number of useful bits of information such as display name, target object, a script to run, an icon and so forth. Two key pieces of information in this table are the &lt;strong&gt;&lt;em&gt;type&lt;/em&gt; &lt;/strong&gt;and &lt;strong&gt;&lt;em&gt;item_type&lt;/em&gt;&lt;/strong&gt; fields.&lt;/p&gt;
&lt;p&gt;Think of the &lt;em&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/em&gt;&lt;strong&gt; &lt;/strong&gt;field as a way to identify similar records belonging to a single navigation control. For example if you have two controls in your solution - one for the setup screen and another for contacts screen - then your records will have values of &quot;setup&quot; and &quot;contacts&quot; for this &lt;em&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/em&gt; field.&lt;/p&gt;
&lt;p&gt;The other important field is &lt;em&gt;&lt;strong&gt;item_type&lt;/strong&gt;.&lt;/em&gt; This helps us categorise records into one of three sub-types.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h2&gt;The Three Types of Items&lt;/h2&gt;
&lt;p&gt;The three subtypes of records defined by the &lt;strong&gt;item_types&lt;/strong&gt; field are:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;header&lt;/li&gt;
&lt;li&gt;separator&lt;/li&gt;
&lt;li&gt;item&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Header records act as titles for other items and are a way to help group similar items in the navigation. They can also be styled to appear different to navigation items.&lt;/p&gt;
&lt;p&gt;Separators are usually blank records that act as separators between groupings of items. You don&#039;t necessarily have to have them as blank either - through putting objects in the portal and hiding them on rows that aren&#039;t separators, you can define any style of separator you want.&lt;/p&gt;
&lt;p&gt;The last type is &quot;item&quot; and these are the actual clickable navigation items which will have a name, target object, and potentially a script to run.&lt;/p&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 600px;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;types&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigate-layout-sections/_resampled/ResizedImage600363-navigate-layout-sections-3.png&quot; alt=&quot;navigate layout sections 3&quot; width=&quot;600&quot; height=&quot;363&quot;&gt;&lt;p class=&quot;caption center&quot; style=&quot;text-align: center;&quot;&gt;The three navigation item types&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Setting up your Navigation Items &lt;/h2&gt;
&lt;p&gt;Next it&#039;s time to create and configure your &lt;em&gt;&lt;strong&gt;navigationItem&lt;/strong&gt;&lt;/em&gt; records. This part is simple, just assign them all the same &lt;em&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/em&gt;,  categorise them based on &lt;em&gt;&lt;strong&gt;item_type&lt;/strong&gt;&lt;/em&gt;, and then fill in all the other required fields.&lt;/p&gt;
&lt;p&gt;Headers will at the very least require a display name, while separators require no additional information.&lt;/p&gt;
&lt;p&gt;Items will require a name, target object, and possible post-script to run. In addition to this you can specify an icon, a prefix text, and some indentation if required.&lt;/p&gt;
&lt;p&gt;One other important field in the setup is the &lt;em&gt;&lt;strong&gt;order&lt;/strong&gt;&lt;/em&gt; field. For simplicity sake all our records are sorted based on this numerical order. Make sure you set the correct order for which you want all your &lt;em&gt;&lt;strong&gt;navigationItem&lt;/strong&gt;&lt;/em&gt; records to appear in the control.&lt;/p&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 600px;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;setup of navigation items&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigate-layout-sections/_resampled/ResizedImage600226-navigate-layout-sections-4.png&quot; alt=&quot;navigate layout sections 4&quot; width=&quot;600&quot; height=&quot;226&quot;&gt;&lt;p class=&quot;caption center&quot; style=&quot;text-align: center;&quot;&gt;Information being set into &lt;em&gt;&lt;strong&gt;NavigationItems&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h2&gt;Building the Navigation Object&lt;/h2&gt;
&lt;p&gt;Right, now it&#039;s time to actually add a portal to the layout for this control.&lt;/p&gt;
&lt;p&gt;First you&#039;ll need a relationship to the &lt;em&gt;&lt;strong&gt;NavigationItems&lt;/strong&gt;&lt;/em&gt; table from your layout context. This could be a relationship to all records where you will make use of Portal-Level filtering to restrict records to just those of a particular &lt;em&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/em&gt;. Alternatively you could program the type predicate into the relationship so you only find those specific records via your relationship. For simplicity sake we use portal filtering as our &lt;em&gt;&lt;strong&gt;NavigationItems&lt;/strong&gt;&lt;/em&gt; table often doesn&#039;t have many records,and so portal filtering performance issues are negligible.&lt;/p&gt;
&lt;p&gt;With the relationship established, add the portal to the layout and add into it your display name field.&lt;/p&gt;
&lt;p&gt;Make sure to sort the portal by the &lt;strong&gt;&lt;em&gt;order&lt;/em&gt; &lt;/strong&gt;field.&lt;/p&gt;
&lt;p&gt;In addition to any display fields added, there are two additional objects that are important to add to the portal:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;a button to run the navigation script.&lt;/li&gt;
&lt;li&gt;a rectangle fill to act as a highlight to indicate the selected section.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;For the button we want to only show this on the rows where &lt;em&gt;&lt;strong&gt;item_type&lt;/strong&gt;&lt;/em&gt; = &quot;item&quot;, which we achieve through a hide conditions.&lt;/p&gt;
&lt;p&gt;The highlight should only be shown on the row which is the selected row which is also done using a hide condition - more on this later.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Formatting Portal Rows&lt;/h2&gt;
&lt;p&gt;There are many ways to display your navigation control. You have control over how you format the items, the headers, separators etc. &lt;/p&gt;
&lt;p&gt;Usually we would make use of layout styles and apply these to objects in the portal. We do this for the hover and navigation button. &lt;/p&gt;
&lt;p&gt;For the display name we would usually also use styles but in the interests of simplicity for the example file conditional formatting has been utilised to format headers differently. To do this with styles we would have the display name field added twice into the portal - one styled for items and one for headers - and hide the relevant objects based on the &lt;em&gt;&lt;strong&gt;item_type&lt;/strong&gt;&lt;/em&gt; of that record.&lt;/p&gt;
&lt;p&gt;Utilising styles allows you to achieve a system-wide consistency of design with your navigation controls.&lt;/p&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 600px;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;the required layout objects&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigate-layout-sections/_resampled/ResizedImage600196-navigate-layout-sections-5.png&quot; alt=&quot;navigate layout sections 5&quot; width=&quot;600&quot; height=&quot;196&quot;&gt;&lt;p class=&quot;caption center&quot; style=&quot;text-align: center;&quot;&gt;the display field, button, and hover fill all highlighted.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Scripting of Navigation&lt;/h2&gt;
&lt;p&gt;We have a single script that carries out navigation to a desired layout section. This script accepts a JSON block as a parameter.&lt;/p&gt;
&lt;p&gt;This JSON block contains information about the selected record, such as its id, name, type, item_type, target, and script name.&lt;/p&gt;
&lt;p&gt;The information within the JSON is parsed out and used to navigate and run any required script.&lt;/p&gt;
&lt;p&gt;In addition to carrying out the navigation, the JSON is then stored in a global variable so that we track what the currently selected item is. This selected item is how we determine back in the portal which row should be highlighted.&lt;/p&gt;
&lt;p&gt;Storing of the selected item is done using a global variable. This global variable is dynamically generated in the script and it&#039;s name is constructed using the &lt;em&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/em&gt;&lt;strong&gt; &lt;/strong&gt;of the navigation control being interacted with.&lt;/p&gt;
&lt;p&gt;For example if you are selecting an item for the &quot;contacts&quot; navigation control, then the global variable name will be &lt;em&gt;&lt;strong&gt;$$NAV.CONTACTS&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;However it&#039;s not quite that simple! FileMaker is great at allowing users to create multiple windows - each with their own contexts, found sets, and states (such as selected tab or panel). For this reason, we need to actually track the selected item at the window level, meaning if a user had 5 windows open then we need to know what the selected section is &lt;em&gt;for each of those five windows!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Turns out there&#039;s a rather nice and simple way to address this issue. We take the window name (which we assume to be unique) and turn it into an MD5 hash number using the following formula:&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;em&gt;&lt;strong&gt;GetAsNumber ( GetContainerAttribute ( Get ( WindowName ) ; &quot;MD5&quot; ) )&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Think of this as a way to map a text string - the window name - into a numerical equivalent. We then use this number as the repetition number of the global variable to store that windows state in - easy!&lt;/p&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 600px;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Storing a windows state in a global variable&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigate-layout-sections/_resampled/ResizedImage600284-navigate-layout-sections-6.png&quot; alt=&quot;navigate layout sections 6&quot; width=&quot;600&quot; height=&quot;284&quot;&gt;&lt;p class=&quot;caption center&quot; style=&quot;text-align: center;&quot;&gt;Storing the windows selected item in a Global Variable repetition&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Specifying an Initial/Default Item&lt;/h2&gt;
&lt;p&gt;Standard layout section objects such as tab controls and sliding panels all have a default section. For tabs you can nominate it, and for panels it is the first panel. When the user first enters the layout, the default tab/panel is chosen.&lt;/p&gt;
&lt;p&gt;Because we are overriding this behaviour with our own navigation control, we need a way to define what our controls default section should be. There are three potential candidates:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The first &quot;item&quot; record in our control based on order.&lt;/li&gt;
&lt;li&gt;A predefined item&lt;/li&gt;
&lt;li&gt;The last selected item if there is one.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;All three are viable options and which option you choose depends upon your use case. In our example file and in our own solutions we have opted for the first option of just selecting the top-most item from the control, regardless of whether one was previously selected.&lt;/p&gt;
&lt;p&gt;You can find this achieved in our example files navigation script. In a situation where the user is not actively determining the selected item - such as entering a layout - then we pass through just the &lt;em&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/em&gt; to the navigation script as JSON:&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;em&gt;&lt;strong&gt;JSONSetElement ( &quot;&quot; ; &quot;type&quot; ; &quot;contacts&quot; ; JSONString )&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The script detects that no item was selected when we only have a type passed, and will instead run an executeSQL query to retrieve the first record whose &lt;em&gt;&lt;strong&gt;item_type&lt;/strong&gt;&lt;/em&gt; is &quot;item&#039;. It will then select it and navigate to it in the usual manner.&lt;/p&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 600px;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Querying for the first item in the navigation control&quot; src=&quot;https://www.teamdf.com/assets/blog-images/navigate-layout-sections/_resampled/ResizedImage600580-navigate-layout-sections-7.png&quot; alt=&quot;navigate layout sections 7&quot; width=&quot;600&quot; height=&quot;580&quot;&gt;&lt;p class=&quot;caption center&quot; style=&quot;text-align: center;&quot;&gt;Querying for the first item in the navigation control&lt;/p&gt;
&lt;p class=&quot;caption center&quot; style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;Taking it Further…&lt;/h2&gt;
&lt;p&gt;This is just scratching the surface of what you could achieve with this simple framework. At the end of the day all we are doing here is showing records in a portal - something any developer can understand - and with a few extra bits of information to help navigate, we are using these as a means to navigate to a panel control - nothing complicated here at all.&lt;/p&gt;
&lt;p&gt;Which is why there are so many ways you could build upon this to do more, such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;A solution-wide navigation system where layouts are navigated to rather than layout sections&lt;/li&gt;
&lt;li&gt;Building accordion style controls using more complex filtering&lt;/li&gt;
&lt;li&gt;Different &lt;em&gt;&lt;strong&gt;item_types&lt;/strong&gt;&lt;/em&gt; for things such as popovers, scripts etc.&lt;/li&gt;
&lt;li&gt;Or more!&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;In fact we&#039;re going to talk about taking this further and utilising &lt;em&gt;&lt;strong&gt;NavigationItems&lt;/strong&gt;&lt;/em&gt; for other purposes in future articles...&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Coming Soon…&lt;/h2&gt;
&lt;p&gt;In this article we&#039;ve covered a way in which we achieve navigation within a layout using a portal based navigation control. We do this because often layouts (such as a preferences screen) may have a large number of sections where a standard tab control may not work. However there are other forms of navigation that a solution needs.&lt;/p&gt;
&lt;p&gt;One such control is a navigation bar that helps the user navigate to all the main screens in a solution. At Digital Fusion we call this the navigation bar and we favour a horizontal bar across the top of layouts.&lt;/p&gt;
&lt;p&gt;In the next article in this series we talk about how we build this navigation bar to be completely contextless and able to be pasted and work on any layout. Not surprisingly we are utilising the &lt;em&gt;&lt;strong&gt;NavigationItems&lt;/strong&gt;&lt;/em&gt; table for this too - albeit with a couple more fields. We&#039;ll cover howe we handle situations where navigation bars might require a large number of screens, how we customise the look and feel, and how we manage dashboards - a situation where multiple users may actually require different dashboard screens. Finally we&#039;ll show how we can build multiple sets of navigation bars, and assign these to users based on their role or any other factor. It&#039;s a powerful control that gives a simple means to implement a custom navigation bar for your users.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;All my articles come with an example file (which is where about 90% of my time goes when preparing articles these days!)  I highly encourage you to check it out as you&#039;ll find everything in there to help you get started building your own navigation controls.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/navigate-layout-sections/navigate-layout-sections.zip&quot; target=&quot;_blank&quot;&gt;Click to download the example file here!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 03 May 2022 07:59:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/navigate-the-df-way-layout-sections/</guid>
		</item>
		
		<item>
			<title>Easy to Generate Debugging Reports</title>
			<link>https://www.teamdf.com/blogs/easy-to-generate-debugging-reports/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;How many times do users let you know of a bug in their solution and yet are unable to provide any detail about what they were doing at the time? What layout were they on? What was the found count? Were any plugins installed? What record were they on?&lt;/p&gt;
&lt;p&gt;These are very common questions the developer may ask and yet not receive a good answer to.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;So how do we find the answers?&lt;/h2&gt;
&lt;p&gt;Well sometimes good users can provide us with the answers but more often than not they simply aren&#039;t paying attention to the state of the solution at the time a bug occurs - which is fair enough. As a developer maybe we can just build some tools to provide us with the answers the user cannot.&lt;/p&gt;
&lt;p&gt;We did just that by building a debugging report script that will collate information into a JSON object that the developer can then do with whatever they please.&lt;/p&gt;
&lt;p&gt;It combines three useful sets of data in JSON format:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;All field values from the users current record (or any nominated record)&lt;/li&gt;
&lt;li&gt;Results of every Get function&lt;/li&gt;
&lt;li&gt;Any other developer specified data which may be of use (e.g. globals, variables, session state..)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This is a single script that can be initiated from anywhere. The JSON is returned as the script result.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Getting record values&lt;/h2&gt;
&lt;p&gt;To get all record values, one might use the Execute FileMaker data API script step, combined with a pre-build layout in order to return this information, but who has time to manage layouts! We wanted a way to do this all within a script and so we utilise FileMakers internal SQL tables &lt;em&gt;FileMaker_Tables&lt;/em&gt; and &lt;em&gt;FileMaker_Fields&lt;/em&gt; to give us all the information we need.&lt;/p&gt;
&lt;p&gt;Andrew Duncan from &lt;a href=&quot;https://www.databuzz.com.au/&quot; target=&quot;_blank&quot;&gt;Databuzz&lt;/a&gt; has an awesome article on these tables which I refer back to constantly, I strongly encourage you to &lt;a href=&quot;https://www.databuzz.com.au/using-executesql-to-query-the-virtual-schemasystem-tables/&quot; target=&quot;_blank&quot;&gt;check out his article here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In fact we actually featured this technique in our top 5 of 2021 article just recently - &lt;a href=&quot;https://www.teamdf.com/blogs/get-record-as-json/&quot; target=&quot;_blank&quot;&gt;check out that article for more detail here!&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Example of Record data JSON&quot; src=&quot;https://www.teamdf.com/assets/blog-images/debugging-reports/debugging-reports-1.png&quot; alt=&quot;debugging reports 1&quot; width=&quot;600&quot; height=&quot;343&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;In short, the process for obtaining the record data is as follows:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Obtain a reference to the records primary key field&lt;/li&gt;
&lt;li&gt;Extract the table occurrence name, and field name&lt;/li&gt;
&lt;li&gt;Use the FileMaker_Fields table to obtain every field name, class and type from that table&lt;/li&gt;
&lt;li&gt;Loop through the field data, excluding items you do not wish to debug&lt;/li&gt;
&lt;li&gt;Build a query to obtain just the field values you do wish to debug&lt;/li&gt;
&lt;li&gt;Loop through the results, generating JSON&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;This is clearly documented and laid out in the script in the example file.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Code for getting field values&quot; src=&quot;https://www.teamdf.com/assets/blog-images/debugging-reports/_resampled/ResizedImage600298-debugging-reports-2.png&quot; alt=&quot;debugging reports 2&quot; width=&quot;600&quot; height=&quot;298&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;  &lt;/p&gt;
&lt;h2&gt;Getting Get Values&lt;/h2&gt;
&lt;p&gt;The Get functions (e.g. Get ( FoundCount )) are invaluable in the information they can provide the developer about the state the solution was in when an issue occurred for the user. Some of the more useful functions include:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Layout Name&lt;/li&gt;
&lt;li&gt;Window Mode&lt;/li&gt;
&lt;li&gt;Installed Plugins&lt;/li&gt;
&lt;li&gt;Found count&lt;/li&gt;
&lt;li&gt;Record lock states&lt;/li&gt;
&lt;li&gt;Window Names&lt;/li&gt;
&lt;li&gt;and more..&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;They are very quick to calculate and so why pick and choose - just evaluate the whole lot!&lt;/p&gt;
&lt;p&gt;The script stores a list of every get function in a variable. We then simply loop through, and build up JSON using ithe function name as the key. The value is simply determined by running the function through the &lt;em&gt;Evaluate&lt;/em&gt; function - so simple!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Code for getting get value results&quot; src=&quot;https://www.teamdf.com/assets/blog-images/debugging-reports/_resampled/ResizedImage600101-debugging-reports-3.png&quot; alt=&quot;debugging reports 3&quot; width=&quot;600&quot; height=&quot;101&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;Getting other data&lt;/h2&gt;
&lt;p&gt;Get values, and record values are all fine and good but often the important information about the users session is kept in things such as global variables and fields. Structures that help store information about the user and what they are doing. For example some systems maintain session information in a table, and so it would be useful to know the ID of that session record. Others maintain a user table and so knowing the user ID could be beneficial. Other things too such as the users current position in a wizard, or tab in a layout can be logged providing that information is being tracked by the developer.&lt;/p&gt;
&lt;p&gt;Our debugging script has a section just for this type of information and given the custom nature of the data, needs to be set up by the developer for each specific solution it is used in.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Code for getting other data&quot; src=&quot;https://www.teamdf.com/assets/blog-images/debugging-reports/_resampled/ResizedImage600127-debugging-reports-4.png&quot; alt=&quot;debugging reports 4&quot; width=&quot;600&quot; height=&quot;127&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;Putting it all together&lt;/h2&gt;
&lt;p&gt;Our debug report script takes two parameters:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;A reference to the primary key field (for record value collection)&lt;/li&gt;
&lt;li&gt;A type of data to collate - record, function, other (or all/blank for everything)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;JSON is simply outputted from the script.&lt;/p&gt;
&lt;p&gt;That&#039;s obviously not the end of the story. It&#039;s then up to the developer to make use of the reports and obtain them. One option may be to email the developer the report, another might be to store the report within the solution in a debug table.  Our preference is both of these! We both store the reports and email them to the developer each time one is submitted. Often times the debug report is a prompt to follow up with the user about the issue more.&lt;/p&gt;
&lt;p&gt;In our example file we opt for the storage mechanism only to illustrate how it can work - you kind of get the idea about what would happen with email!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Benefits&lt;/h2&gt;
&lt;p&gt;This tool has already paid for itself for the time it took to develop. It has been used at least a dozen times and every time has really helped narrow down circumstances around a bug and has helped me as a developer replicate the same conditions the user would have experienced at the time.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;No FileMaker Weetbicks article is complete without an example file and so here it is - &lt;a href=&quot;https://www.teamdf.com/assets/blog-images/debugging-reports/easy-to-generate-debugging-reports.zip&quot; target=&quot;_blank&quot;&gt;click here to download the example file&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Thu, 14 Apr 2022 09:39:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/easy-to-generate-debugging-reports/</guid>
		</item>
		
		<item>
			<title>Solving Circular References in Auto Enter Calculations</title>
			<link>https://www.teamdf.com/blogs/circular-references-in-auto-enter-calculations/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this article we&#039;re going to talk about circular references - what they are and how they can happen in FileMaker solutions, specifically with two Auto-Enter Calculation fields. We&#039;ll cover what actually happens in this situation in regards to the order of Auto-Enter execution and why this does not work with a typical use case.&lt;/p&gt;
&lt;p&gt;Often when a circular reference occurs, the developer is actually trying to achieve something that should in theory be possible, and so we&#039;ll talk about this situation and offer a solution that will provide some really useful outcomes. &lt;/p&gt;
&lt;p&gt;In order to help make all this much clearer, let&#039;s jump right in and talk a bit about what a circular reference actually is...&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;circular reference&quot; src=&quot;https://www.teamdf.com/assets/blog-images/circular-reference/_resampled/ResizedImage128128-circular-0.png&quot; alt=&quot;circular reference&quot; width=&quot;128&quot; height=&quot;128&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example file time!&lt;/h2&gt;
&lt;p&gt;As always we include an example file (packed with info and explanation). We recommend downloading and trying it out for yourself while you read.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/circular-reference/solving-circular-autoenters.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;What is a Circular Reference?&lt;/h2&gt;
&lt;p&gt;In programming, a circular reference is defined as a situation in which two values reference each other.  This situation has the potential to be rather problematic if two functions or values depend on another for definition.&lt;/p&gt;
&lt;p&gt;In FileMaker, circular references can occur in the Auto-Enter calculation definition of fields. A scenario can arise where two calculations are dependent upon one another.&lt;/p&gt;
&lt;p&gt;When this happens, FileMaker evaluates them in such a way that the resulting value for both fields is neither one that is desirable or usable.&lt;/p&gt;
&lt;p&gt;Below is an example of two Auto-Enter calculation fields that reference one another. The outcome the developer is trying to achieve is that when the value of one field is 1 the other field should be 0 and vice versa.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;first circular reference&quot; src=&quot;https://www.teamdf.com/assets/blog-images/circular-reference/circular-1.png&quot; alt=&quot;first circular reference&quot; width=&quot;557&quot; height=&quot;96&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;second circular reference&quot; src=&quot;https://www.teamdf.com/assets/blog-images/circular-reference/circular-2.png&quot; alt=&quot;second circular reference&quot; width=&quot;550&quot; height=&quot;93&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;What happens in Auto-Enters?&lt;/h2&gt;
&lt;p&gt;As mentioned, the outcome of circular referencing in FileMaker is one you may not expect and this is due to the order in which FileMaker evaluates both Auto-Enter Calculations.&lt;/p&gt;
&lt;p&gt;Taking our example from before, let&#039;s see what the order of execution looks like:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;The value in &lt;strong&gt;field1&lt;/strong&gt; is modified by the user.&lt;/li&gt;
&lt;li&gt;The Auto-Enter for &lt;strong&gt;field2&lt;/strong&gt; is triggered, which immediately triggers the Auto-Enter for &lt;strong&gt;field1&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The Auto-Enter for &lt;strong&gt;field1&lt;/strong&gt; is evaluated, and it&#039;s current value is overwritten with the result.&lt;/li&gt;
&lt;li&gt;Now the Auto-Enter for &lt;strong&gt;field2&lt;/strong&gt; finally evaluates.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt; It&#039;s confusing for sure and is best illustrated with an example&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;An example of the issue&lt;/h2&gt;
&lt;p&gt;Again we have 2 fields we wish to toggle the values in between 1 and 0.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;circular toggle example&quot; src=&quot;https://www.teamdf.com/assets/blog-images/circular-reference/circular-3.png&quot; alt=&quot;circular toggle example&quot; width=&quot;285&quot; height=&quot;179&quot;&gt;&lt;/p&gt;
&lt;p&gt;Let&#039;s start by changing the value in field1 from blank to &quot;1&quot;:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Value of &lt;strong&gt;field1&lt;/strong&gt; is set to &quot;1&quot; by the user.&lt;/li&gt;
&lt;li&gt;Auto-Enter for &lt;strong&gt;field2&lt;/strong&gt; triggered, and immediately triggers the Auto-Enter in &lt;strong&gt;field1&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Auto-Enter for &lt;strong&gt;field1&lt;/strong&gt; evaluates &lt;em&gt;(not &quot;&quot; = 1)&lt;/em&gt; and value is set to &quot;1&quot;.&lt;/li&gt;
&lt;li&gt;Auto-Enter for &lt;strong&gt;field2&lt;/strong&gt; evaluates &lt;em&gt;(not 1)&lt;/em&gt; and value set to &quot;0&quot;.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;While upon initial inspection it may look like we got the intended result, let&#039;s now try setting field1 to 0. We would hope that field2 is set to 1:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;value of field1 is set to &quot;0&quot; by the user.&lt;/li&gt;
&lt;li&gt;Auto-Enter for &lt;strong&gt;field2&lt;/strong&gt; triggered, and immediately triggers the Auto-Enter in &lt;strong&gt;field1&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Auto-Enter for &lt;strong&gt;field1&lt;/strong&gt; evaluates &lt;em&gt;(not 0 = 1)&lt;/em&gt; and value remains at &quot;1&quot;.&lt;/li&gt;
&lt;li&gt;Auto-Enter for &lt;strong&gt;field2&lt;/strong&gt; evaluates &lt;em&gt;(not 1 = 0)&lt;/em&gt; and value remains at &quot;0&quot;.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Hmm, that&#039;s not quite what we want is it? In fact, once the first values are defined in these fields, they cannot be changed thereafter because the Auto-Enter firing on &lt;strong&gt;field1&lt;/strong&gt; prevents this by overwriting the new value the user just entered.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;What do we actually want?&lt;/h2&gt;
&lt;p&gt;So that sucks for sure - but can we bend the laws of FileMaker into our favour to provide a beneficial outcome?  Turns out we can!&lt;/p&gt;
&lt;p&gt;First let&#039;s look at what as a developer we might actually want that outcome to look like:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;If the value in &lt;strong&gt;field1&lt;/strong&gt; is modified by the user, then evaluate the Auto-Enter of &lt;strong&gt;field2&lt;/strong&gt; ONLY.&lt;/li&gt;
&lt;li&gt;If the value in &lt;strong&gt;field2&lt;/strong&gt; is modified by the user, then evaluate the Auto-Enter of &lt;strong&gt;field1&lt;/strong&gt; ONLY. &lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The key here is &lt;strong&gt;ONLY&lt;/strong&gt;. We want the fields to reference one another but to not result in a circular reference by way of only one of the Auto-Enter calculations being evaluated - dependent upon the field being actively modified.&lt;/p&gt;
&lt;p&gt;Can we do this? Yes we can!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;A proposed solution example&lt;/h2&gt;
&lt;p&gt;Going back to our earlier example, here is what the new behaviour will be.&lt;/p&gt;
&lt;p&gt;Let&#039;s start by changing the value in field1 from blank to &quot;1&quot;:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Value of &lt;strong&gt;field1&lt;/strong&gt; set to &quot;1&quot; by user.&lt;/li&gt;
&lt;li&gt;Auto-Enter for &lt;strong&gt;field2&lt;/strong&gt; triggered and evaluated &lt;em&gt;(not 1 = 0)&lt;/em&gt; and value set to &quot;0&quot;.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Now change the value in field2 from 0 to 1:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Value of &lt;strong&gt;field2&lt;/strong&gt; set to &quot;1&quot; by user.&lt;/li&gt;
&lt;li&gt;Auto-Enter for &lt;strong&gt;field1&lt;/strong&gt; triggered and evaluated &lt;em&gt;(not 1 = 0)&lt;/em&gt; and value set to &quot;0&quot;.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;The @AE_switch custom function&lt;/h2&gt;
&lt;p&gt;The solution is achieved through creating a Custom Function  (to make life easier) called @AE_switch.  Now, the code is obviously the most interesting part but let&#039;s establish what information is passed to the function first to help set the scene:&lt;/p&gt;
&lt;pre&gt;@AE_switch ( _f1 ; _f2 ; _self ; _expressionTrigger ; _expressionSelf )&lt;/pre&gt;
&lt;p&gt;The parameters are:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;_f1:&lt;/strong&gt;  A reference to the first field in the circular reference.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;_f2:&lt;/strong&gt; A reference to the second field in the circular reference.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;_self:&lt;/strong&gt; A reference to the current field this function is defined in.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt; _expressionTrigger:&lt;/strong&gt; An expression to evaluate upon this field being triggered by the other field.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;_expressionSelf:&lt;/strong&gt; An expression to evaluate upon this field being triggered by itself changing.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;A couple of important things to note:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;The references to &lt;strong&gt;_f1&lt;/strong&gt; and &lt;strong&gt;_f2&lt;/strong&gt; can just be direct references (not hard-coded). However it&#039;s important that in both Auto-Enter calculations where you define this function that the fields you define for &lt;strong&gt;_f1&lt;/strong&gt; and &lt;strong&gt;_f2&lt;/strong&gt; remain consistent.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;_self&lt;/strong&gt; is simply a reference to the function &lt;em&gt;&quot;self&quot;&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Another interesting thing is the usage of _expressionSelf. This is actually optional, but what this allows you to do is define an expression to evaluate upon the field being triggered by the user. This occurs before the Auto-Enter calculation on the other field is executed. Think of this is a way you can still pre-format a fields value, such as ensuring it is a positive number, or filtering out certain unwanted characters. &lt;/p&gt;
&lt;p&gt;If you don&#039;t wish to use an _expressionSelf then just set this to &lt;em&gt;Self&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;How it works&lt;/h2&gt;
&lt;p&gt;Right so we&#039;re finally getting to the good stuff. We want to control the order of execution of Auto-Enter calculations and we do this through two special local variables. Firstly let&#039;s take a look at the function code (you can scroll the code sideways..) &lt;/p&gt;
&lt;pre class=&quot;p1&quot;&gt;Let ( [&lt;br&gt;  ~self = GetFieldName ( _self ) ;&lt;br&gt;  ~me = Case ( ~self = GetFieldName ( _f1 ) ; 1 ; ~self = GetFieldName ( _f2 ) ; 2 ; &quot;&quot; )&lt;br&gt;] ;&lt;br&gt;  Case (&lt;br&gt;    IsEmpty ( ~me ) ; _expressionTrigger ;&lt;br&gt;    ~me = 1 ; If ( $AE_switch2 ; _expressionTrigger &amp;amp; Let ( $AE_switch2 = &quot;&quot; ; &quot;&quot; ) ; Let ( $AE_switch1 = True ; _expressionSelf ) ) ;&lt;br&gt;    ~me = 2 ; If ( $AE_switch1 ; _expressionTrigger &amp;amp; Let ( $AE_switch1 = &quot;&quot; ; &quot;&quot; ) ; Let ( $AE_switch2 = True ; _expressionSelf ) ) ;&lt;span class=&quot;Apple-converted-space&quot;&gt; &lt;br&gt;&lt;/span&gt;    &quot;&quot;&lt;br&gt;  )&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;Note that this function is called in the Auto-Enter calculations of two fields.&lt;/p&gt;
&lt;p&gt;We start by getting the field names of the two fields, and then compare them to the name of the field that this current function is defined in.&lt;/p&gt;
&lt;p&gt;This tells us the context in which the current function is being evaluated  (&lt;strong&gt;field1&lt;/strong&gt; or &lt;strong&gt;field2&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;If for any reason the field is not one of the two defined to be in the circular reference (unlikely) then we just run the expression passed. Think of this as a fallback.&lt;/p&gt;
&lt;p&gt;However almost certainly the field will be either that defined in &lt;strong&gt;_f1&lt;/strong&gt; or &lt;strong&gt;_f2&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We use two switch variables called $AE_switch1 and $AE_switch2.  When a switch variable is enabled, it is telling both Auto-Enter calculations which field is currently actively being evaluated, and thus suppresses the other field from evaluating its expression at that particular time.&lt;/p&gt;
&lt;p&gt;For example if $AE_switch1 is enabled, this means that the user modified &lt;strong&gt;_f1&lt;/strong&gt;. In this case we only wish &lt;strong&gt;_f1&lt;/strong&gt; to evaluate its defined &lt;strong&gt;_expressionSelf&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;When &lt;strong&gt;_f2&lt;/strong&gt; is triggered, it sees that $AE_switch1 is enabled, thus it knows the user modified &lt;strong&gt;_f1&lt;/strong&gt; first, and so it is to evaluate its defined &lt;strong&gt;_expressionTrigger&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Again, these types of things are best illustrated with an example...&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;An Example&lt;/h2&gt;
&lt;p&gt;Let&#039;s return to our toggle example, but this we&#039;ll define each fields Auto-Enter calculations as follows:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;for field1:&lt;/p&gt;
&lt;pre&gt;@AE_switch ( field1 ; field2 ; Self ; not field2 ; If ( Self &amp;lt; 0 ; 0 ; Min ( Self ; 1 ) ) ) &lt;br&gt;&lt;br&gt;&lt;/pre&gt;
&lt;p&gt;and for field2:&lt;/p&gt;
&lt;pre&gt;@AE_switch ( field1 ; field2 ; Self ; not field1 ; If ( Self &amp;lt; 0 ; 0 ; Min ( Self ; 1 ) ) ) &lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;The only thing different in both definitions is the value of &lt;strong&gt;_expressionTrigger&lt;/strong&gt; which is actually our initial calculation definitions.&lt;/p&gt;
&lt;p&gt;You&#039;ll note an interesting expression for _expressionSelf. This is an expression to pre-format a number entered such that it set to 0 for values less than 0, and 1 for values greater than 1.&lt;/p&gt;
&lt;p&gt;Putting it all together now, let&#039;s change the value of field1 to 5:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;field1&lt;/strong&gt; changed to 5 by user.&lt;/li&gt;
&lt;li&gt;Auto-Enter for &lt;strong&gt;field2&lt;/strong&gt; triggered, and immediately triggers the Auto-Enter in &lt;strong&gt;field1&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Auto-Enter of &lt;strong&gt;field1&lt;/strong&gt; evaluates:&lt;/li&gt;
&lt;ol&gt;&lt;li&gt;Case ~me = 1 &lt;em&gt;(Yes):&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;If $AE_switch2 on? &lt;em&gt;(No):&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Turn $AE_switch1 on, and evaluate _expressionSelf:  &lt;em&gt;Min ( 5 ; 1 ) = 1&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;&lt;li&gt;Value of &lt;strong&gt;field1 &lt;/strong&gt;is set to 1.&lt;/li&gt;
&lt;li&gt;Auto-Enter of &lt;strong&gt;field2&lt;/strong&gt; evaluates:&lt;/li&gt;
&lt;ol&gt;&lt;li&gt;Case ~me = 2 (Yes):&lt;/li&gt;
&lt;li&gt;If $AE_switch1 on? &lt;em&gt;(Yes)&lt;/em&gt;:&lt;/li&gt;
&lt;li&gt;Turn $AE_switch1 off, and evaluate _expressionTrigger: &lt;em&gt;not 1 = 0.&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;li&gt;Value of &lt;strong&gt;field2&lt;/strong&gt; is set to 0.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Finally how about setting the value of field2 to -1000?&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;field2&lt;/strong&gt; changed to -1000 by user.&lt;/li&gt;
&lt;li&gt;Auto-Enter for &lt;strong&gt;field1&lt;/strong&gt; triggered, and immediately triggers the Auto-Enter in &lt;strong&gt;field2&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Auto-Enter of &lt;strong&gt;field2&lt;/strong&gt; evaluates:&lt;/li&gt;
&lt;ol&gt;&lt;li&gt;Case ~me = 2 &lt;em&gt;(Yes):&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;If $AE_switch1 on? &lt;em&gt;(No):&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Turn $AE_switch2 on, and evaluate _expressionSelf:  &lt;em&gt;Self &amp;lt; 0, so result = 0&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;&lt;li&gt;Value of &lt;strong&gt;field2 &lt;/strong&gt;is set to 0.&lt;/li&gt;
&lt;li&gt;Auto-Enter of &lt;strong&gt;field1&lt;/strong&gt; evaluates:&lt;/li&gt;
&lt;ol&gt;&lt;li&gt;Case ~me = 1 (Yes):&lt;/li&gt;
&lt;li&gt;If $AE_switch2 on? &lt;em&gt;(Yes)&lt;/em&gt;:&lt;/li&gt;
&lt;li&gt;Turn $AE_switch2 off, and evaluate _expressionTrigger: &lt;em&gt;not 0 = 1.&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;li&gt;Value of &lt;strong&gt;field1&lt;/strong&gt; is set to 1.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Brilliant! We have now hijacked the normal circular reference execution in order to achieve our desired outcome!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Other Uses&lt;/h2&gt;
&lt;p&gt;This technique was originally borne out of the challenge of solving this circular reference issue. We have however utilised this in real world solutions for things other than toggles.&lt;/p&gt;
&lt;p&gt;The most common scenario is one where events are being entered. An event generally has a start and finish date. We can calculate the duration of an event based on subtracting the start date from the finish date.&lt;/p&gt;
&lt;p&gt;But what if the user wants to provide ability to specify either duration or finish date? Here we have a circular reference:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;End date is Auto-Entered based on Start Date + Duration&lt;/li&gt;
&lt;li&gt;Duration is Auto-Entered based on Finish Date - Start Date.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Both End Date and Duration reference each other. We however only wish for one to Auto-Enter when the other is changed by the user.&lt;/p&gt;
&lt;p&gt;We can apply our function very easily to this scenario to allow a user to specify an event either by duration, or by a finish date.&lt;/p&gt;
&lt;p&gt;Furthermore, we can use the _expressionSelf parameter to ensure both duration and finish date are safely entered with valid values before proceeding.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We hope you enjoyed this article and learned something about the weird nature of Auto-Enter calculations and circular references. Once you understand how a circular reference is executed, the solution becomes apparent that we need to control execution through some control variables otherwise we can never achieve a desired outcome.&lt;/p&gt;
&lt;p&gt;For a while now I&#039;ve been writing design based articles but I really enjoyed getting back into some more technical stuff. If you like this article and wish to see more technical oriented content in future please let me know &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;Please have a look at our example file if not already. This has everything you need to implement the @AE_switch custom function as well as a large amount of background info and explanation (which you can also find int his article).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/circular-reference/solving-circular-autoenters.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file!&lt;/a&gt;&lt;a href=&quot;https://www.teamdf.com/[file_link,id=]&quot; target=&quot;_blank&quot;&gt;&lt;br&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Thu, 31 Mar 2022 10:11:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/circular-references-in-auto-enter-calculations/</guid>
		</item>
		
		<item>
			<title>A Clever CSS Chat Display.</title>
			<link>https://www.teamdf.com/blogs/clever-css-chat-display/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this article we&#039;re going to take a look at a very simple approach to displaying an internal chat conversation in FileMaker. The premise is simple - we have a series of messages that need displaying and we want it to look like your standard messaging app (think Messenger, Slack or WhatsApp).&lt;/p&gt;
&lt;p&gt;The underlying chat framework is all FileMaker, this is purely an exercise in display, and trying to make it as simple as possible to implement for developers.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/css-chat/chat-01.jpg&quot; alt=&quot;chat 01&quot; width=&quot;660&quot; height=&quot;418&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;What&#039;s the Issue?&lt;/h2&gt;
&lt;p&gt;If we just want to display messages - which are themselves records in a table - then you may think &quot;why not just use a portal, or list view&quot;.  Well there are a couple of reasons why these are not that suitable.&lt;/p&gt;
&lt;p&gt;The first is a question of size.  We have no way of knowing how large a chat message will be and thus how big to make a field that needs to display it. FileMaker portals have to be of a fixed height, and so while we can simulate a messaging display, the crucial thing we cannot do is dynamically determine a portal rows height.&lt;/p&gt;
&lt;p&gt;Similarly with list-view, unless we are viewing a chat in preview mode (not very useful) then we cannot dynamically determine size of a row.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Why Not Javascript?&lt;/h2&gt;
&lt;p&gt;In searching for a suitable way to solve this issue, we obviously approached Javascript given its reputation as being a problem solver for things that cannot be solved with out of the box FileMaker tools.&lt;/p&gt;
&lt;p&gt;Javascript does offer a number of chat implementations however these are primarily focussed on website chat, such as end user / customer interaction. They also focus heavily on the communication protocol and delve into the need to set up web servers, listeners etc - all well beyond the scope of our requirement.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 600px;&quot;&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 600px;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/css-chat/_resampled/ResizedImage600224-chat-02.png&quot; alt=&quot;chat 02&quot; width=&quot;600&quot; height=&quot;224&quot;&gt;&lt;p class=&quot;caption center&quot; style=&quot;text-align: center;&quot;&gt;Wait, set up what now?&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;This is a good time to mention that as always we include an example file for this article. It pays to check it out as it will help make sense of what we discuss below, as well as showing you what we&#039;re implementing.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/css-chat/css-chat.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the Example File. &lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;HTML to the Rescue!&lt;/h2&gt;
&lt;p&gt;The question was asked - why not just build a display using some basic HTML and CSS? If we could generate some HTML code - styled with CSS - then perhaps that&#039;s all we need.  That is exactly what we did!&lt;/p&gt;
&lt;p&gt;Consider a &amp;lt;div&amp;gt; tag.  &lt;a href=&quot;https://www.w3schools.com/tags/tag_div.asp&quot; target=&quot;_blank&quot;&gt;W3 Schools&lt;/a&gt; defines a &amp;lt;div&amp;gt; tag as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &amp;lt;div&amp;gt; tag defines a division or a section in an HTML document.&lt;/p&gt;
&lt;p&gt;The &amp;lt;div&amp;gt; tag is used as a container for HTML elements - which is &lt;strong&gt;styled with CSS&lt;/strong&gt; or manipulated with JavaScript.&lt;/p&gt;
&lt;p&gt;The &amp;lt;div&amp;gt; tag is easily styled by using the class or id attribute.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; All we need to do is generate a &amp;lt;div&amp;gt; tag for each message and have it render within.  We can then also use CSS to style the contents of that div however we choose.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 443px; text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/css-chat/chat-03.png&quot; alt=&quot;A simple &amp;lt;div&amp;gt; tag&quot; width=&quot;443&quot; height=&quot;99&quot;&gt;&lt;p class=&quot;caption center&quot;&gt;What a simple &amp;lt;div&amp;gt; tag looks like.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;And CSS to the Rescue!&lt;/h2&gt;
&lt;p&gt;As mentioned, the real power here is in the CSS. With CSS we can apply virtually any kind of formatting to the contents inside our &amp;lt;div&amp;gt; tag. In this case we&#039;re going to format it to look like a chat bubble.&lt;/p&gt;
&lt;p&gt;Consider a standard chat display. There is a left side (message sent by you, the person viewing the chat), and a right side (message sent by everyone else).&lt;/p&gt;
&lt;p&gt;We also want to display in this way, and so what we need is 2 different styles - one to format a message on the left hand side, and one to format a message on the right hand side.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example: A Basic Chat framework&lt;/h2&gt;
&lt;p&gt;In order to talk through how we build our HTML, let&#039;s first consider a very basic chat framework. This has been implemented in our example file just enough to show a chat conversation being displayed.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/css-chat/chat-11.jpg&quot; alt=&quot;chat 11&quot; width=&quot;612&quot; height=&quot;107&quot;&gt;&lt;/p&gt;
&lt;p&gt;The basic structure is:&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;strong&gt;Chat&lt;/strong&gt;:&lt;strong&gt; &lt;/strong&gt;1 record per chat (in our example we restrict it to 1 record)&lt;br&gt;&lt;strong&gt;ChatMessages&lt;/strong&gt;:&lt;strong&gt; &lt;/strong&gt;1 record per individual message sent for a given chat.&lt;br&gt;&lt;strong&gt;Users&lt;/strong&gt;:&lt;strong&gt; &lt;/strong&gt;This has 1 record per user of your solution. Note some solutions don&#039;t have a User table, in which case you can just use your FileMaker account names as a substitute.&lt;br&gt;&lt;strong&gt;ChatUsers&lt;/strong&gt;:&lt;strong&gt; &lt;/strong&gt;Defines who is participating in the chat. 1 record per user (or account) per chat. This is simply a join table between Users and Chat.&lt;/p&gt;
&lt;p&gt;So pretty straightforward. With the above framework there is potential to have multiple different chats going on in your solution, involving different people for different purposes.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Formatting a Message Display&lt;/h2&gt;
&lt;p&gt;First we&#039;re going to focus on the ChatMessages table because this is where we need to take our message and turn it into some HTML code for viewing.&lt;/p&gt;
&lt;p&gt;In this table you&#039;ll find a field called message_json. This is a JSON representation of the chat message for display. It contains 2 pieces of information:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;The JSON message&quot; src=&quot;https://www.teamdf.com/assets/blog-images/css-chat/_resampled/ResizedImage60085-chat-04.png&quot; alt=&quot;The JSON message&quot; width=&quot;600&quot; height=&quot;85&quot;&gt;&lt;/p&gt;
&lt;p&gt;The first is &quot;owner&quot;. The owner of a message is a unique identifier of who created it. If you are using the framework above, then this is going to be the ChatUser ID of the person who created the message.&lt;/p&gt;
&lt;p&gt;The second value &quot;message&quot; is a reference to a custom function called @CHAT_messageFormat. We have abstracted the code into a custom function because it is easier to digest, and reusable.&lt;/p&gt;
&lt;p&gt;This function takes 3 parameters:&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;strong&gt;_owner&lt;/strong&gt;: in this case it is a display name for the owner, such as user name or account name.&lt;br&gt;&lt;strong&gt;_message&lt;/strong&gt;: The actual chat message.&lt;br&gt;&lt;strong&gt;_timestamp&lt;/strong&gt;: A timestamp of when the message was created.&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/css-chat/_resampled/ResizedImage600165-chat-05.png&quot; alt=&quot;chat 05&quot; width=&quot;600&quot; height=&quot;165&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now, this function is purely for constructing some HTML in whatever format you desire. In our case we have utilised another custom function &lt;em&gt;@DATE_format&lt;/em&gt; (which we love!) to make our timestamp into a nicer format.&lt;/p&gt;
&lt;p&gt;The HTML part comprises of a single &amp;lt;div&amp;gt; and two &amp;lt;p&amp;gt; tags. In our &amp;lt;p&amp;gt; tags we place the message along with the owner &amp;amp; timestamp.&lt;/p&gt;
&lt;p&gt;You will note that our second line with the owner &amp;amp; timestamp is assigned a class &lt;strong&gt;owner&lt;/strong&gt;. This is so we can use CSS to style this line separately by defining a class of the same name.&lt;/p&gt;
&lt;p&gt;Our main &amp;lt;div&amp;gt; actually has two classes defined for it:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;chat-message&lt;/li&gt;
&lt;li&gt;chat-message-[SIDE]&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The first class is for general formatting of the message, things like font, sizes etc. The second is for positioning a message either left/right, and for colouring accordingly.  Note that &lt;strong&gt;[SIDE]&lt;/strong&gt; is actually a placeholder that we are going to replace when the time comes with either the word &quot;left&quot; or &quot;right&quot;.&lt;/p&gt;
&lt;p&gt;So in actuality there are two classes for this called &lt;strong&gt;chat-message-left&lt;/strong&gt; and &lt;strong&gt;chat-message-right&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Styling the Message&lt;/h2&gt;
&lt;p&gt;If we take a look at the CSS, it&#039;s pretty easy to follow and see how messages are formatted. We won&#039;t go into the technicalities of CSS, suffice to say you&#039;ll find it easy to locate the above classes and make formatting changes. The key classes defined are:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;.chat-container .chat-message: &lt;/strong&gt;Padding and font properties of a message box&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;.chat-container .chat-message p: &lt;/strong&gt;Formatting of the main message content&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;.chat-container .chat-message p.owner: &lt;/strong&gt;Formatting of the second line of owner name &amp;amp; timestamp&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;.chat-container .chat-message-left/right: &lt;/strong&gt;Coloring of the left/right hand message box accordingly.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;There are others but we won&#039;t get into these but you can&#039;t go wrong having a play and seeing what they do. &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Our CSS&quot; src=&quot;https://www.teamdf.com/assets/blog-images/css-chat/_resampled/ResizedImage600489-chat-06.png&quot; alt=&quot;Our CSS&quot; width=&quot;600&quot; height=&quot;489&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Constructing the HTML&lt;/h2&gt;
&lt;p&gt;Okay so now we have a bunch of messages with a representation in HTML. We now need to generate the overall HTML to be rendered in the web viewer which will comprise multiple &amp;lt;div&amp;gt; tags - 1 per message.&lt;/p&gt;
&lt;p&gt;This is simply an exercise of finding our set of messages and looping through them to build up the HTML.&lt;/p&gt;
&lt;p&gt;To make this as simple as possible, we&#039;ll take our JSON payload from earlier, and collate a list of these which we feed to a special custom function &lt;strong&gt;@CHAT_buildMessages&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;It is important to collate the jSON from your records in chronological order because the order in which we build is the order in which they will be displayed.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Constructing the HTML&quot; src=&quot;https://www.teamdf.com/assets/blog-images/css-chat/_resampled/ResizedImage600188-chat-07.png&quot; alt=&quot;Constructing the HTML&quot; width=&quot;600&quot; height=&quot;188&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Our custom function takes 2 parameters:&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;strong&gt;_owner&lt;/strong&gt;: the unique identifier representing who is currently viewing the chat&lt;br&gt;&lt;strong&gt;_messageList&lt;/strong&gt;: A return delimited list of JSON objects, one per message.&lt;/p&gt;
&lt;p&gt;We use a simple While function to loop through each JSON message. From within each message we check the value of the &quot;owner&quot; key, and compare this to the &quot;owner&quot; passed through in the function parameter. This tells us whether the message belongs to the owner and thus should be formatted with the &lt;em&gt;left&lt;/em&gt; class, or whether we instead format it with the &lt;em&gt;right&lt;/em&gt; class.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The End Result&lt;/h2&gt;
&lt;p&gt;Put it all together and you get something this:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;CSS chat!&quot; src=&quot;https://www.teamdf.com/assets/blog-images/css-chat/_resampled/ResizedImage600239-chat-08.png&quot; alt=&quot;CSS chat!&quot; width=&quot;600&quot; height=&quot;239&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Here you can see that Daniel is selected as the owner, and thus all of Daniels messages are displayed on the left side.  If we switch perspective instead to Cath, we now see all her messages on the left.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;the chat from a different users perspective&quot; src=&quot;https://www.teamdf.com/assets/blog-images/css-chat/_resampled/ResizedImage600238-chat-09.png&quot; alt=&quot;the chat from a different users perspective&quot; width=&quot;600&quot; height=&quot;238&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;The main content of the HTML looks like this:&lt;/p&gt;
&lt;pre&gt;&amp;lt;body  = &#039;footer&#039;&quot;&amp;gt;&lt;br&gt;&amp;lt;div class=&quot;chat-container chat-push&quot;&amp;gt;&lt;br&gt;&amp;lt;div class=&quot;chat-message chat-message-right&quot;&amp;gt;&lt;br&gt;&amp;lt;p&amp;gt;&amp;lt;span style=&quot;&quot; &amp;gt;Hi all. Just wanted to let you all know that we will be heading out for lunch on Friday next week&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;p class=&quot;owner&quot;&amp;gt;Daniel Sun 27/2/22 10:20 am&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;/div&amp;gt;&lt;br&gt;&amp;lt;div class=&quot;chat-message chat-message-left&quot;&amp;gt;&lt;br&gt;&amp;lt;p&amp;gt;&amp;lt;span style=&quot;&quot; &amp;gt;Cool, can&#039;t wait!&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;p class=&quot;owner&quot;&amp;gt;Cath Sun 27/2/22 10:25 am&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;/div&amp;gt;&lt;br&gt;&amp;lt;div class=&quot;chat-message chat-message-right&quot;&amp;gt;&lt;br&gt;&amp;lt;p&amp;gt;&amp;lt;span style=&quot;&quot; &amp;gt;????&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;p class=&quot;owner&quot;&amp;gt;James Sun 27/2/22 10:39 am&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;/div&amp;gt;&lt;br&gt;&amp;lt;div class=&quot;chat-message chat-message-right&quot;&amp;gt;&lt;br&gt;&amp;lt;p&amp;gt;&amp;lt;span style=&quot;&quot; &amp;gt;I can&#039;t make it sorry, thanks for the invite though.&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;p class=&quot;owner&quot;&amp;gt;Mary Sun 27/2/22 10:45 am&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;/div&amp;gt;&lt;br&gt;&amp;lt;div class=&quot;chat-message chat-message-right&quot;&amp;gt;&lt;br&gt;&amp;lt;p&amp;gt;&amp;lt;span style=&quot;&quot; &amp;gt;All good Mary, thanks for letting me know.&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;p class=&quot;owner&quot;&amp;gt;Daniel Sun 27/2/22 2:49 pm&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;/div&amp;gt;&lt;br&gt;&amp;lt;div class=&quot;chat-message chat-message-left&quot;&amp;gt;&lt;br&gt;&amp;lt;p&amp;gt;&amp;lt;span style=&quot;&quot; &amp;gt;Hey Daniel, will there be vegetarian options available?&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;p class=&quot;owner&quot;&amp;gt;Cath Mon 28/2/22 8:58 am&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;/div&amp;gt;&lt;br&gt;&amp;lt;div class=&quot;chat-message chat-message-right&quot;&amp;gt;&lt;br&gt;&amp;lt;p&amp;gt;&amp;lt;span style=&quot;&quot; &amp;gt;Yes they cater to vegetarians and vegans. There is a menu online, I&#039;ll email you further details&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;p class=&quot;owner&quot;&amp;gt;Daniel Mon 28/2/22 9:05 am&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;/div&amp;gt;&lt;br&gt;&amp;lt;div class=&quot;chat-message chat-message-left&quot;&amp;gt;&lt;br&gt;&amp;lt;p&amp;gt;&amp;lt;span style=&quot;&quot; &amp;gt;Thanks!&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;p class=&quot;owner&quot;&amp;gt;Cath Mon 28/2/22 10:41 am&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;/div&amp;gt;&lt;br&gt;&amp;lt;div class=&quot;chat-message chat-message-right&quot;&amp;gt;&lt;br&gt;&amp;lt;p&amp;gt;&amp;lt;span style=&quot;&quot; &amp;gt;I&#039;m off for a run&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;p class=&quot;owner&quot;&amp;gt;James Mon 28/2/22 12:30 pm&amp;lt;/p&amp;gt;&lt;br&gt;&amp;lt;/div&amp;gt;&lt;br&gt;&amp;lt;/div&amp;gt;&lt;br&gt;&amp;lt;/body&amp;gt;&lt;/pre&gt;
&lt;p&gt;Nothing more than a series of &amp;lt;div&amp;gt; tags, with the appropriate style applied - so simple!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Taking it Further&lt;/h2&gt;
&lt;p&gt;Now, this is meant to illustrate a very basic approach to a chat display and we think we achieved this satisfactorily. However there are some things to consider:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;This is not live. You need to refresh the entire chat if a message is added&lt;/li&gt;
&lt;li&gt;Given the entire message is refreshed, incredibly long chats might take longer to build&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The intention of this is for relatively small chats within a solution, that aren&#039;t &quot;live&quot; chats. However we see potential to extend this in a number of ways, one of which is actually utilising Javascript to dynamically add &amp;lt;div&amp;gt; tags to the HTML when a message is received. We could utilise the Javascript functionality in FileMaker 19 to push new messages to a web viewer, or have the chat be entirely loaded by javascript functions.&lt;/p&gt;
&lt;p&gt;We&#039;d love to see what you&#039;d come up with!&lt;/p&gt;
&lt;p&gt;Other cool potential things that could be done with this include:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Adding an avatar image to the display for a user&lt;/li&gt;
&lt;li&gt;Customising message colors per user&lt;/li&gt;
&lt;li&gt;Clickable links in messages that run scripts, or open URLs&lt;/li&gt;
&lt;li&gt;Hover states on messages&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 600px; text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;W3 Schools has an example of an Avatar chat&quot; src=&quot;https://www.teamdf.com/assets/blog-images/css-chat/_resampled/ResizedImage600150-chat-10.png&quot; alt=&quot;W3 Schools has an example of an Avatar chat&quot; width=&quot;600&quot; height=&quot;150&quot;&gt;&lt;p class=&quot;caption center&quot; style=&quot;text-align: center;&quot;&gt;W3 Schools has an example of an Avatar chat display&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;Here again is a download link to our example file. We hope you find it useful:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/css-chat/css-chat.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 22 Mar 2022 08:13:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/clever-css-chat-display/</guid>
		</item>
		
		<item>
			<title>A Cooler Color Picker</title>
			<link>https://www.teamdf.com/blogs/a-cooler-color-picker/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Allowing a user to easily select a color in your FileMaker solution is hugely beneficial. Often times we need a user to pick a color for something such as a status, a way to identify a record, or a color for a chart.&lt;/p&gt;
&lt;p&gt;We want to provide a simple approach for the user in which they can visually select a color instead of entering it as hexadecimal or RGB values.&lt;/p&gt;
&lt;p&gt;Currently in the FileMaker world there are 2 approaches, both of which utilise a web viewer. One is to use HTML5 to use the native OS color picker and the other is to use a javascript based color picker library.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;OS Color Picker&quot; src=&quot;https://www.teamdf.com/assets/blog-images/colorpicker/colorpicker-1.png&quot; alt=&quot;OS Color Picker&quot; width=&quot;317&quot; height=&quot;301&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p&gt;The native OS picker is visually very nice. Its major benefit is that it is not limited to the confines of the web viewer, and so the web viewer object itself merely acts as a color swatch displaying the selected color. You can find examples of an OS color picker approach in my &lt;a title=&quot;elemental_fm&quot; href=&quot;http://www.elemental-fm.com&quot; target=&quot;_blank&quot;&gt;elemental_ux&lt;/a&gt; solution.&lt;/p&gt;
&lt;p&gt;However one of the big drawbacks I see with the OS picker is its cross-platform differences. You will get a different experience on a Mac versus on Windows. The picker also doesn&#039;t work at all on FileMaker Go, and is flaky on WebDirect.&lt;/p&gt;
&lt;p&gt;For these reasons we went with a javascript based approach.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;Example files sit at the core of all our articles and much time and love goes into them, not only to present a particular technique but also as a way for us to help refine the technique.  We always encourage you to download and try out the example file for yourself as the best way to read and understand the article is by having the example file open at the same time and exploring both.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/colorpicker/a-cooler-colorpicker.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the Color Picker example file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h2&gt;The Javascript Approach&lt;/h2&gt;
&lt;p&gt;By using a javascript based color picker we achieve the following benefits:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Cross-platform consistency - it works the same on all platforms.&lt;/li&gt;
&lt;li&gt;Additional configuration options - you have more control over the pickers setup, look and feel.&lt;/li&gt;
&lt;li&gt;Simple reusable code&lt;/li&gt;
&lt;li&gt;Utilises &lt;strong&gt;FileMaker.PerformScript&lt;/strong&gt; javascript call to pass color back to FileMaker.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;In looking for a suitable javascript library for a color picker our main requirement was that the picker be large enough in size to be presentable in a card window as well as a popover. We also wanted it to be simple to implement and customisable for developers.&lt;/p&gt;
&lt;p&gt;We went with the Pickr library which you can find &lt;a title=&quot;Pickr&quot; href=&quot;https://github.com/Simonwep/pickr&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Our Standard Color Picker&quot; src=&quot;https://www.teamdf.com/assets/blog-images/colorpicker/colorpicker-2.png&quot; alt=&quot;Our Standard Color Picker&quot; width=&quot;472&quot; height=&quot;189&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Two different implementations&lt;/h2&gt;
&lt;p&gt;We mentioned before the requirement to have the picker work in both a card window and a popover.  The reason for this is that web viewers do not work when placed inside a portal and so if you wanted to select a color from within one you would need to find an approach where the color was selected outside of the portal.&lt;/p&gt;
&lt;p&gt;We found building a simple card window layout containing the web viewer for the color picker was ideal. When a color needs to be selected, the picker is invoked, a color is chosen, and the card closes. Upon closing the requested field is populated with the chosen color (more on how this works later).&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Card Window Color Picker&quot; src=&quot;https://www.teamdf.com/assets/blog-images/colorpicker/_resampled/ResizedImage600363-colorpicker-3.png&quot; alt=&quot;Card Window Color Picker&quot; width=&quot;600&quot; height=&quot;363&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;We still wanted to offer an approach where the color picker is able to placed within an existing layout for times when a color is chosen outside of a portal. For this approach we utilise a popover. This allows you to have multiple pickers on the same layout.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Popover Color Picker&quot; src=&quot;https://www.teamdf.com/assets/blog-images/colorpicker/_resampled/ResizedImage600355-colorpicker-4.png&quot; alt=&quot;Popover Color Picker&quot; width=&quot;600&quot; height=&quot;355&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Card Window Approach&lt;/h2&gt;
&lt;p&gt;The card window picker can be utilised anywhere by any button, to set any field. The basic workflow is as follows:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;The user has a field to set a color into - let&#039;s call this &lt;strong&gt;Home::color&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;The user invokes the &lt;strong&gt;ColorPicker_Open&lt;/strong&gt; script, passing it the name of the field to be set, and the type of picker being used &quot;card&quot;.&lt;/li&gt;
&lt;li&gt;The card window opens, and the color picker is rendered in the web viewer&lt;/li&gt;
&lt;li&gt;The user makes their choice of color and presses &quot;save&quot; (or alternatively presses &quot;clear&quot; to remove the color, or cancel to discard selection)&lt;/li&gt;
&lt;li&gt;The javascript calls the &lt;strong&gt;ColorPicker_Set&lt;/strong&gt; script, passing it the chosen color&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;ColorPicker_Set&lt;/strong&gt; script will tidy up and close the picker, and then set the &lt;strong&gt;Home::color&lt;/strong&gt; field.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;We pass the parameters through to the open script in JSON format, and they look like this:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Parameters to the Card Window Picker&quot; src=&quot;https://www.teamdf.com/assets/blog-images/colorpicker/_resampled/ResizedImage600127-colorpicker-5.png&quot; alt=&quot;Parameters to the Card Window Picker&quot; width=&quot;600&quot; height=&quot;127&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;There really is nothing overly complicated here, it&#039;s about as basic a Javascript/FM integration as you can get!&lt;/p&gt;
&lt;p&gt;In addition to the open and set scripts, there is a third script &lt;strong&gt;ColorPicker_Close&lt;/strong&gt; which is responsible for the tidy-up of the picker after a selection is made. More on this later for the geeks who like to know the technicalities!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Popover Approach&lt;/h2&gt;
&lt;p&gt;The popover approach is almost identical to the card approach however instead of explicitly calling the &lt;strong&gt;ColorPicker_Open&lt;/strong&gt; script, we instead set it as the OnObjectEnter trigger for the popover.  Similarly the onObjectExit trigger for the popover is set to the &lt;strong&gt;ColorPicker_Close&lt;/strong&gt; script.   &lt;/p&gt;
&lt;p&gt;These two scripts will initialise the picker in the popover, and tidy-up and close the picker when done.&lt;/p&gt;
&lt;p&gt;The parameters passed to the open script are the same with one exception. For popovers we also pass through the name of the web viewer object that is in this particular popover. Because you can have more than one popover picker on a layout, we need to differentiate between them.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Parameters to the Popover Picker&quot; src=&quot;https://www.teamdf.com/assets/blog-images/colorpicker/_resampled/ResizedImage600139-colorpicker-6.png&quot; alt=&quot;Parameters to the Popover Picker&quot; width=&quot;600&quot; height=&quot;139&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Managing Many Pickers&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;We are potentially dealing with multiple color pickers here, and each picker needs to be aware of the field that it needs to set when a selection is made. &lt;/p&gt;
&lt;p&gt;We saw 2 ways to achieve this - one would be to pass it through to the javascript code and store it there. The other is to store the field to set within FileMaker in global variables. We went with the latter approach because while not as elegant, it allowed us to illustrate some cool techniques for this article!  (We will likely change it to store it within each web viewer as this is much nicer.)&lt;/p&gt;
&lt;p&gt;Anyways, let&#039;s delve into what&#039;s going on here. This is for the FM geeks who like the nitty gritty.&lt;/p&gt;
&lt;p&gt;We can have multiple pickers in a few ways:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Multiple windows, each with a card window picker open&lt;/li&gt;
&lt;li&gt;Multiple windows, each with a popover picker open&lt;/li&gt;
&lt;li&gt;Multiple popovers on a layout (albeit one open at any given time).&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;When a picker opens, we need to know the field that needs to be set with a color, and we need to store this field name so that when the time comes we can retrieve it for setting. We also need to tidy up after ourselves and clear this variable when complete.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Open Script&lt;/h2&gt;
&lt;p&gt;The open script kicks things off by gathering the passed parameters, and loading the html javascript and css code into the web viewer - all stock standard stuff.&lt;/p&gt;
&lt;p&gt;When it comes to storing the field name to be set, we want to associate that field name to this specific card picker instance. We do this by assigning the card a unique window name, using &lt;strong&gt;Get ( UUID )&lt;/strong&gt;. We then define a variable called &lt;strong&gt;$ident&lt;/strong&gt; to store this value.&lt;/p&gt;
&lt;p&gt;In the case of a popover, because only one popover can be active on any given layout at any given time, our $identifier value just needs to represent the current window name.  For this, we assign a value to &lt;strong&gt;$ident&lt;/strong&gt; of&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;colorpicker_&quot; &amp;amp; Get ( WindowName )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Right, so we now have a variable that is a unique identifier of the specific card picker, or popover picker being instantiated. This will be different for situations where multiple windows are open - each with their own active picker.&lt;/p&gt;
&lt;p&gt;Next, we take this value, and hash it into an MD5 hash. This returns us a large numerical string. We do this as follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;GetAsNumber ( GetContainerAttribute ( $ident ; &quot;MD5&quot;) )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We are utilising a container function on a text string which can give us an MD5 hash of that text.&lt;/p&gt;
&lt;p&gt;The final step is to take this number, and treat it as a repetition value for a global variable. Into this repetition we set our field name for the color field to be set:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Set Variable [ $$COLORPICKER.FIELD[$hash] ; Value: Home::Color ] &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Determining our hash and storing color field&quot; src=&quot;https://www.teamdf.com/assets/blog-images/colorpicker/_resampled/ResizedImage600114-colorpicker-7.png&quot; alt=&quot;Determining our hash and storing color field&quot; width=&quot;600&quot; height=&quot;114&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p&gt;The beauty of this technique is you can effectively take a string, and turn it into a repetition into which you can place a value. You can then easily regenerate that same hash number later to retrieve and clear this repetition.&lt;/p&gt;
&lt;h2&gt;The Close and Set Scripts&lt;/h2&gt;
&lt;p&gt;Now that we know how this part works, setting the field to the chosen color, and clearing the global variable value when done is easy.  We simply regenerate our hash by evaluating the window name, and retrieve or clear the variable as needed. The &lt;strong&gt;Set Field by Name&lt;/strong&gt; step is used to set the color into the chosen field.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Setting color field &amp;amp; tidy up&quot; src=&quot;https://www.teamdf.com/assets/blog-images/colorpicker/_resampled/ResizedImage600260-colorpicker-8.png&quot; alt=&quot;Setting color field &amp;amp; tidy up&quot; width=&quot;600&quot; height=&quot;260&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Displaying your Chosen Color&lt;/h2&gt;
&lt;p&gt;So we have a color chosen - in this case hexadecimal. So what? What good is a hexadecimal color as a text string, if we can&#039;t actually turn it into a physical color? Fortunately we can and it&#039;s really easy!&lt;/p&gt;
&lt;p&gt;There is a neat little trick you can use to generate a 1x1 pixel gif image of a chosen hexadecimal color. This is done by producing it as base64 encoded text, which is then decoded back into a gif file for rendering in a container. The code is as follows and we have wrapped it up into a custom function called @COLOR_swatch in the example file:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If (  IsEmpty ( _hex ) ; &quot;&quot; ; HexDecode ( &quot;47494638376101000100910000000000&quot; &amp;amp; Substitute ( _hex ; &quot;#&quot; ; &quot;&quot; ) &amp;amp; &quot;FFFFFF00000021F90409000003002C00000000010001000002024C01003B&quot; ; &quot;red.gif&quot; ) )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By calculating/inserting this result into a container, you can create a color swatch of any size. Just set your container properties to &quot;Reduce or Enlarge Image to Fit&quot;  and remove the option to Maintain Original proportions.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Color swatch example&quot; src=&quot;https://www.teamdf.com/assets/blog-images/colorpicker/colorpicker-9.png&quot; alt=&quot;Color swatch example&quot; width=&quot;273&quot; height=&quot;95&quot;&gt; &lt;/p&gt;
&lt;h2&gt;Taking things further with Customisation&lt;/h2&gt;
&lt;p&gt;We decided on a simple implementation of Pickr for our Color Picker, but the reality is Pickr is quite powerful and you can produce some cool pickers simply by altering the configuration parameters in the javascript setup.&lt;/p&gt;
&lt;p&gt;If you wish to investigate this further, the documentation will provide you with all necessary configuration options.&lt;/p&gt;
&lt;p&gt;You can find this code in the example file in the &lt;strong&gt;ColorPicker_Open&lt;/strong&gt; script. Here are just a few examples of what you can do:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;3 Varieties of PIckr style&quot; src=&quot;https://www.teamdf.com/assets/blog-images/colorpicker/_resampled/ResizedImage600236-colorpicker-10.png&quot; alt=&quot;3 Varieties of PIckr style&quot; width=&quot;600&quot; height=&quot;236&quot;&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;3 Different varieties of picker - Classic (what we use), Monolith and Nano&lt;/li&gt;
&lt;li&gt;Show/Hide predefined swatches for quick selection&lt;/li&gt;
&lt;li&gt;Determine primary color mode (Hex, RGB etc)&lt;/li&gt;
&lt;li&gt;Show preview of currently selected color&lt;/li&gt;
&lt;li&gt;Enable/Disable ability to select transparency&lt;/li&gt;
&lt;li&gt;Relabel buttons&lt;/li&gt;
&lt;li&gt;Restyle elements via CSS&lt;/li&gt;
&lt;li&gt;Bind events to almost any action, allowing you to run Javascript or FileMaker scripts when events occur.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; and more.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;In Conclusion&lt;/h2&gt;
&lt;p&gt;Pickr is by far the simplest and best javascript based pickr we have come across, and implementing it was really easy. We hope that we have done a good enough job that you can take the example file and easily incorporate the picker into your own solutions and improve upon what we have done.&lt;/p&gt;
&lt;p&gt;We&#039;d love to see folks take this and improve upon it by optimising how the picker manages the storage of the field it is required to set the color into - perhaps storing it in the Javascript? If anyone would like to take up the challenge we&#039;d love to see what you come up with.&lt;/p&gt;
&lt;p&gt;Even if you don&#039;t use the picker, consider the technique for generating color swatches, this is a really powerful and awesome function. You&#039;ll also find on &lt;a title=&quot;Brian Dunning .com site for FileMaker custom functions&quot; href=&quot;http://briandunning.com&quot; target=&quot;_blank&quot;&gt;briandunning.com&lt;/a&gt; a number of custom functions that can convert an RGB value into a hexadecimal value which would allow you to utilise this swatch technique with the standard FileMaker RGB function.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;Example files sit at the core of all our articles and much time and love goes into them, not only to present a particular technique but also as a way for us to help refine the technique.  We always encourage you to download and try out the example file for yourself as the best way to read and understand the article is by having the example file open at the same time and exploring both.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/colorpicker/a-cooler-colorpicker.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the Color Picker example file&lt;/a&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Fri, 11 Mar 2022 06:42:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/a-cooler-color-picker/</guid>
		</item>
		
		<item>
			<title>Why Upgrade?</title>
			<link>https://www.teamdf.com/blogs/why-upgrade/</link>
			<description>&lt;p&gt;We&#039;ve been building custom FileMaker solutions for 26 years now. As you’d expect, we’ve seen a lot of versions come and go in that time. Claris continuously invest in and enhance the platform which keeps it not just current and viable, but leading the way as a low-code, rapid development platform.&lt;/p&gt;
&lt;p&gt;That said though, it’s incredibly stable and we’ve seen plenty of our clients running their apps for decades on the same version we worked on with them.&lt;/p&gt;
&lt;p&gt;Recently we’ve had some discussions with a client who was still running their solution on FileMaker 16 and we advised them to upgrade to the latest version (FileMaker 19 as of writing). But why? I mean their solution was working fine, stable and everyone was happy. Why rock the boat? They hadn’t had any issues and in fact we hadn’t heard from them for some time…&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/why-upgrade/_resampled/ResizedImage659325-dont-rock-the-boat.jpg&quot; alt=&quot;dont rock the boat&quot; width=&quot;659&quot; height=&quot;325&quot;&gt;&lt;/p&gt;
&lt;p&gt;Let’s explore some pros and cons of upgrading and why we think it’s a good idea, even if your FileMaker application is working “fine”:&lt;/p&gt;
&lt;p&gt;Either by choice or omission, it’s easy to understand why you might not keep up-to-date with the latest FileMaker versions:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;If it ain&#039;t broke, Don&#039;t fix it&lt;/strong&gt; - As I mentioned, FileMaker is inherently stable and we’ve seen solutions we built decades ago ticking along, quietly doing their thing.&lt;br&gt;&lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New License Costs&lt;/strong&gt; - If you’ve got a perpetual (permanent) license then you’ll be looking at an upgrade or if it’s more than a couple of versions old, purchasing anew. And these days most lisenses are now annual (albeit lower than the older perptual licenses). But if it’s working why would you want this cost?&lt;br&gt;&lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cost of Upgrading&lt;/strong&gt; - It takes time to upgrade a server, and it means that every user’s software will need to be updated too.&lt;br&gt;&lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plugins and Other Dependencies&lt;/strong&gt; - Updating the FileMaker software — or in fact your hardware or Operating System — may break these, particularly older plugins. That could mean work and/or cost finding updated versions or replacing them in some form if they’re no longer supported.&lt;br&gt;&lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logistics and Disruption&lt;/strong&gt; - It can require some planning and coordination to ensure a smooth transition for your team. Users may need to upgrade their own FileMaker Pro versions and this can occasionally require support. There may be some downtime as the upgrade is performed.&lt;br&gt;&lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware, Operating System and Compatibility&lt;/strong&gt; - Depending on how old things are, it may be necessary to upgrade some users’ machines or business hardware and software to support the upgrade and keep everything working.&lt;/li&gt;
&lt;/ul&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/why-upgrade/burning-money.jpg&quot; alt=&quot;burning money&quot; width=&quot;660&quot; height=&quot;332&quot;&gt;&lt;/p&gt;
&lt;h2&gt;We Get It&lt;/h2&gt;
&lt;p&gt;Nobody wants to &quot;burn money&quot;, but...&lt;/p&gt;
&lt;p&gt;We would argue that those factors are all positive in the short term, and sooner or later they will catch up with you because you’ll be forced to upgrade for compatibility. And along the way you’re missing out on some important benefits. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1 Device Support&lt;/strong&gt; - Currently, Claris offer support for the latest two versions of FileMaker (19 and 18). This means we have access to their technical teams for any issues associated with the platform itself and they actively invest in keeping these versions current and compatible with the prevailing operating systems and devices.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2 Protection from Hacking&lt;/strong&gt; - Claris rank Security as the number one priority for the platform and have taken some major steps in recent years to make FileMaker much more secure. With hacking and data breaches a common target, and now that most FileMaker databases are on the cloud or exposed to the internet, it is vital to stay right on top of the security measures Claris are putting in and constantly updating to the latest standards.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/why-upgrade/protection-umbrella.jpg&quot; alt=&quot;protection umbrella&quot; width=&quot;660&quot; height=&quot;300&quot;&gt;&lt;/p&gt;
&lt;p&gt;A good example here is the recent Log4J and Heartbleed type vulnerabilities. These were serious deficits that malicious actors or code could exploit to basically hijack a business’s systems. Patches were available quickly once they were exposed but only for currently supported operating systems. Out of date, un-updated and unsupported older systems are basically left exposed.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/why-upgrade/_resampled/ResizedImage660316-hacker-in-a-hoodie.jpg&quot; alt=&quot;hacker in a hoodie&quot; width=&quot;660&quot; height=&quot;316&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3 Avoid Incompatibility with Windows or macOS&lt;/strong&gt; - by staying current with FileMaker you’ll be able to stay up to date with your Windows, Mac or iOS systems, which means not only getting all the advantages of new features they bring but also the all important security of those. Apple and Microsoft address weakness in their platforms every month, but only the most recent versions. Plus if you get new gear it will come with the latest OS whether you like it or not.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4 Avoid Costly Support Issues&lt;/strong&gt; - the older your gear the more risk you have that something like a hard drive might fail and you’ll be unable to quickly get the system back up and running. If something does fail you may be forced to update everything at once just to get everything working again. This could well happen at a time not of your choosing and may take longer to sort out than it would if it was planned and managed. We have seen some situations like this take days to resolve as each unplanned replacement and upgrade forced other changes throughout the business. The costs of resolving these unplanned outages can be much higher than a managed upgrade. See the comment below from Paul Hutton, one of our developers on the front line of this kind of issue.*&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5 Faster, Stronger, Better&lt;/strong&gt; - FileMaker 19 (the current version as of writing) is faster, more stable and easier for us to support and work on. In short, it’s better for users and also for us as developers. That means our work supporting you is more efficient. Also, within the latest version is an important tranche of new updating technology which means from this version on we can update and upgrade much faster and easier, with less disruption. The grass is greener on the FM 19 side and that means its even less costly to maintain currency of your systems once you get up to this version.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/why-upgrade/greener-grass.jpg&quot; alt=&quot;greener grass&quot; width=&quot;660&quot; height=&quot;300&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6 The Longer You Leave It, The Worse It Gets&lt;/strong&gt; - there is a term in the IT industry called “technical debt” which refers to the future cost you incur as a result of short term cost saving measures such as shortcuts in code, lack of equipment maintenance and lack of software updates.&lt;/p&gt;
&lt;p&gt;Consider that the more out of date your system versions are, the more careful planning, testing and steps we have to take to bring you back to currency. It’s actually much more complicated to bring you up from say FileMaker 12 than FileMaker 17 for example. We basically need to implement a program of leapfrogging through versions and may or may not need to perform file conversions along the way. This costs more, will probably incur longer disruptions and could involve more issues such as functional incompatibilities (if for example your solution is using deprecated functions or script steps from older versions). &lt;/p&gt;
&lt;h2&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;“I’m seeing this quite a bit with a certain group of clients: old machines, old FM Pro, old FM Server. Then a staff member gets a new machine and it goes like this: they can’t install old FM Pro because it’s incompatible, so they install the newest version, but then the new FM Pro doesn’t work an old server version, so they call us to update server, now all the other users have to update FM Pro, and it’s all done in a rush, without planning, usually with some loss of access and loss of productivity. Worst case they have a mix of machines that can’t all handle the update and end up with some people unable to access the system until their computers are updated!&lt;/p&gt;
&lt;p&gt;Better to schedule the upgrade, do it in a planned and measured way.”&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;— Paul Hutton, Senior Developer, 20 Years!&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt; &lt;/p&gt;</description>
			<pubDate>Wed, 09 Mar 2022 13:49:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/why-upgrade/</guid>
		</item>
		
		<item>
			<title>Why Build Custom Software?</title>
			<link>https://www.teamdf.com/blogs/why-custom/</link>
			<description>&lt;p&gt;There are many reasons why some organisations and businesses really benefit from building their own &lt;strong&gt;custom&lt;/strong&gt; operational software…&lt;/p&gt;
&lt;p&gt;Here&#039;s one. I think it&#039;s interesting and if you’re considering your business software options this is definitely worth exploring.&lt;/p&gt;
&lt;p&gt;One of our clients runs an educational accommodation facility, sort of like a hotel for teaching and research groups. They have a commercial kitchen used to feed large groups of people at a time, sometimes multiple groups over many days. They have catering companies on contracts to do this and the contracts come up every few years and sometimes change hands.&lt;/p&gt;
&lt;h2&gt;Things Change&lt;/h2&gt;
&lt;p&gt;They&#039;ve recently got a contract with a new catering firm and decided to dramatically change the way they quote, invoice and book catering for clients.&lt;/p&gt;
&lt;p&gt;They asked us to make changes in the system to make this work.&lt;/p&gt;
&lt;p&gt;Luckily we had designed the system to be fairly flexible and also... it&#039;s built with FileMaker. With the flexibility of this platform, and being a custom solution built solely for them, it took us around two days to make the changes once we got cracking.&lt;/p&gt;
&lt;p&gt;As soon as we deployed it we asked for their latest prices on catering as that was the final piece of the puzzle to make it work for them.&lt;/p&gt;
&lt;h2&gt;And Change…&lt;/h2&gt;
&lt;p&gt;At this point, the manager called and said, &quot;Actually, the bosses in our organisation have decided to make another change and we won&#039;t be doing catering quotes, invoicing or booking like that at all any more.”&lt;/p&gt;
&lt;p&gt;Lucky for them they have a system that rolls with those punches and doesn’t cost 10&#039;s or 100&#039;s of thousands of dollars every time they reinvent the wheel, which they do all the time all over the place.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Sometimes it is better to reinvent the wheel&quot; src=&quot;https://www.teamdf.com/assets/blog-images/why-custom/_resampled/ResizedImage659283-wheel.jpg&quot; alt=&quot;wheel&quot; width=&quot;659&quot; height=&quot;283&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Flexibility&lt;/h2&gt;
&lt;p&gt;Commercial Off The Shelf (COTS) software and products including SaaS options are an excellent choice in many firms but may not be especially flexible or responsive when your needs change.&lt;/p&gt;
&lt;p&gt;Whereas, low code software platforms such as Claris FileMaker can offer a huge degree of agility and responsiveness without being monstrously expensive or time consuming to implement.&lt;/p&gt;
&lt;p&gt;The big takeaway from this type of story is that it’s important to think about the decision making and operational environment when assessing software options for your business. Are you fluid and dynamic? Do your processes change and respond to the market? Will you need flexibility?&lt;/p&gt;
&lt;p&gt;There may well also be external forces at play: Are there other departments, clients, suppliers or governmental compliance causes that could impose changes on you next year (or even next week)? How quickly do you need to adapt and accommodate?&lt;/p&gt;
&lt;p&gt;There’s more to the ‘cost’ of your software choices than the immediate bottom line. Make sure you consider any potential for changes in the way you work as you’re exploring your software options.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/why-custom/_resampled/ResizedImage660423-adapt-or-fail.jpg&quot; alt=&quot;Adapt or Fail&quot; width=&quot;660&quot; height=&quot;423&quot;&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 22 Feb 2022 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/why-custom/</guid>
		</item>
		
		<item>
			<title>Best of 2021: Idle Record Release</title>
			<link>https://www.teamdf.com/blogs/idle-release/</link>
			<description>&lt;h2&gt;When Users Hold Records&lt;/h2&gt;
&lt;p&gt;The last of my &lt;a title=&quot;Weetbicks Best Of 2021&quot; href=&quot;https://www.teamdf.com/blogs/weetbicks-best-of-2021/&quot;&gt;2021 Best Ofs&lt;/a&gt; is a couple of scripts to help with those pesky users who leave records uncommitted and then bugger off for a coffee or take a long lunch break. Super annoying for other users and for you as a developer if you wish to make a field definition change on a production version — hey, it happens, deal with it!&lt;/p&gt;
&lt;p&gt;We facilitate the commit of an iDLE user through an OnTimer installed for each individual user. The OnTimer is running a script that will monitor the users active field (if there is one) and determine if they are idle in that field. &lt;/p&gt;
&lt;p&gt;This is done by storing information about the users last active field in a global variable repetition. We use different repetitions for multiple windows the user may have open to track states of multiple windows.&lt;/p&gt;
&lt;p&gt;Information we capture about the users field include:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Active field name&lt;/li&gt;
&lt;li&gt;Active field contents&lt;/li&gt;
&lt;li&gt;Record Modification Count&lt;/li&gt;
&lt;li&gt;Record Open Count&lt;/li&gt;
&lt;li&gt;Record Open State&lt;br&gt;&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;IDLE release checking&quot; src=&quot;https://www.teamdf.com/assets/blog-images/top-5-of-2021/top-5-of-2021-9.png&quot; alt=&quot;top 5 of 2021 9&quot; width=&quot;427&quot; height=&quot;284&quot;&gt;&lt;/p&gt;
&lt;p&gt;All of this information is stored in the variable. If the next time the OnTimer runs none of this information has changed then the record is committed. &lt;/p&gt;
&lt;p&gt;For example we might wish to set our onTimer to 30 seconds. By doing so will allow a user to sit idle in a field making no modifications for no more than 30 seconds. If they are typing in the field then the stored information will differ from the previous time it was run and so the user is free to continue without the threat of a commit happening.&lt;/p&gt;
&lt;p&gt;The technique uses a script to enable the idle release timer, one to disable, and one to carry out the commit.&lt;/p&gt;
&lt;p&gt;The enable script allows you to define your own terms for when the IDLE release process is to be installed.  This is useful because as a developer having this OnTimer run can be painful as it will jump the developer out of active script steps you may be writing in.  So we disable this for full access users.  There is also little need to run this if executing on server.  Certain windows are only spawned for temporary purposes such as carrying out actions in a script. In this case you may wish to not use idle release for these types of windows.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;Example file&quot; href=&quot;https://www.teamdf.com/assets/blog-images/idle-release/IDLE-Release.zip&quot; target=&quot;_blank&quot;&gt;Example File Download&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Thu, 23 Dec 2021 09:13:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/idle-release/</guid>
		</item>
		
		<item>
			<title>Best of 2021: PSOS Helper</title>
			<link>https://www.teamdf.com/blogs/best-of-2021-psos-helper/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;When developing and maintaining client solutions a really common task is to write a script to either add, modify or delete data for the user. This is usually a time consuming batch style operation that is often faster to run on the server rather than the client.&lt;/p&gt;
&lt;p&gt;To run a script on FileMaker Server you have the option of either setting up a scheduled script via the admin console, or running it using the &lt;strong&gt;&lt;em&gt;Perform Script on Server (PSOS) &lt;/em&gt;&lt;/strong&gt;script step.&lt;/p&gt;
&lt;p&gt;The latter option is the fastest option when needing to quickly run a one-off script.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Catch…&lt;/h2&gt;
&lt;p&gt;There&#039;s always a catch. To run a script on server via PSOS, you first need to run a local script that can itself run the &lt;strong&gt;&lt;em&gt;Perform Script on Server&lt;/em&gt;&lt;/strong&gt; step to call your server-side script – what a drama!&lt;/p&gt;
&lt;p&gt;For a long time I used a piece of code that I would always write out at the top of these scripts to achieve this:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;PSOS helper code&quot; src=&quot;https://www.teamdf.com/assets/blog-images/top-5-of-2021/_resampled/ResizedImage600131-top-5-of-2021-6.png&quot; alt=&quot;top 5 of 2021 6&quot; width=&quot;600&quot; height=&quot;131&quot;&gt;&lt;/p&gt;
&lt;p&gt;Technically speaking there is nothing wrong with this code, I just got tired of writing this all the time. I wanted to abstract this out to a single reusable script. One that could be placed at the top of any other script to force that script to run on the server.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;A Better, Reusable Option&lt;/h2&gt;
&lt;p&gt;This is what I came up with:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;PSOS Helper Code v2.0&quot; src=&quot;https://www.teamdf.com/assets/blog-images/top-5-of-2021/_resampled/ResizedImage600211-top-5-of-2021-7.png&quot; alt=&quot;top 5 of 2021 7&quot; width=&quot;600&quot; height=&quot;211&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we are passing the name of the script to execute on server as a parameter. &lt;/p&gt;
&lt;p&gt;This helper script will terminate if already running on server (to prevent repeat recursive PSOS calls).&lt;/p&gt;
&lt;p&gt;If it is being initiated by the client, it will perform script on server by name, using the name passed as a parameter. &lt;/p&gt;
&lt;p&gt;The halt is to terminate the script that initiated the call. The initiating script is actually the one that is going to be run on server, so we don&#039;t need to also continue to run it on client.&lt;/p&gt;
&lt;p&gt;Thus, in order to run a script on server, it just requires the below step as its first script step. The rest of the script can be written as if it is to be run on server.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Calling the PSOS helper&quot; src=&quot;https://www.teamdf.com/assets/blog-images/top-5-of-2021/_resampled/ResizedImage60087-top-5-of-2021-8.png&quot; alt=&quot;top 5 of 2021 8&quot; width=&quot;600&quot; height=&quot;87&quot;&gt;&lt;/p&gt;
&lt;p&gt;A single step at the top of any script to have it run on server.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Synchronous Execution&lt;/h2&gt;
&lt;p&gt;The PSOS helper is really optimised here to be run for one-off scripts. It is Asynchronous in that it does not wait for the currently running script.&lt;/p&gt;
&lt;p&gt;To run this as part of a solution where certain scripts are run PSOS, then first thing you&#039;ll need to do is remove the Halt script step on line 23. This will allow further execution of other scripts to occur.  If you wish this to be Synchronous, then change the PSOS call on line 22 to wait for completion. Usually a PSOS that waits for completion expects to get a result back, so in order to achieve this you can exit here and return &lt;em&gt;&lt;strong&gt;Get ( ScriptResult )&lt;/strong&gt;&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;As always an example is included. This file doesn&#039;t really do much other than contain some. further information around the script, as well as the helper script itself so that you can put it in your own solutions.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;PSOS Helper Example File&quot; href=&quot;https://www.teamdf.com/assets/blog-images/psos-helper/PSOS-Helper.zip&quot; target=&quot;_blank&quot;&gt;Download the Example File&lt;/a&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Thu, 16 Dec 2021 11:30:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/best-of-2021-psos-helper/</guid>
		</item>
		
		<item>
			<title>Best of 2021: Keystroke Tester</title>
			<link>https://www.teamdf.com/blogs/keystroke-tester/</link>
			<description>&lt;h2&gt;Keystroke Tester&lt;/h2&gt;
&lt;p&gt;Less a piece of code and more of a utility (and could easily be made into a FileMaker Add-on). I built this keystroke tester for our own internal frameworks to help developers quickly and easily derive modifier key numbers as well as codes for various keystrokes pressed. &lt;/p&gt;
&lt;p&gt;This is invaluable as a time saver when needing to work with the various keystroke triggers.&lt;/p&gt;
&lt;p&gt;The tester opens in a card window and will respond to your keystrokes or modifier keys pressed, providing you with real time feedback:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Keystroke tester in action&quot; src=&quot;https://www.teamdf.com/assets/blog-images/top-5-of-2021/_resampled/ResizedImage600326-top-5-of-2021-5.png&quot; alt=&quot;top 5 of 2021 5&quot; width=&quot;600&quot; height=&quot;326&quot;&gt;&lt;/p&gt;
&lt;p&gt;The keystroke tester will likely feature in a future &lt;a href=&quot;http://www.elemental-fm.com&quot;&gt;elemental&lt;/a&gt; release as an Add-on, but if anyone would like to build this as an Add-on sooner feel free to do so and let us know in the comments here.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/keystroke-tester/Keystroke-Tester.zip&quot; target=&quot;_blank&quot;&gt;Download the example file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Fri, 10 Dec 2021 11:16:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/keystroke-tester/</guid>
		</item>
		
		<item>
			<title>Best of 2021: Get Record as JSON</title>
			<link>https://www.teamdf.com/blogs/get-record-as-json/</link>
			<description>&lt;h2&gt;Get Record as JSON&lt;/h2&gt;
&lt;p&gt;This is my personal favourite in this &quot;Best of 2021&quot; series — I guess that makes it the Best Of The Best! This is a really simple and reusable script for obtaining an entire record represented in JSON format.&lt;/p&gt;
&lt;p&gt;I built this initially for a debugging tool used in a client solution (see an upcoming article for this). The user could press a button to submit a debug report to the developer. Part of that debug report is a JSON representation of the record they are currently viewing. This was really useful in helping to diagnose issues because I was able to see all field values at the time of the issue. &lt;/p&gt;
&lt;p&gt;As usual I&#039;ve prepared a sample file to show you how this works which you can download here.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;Zipped example file for Get Record As JSON&quot; href=&quot;https://www.teamdf.com/assets/blog-images/get-record-as-json/Get-Record-as-JSON.zip&quot; target=&quot;_blank&quot;&gt;Download Get Record As JSON example&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p&gt;The JSON is built using 2 key features. The first is using FileMaker&#039;s underlying internal SQL functions to obtain a list of all fields within a desired table. Using this list of fields it becomes rather easy to then formulate an executeSQL query to return all these field values from a nominated record.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/get-record-as-json/_resampled/ResizedImage660424-record-json-screenshot.png&quot; alt=&quot;record json screenshot&quot; width=&quot;660&quot; height=&quot;424&quot;&gt;&lt;/p&gt;
&lt;p&gt;This script needs a single parameter which is a reference to the primary key field of the record you wish to return a JSON representation of. We use the &lt;em&gt;GetFieldName&lt;/em&gt; function to achieve this.&lt;/p&gt;
&lt;p&gt;From this single reference the script can derive the table occurrence name. Using the underlying &lt;em&gt;FileMaker_Tables&lt;/em&gt; table, an executeSQL query can obtain the base table name. Using this, we can then query the &lt;em&gt;FileMaker_Fields&lt;/em&gt; table to obtain a list of all the fields within this table.&lt;/p&gt;
&lt;p&gt;Finally we can formulate a query to get all fields values from the desired record in that table by using the known primary key name, and value (obtained through the &lt;em&gt;Evaluate&lt;/em&gt; function).&lt;/p&gt;
&lt;p&gt;This is easiest to be seen just by looking at the script yourself in the example file.&lt;/p&gt;
&lt;p&gt;You may wonder why we don&#039;t just obtain &quot;*&quot; from the table to get all field values, in favour of explicitly asking for every field by name. The reason for this lies in the fact the &lt;em&gt;FileMaker_Fields&lt;/em&gt; internal table allows us to also obtain information such as field type, and storage type (e.g. calculation, stored, global).&lt;/p&gt;
&lt;p&gt;This is useful because it allows you in the script to set some criteria as to what types of fields you wish to return for your JSON representation. You may wish for example to omit summary fields, unstored calculations, global fields, containers etc. &lt;/p&gt;
&lt;p&gt;This loop to extract certain fields has been left in the script and is well commented but for the sake for the example I have left every field included.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/get-record-as-json/_resampled/ResizedImage660446-get-record-as-json-script.png&quot; alt=&quot;get record as json script&quot; width=&quot;660&quot; height=&quot;446&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE: &lt;/strong&gt;Because the field values are obtained through an executeSQL query this technique does not cater for repeating fields or container fields. A container field will return the file name but not the field contents per se; repeating fields will return the first repetition value only. You can always represent a container by create a calculation for it which is the base64 encoded representation.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;What FileMaker Weetbicks article wouldn&#039;t be complete without an example file? In this you&#039;ll find everything discussed in the article. I think the best way to learn is to jump in and explore.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/get-record-as-json/Get-Record-as-JSON.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We love feedback so please leave a comment if you have anything to say - even if you don&#039;t it would be nice to hear from you :) &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Mon, 29 Nov 2021 10:16:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/get-record-as-json/</guid>
		</item>
		
		<item>
			<title>Best of 2021: Multi-Row Portal Selection</title>
			<link>https://www.teamdf.com/blogs/multi-row-portal-selection/</link>
			<description>&lt;p&gt;This is a great UI technique I use all the time when I wish for a user to be able to select multiple rows from a portal. Rather than laboriously single-clicking rows it is much more intuitive to give the user an operating system like experience for file selection. By this I mean the use of modifier keys to select multiple rows:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Single-click for single row selection only&lt;/li&gt;
&lt;li&gt;Cmd / Ctrl click for arbitrary multiple row selections&lt;/li&gt;
&lt;li&gt;Shift-click for selecting a nominated range of rows.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Further to the above, functionality can be extended through the use of buttons (or my preference of custom menus) to carry out select all/no rows.&lt;/p&gt;
&lt;p&gt;To start with, grab my example file &lt;a title=&quot;Multi-row selection demo file&quot; href=&quot;https://www.teamdf.com/assets/blog-images/multi-row-portal-selection/Mutli-Row-Portal-Selection.fmp12.zip&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; so you can follow along and explore the technique for yourself.&lt;/p&gt;
&lt;p&gt;What you&#039;ll see in the demo is a portal like this in which selecting rows by Shift-clicking or Command-clicking lets you create an ad hoc selection of items from the list: &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multi-row-portal-selection/_resampled/ResizedImage660387-multi-row-selection.jpg&quot; alt=&quot;multi row selection&quot; width=&quot;660&quot; height=&quot;387&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the picture above we have a simple portal with 3 rows selected. The primary key values of the selected rows are stored in a field/variable of your choosing for use however you see fit.&lt;/p&gt;
&lt;p&gt;This is achieved with the following components:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;A portal of records (obviously!)&lt;/li&gt;
&lt;li&gt;A script run from within the portal context&lt;/li&gt;
&lt;li&gt;A field to store the selected Primary Keys&lt;/li&gt;
&lt;li&gt;A secondary helper field to store the last selected Primary Key&lt;/li&gt;
&lt;li&gt;A custom function to help identify the pressed modifier keys (in english)&lt;/li&gt;
&lt;li&gt;A field on the child table to obtain the found count of portal rows.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The last item on this list is purely for the script to know how many records it is dealing with for certain scenarios. The easiest way to achieve this is through an unstored calculation on the table set to the &lt;strong&gt;Get ( FoundCount )&lt;/strong&gt; function. For more on this technique refer to &lt;a href=&quot;https://www.teamdf.com/blogs/a-lightning-fast-alternative-to-the-count-function/&quot; target=&quot;_blank&quot;&gt;my earlier article here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The script accepts the following parameters in JSON:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;id - The id the user has selected.&lt;/li&gt;
&lt;li&gt;force - 1 if you wish to force selection of the id, rather than toggle it.&lt;/li&gt;
&lt;li&gt;all - 1 if you wish to select every portal row.&lt;/li&gt;
&lt;li&gt;clear - 1 if you wish to clear every portal row.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The script has been mostly abstracted, there are just 4 components to set up as shown below (These could very easily just be added as script parameters as well if you wish making the script 100% abstracted for use throughout your solution).&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Specifying required information for the script&quot; src=&quot;https://www.teamdf.com/assets/blog-images/top-5-of-2021/top-5-of-2021-2.png&quot; alt=&quot;top 5 of 2021 2&quot; width=&quot;565&quot; height=&quot;334&quot;&gt;&lt;/p&gt;
&lt;p&gt;We simply need to specify, in the script, the fields for storing selected ids, the last selected id, the portal primary key, and a field to tell us how many records there are.&lt;/p&gt;
&lt;p&gt;The script takes care of the rest and handles the various modifier key situations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE: &lt;/strong&gt; This technique only works right now for portals that do not use portal-level filtering and sorting – it is for relationship level sorting and filtering only. This is because our script does not do any recursive looping through portal rows to achieve selection (something that would be required if portal level filtering/sorting were to be used). &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;What FileMaker Weetbicks article wouldn&#039;t be complete without an example file? In this you&#039;ll find everything discussed in the article. I think the best way to learn is to jump in and explore.&lt;/p&gt;
&lt;p&gt;&lt;a title=&quot;Multi-row selection demo file&quot; href=&quot;https://www.teamdf.com/assets/blog-images/multi-row-portal-selection/Mutli-Row-Portal-Selection.fmp12.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We love feedback so please leave a comment if you have anything to say - even if you don&#039;t it would be nice to hear from you :) &lt;a title=&quot;Multi-row selection demo file&quot; href=&quot;https://www.teamdf.com/assets/blog-images/multi-row-portal-selection/Mutli-Row-Portal-Selection.fmp12.zip&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Thu, 18 Nov 2021 09:34:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/multi-row-portal-selection/</guid>
		</item>
		
		<item>
			<title>Weetbicks Best Of 2021</title>
			<link>https://www.teamdf.com/blogs/weetbicks-best-of-2021/</link>
			<description>&lt;h2&gt;Intro&lt;/h2&gt;
&lt;p&gt;I’ve been a FileMaker developer now for 15 years. In that time I have come up with some really cool stuff - a lot of which I’ve shared here over the years and can be found in the older articles. But as time goes on it gets harder and harder to come up with unique stuff, especially with the community so strong and thriving with awesome developers. Gone are the days where the opportunity to push FileMaker to new limits was quite within reach (Javascript/APIs excluded!).&lt;/p&gt;
&lt;p&gt;With that said I still do things from time-to-time that make me sit back and think &quot;hey that&#039;s pretty cool&quot;. They may not be flashy, ground breaking or overly complex, but they solve the problem at hand and end up becoming staples in my development toolkit.&lt;/p&gt;
&lt;p&gt;So without further ado I&#039;d like to share with you several of these from the year-to-date, starting with:&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;a title=&quot;Multi-row Portal Selection article&quot; href=&quot;https://www.teamdf.com/blogs/multi-row-portal-selection/&quot;&gt;Multi-Row Portal Selection&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;a title=&quot;Get Record as JSON&quot; href=&quot;https://www.teamdf.com/blogs/get-record-as-json&quot; target=&quot;_blank&quot;&gt;Get Record as JSON&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;a title=&quot;Keystroke Tester article&quot; href=&quot;https://www.teamdf.com/blogs/keystroke-tester/&quot;&gt;Keystroke Tester&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;span&gt;&lt;a title=&quot;PSOS Helper Article&quot; href=&quot;https://www.teamdf.com/blogs/best-of-2021-psos-helper&quot;&gt;PSOS Helper&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;a title=&quot;Idle Release article&quot; href=&quot;https://www.teamdf.com/blogs/idle-release/&quot;&gt;Idle Release&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;There are plenty more in the old toolkit but these are the ones that I have used with much success in the solutions I develop.&lt;/p&gt;
&lt;p&gt;I hope you enjoy&lt;br&gt;- Daniel (aka Weetbicks) &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Thu, 18 Nov 2021 09:34:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/weetbicks-best-of-2021/</guid>
		</item>
		
		<item>
			<title>DF Con 2021</title>
			<link>https://www.teamdf.com/blogs/df-con-2021/</link>
			<description>&lt;p&gt;Some say the way to a man’s heart is through his stomach, well the way to a FileMaker Developer&#039;s heart is locking them in a room for a couple of days so they can over indulge in all things technical.&lt;/p&gt;
&lt;p&gt;So it began, for 2021, Digital Fusion decided we would hold our own conference. As we grow in size, with a team of 18 now, we thought we could go it alone, and create our own content, events and social gatherings.&lt;/p&gt;
&lt;h3&gt;Trans-Tasman Limitations&lt;/h3&gt;
&lt;p&gt;Planning for the event took a bit of a turn for the worse when the Australia and New Zealand borders were slammed shut with outbreaks of Covid in NSW. The intention was to get our Aussie team over to Christchurch so we could all be in one place, something that has been hard to achieve since the pandemic took hold.&lt;/p&gt;
&lt;p&gt;We swapped our dates from August to October and started planning, even getting flights booked from Brisbane to Christchurch. Sadly, the border remained closed, so we swiftly moved to Plan B, organising a conference where we&#039;d remote-in three of our team.&lt;/p&gt;
&lt;h3&gt;A Resort Close To Home&lt;/h3&gt;
&lt;p&gt;October came around, and we all headed out to the beautiful Clearwater Resort on the outskirts of Christchurch. We were blessed with some stunning weather, which helped enhance what is a stunning location — think lakes, golf courses and swanky accommodation.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/df-con-21/view.jpg&quot; alt=&quot;view&quot; width=&quot;660&quot; height=&quot;371&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Kicking things off on Wednesday afternoon, we went straight into the keynote presentation by our illustrious CEO, Craig Saunders. This was kept short and sweet as his main speaking spot was the following day, and he didn’t want to let too many cats out of the bag.&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;Team Building Stuff&lt;/h3&gt;
&lt;p&gt;We then moved onto learning a little about ourselves and those around us! We brought in Ramon Utting to take us through &lt;a title=&quot;Clifton Strengths website&quot; href=&quot;https://www.gallup.com/cliftonstrengths/en/home.aspx&quot; target=&quot;_blank&quot;&gt;Clifton Strengths&lt;/a&gt; which is a world-renown way of understanding your &quot;strengths&quot; or motivators. If you have never heard or read about this, in essence the process finds key words that describe you, and then learn how these words fit into you as a person and how they affect your interactions with others. More importantly perhaps, you gain insight into others motivators and what they mean.&lt;/p&gt;
&lt;p&gt;As you can imagine, with 16 developers/technical folk, we have a lot of very similar traits throughout our team. That said, we learned a lot about how we fit together as a wider group, and through understanding ourselves a bit beter, gained insight into how we interact with clients and others outside DF.&lt;/p&gt;
&lt;p&gt;Wednesday evening was a mixture of pizza and quizzes. The ever wonderful Jo and her trusty sidekick Greig, had setup a great quiz, asking questions about Digital Fusion, FileMaker and us as individuals. The victor on the evening was Daniel, followed by Steve and Paul H. Lots of fun was had by all.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/df-con-21/_resampled/ResizedImage659371-presenting.jpg&quot; alt=&quot;presenting&quot; width=&quot;659&quot; height=&quot;371&quot;&gt;&lt;br&gt;View from Clearwater, Christchurch&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/df-con-21/_resampled/ResizedImage659371-view-from-australia.jpg&quot; alt=&quot;view from australia&quot; width=&quot;659&quot; height=&quot;371&quot;&gt;&lt;br&gt;View from our Australian team&lt;/p&gt;
&lt;h3&gt;Content Day&lt;/h3&gt;
&lt;p&gt;Thursday was &quot;D-Day&quot; and we certainly had a full one planned, made up mostly of presentations by our team. This is not always easy, speaking in front of your peers, but without exception they all did a stellar job and the feedback was extremely positive. Here&#039;s how the programme stacked up:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/df-con-21/_resampled/ResizedImage659371-DFCON21-Sessions1.png&quot; alt=&quot;DFCON21 Sessions1&quot; width=&quot;659&quot; height=&quot;371&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span&gt;Sessions – Morning&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/df-con-21/_resampled/ResizedImage659370-dfcon2021-schedule-2.jpeg&quot; alt=&quot;dfcon2021 schedule 2&quot; width=&quot;659&quot; height=&quot;370&quot;&gt;&lt;br&gt;Sessions – Afternoon&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;Guest Stars&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;We were also graced by Joel Katz and John Matthews from Claris, who joined us to take us through and update on whats happening in their world.&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;Wrapping Up In Style&lt;/h3&gt;
&lt;p&gt;Following a long day in the conference room, we retreated to celebrating a great event and an awesome team. We brought in a company called The Cocktail People to show us all how to make some splendid drinks. To our surprise, we were all asked to make a couple of our own, which had differing levels of skills. Let’s just say none of our team would be cast in the remake of &lt;em&gt;Cocktail&lt;/em&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/df-con-21/cocktails.jpg&quot; alt=&quot;cocktails&quot; width=&quot;660&quot; height=&quot;371&quot;&gt;&lt;/p&gt;
&lt;p&gt;And that was a wrap, a wonderful two days spent together as a team. We are not sure if this will be a one off, Claris Engage might be back to face-to-face in the US next year... both formats are incredibly valuable so perhaps we&#039;ll be able to do both in the future?&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Mon, 01 Nov 2021 15:57:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/df-con-2021/</guid>
		</item>
		
		<item>
			<title>Powerful Pivot Table Presetting</title>
			<link>https://www.teamdf.com/blogs/powerful-pivot-table-presetting/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;When it comes to reporting in FileMaker, there are a few options available to developers&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Visual reports, using sub-summary parts, table view etc&lt;/li&gt;
&lt;li&gt;Exporting data&lt;/li&gt;
&lt;li&gt;Charting (ugh!)&lt;/li&gt;
&lt;li&gt;Tableau Connector&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;While it may seem like there is a plethora of options, with the exception of Tableau all these other methods require the developer to have a fair amount of input in producing a desired report output for the end user. FileMaker does not have very good end-user level tools available to help construct your own reports and interrogate your own data.&lt;/p&gt;
&lt;p&gt;Sure, you can open up table view to your users and let them add sub-summary parts and summary fields, but do you really want them to do this? Do you want them to add new fields? Do you want to be restricted to making sure your field names are nice and friendly in order for export fields to make sense?&lt;/p&gt;
&lt;p&gt;No? Neither do I.  There must be a better solution. One where we can give the user far greater control over constructing their own meaningful reports and obtaining useful information about the data in their solutions.  &lt;/p&gt;
&lt;p&gt;This is where Pivot Tables come in.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;What is a Pivot Table?&lt;/h2&gt;
&lt;p&gt;Microsoft gives the following succinct definition of a pivot table:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span&gt;A PivotTable is a powerful tool to calculate, summarize, and analyze data that lets you see comparisons, patterns, and trends in your data.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To me, a pivot table is very much like a chart, but rather than a visual summarization of an X and Y axis, they are instead a table-based summarization of a row and column.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Consider this example...&lt;/h2&gt;
&lt;p&gt;Let&#039;s say our solution has invoices.  Invoices are for customers, and are for selling products.&lt;/p&gt;
&lt;p&gt;What kind of useful information might someone want to learn from their invoices that could help make better business decisions?&lt;/p&gt;
&lt;p&gt;Well, one such thing could be how much each customer has been invoiced for each type of product. This could help the business know which products are popular with which customers.&lt;/p&gt;
&lt;p&gt;In FileMaker, we could provide this information as a sub-summary report. However these reports are restricted to vertical display. Layout parts are vertically stacked and so while we could produce these using simple sub-summary parts and summary fields, we might end up with pages of data to display this information.&lt;/p&gt;
&lt;p&gt;Pivot tables on the other hand are just that - tables - and display this same information in a tabular format using rows and columns:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;A basic pivot example plotting customers and products&quot; src=&quot;https://www.teamdf.com/assets/blog-images/powerful-pivot-presets/_resampled/ResizedImage600199-powerful-pivot-presets-1.png&quot; alt=&quot;powerful pivot presets 1&quot; width=&quot;600&quot; height=&quot;199&quot;&gt;&lt;/p&gt;
&lt;p&gt;The information presented above is much cleaner to read.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Using PivotTable.js &lt;/h2&gt;
&lt;p&gt;So we&#039;re going to use a pivot table in FileMaker, exciting times! For this we choose &lt;a href=&quot;https://pivottable.js.org/examples/&quot;&gt;PivotTable.js&lt;/a&gt; because it is open source, highly flexible and easy to use (and has been previously integrated as we&#039;ll see below).&lt;/p&gt;
&lt;p&gt;PivotTable.js is loaded with cool features that you get right out of the box, some which come to mind are:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Multiple fields defined for rows and columns, think of this as akin to live sub-summary part groupings&lt;/li&gt;
&lt;li&gt;Filtering of rows and columns to specific values&lt;/li&gt;
&lt;li&gt;Sorting rows and columns&lt;/li&gt;
&lt;li&gt;Over a dozen ways to visualise your data, from tables, heatmaps, charts and exports!&lt;/li&gt;
&lt;li&gt;Multiple aggregators (like summary fields) - show counts, sums, averages, std deviations, max/min and more!&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;There are so many more cool things but these should give you a good idea of what to expect.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Heatmap and filtering options&quot; src=&quot;https://www.teamdf.com/assets/blog-images/powerful-pivot-presets/_resampled/ResizedImage600386-powerful-pivot-presets-2.png&quot; alt=&quot;powerful pivot presets 2&quot; width=&quot;600&quot; height=&quot;386&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;How NOT to Reinvent the Wheel!&lt;/h2&gt;
&lt;p&gt;Now, we&#039;re not the first to talk about PivotTable.js by any stretch of the imagination, this has been well covered before, with great articles and demo files which we ourselves have utilised for this article. &lt;/p&gt;
&lt;p&gt;The main one is a great article from that javascript wizard Jeremy Brown. &lt;a href=&quot;https://www.soliantconsulting.com/blog/pivot-table-filemaker/&quot;&gt;You can check it out here&lt;/a&gt;.  In it he goes into more detail about the integration of PivotTable.js and provides a really cool demo file too.  We encourage you to check this out, as it will help you get up to speed with integration - something we aren&#039;t going to cover here, as our integration is based on Jeremy&#039;s.&lt;/p&gt;
&lt;p&gt;PivotTable.js has also been featured in Carafe.FM as an add-on which you can &lt;a href=&quot;https://carafe.fm/bundle/pivot-table-widget-studio/&quot;&gt;check out here&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://www.soliantconsulting.com/blog/pivot-table-filemaker/&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/powerful-pivot-presets/_resampled/ResizedImage19972-powerful-pivot-preset-soliant.png&quot; alt=&quot;powerful pivot preset soliant&quot; width=&quot;199&quot; height=&quot;72&quot;&gt;&lt;/a&gt;         &lt;a href=&quot;https://carafe.fm/bundle/pivot-table-widget-studio/&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/powerful-pivot-presets/_resampled/ResizedImage19952-powerful-pivot-preset-carafe.png&quot; alt=&quot;powerful pivot preset carafe&quot; width=&quot;199&quot; height=&quot;52&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;So What&#039;s Missing?&lt;/h2&gt;
&lt;p&gt;We used PivotTable.js in our solutions and our clients loved it. But there was something missing. Clients were not able to save the pivots they constructed. Each time they logged back in they would have to rebuild their previous configurations.  &lt;/p&gt;
&lt;p&gt;Hmm, wouldn&#039;t it be great to be able to easily save and load configurations of the Pivot Table so that users can easily recall their favourites.  Each construction of a pivot table is really like a report in and of itself.  With save capabilities users can basically build their own reports !&lt;/p&gt;
&lt;p&gt;And so that is exactly what we did. Turns out it wasn&#039;t too difficult.  Thanks to FileMaker 19&#039;s new web viewer integrations, we can utilise the following two powerful actions:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;em&gt;Perform Javascript in Web Viewer&lt;/em&gt; script step&lt;/li&gt;
&lt;li&gt;FileMaker.PerformScriptWithOption javascript function&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;In the following sections we&#039;ll see these in action.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/powerful-pivot-presets/_resampled/ResizedImage600121-powerful-pivot-presets-3.png&quot; alt=&quot;powerful pivot presets 3&quot; width=&quot;600&quot; height=&quot;121&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Saving Presets&lt;/h2&gt;
&lt;p&gt;The first step is to get the users current configuration of the pivot table out of the web viewer and stored in FileMaker.  We achieve this through a very simple process:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;A FileMaker Script calls the &lt;em&gt;getPreset&lt;/em&gt; javascript function&lt;/li&gt;
&lt;li&gt;This javascript function in turn runs a FileMaker script using the &lt;em&gt;FileMaker.PerformScriptWithOption&lt;/em&gt; function and passes it the current configuration as a parameter.&lt;/li&gt;
&lt;li&gt;This script in turn sets the configuration into a global variable.&lt;/li&gt;
&lt;li&gt;The original script continues to run, and stores that global variable contents into a preset record.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Note that we use the &lt;em&gt;FileMaker.PerfromScriptWithOption&lt;/em&gt; rather than the &lt;em&gt;FileMaker.PerformScript&lt;/em&gt; function.  &lt;/p&gt;
&lt;p&gt;in FileMaker 19.0 release, the default behaviour was to run the initiated script after any currently running scripts are finished.&lt;/p&gt;
&lt;p&gt;Instead what we want is to have the script run immediately, returning it&#039;s configuration data for use in the earlier script, in order to be saved as a preset. To do this, we make use of the new FileMaker.PerformScriptWithOption call which allows you to specify how the currently running script is handled when the new script is run.&lt;/p&gt;
&lt;p&gt;You can learn about these options &lt;a href=&quot;https://help.claris.com/en/pro-help/content/options-for-starting-scripts.html&quot;&gt;here in this Claris Article&lt;/a&gt;.  We want to use option &quot;5&quot; which is suspend &amp;amp; resume, meaning the initiating script is suspended, the new script run, and then the initial script is resumed - exactly the same as if you were running a sub script.&lt;/p&gt;
&lt;p&gt;So that&#039;s the FileMaker side of the equation, we just need to write a javascript function to return the current config. This is really easy. in PivotTable.js there is a variable &quot;currentConfig&quot; that contains just that. We simply return this to FileMaker as shown below:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p class=&quot;p1&quot;&gt;var currentConfig;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;function getPreset(parameters) {&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;     FileMaker.PerformScriptWithOption ( &quot;PIVOT: Get Preset&quot;, JSON.stringify ( currentConfig ) , &quot;5&quot; ) ;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;};&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Loading Presets&lt;/h2&gt;
&lt;p&gt;Loading a preset is basically the reverse. We have the preset code stored in FileMaker and we want to pass this into the web viewer and have PivotTable.js load it in for us.&lt;/p&gt;
&lt;p&gt;This is done by calling a second javascript function - &lt;em&gt;updatePreset&lt;/em&gt; - and passing it the configuration code. &lt;/p&gt;
&lt;p&gt;This function will in turn parse the JSON configuration sent to it, and load it into PivotTable.js&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p class=&quot;p1&quot;&gt;function updatePreset(config) {&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;    &lt;/span&gt;let configjs = JSON.parse(config);&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;    &lt;/span&gt;configjs.onRefresh = function(config) {&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;        &lt;/span&gt;//delete some values which will not serialize to JSON&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;        &lt;/span&gt;delete config[&quot;aggregators&quot;];&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;        &lt;/span&gt;delete config[&quot;renderers&quot;];&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;        &lt;/span&gt;delete config[&quot;rendererOptions&quot;];&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;        &lt;/span&gt;delete config[&quot;localeStrings&quot;];&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;        &lt;/span&gt;currentConfig = config;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;    &lt;/span&gt;};&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;    &lt;/span&gt;$(&quot;#output&quot;).pivotUI($.pivotUtilities.tipsData, configjs, true);&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;If you don&#039;t understand how it works, don&#039;t worry - you don&#039;t need to.  The end result is the ability for end users to save their own presets! &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;Preset Saving and Loading&quot; src=&quot;https://www.teamdf.com/assets/blog-images/powerful-pivot-presets/_resampled/ResizedImage600296-powerful-pivot-presets-4.png&quot; alt=&quot;powerful pivot presets 4&quot; width=&quot;600&quot; height=&quot;296&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;FileMaker.PerformScriptWithOption&lt;/h2&gt;
&lt;p&gt;Just a quick note on the usage of FileMaker.PerformScriptWithOption for the saving of presets.  We use Option 5 of suspend/resume. This was only introduced in version 19.1.2 and above, so those of you still on an original release version of 19 will not see this working as expected - you should upgrade to the latest release of 19.&lt;/p&gt;
&lt;p&gt;If you choose not to, then you can still achieve saving of presets without issue, you just need to be a little more creative in your scripting. Given the javascript initiated script will be queued to run, you need to have this script carry out the preset saving.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;What FileMaker Weetbicks article wouldn&#039;t be complete without an example file? In this you&#039;ll find everything discussed in the article, along with a simple pivot table example, and a preset example. You&#039;ll also find links to resources we have used to create this file and write this article.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/powerful-pivot-presets/Powerful-Pivot-Table-Presetting.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/prominentcolorcoolness/prominent-color-coolness.zip&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;We love feedback so please leave a comment if you have anything to say - even if you don&#039;t it would be nice to hear from you :) &lt;/p&gt;</description>
			<pubDate>Thu, 30 Sep 2021 21:59:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/powerful-pivot-table-presetting/</guid>
		</item>
		
		<item>
			<title>Lovely Logos &amp; Pretty Profile Pics</title>
			<link>https://www.teamdf.com/blogs/lovely-logos-and-pretty-profile-pics/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Contacts. Almost every FileMaker solution has them. Contacts can be people, companies, suppliers, friends or colleagues, and the list goes on. Almost every Claris FileMaker developer who has been in the game for more than 5 minutes has most likely built a solution that contains contacts.&lt;/p&gt;
&lt;p&gt;In terms of database sexiness, contacts can be pretty boring. They usually have a name, phone number, email address, website for starters. Where&#039;s the pizzaz, the bounce, the pop?&lt;/p&gt;
&lt;p&gt;Contacts can be spiced up by adding a bit of imagery to help represent them. This can come in the form of a company logo, or a profile picture (if our contact is a person).&lt;/p&gt;
&lt;p&gt;In fact, a lot of CRM solutions will have the ability to upload a picture of the contact, but let&#039;s be honest, how many people actually do this?  All too often you see a silhouette where a picture should be.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;CRM without a company logo&quot; src=&quot;https://www.teamdf.com/assets/blog-images/lovely-logos-pretty-profiles/_resampled/ResizedImage600363-lovely-logo-1.png&quot; alt=&quot;CRM without a company logo&quot; width=&quot;600&quot; height=&quot;363&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;h2&gt;What can we do about this?&lt;/h2&gt;
&lt;p&gt;Fortunately we live in the age of the API. A lot of the time API&#039;s are thought of as boring text input/output tools: pass an API a request, and get a bunch of JSON data back. But not all API&#039;s are so textual. There are hundreds of awesome design based API&#039;s out there for image manipulation and retrieval.&lt;/p&gt;
&lt;p&gt;We&#039;re going to pick a select bunch for this article that specialise in returning either a company logo from a website URL, or a user profile picture using a supplied email address.&lt;/p&gt;
&lt;p&gt;Note that for specific code examples and content, we encourage you to download the example file at the end of this article - there you will find everything we discuss in the article and it is completely unlocked for you to explore and learn.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;CMS with a company logo&quot; src=&quot;https://www.teamdf.com/assets/blog-images/lovely-logos-pretty-profiles/_resampled/ResizedImage600363-lovely-logo-2.png&quot; alt=&quot;CMS with a company logo&quot; width=&quot;600&quot; height=&quot;363&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Company Logo Retrieval using Clearbit&lt;/h2&gt;
&lt;p&gt;For company logo retrieval we use the &lt;a title=&quot;Clearbit Company Logo API&quot; href=&quot;https://clearbit.com/blog/logo/&quot; target=&quot;_blank&quot;&gt;ClearBit Company Logo API&lt;/a&gt;.  This is a free API and will return the logo for any website, providing that website has used the Open Graph meta-tags &lt;strong&gt;og:image &lt;/strong&gt;or&lt;strong&gt; og:logo &lt;/strong&gt;as part of their page metadata. ClearBit will cache these images and serve them up super-fast to you via CDN.&lt;/p&gt;
&lt;p&gt;Making the API call couldn&#039;t be simpler as it is a straightforward get request:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span&gt;https://logo.clearbit.com/&lt;strong&gt;DOMAIN&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;where &lt;strong&gt;DOMAIN&lt;/strong&gt; is the websites domain name. That&#039;s it!  You can also specify the size or format you wish to have returned by using some additional parameters, or specify whether you wish the image to be greyscale, e.g.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;https://logo.clearbit.com/filemakerhacks.com?size=512&amp;amp;format=png&amp;amp;greyscale=false&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Most websites you&#039;ll find have this meta-tag provided because it is the image that is used by various social media networks when a post is made linking to that website.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;The example file will show you how to use the API&quot; src=&quot;https://www.teamdf.com/assets/blog-images/lovely-logos-pretty-profiles/_resampled/ResizedImage600363-lovely-logo-3.png&quot; alt=&quot;The example file will show you how to use the API&quot; width=&quot;600&quot; height=&quot;363&quot;&gt;&lt;/p&gt;
&lt;p&gt;ClearBit also has other APIs that they offer (both free and paid) to retrieve even more information about a company or person using their website URL or email address. If you wanted to supercharge your CRM you could utilise these APIs to attempt to auto-complete a bunch of information about your contacts - how cool would that be!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Profile Picture Retrieval using Gravatar (and others)&lt;/h2&gt;
&lt;p&gt;Profile pictures of people - while likely far more common than company logos online - are actually a little harder to obtain.  You&#039;d think with everybody having profiles in facebook, linkedin, instagram, twitter etc, that these would be easy to get. But these images are largely protected from API&#039;s gaining access and unless you know specific profile usernames, they cannot be readily retrieved using information such as an email address.&lt;/p&gt;
&lt;p&gt;This is where &lt;a title=&quot;Gravatar&quot; href=&quot;http://www.gravatar.com&quot; target=&quot;_blank&quot;&gt;Gravatar&lt;/a&gt; comes in handy.  Gravatar is a service created by wordpress where users can sign up for an account and create a globally recognised avatar and profile. These can then be used on sites that support gravatar, without the need for recreating your profile across multiple sites.&lt;/p&gt;
&lt;p&gt;While Gravatar is getting more popular, it has not had huge uptake and for that reason it can be a little hit and miss getting a profile picture from it.&lt;/p&gt;
&lt;p&gt;Fortunately for us though the Gravatar API is free to use, and so use it we shall.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span&gt;https://www.gravatar.com/avatar/&lt;strong&gt;HASH&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the basic GET request to obtain a profile picture.  &lt;strong&gt;HASH&lt;/strong&gt; is actually the MD5 hash of an email address. We can easily calculate the MD5 hash in Claris FileMaker using the GetContainerAttribute function. Here is how I would get my email address as MD5:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;GetContainerAttribute ( Lower ( &quot;daniel@teamdf.com&quot; ) ; &quot;MD5&quot; )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Somewhat odd that we use a container function, but this works fine on text also.&lt;/p&gt;
&lt;p&gt;Gravatar can accept size parameters also. It can even generate for you a unique avatar using one of 8 different generators if a profile picture cannot be found.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;Obtaining profile pictures with Gravatar&quot; src=&quot;https://www.teamdf.com/assets/blog-images/lovely-logos-pretty-profiles/_resampled/ResizedImage600363-lovely-logo-4.png&quot; alt=&quot;Obtaining profile pictures with Gravatar&quot; width=&quot;600&quot; height=&quot;363&quot;&gt;&lt;/p&gt;
&lt;p&gt;Gravatar is also able to retrieve profile information for an email address, and we have utilised this in our example file to extract usernames of profiles also as a nice added bonus.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Additional APIs for Retrieval&lt;/h2&gt;
&lt;p&gt;If &lt;a title=&quot;Gravatar&quot; href=&quot;http://www.gravatar.com&quot; target=&quot;_blank&quot;&gt;Gravatar&lt;/a&gt; or &lt;a title=&quot;Clearbit&quot; href=&quot;http://www.clearbit.com&quot; target=&quot;_blank&quot;&gt;ClearBit&lt;/a&gt; cannot retrieve the correct image, there is a possibility one of these two other APIs can do it: &lt;a title=&quot;AvatarAPI&quot; href=&quot;https://avatarapi.com/&quot; target=&quot;_blank&quot;&gt;AvatarAPI&lt;/a&gt; and &lt;a title=&quot;Libravatar&quot; href=&quot;https://www.libravatar.org/&quot; target=&quot;_blank&quot;&gt;Libravatar&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;AvatarAPI queries google profiles to retrieve a profile picture based on email address. It works best with gmail addresses but can work for others if the user has established a google profile using a non-gmail address.&lt;/p&gt;
&lt;p&gt;Libravatar is a similar service to Gravatar in that you sign up for an account and add your avatar &amp;amp; profile, which can then be served up to other websites that wish to utilise the service to populate profile information.&lt;/p&gt;
&lt;p&gt;Both of these APIs have been integrated into our example as fallbacks in the event Gravatar is unable to successfully retrieve a profile picture.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Removing Backgrounds from Images&lt;/h2&gt;
&lt;p&gt;Just cos APIs are so cool we thought we would throw in this little gem. Let&#039;s say you receive a company logo or profile picture which has an annoying, distracting or otherwise offensive background? Wouldn&#039;t it be nice to get rid of that? &lt;/p&gt;
&lt;p&gt;Well, there are APIs for that too! In fact there are quite a number of APIs providing this service. Out of all of them, most will cost you per removal (around 1-4 cents on average).&lt;/p&gt;
&lt;p&gt;In order to illustrate the removal however we have used in our example file two free APIs - each come with restrictions on using the free service but the point here is to show that this is achievable and what the results can look like.&lt;/p&gt;
&lt;p&gt;The two free APIs we have explored are &lt;a title=&quot;Imagezerow&quot; href=&quot;https://imagezerow.com/#/api&quot; target=&quot;_blank&quot;&gt;Imagezerow&lt;/a&gt; and &lt;a title=&quot;Pixmiller&quot; href=&quot;https://pixmiller.com/en/api-docs/&quot; target=&quot;_blank&quot;&gt;PixMiller&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;Before and After background Removal&quot; src=&quot;https://www.teamdf.com/assets/blog-images/lovely-logos-pretty-profiles/_resampled/ResizedImage600240-lovely-logos-5.png&quot; alt=&quot;Before and After background Removal&quot; width=&quot;600&quot; height=&quot;240&quot;&gt;&lt;/p&gt;
&lt;p&gt;The APIs&#039; use machine learning and are pretty darn good at knowing what to remove, as demonstrated by Mini-Weet above.  Images are returned with transparent background which is perfect for you to then provide your own desired background colors. (perhaps you could combine this with some techniques in our &lt;a title=&quot;Prominent Color Coolness&quot; href=&quot;https://www.teamdf.com/blogs/prominent-color-coolness/&quot; target=&quot;_blank&quot;&gt;previous article for background colors&lt;/a&gt;!).&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Still Can&#039;t Find an Image for Your Contact?&lt;/h2&gt;
&lt;p&gt;Fear not. Just because API&#039;s may not be able to locate an actual logo or profile picture, this doesn&#039;t mean you need to present the contact with bland text. There are &lt;strong&gt;heaps&lt;/strong&gt; of other Avatar generating APIs out there that can produce a nice unique image for your contacts.&lt;/p&gt;
&lt;p&gt;In our &lt;a title=&quot;elemental_ux&quot; href=&quot;https://www.elemental-fm.com/elemental-ux&quot;&gt;elemental_ux&lt;/a&gt; solution we have over 20 different avatar generating APIs, all with working examples - you just need to copy/paste the script you want and specify your parameters.&lt;/p&gt;
&lt;p&gt;Here at Digital Fusion we utilise avatars along with profile pictures and logos to produce a rich contact experience:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;Logo and Avatar&quot; src=&quot;https://www.teamdf.com/assets/blog-images/lovely-logos-pretty-profiles/_resampled/ResizedImage600384-lovely-logos-6.png&quot; alt=&quot;Logo and Avatar&quot; width=&quot;600&quot; height=&quot;384&quot;&gt;&lt;/p&gt;
&lt;p&gt;All contacts are generated an avatar via API. We use the &lt;a title=&quot;UI-Avatars&quot; href=&quot;https://ui-avatars.com/&quot; target=&quot;_blank&quot;&gt;UI-Avatars.com API&lt;/a&gt; (which can also be found in &lt;a title=&quot;Elemental_UX&quot; href=&quot;https://www.elemental-fm.com/elemental-ux&quot;&gt;elemental_ux&lt;/a&gt;) to achieve this. In addition we also utilise the above APIs for logo and profile picture retrieval.&lt;/p&gt;
&lt;p&gt;Logos and profile pictures can often be inconsistent in their size and ratio and so aren&#039;t suitable for display in portals and lists. This is where the consistently sized avatar is perfect.&lt;/p&gt;
&lt;p&gt;The logos are used only in a large container space where ratio is not an issue. For years we struggled trying to display logos beside a company name nicely, before biting the bullet and going with avatars instead - and we have never looked back!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;What FileMaker Weetbicks article wouldn&#039;t be complete without an example file? All the main APIs featured in this article have been integrated into our example file so you can copy and use in your own solutions. We hope you enjoy it. &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;Download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/lovelylogosprettyprofiles/lovely-logos-pretty-profiles.zip&quot;&gt;Click here to download the example file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/prominentcolorcoolness/prominent-color-coolness.zip&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;We love feedback so please leave a comment if you have anything to say - even if you don&#039;t it would be nice to hear from you :) &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Mon, 30 Aug 2021 22:25:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/lovely-logos-and-pretty-profile-pics/</guid>
		</item>
		
		<item>
			<title>Prominent Color Coolness</title>
			<link>https://www.teamdf.com/blogs/prominent-color-coolness/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this article we&#039;re going to show a simple web viewer based approach to achieve beautiful dynamic background gradients and fills that are based upon an images most prominent colors. Further to this we&#039;ll show a way to render those solid fills in a container field. Finally, we&#039;ll demonstrate how to choose the optimal color for text that is to be placed on top of these fills for maximum readability.&lt;/p&gt;
&lt;p&gt;Note that for specific code examples and content, we encourage you to download the example file at the end of this article.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;What Are We Talking About?&lt;/h2&gt;
&lt;p&gt;If you have used Spotify before, you may nave noticed that album pages contain a nice gradient background behind the album art. This gradient is based upon the prominent colors within the album art itself. It creates a really nice effect and gives each album page it&#039;s own sense of personality beyond just the album cover.&lt;/p&gt;
&lt;div class=&quot;captionImage leftAlone&quot; style=&quot;width: 678px;&quot;&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;Spotify Album Art&quot; src=&quot;https://www.teamdf.com/assets/blog-images/prominent-color-coolness/_resampled/ResizedImage678169-prominent-color-coolness-1.png&quot; alt=&quot;Spotify Album Art&quot; width=&quot;678&quot; height=&quot;169&quot;&gt;&lt;/div&gt;
&lt;p&gt;Wouldn&#039;t it be cool to achieve the same thing in FileMaker? This idea came to me when developing a solution for a company who restores artworks. Their solution had a page displaying a grid of artworks. The various dimensions of artworks created a cluttered and uneven feel. To remedy this I wanted a consistent background, but wanted to ensure that background matched the artwork.&lt;/p&gt;
&lt;p&gt;Below you can get a sense of what this achieved by comparing before and after.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;Before and After&quot; src=&quot;https://www.teamdf.com/assets/blog-images/prominent-color-coolness/prominent-color-coolness-2.gif&quot; alt=&quot;Before and After&quot; width=&quot;687&quot; height=&quot;419&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;JavaScript To The Rescue!&lt;/h2&gt;
&lt;p&gt;These days most problems in FileMaker can be solved with JavaScript, and this problem was no different. A bit of hunting led me to &lt;a title=&quot;grade.js&quot; href=&quot;https://benhowdle89.github.io/grade/&quot; target=&quot;_blank&quot;&gt;grade.js&lt;/a&gt;, a library which produces a gradient using the 2 most prominent colors in an image.  &lt;/p&gt;
&lt;p&gt;grade.js will insert a gradient background in a &lt;em&gt;&amp;lt;div&amp;gt;&lt;/em&gt; element. It does this using the image specified inside the &lt;em&gt;&amp;lt;div&amp;gt;&lt;/em&gt; element, using an &lt;em&gt;&amp;lt;img&amp;gt;&lt;/em&gt; element.&lt;/p&gt;
&lt;p&gt;Our code takes this further, styling the &lt;em&gt;&amp;lt;div&amp;gt;&lt;/em&gt; element fill the entire web page (and thus the web viewer).&lt;/p&gt;
&lt;p&gt;An image from a FileMaker container field can be inserted into the &lt;em&gt;&amp;lt;img&amp;gt;&lt;/em&gt; element by encoding it as Base64, as shown below:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;lt;img src=&quot;data:image/png;base64,**IMAGE**&quot; style=&quot;display: none;&quot; /&amp;gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You&#039;ll also note we use a style to hide the image. This is because it&#039;s easier for us to overlay the container field in FileMaker than it is to correctly position the image in html.  &lt;/p&gt;
&lt;p&gt;FileMaker 19 introduced a change to web viewers, allowing them to render underneath other FileMaker objects. Prior to 19, web viewers always rendered in front of all other objects, much to this developers frustration.&lt;/p&gt;
&lt;p&gt;The end result is quite awesome.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Movie Poster Gradients&quot; src=&quot;https://www.teamdf.com/assets/blog-images/prominent-color-coolness/_resampled/ResizedImage678176-prominent-color-coolness-3.png&quot; alt=&quot;Movie Poster Gradients&quot; width=&quot;678&quot; height=&quot;176&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Returning Color Data To FileMaker&lt;/h2&gt;
&lt;p&gt;Another neat thing grade.js can do is make available the color data used to generate the gradient. This information can then easily be passed back to FileMaker by utilising the &lt;em&gt;FileMaker.PerformScriptWithOption&lt;/em&gt; function call within the javascript.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;JSON Data returned from grade.js&quot; src=&quot;https://www.teamdf.com/assets/blog-images/prominent-color-coolness/_resampled/ResizedImage678218-prominent-color-coolness-4.png&quot; alt=&quot;JSON Data returned from grade.js&quot; width=&quot;678&quot; height=&quot;218&quot;&gt;&lt;/p&gt;
&lt;p&gt;This information can be parsed to do things like color text, or generate saved solid fills as we&#039;ll show later.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Generating Solid Fills &lt;/h2&gt;
&lt;p&gt;Gradients are pretty, but what if you just want a single solid color? Fortunately there are lots of examples out there on the web of how to do just this. I found one &lt;a href=&quot;http://jsfiddle.net/xLF38/818/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; on &lt;a href=&quot;https://jsfiddle.net&quot; target=&quot;_blank&quot;&gt;jsfiddle.net&lt;/a&gt;. Again it&#039;s very simple and works almost exactly the same as our gradient example. This code sets the html body background color to the average color in  an image element.&lt;/p&gt;
&lt;p&gt;Again we base64 encode and inject our image and make it invisible in the page. With some CSS styling we can ensure the background fills the entire web viewer.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;Returning RGB values for a Solid Fill&quot; src=&quot;https://www.teamdf.com/assets/blog-images/prominent-color-coolness/_resampled/ResizedImage600224-prominent-color-coolness-5.png&quot; alt=&quot;Returning RGB values for a Solid Fill&quot; width=&quot;600&quot; height=&quot;224&quot;&gt;&lt;/p&gt;
&lt;p&gt;This library can also return us RGB information about the background color generated using &lt;em&gt;FileMaker.PerformScriptWithOption&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Web Viewer Dilemma&lt;/h2&gt;
&lt;p&gt;Web viewers can do so many cool things, but one thing they cannot do is get placed inside a portal. So far we&#039;ve shown fills that exist within the web viewer, and as such these are restricted to non-portal implementations.  Web viewers also take a brief moment to load, and so there are very small flashes that can be seen while they load.&lt;/p&gt;
&lt;p&gt;If we want to show these fills in a portal, then they have to exist outside of a web viewer. In this example we focus specifically achieving this for solid fills.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Rendering RGB As A Fill Color&lt;/h2&gt;
&lt;p&gt;As we saw in the previous example, our solid fill code can return the numerical values for red, green, and blue. The problem to solve is how to transform this into a visible solid fill in FileMaker, that isn&#039;t using the web viewer to render.&lt;/p&gt;
&lt;p&gt;Fortunately this problem was solved for us back in 2013 in &lt;a href=&quot;https://excelisys.com/filemaker-base64-decode-status-progress-bar/&quot; target=&quot;_blank&quot;&gt;this great article&lt;/a&gt; from Excelisys. When the &lt;em&gt;Base64Encode&lt;/em&gt; and &lt;em&gt;Base64Decode&lt;/em&gt; functions were introduced to FileMaker, the guys at Excelisys used them to produce a 1x1px bitmap image of a color in a nominated RGB color. This was then used to produce a progress bar that could be dynamically adjusted - all without a web viewer.  Cutting edge stuff back then for sure! Progress bars these days can be done in other ways such as button bars, or in web viewers, but the code still has great use.&lt;/p&gt;
&lt;p&gt;We have taken the Excelisys progress bar code and instead  used it to produce our own 100% filled progress bar of our required color. We can then use this as a background fill to display in portals.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;Solid fills in a portal&quot; src=&quot;https://www.teamdf.com/assets/blog-images/prominent-color-coolness/prominent-color-coolness-6.png&quot; alt=&quot;Solid fills in a portal&quot; width=&quot;299&quot; height=&quot;512&quot;&gt;&lt;/p&gt;
&lt;p&gt;There are a series of custom functions used to achieve this effect, which are available in the example file provided at the end of this article.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Text Overlay Dilemma&lt;/h2&gt;
&lt;p&gt;Okay, we have our image our and our fill, but what about displaying text on our background?  We want the text to be optimally readable regardless of whether the background is dark or light. So how do we do it?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt; ( ( r * .299 ) + ( g * .587 ) + ( b * .114 ) ) &amp;gt; 186&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is how we do it. This code tells us whether a given color defined by its RGB components is a light image. If the calculation result is greater than 186 then it&#039;s a fair bet that the image is of the lighter persuasion and thus the text should be of the dark variety.  &lt;/p&gt;
&lt;p&gt;Conversely if the number is less than or equal to 186, it&#039;s a dark image and so light text is favourable.&lt;/p&gt;
&lt;p&gt;In our example file we bundle this up into a custom function that accepts the RGB values as parameters. We return either a light or dark color using the &lt;em&gt;RGB&lt;/em&gt; text formatting function.&lt;/p&gt;
&lt;p&gt;This result can then be used to color text using the &lt;em&gt;TextColor&lt;/em&gt; function.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;Dark and Light text&quot; src=&quot;https://www.teamdf.com/assets/blog-images/prominent-color-coolness/prominent-color-coolness-7.png&quot; alt=&quot;Dark and Light text&quot; width=&quot;300&quot; height=&quot;218&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Taking It Further&lt;/h2&gt;
&lt;p&gt;What we&#039;ve shown really is the tip of the iceberg and there are so many more cool libraries out there and code examples that you could utilise in FileMaker. Below are just a few that caught our attention but we have not had time to explore further:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/fast-average-color/fast-average-color&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Fast Average Color&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A cool library for getting average color of images for background display, with a heap of customisations around background display.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://lokeshdhakar.com/projects/color-thief/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Color Thief&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This library can return you a color palette of prominent colors of a provided image. Again, a ton of options possible. &lt;a href=&quot;https://codepen.io/davidramsay95/pen/MWbRdYb&quot; target=&quot;_blank&quot;&gt;Here is one such implementation&lt;/a&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/prominentcolorcoolness/prominent-color-coolness.zip&quot; target=&quot;_blank&quot;&gt;.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://codepen.io/mcheah/pen/MWbRdBE&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Image Blur&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is a simple nifty CSS hack that produces a background from an image by blurring it beyond recognition.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;We encourage you to try these or any others you find and share your results!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;What FileMaker Weetbicks article wouldn&#039;t be complete without an example file? The images in this article are from our file and we hope you enjoy it.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/prominentcolorcoolness/prominent-color-coolness.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;</description>
			<pubDate>Wed, 18 Aug 2021 23:04:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/prominent-color-coolness/</guid>
		</item>
		
		<item>
			<title>How to Remove a Saved Password from FileMaker Go</title>
			<link>https://www.teamdf.com/blogs/remove-a-saved-password-from-filemaker-go/</link>
			<description>&lt;h2&gt;The Problem is...&lt;/h2&gt;
&lt;p&gt;Have a database on your iPad with a saved password that automatically logs you in?&lt;/p&gt;
&lt;p&gt;Has it been saved to the keychain under someone else&#039;s credentials?&lt;/p&gt;
&lt;p&gt;Finding how to remove a password from Claris FileMaker Go is not the easiest, so we&#039;ve put together a step-by-step guide to remove those saved credentials so you log in again with your correct account...&lt;/p&gt;
&lt;h2&gt;Remove a Password in 6 Easy Steps&lt;/h2&gt;
&lt;p&gt;1. If you have a file open, close it. Closing files/systems is solution specific, so if you’re not sure, ask your developer.  If you can&#039;t see your solution open, press and hold the FileMaker Go app button to see open if you have open.&lt;/p&gt;
&lt;p&gt;2. Tap on the &quot;Settings&quot; icon toward the top left of the screen. The &quot;Settings&quot; icon only appears on &quot;My Apps&quot; and &quot;Hosts&quot;.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/remove-password-fmgo/_resampled/ResizedImage660461-Step-1-2.png&quot; alt=&quot;Step 1 2&quot; width=&quot;660&quot; height=&quot;461&quot;&gt;&lt;/p&gt;
&lt;p&gt;3. Tap on &quot;Manage Keychain&quot;, you will be prompted for Face ID, Touch ID or your Passcode depending on the type of device you have.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/remove-password-fmgo/Step-3-660.png&quot; alt=&quot;Step 3&quot; width=&quot;660&quot; height=&quot;462&quot;&gt; &lt;/p&gt;
&lt;p&gt;4. Once you have been successfully authenticated, you will see a list of saved passwords for solutions and hosts. Tap on the &quot;Edit&quot; button to edit the list.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/remove-password-fmgo/_resampled/ResizedImage660461-Step-4-660.png&quot; alt=&quot;Step 4&quot; width=&quot;660&quot; height=&quot;461&quot;&gt;&lt;/p&gt;
&lt;p&gt;5. Tap the &quot;-&quot; icon to the right of the items that you wish to remove. Once you’ve removed the saved passwords, tap the &quot;Done&quot; button.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/remove-password-fmgo/Step-5-660.png&quot; alt=&quot;Step 5&quot; width=&quot;660&quot; height=&quot;462&quot;&gt;&lt;/p&gt;
&lt;p&gt;6. Additional tip - It’s also possible to swipe from right to left on the save password in the list to reveal a delete option.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/remove-password-fmgo/Step-6-660.png&quot; alt=&quot;Step 6&quot; width=&quot;660&quot; height=&quot;462&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Fri, 11 Jun 2021 09:52:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/remove-a-saved-password-from-filemaker-go/</guid>
		</item>
		
		<item>
			<title>Hotting Up FileMaker</title>
			<link>https://www.teamdf.com/blogs/hotting-up-filemaker/</link>
			<description>&lt;p&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovukz87zz89zz86zz66z7ez84zgz68zz75zjffhz83z54a9cvz65zz81zz78zrz66z3mz85z&quot;&gt;For many years, FileMaker was somewhat of a&lt;/span&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovukz87zz89zz86zz66z7ez84zgz68zz75zjffhz83z54a9cvz65zz81zz78zrz66z3mz85z s-apos&quot;&gt; &lt;/span&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovukz87zz89zz86zz66z7ez84zgz68zz75zjffhz83z54a9cvz65zz81zz78zrz66z3mz85z h-apos&quot;&gt;&#039;closed&lt;/span&gt;&lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovukz87zz89zz86zz66z7ez84zgz68zz75zjffhz83z54a9cvz65zz81zz78zrz66z3mz85z&quot;&gt; shop&#039; when it came to extending it’s capabilities.&lt;/span&gt; If we ever wanted to do anything &quot;outside the box&quot; (basically cool stuff) we really had to blur the lines of what FileMaker intended. (Which we certainly did with our &lt;a href=&quot;https://www.teamdf.com/products/reactor-2/&quot;&gt;Reactor plugin!&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;However with FileMaker 19 Claris opened up FileMaker with “add ons” and JavaScript support, which means the development community can now extend the capabilities of FileMaker in some very cool, very powerful ways.&lt;/p&gt;
&lt;p&gt;So we got to work, or in particular Daniel and Steve got to work, and we’ve come up with three new developer products — one is an add-on, the other a tool for crafting nicer interfaces, and the third a module for change logging.&lt;/p&gt;
&lt;p&gt;All are designed to make both the developers life easier, and provide a nicer experience for your end users, whether they’re sitting at their desks using FileMaker Pro, out in the field using FileMaker Go, or anywhere using FileMaker WebDirect.&lt;/p&gt;
&lt;p&gt;So to give you a brief rundown of the three products:&lt;/p&gt;
&lt;h2&gt;elemental_ux&lt;/h2&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/hotting-up-filemaker/elemental-ux.png&quot; alt=&quot;elemental_ux&quot; width=&quot;660&quot; height=&quot;165&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a title=&quot;elemental_ux&quot; href=&quot;https://www.elemental-fm.com/elemental-ux&quot; target=&quot;_blank&quot;&gt;elemental_ux&lt;/a&gt; is a design resource that helps developers build better looking user interfaces. Think of this as an image gallery. Somewhere you can go to access awesome avatars, icons, gradients and much more. It’s our attempt at giving developers the tools to take the ordinary to the extraordinary in design of FileMaker Databases.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/hotting-up-filemaker/elemental-ux.gif&quot; alt=&quot;elemental ux&quot; width=&quot;660&quot; height=&quot;352&quot;&gt;&lt;/p&gt;
&lt;h2&gt;elemental_log&lt;/h2&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/hotting-up-filemaker/elemental-log.png&quot; alt=&quot;elemental_log&quot; width=&quot;660&quot; height=&quot;165&quot;&gt;&lt;/p&gt;
&lt;p&gt;Possibly the most mundane of the three, but easily the most important and business critical: &lt;a title=&quot;elemental_log&quot; href=&quot;https://www.elemental-fm.com/elemental-log&quot; target=&quot;_blank&quot;&gt;elemental_log&lt;/a&gt; is data change logging toolset that embeds in your solution and tracks every field change in every table that you ask it to. This provides a complete audit log of who’s changed which data, when, and what values it’s gone from and too. &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/hotting-up-filemaker/elemental-ux-660.gif&quot; alt=&quot;elemental_ux&quot; width=&quot;660&quot; height=&quot;397&quot;&gt;&lt;/p&gt;
&lt;p&gt;Log has been built to be as easy to use and set up as possible, with much attention paid to the design and the configuration. The joy of this is that there are very few steps required to get it up and running.&lt;/p&gt;
&lt;h2&gt;elemental_dropzone&lt;/h2&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/hotting-up-filemaker/elemental-dropzone.png&quot; alt=&quot;elemental_dropzone&quot; width=&quot;660&quot; height=&quot;165&quot;&gt;&lt;/p&gt;
&lt;p&gt;Last but not least, our latest offering is from an amazing combo of Daniel and Steve…&lt;/p&gt;
&lt;p&gt;&lt;a title=&quot;elemental_dropzone&quot; href=&quot;https://www.elemental-fm.com/elemental-dropzone&quot; target=&quot;_blank&quot;&gt;elemental_dropzone&lt;/a&gt; is about to make your lives 110% easier, by giving you the ability to drag and drop multiple files and folders directly into your FileMaker solutions in a single go.&lt;/p&gt;
&lt;p&gt;Not only does this work on FileMaker Pro, it also works on FileMaker Go and FileMaker WebDirect. This means if you are working on an iPad out in the field, you can add things like photos, signatures, documents, directly out of folders and right into your solution all at once without needing to add one file at a time.&lt;/p&gt;
&lt;p&gt;And for your convenience, fellow developers, we’ve released this as a FileMaker Add-on, so it&#039;s always going to be there in your layout tools, ready to drop into any layout where it’s required.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/hotting-up-filemaker/elemental-dropzone-660.png&quot; alt=&quot;elemental dropzone&quot; width=&quot;660&quot; height=&quot;400&quot;&gt;&lt;/p&gt;
&lt;p&gt;To learn more about our elemental products, visit our dedicated website at:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;Elemental Website&quot; href=&quot;https://www.elemental-fm.com&quot; target=&quot;_blank&quot;&gt;elemental-fm.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 18 May 2021 10:54:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/hotting-up-filemaker/</guid>
		</item>
		
		<item>
			<title>Wellington… Here We Come!</title>
			<link>https://www.teamdf.com/blogs/wellington-here-we-come/</link>
			<description>&lt;p&gt;We’ve made a mental note that future job ads must include a reference to people named Paul/Paula/Pablo... You may ask why and that&#039;s because we have just taken on our latest &#039;Paul&#039;, this one being Paul Baker who will head up our new office in Wellington.&lt;/p&gt;
&lt;p&gt;Paul Baker (or PB as he will be known) takes our &#039;Paul&#039; count up to three, joining Paul Hutton and Paul Thomas (PT). Not a bad collection for a company of sixteen.&lt;/p&gt;
&lt;p&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/wellington-here-we-come/hutton-thomas-baker.png&quot; alt=&quot;hutton thomas baker&quot; width=&quot;660&quot; height=&quot;386&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;Left to right: Paul Hutton, Paul Thomas and Paul Baker&lt;/p&gt;
&lt;p&gt;But back to Paul Baker, and welcoming him to the team at Digital Fusion. We always consider ourselves fortunate when we are able to take on new team members with Claris FileMaker experience. In the case of PB, he comes to us with an extensive background in the print industry, where he has put his FileMaker skills to good use, developing solutions that made the lives of his colleagues a lot easier.&lt;/p&gt;
&lt;p&gt;In the last company he worked for, he took them from pen and paper, to full automation using custom built production and asset capture, Claris Filemaker solutions. Included was WebDirect access for clients and iPad capabilities for staff to capture live information out in the field.&lt;/p&gt;
&lt;p&gt;We are excited to have Paul up in Wellington, an area where we have some great clients already and now with him on the ground there we will be better able to serve the region.&lt;/p&gt;
&lt;p&gt;In his personal life, Paul is married and has a young son. He lives, and will work, in the central city, getting to take in the vibrancy of the fantastic city of Wellington.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/wellington-here-we-come/paul-son.png&quot; alt=&quot;Paul and his son&quot; width=&quot;660&quot; height=&quot;432&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Thu, 06 May 2021 17:20:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/wellington-here-we-come/</guid>
		</item>
		
		<item>
			<title>SSL Certs and The Chain Of Trust</title>
			<link>https://www.teamdf.com/blogs/ssl-certificates-and-the-chain-of-trust/</link>
			<description>&lt;p&gt;In the fun world of FileMaker Server configuration, one of the key tasks is to set up the domain name and an associated “SSL Certificate” — the cert verifies the server’s identity, and provides an encryption key used to encode data that flows between users and the server.&lt;/p&gt;
&lt;p&gt;This is all marvelous stuff of course because it means that there’s no-way for someone to trick you into connecting to a different server than the one you meant to and because all the private personal and business data that is zooming along the wires and airwaves between you and the server is indecipherable to anyone else.&lt;/p&gt;
&lt;p&gt;But there are some tricks to setting up secure certificates and how they work so we thought we’d share a recent experience we had when one of the certication authorities dropped the ball and broke what’s called the “Chain of Trust”…&lt;/p&gt;
&lt;h2&gt;Chain Of Trust&lt;/h2&gt;
&lt;p&gt;When you purchase and install an SSL Certificate on your FileMaker Server, you expect that you own the whole ‘kit and caboodle’, or at least you do for the timeframe you have purchased the certificate for.&lt;/p&gt;
&lt;p&gt;To some degree that is correct, but there is a chain of trust that sits above your certificate that you ought to understand… in essence there are many organisations that can issue certificates, but only a few that are known and trusted by an operating system.&lt;/p&gt;
&lt;p&gt;Therefore an issuer of a certificate has to be able to prove they are who they say they are and they do this by holding certificates signed by a higher authority.&lt;/p&gt;
&lt;h2&gt;The Root Of The Matter&lt;/h2&gt;
&lt;p&gt;At the top of the chain is a root certificate: every operating system and browser comes pre-installed with a bunch of known root certificates, which are securely stored in what is called a “trust store”.&lt;/p&gt;
&lt;p&gt;(It’s worth noting that the private keys for these certificates are very closely guarded by the issuing certificate authorities! A certificate is validated with a private key.)&lt;/p&gt;
&lt;p&gt;Taking an example certificate that we have, which proves that our teamdf.cloud servers are in fact genuine teamdf.cloud servers, the chain of trust looks like this:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div class=&quot;captionImage leftAlone&quot; style=&quot;width: 660px; text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Chain Of Trust diagram&quot; src=&quot;https://www.teamdf.com/assets/blog-images/ssl-chain-of-trust/chain-of-trust-diagram.png&quot; alt=&quot;Chain Of Trust diagram&quot; width=&quot;400&quot; height=&quot;446&quot;&gt;&lt;p class=&quot;caption leftAlone&quot; style=&quot;text-align: center;&quot;&gt;An Example Chain Of Trust&lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;&lt;br&gt;Middlepeople&lt;/h2&gt;
&lt;p&gt;In this case teamdf.cloud is validated by Sectigo Ltd, who are in turn validated by The USERTRUST Network certification authority, and the operating system or browser on your device has a root certificate for USERTRUST allowing everything to be proven.&lt;/p&gt;
&lt;p&gt;An important thing to note here is that there may be more than one “middlepeople” in the scheme and therefore many intermediate certificates will exist in the chain. This tree structure means lots of companies can manage and issue certificates, spreading the burden and allowing different security services to be provided. &lt;/p&gt;
&lt;p&gt;It is common for an authoritiy to have multiple root certificates and to issue many intermediate certificates to other organisations.&lt;/p&gt;
&lt;h2&gt;What Could Go Wrong?&lt;/h2&gt;
&lt;p&gt;You may find that even though your certificate has just been purchased, those up the chain of trust have expired. This can cause quite a bit of confusion so it’s important to understand the above and have ways to rectify things.&lt;/p&gt;
&lt;p&gt;This is exactly what happened recently with Sectigo’s AddTrust root certificate expiring (https://sectigo.com/resource-library/sectigos-addtrust-root-is-soon-to-expire-what-you-need-to-know)&lt;/p&gt;
&lt;p&gt;A certificate authority, whether they are a root authority or an intermediate authority, has the ability to expire or revoke a certificate at any time. This can cause your certificate to become invalid and require a new set of intermediate certificates.&lt;/p&gt;
&lt;p&gt;When you purchase your certificate you will be given details (links or downloads) for the intermediate certificate(s) as well. When you install the SSL certificate on FileMaker Server you will need to include these intermediate certificates (if more than one certificate is required you’ll need to combine them into a single file for upload).&lt;/p&gt;
&lt;div class=&quot;captionImage leftAlone&quot; style=&quot;width: 648px; text-align: center;&quot;&gt;&lt;br&gt;&lt;div class=&quot;captionImage center&quot; style=&quot;width: 648px;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;FileMaker Server Import Certificate Dialog&quot; src=&quot;https://www.teamdf.com/assets/blog-images/ssl-chain-of-trust/_resampled/ResizedImage648533-fms-import-cert-dialog.png&quot; alt=&quot;FileMaker Server Import Certificate Dialog&quot; width=&quot;648&quot; height=&quot;533&quot;&gt;&lt;p class=&quot;caption center&quot;&gt;FileMaker Server Import Certificate Dialog&lt;/p&gt;
&lt;/div&gt;
&lt;p class=&quot;caption leftAlone&quot; style=&quot;text-align: left;&quot;&gt;When you have installed your certificate on FileMaker Server, connecting via FileMaker Pro, WebDirect, Data API or the admin console, the certificate will be verified by looking up the chain and verifying all the certificates it encounters right back to the root certificate at the top.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If you haven’t installed the intermediate certificate correctly or the chain is broken (e.g. an expired certificate), you will get an error. You can verify a certificate by clicking on the lock in the address bar of your browser or in a FileMaker Pro window.&lt;/p&gt;
&lt;div class=&quot;captionImage leftAlone&quot; style=&quot;width: 660px; text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Safari window highlighting the SSL lock icon&quot; src=&quot;https://www.teamdf.com/assets/blog-images/ssl-chain-of-trust/secure-safari.png&quot; alt=&quot;Safari window highlighting the SSL lock icon&quot; width=&quot;660&quot;&gt;&lt;p class=&quot;caption leftAlone&quot;&gt;Safari window highlighting the SSL lock icon&lt;/p&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;div class=&quot;captionImage leftAlone&quot; style=&quot;width: 660px;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;FileMaker Pro window highlighting SSL lock icon&quot; src=&quot;https://www.teamdf.com/assets/blog-images/ssl-chain-of-trust/secure-filemaker.png&quot; alt=&quot;FileMaker Pro window highlighting SSL lock icon&quot; width=&quot;660&quot;&gt;&lt;p class=&quot;caption leftAlone&quot; style=&quot;text-align: center;&quot;&gt;FileMaker Pro window highlighting SSL lock icon&lt;/p&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;div class=&quot;captionImage leftAlone&quot; style=&quot;width: 596px;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Certificate Window&quot; src=&quot;https://www.teamdf.com/assets/blog-images/ssl-chain-of-trust/view-certificate.png&quot; alt=&quot;Certificate Window&quot; width=&quot;596&quot;&gt;&lt;p class=&quot;caption leftAlone&quot; style=&quot;text-align: center;&quot;&gt;Certificate Window&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Trouble Shooting&lt;/h2&gt;
&lt;p&gt;So if things aren&#039;t working correctly some of the things to look into are:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Check that all the certificates have been installed correctly&lt;/li&gt;
&lt;li&gt;Make sure you purchased your certificates from an authorised CA*&lt;/li&gt;
&lt;li&gt;Double check that the server itself has been setup correctly&lt;/li&gt;
&lt;li&gt;Use openssl to verify the certificates chain of trust, eg.&lt;/li&gt;
&lt;/ul&gt;&lt;blockquote&gt;
&lt;pre style=&quot;text-align: center;&quot;&gt;openssl verify -purpose sslserver -CAfile intermediateCertificate.crt certificate.crt&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;* CA = &lt;a title=&quot;Wikipedia description of a Certificate Authority&quot; href=&quot;https://en.wikipedia.org/wiki/Certificate_authority&quot; target=&quot;_blank&quot;&gt;Certificate Authority&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With SSL certificates now required on all FileMaker server installations, there are going to be some catches along the way. The above outlines things in a relatively simple form, but if you do strike issues, post a message below and we&#039;ll see if we can help resolve them.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Mon, 24 Aug 2020 15:25:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/ssl-certificates-and-the-chain-of-trust/</guid>
		</item>
		
		<item>
			<title>FileMaker 19 Release</title>
			<link>https://www.teamdf.com/blogs/filemaker-19-release/</link>
			<description>&lt;p&gt;FileMaker 19 is here and with it we see a bunch of incremental improvements and some nice new features... and the end of the major annual update!&lt;/p&gt;
&lt;p&gt;As Claris modernise their approach, they’ve pledged to move to smaller more frequent updates throughout the year - more of a continuous improvement approach. We think this is brilliant, we’ll see fixes and improvements much more quickly.&lt;/p&gt;
&lt;p&gt;This first new version since rebranding to Claris, has a new icon: after 30-odd years of folders, FileMaker now sports the new Claris logo as it’s app icon. And the &quot;Advanced&quot; part of the name has been dropped — it&#039;s just &quot;FileMaker Pro&quot; now whether using the Advanced tools or not. &lt;/p&gt;
&lt;h2&gt;&lt;br&gt;New Stuff&lt;/h2&gt;
&lt;p&gt;So what is actually new in this version? Well it’s pretty much as planned and revealed at DevCon in August last year. To recap: &lt;/p&gt;
&lt;p&gt;On iOS mobile devices we get access to some more of the device technology such as NFC reading to be able to react to things like RFIDs and Bluetooth devices plus access to the Machine Learning engine in all Apple devices (including Macs) and Siri Shortcuts, opening up the opportunity to enable voice control of our apps.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/fm19-release/_resampled/ResizedImage659304-nfc-scan.png&quot; alt=&quot;nfc scan&quot; width=&quot;659&quot; height=&quot;304&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;Tag reading – Voice control – Artificial Intelligence&lt;/p&gt;
&lt;h2&gt;User Interface Widgets&lt;/h2&gt;
&lt;p&gt;Perhaps most exciting and visible will be new “widgets” that we can add to your FileMaker solutions: it will now be possible, thanks to new JavaScript commands, to embed complex widgets such as Calendars, Kanban boards, Gantt Charts and other diagramming, drawing, annotation and visualisation tools right into FileMaker solutions.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/fm19-release/widgets.jpg&quot; alt=&quot;widgets&quot; width=&quot;660&quot; height=&quot;301&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;While this stuff is new as a native feature, we have been doing this for over 12 years with our Reactor plugin. At this stage Reactor still offers a nicer more integrated way of achieving the same result, but Reactor doesn’t work with iOS or WebDirect, whereas the new JavaScript commands do.&lt;/p&gt;
&lt;p&gt;Claris intend to make some of these widgets available in a further update coming soon via an “add-on” mechanism that will drop in ready-made controls, but for now they’re not available, however feel free to talk to us now as we have years of experience creating these interfaces in FileMaker.&lt;/p&gt;
&lt;h2&gt;Web Browser Compatibility Improves&lt;/h2&gt;
&lt;p&gt;We also move a big step closer to 100% compatiblity when using a web browser to access your apps — we can now use the card window (a sub-window within the main window you’re using) in WebDirect.&lt;/p&gt;
&lt;p&gt;What that means in practice really is that we’re very close now to being able to use FileMaker solutions from a browser, with minimal changes. Which also means you can access your solution from any computer or device connected to the internet. And in businesses where you’re not allowed to install apps without jumping through hoops, you’re good to go without that worry.&lt;/p&gt;
&lt;p&gt;Personally I still believe that for apps you use extensively, you’re better off having them installed as a standalone app... but at least with WebDirect giving very close to the same experience, you have the choice and it is certainly a boon for those times when you need that access.&lt;/p&gt;
&lt;h2&gt;JSON Commands&lt;/h2&gt;
&lt;p&gt;At the very geeky end of the scale there’s a great new JSON command that makes it much easier for us to pull data out of FileMaker into JSON format — this will speed up certain development tasks and really represents further “opening up” of the platform.&lt;/p&gt;
&lt;p&gt;JSON is very much the standard way that data is exchanged between applications (via APIs) and even within applications such as when synchonising data between a mobile app and a server when that mobile app has to be able to work offline.&lt;/p&gt;
&lt;h2&gt;Hello Darkness My Old Friend&lt;/h2&gt;
&lt;p&gt;For developers, FileMaker Pro now does “Dark Mode” on the Mac — since developers are allergic to sunlight this is a real boon. We can work with curtains drawn and at night, using dark mode to minimise the light cast from the screen, safe now in the knowledge that FileMaker won’t break the mood with a bright white blast from the script workspace or database definitions…&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/fm19-release/dark-mode.png&quot; alt=&quot;dark mode&quot; width=&quot;660&quot; height=&quot;454&quot;&gt;&lt;/p&gt;
&lt;p&gt;However to make a database itself, i.e. your app, have “dark mode” compatibility we still have to actually design dark layouts — we haven’t done it yet, but one possibility would be to have two versions of every layout, and navigate according to the system setting.&lt;/p&gt;
&lt;p&gt;I can see this being particularly useful in some settings — for example with Aerial Toolbox’s helicopter flight record system it would make sense to use a light coloured background for daytime operations and switch to a ‘dark mode’ after sunset.&lt;/p&gt;
&lt;h2&gt;Our Recommendations&lt;/h2&gt;
&lt;p&gt;Don’t jump in just yet…&lt;/p&gt;
&lt;p&gt;With FileMaker Pro: there’s some good stuff in this update but we’re seeing some user experience issues, including images in container fields distorting, slowness switching between screens, and some other small issues being reported. We reckon it’s probably better to wait til the first “point update” which usually follows fairly soon after a release in which Claris will likely address these issues.&lt;/p&gt;
&lt;p&gt;For FileMaker Server: we’re keen to embrace the updates but we advise a cautious approach to updating your FileMaker Servers so suggest holding off for a short period: we’re switching some of our servers over to 19 right away, and will offer advice later in June on making the upgrade if all is going well.&lt;/p&gt;</description>
			<pubDate>Wed, 27 May 2020 23:30:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-19-release/</guid>
		</item>
		
		<item>
			<title>Complying with a Pandemic</title>
			<link>https://www.teamdf.com/blogs/complying-with-a-pandemic/</link>
			<description>&lt;h3&gt;As Australia and New Zealand start to loosen the grips of lockdowns and businesses get back to work, you may find that costs for compliance are growing...&lt;/h3&gt;
&lt;p&gt;In short, the biggest element of compliance will be your time.&lt;/p&gt;
&lt;h2&gt;Good Ideas&lt;/h2&gt;
&lt;p&gt;A prime example of this was flagged with me over the weekend while sharing a few Zoom-drinks with friends who run a small electrical company. They have six staff in total and do a mix of domestic and light commercial work, all in the Christchurch region.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/pandemic-compliance/_resampled/ResizedImage659403-zoom-fun.jpg&quot; alt=&quot;zoom fun&quot; width=&quot;659&quot; height=&quot;403&quot;&gt;&lt;/p&gt;
&lt;h2&gt;New Rules&lt;/h2&gt;
&lt;p&gt;Since the lockdown rules were flagged to be relaxed last week, they’ve been inundated with documentation that they need to complete. This is not from the government, but from their clients — it’s what they need to do to comply with other companies compliance rules!&lt;/p&gt;
&lt;p&gt;These weren’t just documents that need to be signed-off by the business owners, but rather each staff member had to complete each form and sign it. Their only way to do this was to print out each document, get each staff member over to their home to complete, scan them and send them back. They have no simple way to automate this process, and they foresee that this is the ‘new norm’…&lt;/p&gt;
&lt;p&gt;That’s only the start of a full time paper battle — they’re going to need to keep detailed records of who’s complied, and who was onsite when, plus of course that the actions they’ve agreed to are being undertaken. Did those gloves get disposed of correctly? Is everyone maintaining the correct social distance...&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/pandemic-compliance/_resampled/ResizedImage659291-social-distancing.jpg&quot; alt=&quot;social distancing&quot; width=&quot;659&quot; height=&quot;291&quot;&gt;&lt;/p&gt;
&lt;h2&gt;FileMaker + DocuSign!&lt;/h2&gt;
&lt;p&gt;When I mentioned that we’ve built solutions which used FileMaker integrations like DocuSign, and they could pretty much automate their whole process, including a robust and legally recognised digital siganture system, their ears pricked up…&lt;/p&gt;
&lt;p&gt;But when you’re a small business using ‘off the shelf’ software, investing in a custom build is a bit daunting. So I put my sales hat on again and we did the math on how many hours/days they would save. When you start adding it up, an upfront investment like that starts making a lot of sense: the right solution could save a ½ or possibly full time position.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/pandemic-compliance/_resampled/ResizedImage660489-electrician-ipad.jpg&quot; alt=&quot;electrician ipad&quot; width=&quot;660&quot; height=&quot;489&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Fri, 08 May 2020 18:51:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/complying-with-a-pandemic/</guid>
		</item>
		
		<item>
			<title>Claris Connect - A First Look</title>
			<link>https://www.teamdf.com/blogs/claris-connect-first-look/</link>
			<description>&lt;p&gt;Claris have just released their new product &lt;strong&gt;Claris Connect,&lt;/strong&gt; a cloud based service to orchestrate the connection and flow of data between different applications, including of course Claris FileMaker.&lt;/p&gt;
&lt;p&gt;This means you can potentially do things like have a &quot;card&quot; created in, say &lt;a title=&quot;Trello Web Site&quot; href=&quot;https://trello.com&quot; target=&quot;_blank&quot;&gt;Trello&lt;/a&gt;, automatically post a message in &lt;a title=&quot;Slack Web Site&quot; href=&quot;https://trello.com&quot; target=&quot;_blank&quot;&gt;Slack&lt;/a&gt;, and create a task record in your custom FileMaker application.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/claris-connect/claris-connect-flows.jpg&quot; alt=&quot;claris connect flows&quot; width=&quot;300&quot; height=&quot;595&quot;&gt;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;The Business Case&lt;/h3&gt;
&lt;p&gt;For businesses this gives you way of using those smaller dedicated apps that you love, and linking them together to eliminate double entry and avoiding the need to build an API integration, or in some cases an entire custom app might not be needed at all — why not just tie together several different dedicated apps?&lt;/p&gt;
&lt;p&gt;We&#039;ll come back and talk more about the business case for it in a later article, but for now as developers we were just dead keen to get our hands on it and have play around to see what it&#039;s capable of and get a true sense of how we might be able to use it to add value for our clients.&lt;/p&gt;
&lt;p&gt;A few members of our team have jumped in and had a go so here&#039;s what we&#039;ve found out and where we think it&#039;s going:&lt;/p&gt;
&lt;h3&gt;It&#039;s Early&lt;/h3&gt;
&lt;p&gt;Early signs are that it’s very promising, for both the casual ‘citizen developer’ right through to our professional developers here at Digital Fusion. There are some integrations/flows that would normally take a number of days that could potentially be implemented now in just a few hours. It’s early days in the life of the product, so we are interested to see how things evolve over time. &lt;/p&gt;
&lt;p&gt;Our initial trials involved using Trello, FileMaker and Slack, connecting flows between them, so here&#039;s what we were able to achieve in about half day:&lt;/p&gt;
&lt;h3&gt;Let&#039;s Give It A Go Then&lt;/h3&gt;
&lt;p&gt;We set out to build a relatively complex workflow, connecting three different cloud based apps, each with their own complexities, in a very simple flow of information:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;User creates a new card (task) in a Trello board&lt;/li&gt;
&lt;li&gt;Have a message posted to Slack channel, posted by the Trello user, naming the card &amp;amp; id # of that card.&lt;/li&gt;
&lt;li&gt;Execute a script in a FileMaker database to add that task&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Adding the initial Trello trigger was a breeze, very easy to connect it to Trello &amp;amp; select the board we wanted to monitor.&lt;/p&gt;
&lt;p&gt;Likewise connecting to Slack account was easy. There was a little time involved in figuring out posting to Slack but overall that was easy too. We ran into an issue where it does not appear Claris Connect can post to a private channel so we had to re-add the channel as a public one.&lt;/p&gt;
&lt;p&gt;One really awesome thing about it was Claris Connect makes available to you any piece of information the Trello API returns, which you can use in future actions in the workflow. So we were able to formulate a message to post into Slack utilising any bit of Trello information. We could also grab the name of the Trello user and make that the “bot” name who posts, so it looks like the person who added the card is telling you in Slack.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;The next step was to execute a script in FileMaker: the setup of this was actually pretty damn easy too. Very easy to connect to a FileMaker Server (must be 18v3) and select the database. We did have a few issues at this point in time with the script failing to execute on a number of occasions when passed information from Trello. Hopefully these bugs can be resolved in Claris Connect rather promptly as one of the most important aspects of this workflow requires this. It was at this point we came a bit unstuck and had to abandon completion of the workflow.&lt;/p&gt;
&lt;p&gt;The “Test” feature is cool as it allows you to sample and verify the action (in this case run script).&lt;/p&gt;
&lt;p&gt;Because we could only create three flows as part of our trial license, it did limit what we would love to have tested — ultimately we wanted to add the following:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Workflow for when a card updated, to update the task in the database&lt;/li&gt;
&lt;li&gt;Workflow for when card deleted, i.e. remove the task from the database&lt;/li&gt;
&lt;li&gt;Workflow for adding a message to Slack channel, the idea here is to be able to automatically add timesheet entries by typing a a slack post containing the Trello ID, hours &amp;amp; comment.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;As mentioned above, we are really exited by the opportunities the product can bring to our development team here at Digital Fusion. We are going to keep a very close eye on how the product evolves and further opportunities for us to use it in our development.&lt;/p&gt;
&lt;p&gt;You can find out more inlcuding pricing and sign-up for a trial yourself at the &lt;a title=&quot;Claris Connect web site&quot; href=&quot;https://www.claris.com/connect/&quot; target=&quot;_blank&quot;&gt;Claris Connect web site&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Sat, 07 Mar 2020 00:06:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/claris-connect-first-look/</guid>
		</item>
		
		<item>
			<title>Welcome MacBusiness</title>
			<link>https://www.teamdf.com/blogs/welcome-macbusiness/</link>
			<description>&lt;p&gt;To kick off 2020 we’re absolutely thrilled to announce that the FileMaker team from MacBusiness in Christchurch NZ, are now part of team Digital Fusion, bringing 3 new developers to our team and a number of well established clients. In return we’re offering a bigger team for Jo, David and Sarah to be part of, and greater flexibility and capacity for those clients that we’ll be looking after under the DF umbrella.&lt;/p&gt;
&lt;p&gt;David Christie, founder of MacBusiness brings over 25 years experience in FileMaker, Jo some 20 years, and Sarah over 15 years. These people know their stuff… MacBusiness has a top notch reputation and we know them well, having shared our knowhow and a few drinks from time to time over the years.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/welcome-macbusiness/david-jo-sarah-660x100ppi.jpg&quot; alt=&quot;david jo sarah 660x100ppi&quot; width=&quot;660&quot;&gt;&lt;/p&gt;
&lt;p&gt;This brings our wonderful team up to 16 in total now, and with Sarah based in the North Island we have a new location to mark on the map — sunny Hawke&#039;s Bay. Moreover, as soon as we can convince these three to get certified, the sooner we’ll set a new record for the number of certified developers in… well, I reckon the Southern Hemisphere… certainly the Asia Pacific region any way.&lt;/p&gt;
&lt;p&gt;And for those clients joining us from the MacBusiness fold — we are really looking forward to meeting you and getting to know you… but your existing team are right here and available for you as always.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 14 Jan 2020 16:30:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/welcome-macbusiness/</guid>
		</item>
		
		<item>
			<title>Master Class In...</title>
			<link>https://www.teamdf.com/blogs/master-class-in/</link>
			<description>&lt;p&gt;Eight of us crowd into the lounge of our Pyrmont office in Sydney Australia - four on a sofa, three on straight backed chairs and one standing. Albert Harum-Alvarez of &lt;a title=&quot;SmallCo&amp;#039;s website&quot; href=&quot;https://smallco.co&quot; target=&quot;_blank&quot;&gt;SmallCo&lt;/a&gt; occupies the hot-seat from which to dispense his wisdom. Outside the sparkling waters of the harbour suggest a serenity that’s buffeted and bullied by the sounds of the inner-city streetscape…&lt;/p&gt;
&lt;div class=&quot;leftAlone&quot; style=&quot;width: 660px;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Pyrmont, Sydney&quot; src=&quot;https://www.teamdf.com/assets/blog-images/master-class-sydney-2019/image1-pyrmont.jpg&quot; alt=&quot;image1 pyrmont&quot; width=&quot;660&quot;&gt;&lt;/div&gt;
&lt;p&gt;The imagery of Albert’s slides take us literally half a world away as his metaphors, analogies and anecdotes gently tease and cajole us away from the structured rigour of pragmatic software. He wants us to find the &#039;who&#039; of the application, not just the &#039;what&#039; or the &#039;how&#039;. Define the character of your software and stay true to it throughout he tells us.&lt;/p&gt;
&lt;p&gt;When someone says design we think colour theory, the rule of thirds, the golden ratio, proximity, grouping and alignment. All of these rate a mention as respected fundamentals, but there is a perspective that Albert wants us to grasp - a way of feeling, seeing and thinking about our software.&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;…Character&lt;/h2&gt;
&lt;p&gt;We are to ask the question –&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;em&gt;Is my app an extension of the user?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I’m reminded of Haptic Perception, the blurring of the line between body and tool as our proprioception encompasses the tool itself. Imagine a tennis racket, it’s not our sight that assures us that it will connect with the ball - it’s our understanding of the space it occupies in the world as an extension of ourself.&lt;/p&gt;
&lt;p&gt;Designers of smart devices acknowledge this with Haptic Touch providing sensory feedback - the artificial click in response to pressure as reassuring as the impact of the tennis ball felt through the racket grip.&lt;/p&gt;
&lt;p&gt;Is the App a comfortable tool that fits the contours of the user’s mind as the ergonomic grip of Albert’s Makita Sander fits the contours of his hand? Is it an extension of self that expands my capacity to remember, anticipate and communicate?&lt;/p&gt;
&lt;p&gt;Does it in fact augment my abilities to super power status as spider venom did for Peter Parker? How else can I describe summoning a vehicle to take me anywhere I should desire with a flurry of gestures over glass?&lt;/p&gt;
&lt;p&gt;Or is it my Sidekick? A helpful friend, a Copilot, a Navigator, or a Streetwise Buddy who gives me an edge in tricky situations?&lt;/p&gt;
&lt;p&gt;Perhaps I’m the sidekick - the App is my mentor, my teacher, my trusted adviser- guiding me towards mastery of a skill.&lt;/p&gt;
&lt;p&gt;If we think of our apps in these terms a sense of character can emerge that we can nurture and cultivate as we develop. If we stay true to this and inhabit the app as a writer inhabits their protagonist, we can intuitively identify the jarring out of character moments.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Idea sharing between participants at the FileMaker Design Masterclass Sydney&quot; src=&quot;https://www.teamdf.com/assets/blog-images/master-class-sydney-2019/image2-sharing-ideas.jpg&quot; alt=&quot;Idea sharing between participants at the FileMaker Design Masterclass Sydney&quot; width=&quot;660&quot; height=&quot;500&quot;&gt;&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;…Ego Management&lt;/h2&gt;
&lt;p&gt;Albert didn’t use the term, but frictionless is a notion that I inferred. Imagine tools so ergonomic to the body and mind, so effortless, you barely notice they are there.&lt;/p&gt;
&lt;p&gt;And here’s the rub, the ego of a healthy human doesn’t gain sustenance from unnoticed achievements. We want our effort, our cleverness, our anticipation of the user’s needs to be noticed and admired.&lt;/p&gt;
&lt;p&gt;Albert’s example was a [Compose Message…] button presenting all of the wonderful ways he and his team had achieved to send a message: “How would you like to send your message?” the app asked helpfully. But this is not the question that responds to the users immediate need. As unexciting as it is, what they need right now is an empty text field with a flashing cursor.&lt;/p&gt;
&lt;h2&gt;…Minimalism&lt;/h2&gt;
&lt;p&gt;Another ideal Albert asked us to pursue was that of less is more. Why is that element on the screen? What is the user doing here? At this point, do they need to see that data? Then why is it there? WHY IS IT THERE?&lt;/p&gt;
&lt;p&gt;He drove towards single purpose layouts, insisting that ONLY the data and controls required for that purpose be present. This implies carefully orchestrated workflows rather than Swiss army knife single views where everything is possible.&lt;/p&gt;
&lt;h2&gt;...Faces&lt;/h2&gt;
&lt;p&gt;I’m not sure about you, but I’ve always thought of a portal as a table. It’s a way of presenting information, if the user wants to see more information there’s a helpful button that will take them to a detailed view. Albert sees them as lists. There are a number of types of lists (roster, log, ledger, punch list, cart or bunch) and a list shouldn’t try to be a type that it is not.&lt;/p&gt;
&lt;h3&gt;Take a roster for example…&lt;/h3&gt;
&lt;p&gt;Hang on, let me qualify roster - I think of a work schedule for employees, but Albert uses the term as a collection of items to choose from …a roster’s sole purpose then, is to present key data points that will allow the user to recognise the record they want to view.&lt;/p&gt;
&lt;p&gt;Albert’s got another analogy for us - “You don’t recognise a person by their elbow, so don’t show a picture of their elbow, put their face on the screen”. He’s telling us to chunk together key data-points to build a &lt;strong&gt;face&lt;/strong&gt; for the record. And to give the face character, in fact make it a caricature.&lt;/p&gt;
&lt;p&gt;If it were a human caricature it would have big eyes, but in this case exaggerate the data-points that the user will instantly recognise, often the Vernacular ID. Love that term - Albert introduced me to it, the handle by which the people in the workplace refer to that entity in their day to day conversations.&lt;/p&gt;
&lt;div class=&quot;captionImage leftAlone&quot; style=&quot;width: 660px;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;UI example - Before and After the Master Class&quot; src=&quot;https://www.teamdf.com/assets/blog-images/master-class-sydney-2019/image3-before-v-after.jpg&quot; alt=&quot;UI example - Before and After the Master Class&quot; width=&quot;660&quot; height=&quot;423&quot;&gt;&lt;p class=&quot;caption leftAlone&quot; style=&quot;text-align: center;&quot;&gt;Before v After&lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;&lt;br&gt;To wrap up&lt;/h2&gt;
&lt;p&gt;Reflect on the hierarchy of tools and techniques that we have. FileMaker gives us fields, and buttons and shapes and portals… and so on. These are the raw materials. Then we have the first layer of design abstraction: alignment, positioning, colour signifiers. At the next layer we diverge into an aesthetic stream with the rule of thirds and the golden ratio; and a usability stream with techniques such as grouping and proximity of elements. Albert’s master class extends the latter — he is teaching us to design for intent, for purpose, for use case. Fit the data and the design to the purpose of the app, and to facilitate the intent of the user.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 03 Dec 2019 00:14:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/master-class-in/</guid>
		</item>
		
		<item>
			<title>Forward Thinking</title>
			<link>https://www.teamdf.com/blogs/forward-thinking/</link>
			<description>&lt;p&gt;At the FileMaker Developer Conference in the US this year FileMaker Inc. announced a few rather far reaching and exciting changes, starting with a new company name, “Claris”, followed by some new products in the pipeline, and of course a slew of nice new features coming to FileMaker itself.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;right&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/forward-thinking-claris-devcon-2019/claris-ceo-brad-freitag-2.jpg&quot; alt=&quot;claris ceo brad freitag 2&quot; width=&quot;300&quot; height=&quot;246&quot;&gt;All this comes on the back of the new CEO, Brad Freitag, who’s bringing a whole new level of invigoration and innovation to the organisation.&lt;/p&gt;
&lt;p&gt;The strategy revealed at DevCon this year was profound, exciting and deep reaching.&lt;/p&gt;
&lt;p&gt;But first, rest assured there are no plans to break or upset the platform that has evolved with much care and attention over the last 20 years.&lt;/p&gt;
&lt;h3&gt;&lt;br&gt;Clear Yet Cloudy&lt;/h3&gt;
&lt;p&gt;There will be a shift to a more “Cloud First” way of thinking, which can only mean good things for FileMaker:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Better performance over the internet&lt;/li&gt;
&lt;li&gt;Easier and more instant options for getting started in the cloud&lt;/li&gt;
&lt;li&gt;Better features for web users (FileMaker WebDirect)&lt;/li&gt;
&lt;li&gt;More web-like behaviours such as responsive layouts&lt;/li&gt;
&lt;li&gt;Standardised deployment and maintenance of FileMaker Server&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The emphasis on mobile is not letting up either: there are exciting new features coming for FileMaker Go including:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Siri integration&lt;/li&gt;
&lt;li&gt;Access to the iOS Machine Learning engine&lt;/li&gt;
&lt;li&gt;NFC reading — the ability to read RF ID tags and such&lt;/li&gt;
&lt;/ul&gt;&lt;h3&gt;&lt;br&gt;Think New&lt;/h3&gt;
&lt;p&gt;In addition to taking care of the existing platform, the team are also going to expand beyond FileMaker and tap into some new ways of thinking. And one of those is the idea of Workflow Apps — applications formed by tying together different apps and services using ready made connections (APIs) and logic commands to create, workflows and automation of data moving between different applications.&lt;/p&gt;
&lt;p&gt;To jump start this technology, rather than try and build it onto the side of FileMaker they acquired a company called “Stamplay” which has been doing this sort of thing for a few years.&lt;/p&gt;
&lt;p&gt;Out of that acquisition a new product is coming called “Claris Connect”, which promises to allow problem solvers and developers to build workflow apps, and which will open a up a world of connectivity to FileMaker by making it much easier to connect to other apps — think Salesforce, Box, Mailchimp, Slack etc.&lt;/p&gt;
&lt;p&gt;Out beyond that, the company has started a “Labs” division where they’re experimenting with Next Gen products — ensuring the suite as a whole provides some truly innovative and exciting technology for supporting and creating more Workplace Innovation long into the future.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/forward-thinking-claris-devcon-2019/_resampled/ResizedImage659258-claris-platforms-teaser.png&quot; alt=&quot;claris platforms teaser&quot; width=&quot;659&quot; height=&quot;258&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;And Why Claris?&lt;/h2&gt;
&lt;p&gt;In the spirit of broadening the product offering, and representing the new thinking they sought a new name… and Claris, which derives from the Latin “clarus” meaning clear, bright, renowned, famous, upstanding, respected” was a very logical choice. We think it’s a brilliant brand name, nice that it harks back to the history of the company, but make no mistake this is a very new, very different Claris.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Fri, 04 Oct 2019 16:04:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/forward-thinking/</guid>
		</item>
		
		<item>
			<title>Easily Print or Capture Web Viewer content</title>
			<link>https://www.teamdf.com/blogs/print-capture-web-viewers/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Back in 2008 when Digital Fusion released &lt;a href=&quot;https://www.teamdf.com/products/reactor/&quot; target=&quot;_blank&quot;&gt;Reactor&lt;/a&gt;, we used web viewers a lot and we printed them a lot too. Display of javascript based gantt charts, calendars and other rich UI widgets would inevitably require printing by clients and so we&#039;d come up with correctly sized print layouts to do the job.&lt;/p&gt;
&lt;p&gt;That was the pre FileMaker 16 days, dating back to the introduction of web viewers in version 8.5. Printing web viewers back then worked pretty darn good.&lt;/p&gt;
&lt;p&gt;Then in FileMaker 16 things changed. All of a sudden web viewers that render content fine in browse mode, would fail to render when in Preview mode, printed, or saved as PDF. The exact reasons for this change are murky and unclear.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/print-wv/_resampled/ResizedImage6464-printwv-2.png&quot; alt=&quot;printwv 2&quot; width=&quot;64&quot; height=&quot;64&quot;&gt; &lt;/p&gt;
&lt;p&gt;These days, javascript is everywhere and more popular in FileMaker than ever. It therefore makes sense that people are going to want to be able to print the content they build for the web viewer.&lt;/p&gt;
&lt;p&gt;In this article we cover a really simple and easy technique you can quickly add to your own solution to start printing web viewer content.  No plugins are needed and no external OS level scripting or screen capturing required.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;It&#039;s an API, duh!&lt;/h2&gt;
&lt;p&gt;Is anything these days not solvable with an API? I like to think not. When looking for a solution to a problem such as this, my first option is to look for an API that can do the job. So when looking for an API to solve this issue I looked for one capable of rendering html content.&lt;/p&gt;
&lt;p&gt;The results took me to &lt;a href=&quot;https://www.phantomjscloud.com&quot; target=&quot;_blank&quot;&gt;phantomjscloud.com.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PhantomJsCloud is actually a spinoff of an earlier project named PhantomJS. This was a headless browser API allowing testers to carry out user interactions on a website through javascript. Developers would write code to simulate user actions on a site.  This project has since been discontinued.&lt;/p&gt;
&lt;p&gt;PhantomJsCloud is a cloud based variant based on the same principle. It has a restful API where you can request the API to render a website and return the rendered site as an image, pdf, text or json.&lt;/p&gt;
&lt;p&gt;Where PhantomJsCloud is really useful for us as FileMaker developers is its ability to render specific html code you specify, and it is this feature we use to print the web viewer.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The basic steps involved&lt;/h2&gt;
&lt;p&gt;Setup of the API is really easy. The API is free for up to 500 calls per day - more than enough for most people. With it you get an API key that you use in each request. There is no additional authentication required.&lt;/p&gt;
&lt;p&gt;Let&#039;s say you wanted to print a web viewer that contained a javascript based chart such as the one below:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/print-wv/_resampled/ResizedImage499236-printwv-3.png&quot; alt=&quot;printwv 3&quot; width=&quot;499&quot; height=&quot;236&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;The steps involved to print are:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Obtain the code used in the web viewer. This is usually stored in a field and rendered in the web viewer with a Data URL such as &quot;data:text/html,&quot;. Alternatively you can still use a URL to render if your web viewer is displaying a site.&lt;/li&gt;
&lt;li&gt;Sign up to &lt;a href=&quot;https://www.phantomjscloud.com&quot; target=&quot;_blank&quot;&gt;phantomjscloud.com&lt;/a&gt; and receive your API key&lt;/li&gt;
&lt;li&gt;Using the Insert from URL script step, send a POST request to the API with your code/url.&lt;/li&gt;
&lt;li&gt;The API will return you an image of the rendered code/site. Place this in a container field&lt;/li&gt;
&lt;li&gt;Print the container field image.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;That&#039;s it in a nutshell. We&#039;ll go into a little more detail as to how the setup and post request is constructed, but that is really all there is to it.&lt;/p&gt;
&lt;p&gt;I encourage you to &lt;a href=&quot;https://www.teamdf.com/assets/blog-images/print-wv/Weetbicks-PrintWebViewer.zip&quot; target=&quot;_blank&quot;&gt;download and try out the example file for this article.&lt;/a&gt;  You can use it to follow along with the rest of the article.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Sign up to the API&lt;/h2&gt;
&lt;p&gt;Simply go to &lt;a href=&quot;https://www.phantomjscloud.com&quot; target=&quot;_blank&quot;&gt;phantomjscloud.com&lt;/a&gt; and sign up for an account.  Verify your email address, and when you sign in on the dashboard screen you&#039;ll find your API key, that&#039;s really all there is to this part. &lt;/p&gt;
&lt;p&gt;If you require more than 500 requests per day, there are pre-pay options or pricing plans available, but we think most developers won&#039;t need more than 500 a day.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/print-wv/_resampled/ResizedImage200108-printwv-4.png&quot; alt=&quot;printwv 4&quot; width=&quot;200&quot; height=&quot;108&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Gather your web viewer code&lt;/h2&gt;
&lt;p&gt;There are so many different ways to render code in a web viewer. Some like to use a Data URL to render html content stored in a field or variable. Others might like to export their files to disk and reference them via the web viewer URL. Others might  use a plugin to render content.&lt;/p&gt;
&lt;p&gt;Whichever method you use, you&#039;re going to need your html code to be available to you in a script so that you can pass it to the API. If you simply display a standard URL in your web viewer than you are all set.&lt;/p&gt;
&lt;p&gt;The API can accept either html code, or a URL to render.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/print-wv/printwv-5.png&quot; alt=&quot;printwv 5&quot; width=&quot;345&quot; height=&quot;94&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;using code in a field, rendered using a data URL. &lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;Formulate your request to the API&lt;/h2&gt;
&lt;p&gt;The API request is a POST, and for this we&#039;ll use the &quot;Insert from URL&quot; script step, and some CURL parameters.&lt;/p&gt;
&lt;p&gt;The URL for the request is pretty simple, it&#039;s the PhantomJsCloud site URL with the API key included:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/print-wv/printwv-6.png&quot; alt=&quot;printwv 6&quot; width=&quot;508&quot; height=&quot;80&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;The request is formulated as JSON, and sent as data in the CURL part of the request as a POST.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;In our &lt;a href=&quot;https://www.teamdf.com/assets/blog-images/print-wv/Weetbicks-PrintWebViewer.zip&quot; target=&quot;_blank&quot;&gt;example file&lt;/a&gt; we have done the heavy lifting for you and written a standalone script you can use in your own solution. In it we&#039;ve included the basic request parameters used, these include:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Viewport width/height - this tells the API what sized &quot;virtual&quot; browser window it should use to render and capture the content in. This is essentially how you tell the API what size image you want.&lt;/li&gt;
&lt;li&gt;Render format - you can choose png, jpg, text or json. For the example solution we&#039;ve included png, jpg and pdf.&lt;/li&gt;
&lt;li&gt;Render output quality - for jpg images you can specify quality between 0 and 100.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;When it comes specifying what to render, the two key json key parameters are &quot;content&quot; and &quot;url&quot;.  If you are simply rendering a URL, you specify the URL, and content can be empty.&lt;/p&gt;
&lt;p&gt;If however you specify content, then the content parameter will include your html code. The URL parameter must be set to &quot;http://localhost/blank&quot; for it to work.&lt;/p&gt;
&lt;p&gt;We send the request as a POST using CURL options as shown below. The $body variable contains our JSON request.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/print-wv/printwv-7.png&quot; alt=&quot;printwv 7&quot; width=&quot;443&quot; height=&quot;155&quot;&gt;&lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;Store the response&lt;/h2&gt;
&lt;p&gt;The response from the API is typically an image (unless you specify the text or json options). So you simply set the result from the Insert from URL step into a container field.  When done, now you have an image in a container that you are able to print however you wish, and that&#039;s all there is to it!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;An alternative use case - SVG image conversion&lt;/h2&gt;
&lt;p&gt;Rendering code as an image using an API is a really novel way to render the web viewer. But there are other interesting applications to this API.  One of which solves an issue I had recently when developing the &lt;a href=&quot;https://www.elemental-fm.com&quot; target=&quot;_blank&quot;&gt;Elemental&lt;/a&gt; solution. In this solution some of the APIs I integrated with would return the result as an SVG image. This meant that the SVG was unable to be rendered in a container field, and so for those examples, the image had to be rendered in a web viewer only.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/print-wv/_resampled/ResizedImage300202-printwv-8.png&quot; alt=&quot;printwv 8&quot; width=&quot;300&quot; height=&quot;202&quot;&gt;&lt;br&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;This meant the image - in this case an avatar - could not be easily used by a developer. It couldn&#039;t be rendered in a portal (web viewers don&#039;t render in portals), and so the only option is to convert.  In Elemental, my solution was a clunky web based method that was unreliable. It involved rendering there SVG in a canvas object in a web viewer, then converting the canvas to base64 encoded PNG. In order to extract the PNG out of the web viewer, a callback URL to a FileMaker script was used and the base64 encoded image passed to the script as a parameter. However there were 2 major issues:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;FMP urls have a size limit on parameters, so larger SVG&#039;s did not work&lt;/li&gt;
&lt;li&gt;The overall technique was clunky, and didn&#039;t work on windows and was unreliable.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The technique was abandoned. However in using this technique, I realised this actually solves the SVG conversion issue really nicely, here&#039;s how:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Render the SVG in a web viewer inside a div element.&lt;/li&gt;
&lt;li&gt;Use some CSS styling to size the div element to the size of the web page. This allows the SVG to dynamically scale to be the same size as the websites view portal.&lt;/li&gt;
&lt;li&gt;Now just run the code through the API and return the result as a PNG image.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;In the example file for this article you&#039;ll find this exact technique as a working example. It can be used to convert any SVG of any size or complexity to png or JPG quickly and reliably.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Other functionality of the API&lt;/h2&gt;
&lt;p&gt;We&#039;ve used the API purely for rendering a site as an image to suit our needs. However the API is pretty cool and does some other potentially useful things, such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Return a sites text content only, useful for extracting content out of a site&lt;/li&gt;
&lt;li&gt;A separate automation API that can be used to programmatically interact with a site or content. This can be useful if you require your code to have user actions applied before it is rendered and captured by the API.&lt;/li&gt;
&lt;li&gt;Zoom a page prior to capture&lt;/li&gt;
&lt;li&gt;Render a site a a thumbnail - great if you want to capture a company site as a preview thumbnail, it uses smarts to extract best look of a site.&lt;/li&gt;
&lt;li&gt;Generate a PDF of a web page - this is awesome! If your web viewer contains a large amount of data, or is wide/deep in terms of scroll depth, you can use this to produce a PDF render of its entire contents, something you can&#039;t do with a straightforward image capture.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;A warning about security&lt;/h2&gt;
&lt;p&gt;You must take caution when using any API, especially if you are sending it sensitive or private confidential information in your site or code. Any information you send to the API could be stored on the servers at their end, and so make sure you only use this for generic purposes where you are not using information you wish to keep private.&lt;/p&gt;
&lt;p&gt;If security is a concern, then consider purchasing &lt;a href=&quot;https://phantomjscloud.com/enterprise.html&quot; target=&quot;_blank&quot;&gt;phantomJsCloud enterprise plans&lt;/a&gt;. These are private cloud instances dedicated to your solution.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;In conclusion&lt;/h2&gt;
&lt;p&gt;We&#039;ve found this to be a really easy to implement and reliable way to render web viewer content generated directly from FileMaker. The API takes around 1-2 seconds on average to return the rendered image (usually 30-40kb in size). Other methods we tried involved plugins that screen capture the web viewer part of your screen. The issue here is around resolution and size of the capture, it is quite limiting. The API gives fuller flexibility around this. Not to mention no plugin is needed. This one is definitely worth checking out.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Example File&lt;/h2&gt;
&lt;p&gt;We always strive to provide the best example file to help you understand the article and get a head start on implementing techniques found therein. Please download and try it out for yourself below:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/print-wv/Weetbicks-PrintWebViewer.zip&quot; target=&quot;_blank&quot;&gt;Click to download the example file here.&lt;/a&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Wed, 25 Sep 2019 07:09:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/print-capture-web-viewers/</guid>
		</item>
		
		<item>
			<title>Take the Short Cut</title>
			<link>https://www.teamdf.com/blogs/take-the-short-cut/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Learn shortcuts. Get Better. The End.&lt;/p&gt;
&lt;p&gt;... well okay not quite, but this is perhaps the single biggest piece of advice I could give anyone looking to improve their skills as a FileMaker developer.&lt;/p&gt;
&lt;p&gt;You can learn all kinds of tricks and techniques and yeah they&#039;re all great and will make you a better developer. But if you can double or even triple the speed at which you carry out actions in FileMaker through memorising and committing keyboard shortcuts to muscle memory, you&#039;ll free up &lt;strong&gt;so much time&lt;/strong&gt; to do so much more.&lt;/p&gt;
&lt;p&gt;In this article we&#039;ll show some examples of routine tasks done with and without shortcuts to illustrate how much more efficient your development can be.&lt;/p&gt;
&lt;p&gt;We will also cover how you can extend FileMaker&#039;s existing suite of shortcuts to fill in the gaps in the product. Some of the missing shortcuts are so critical to speedy development it&#039;s amazing they&#039;re not built in, but we&#039;ll show you how you can easily define and add your own (if you are on a mac!)&lt;/p&gt;
&lt;p&gt;Finally we&#039;ll go into more depth about some of our favourite custom shortcuts we use, and show some cool shortcuts you might never have thought you could do.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Learning shortcuts can be tedious!&lt;/h2&gt;
&lt;p&gt;If you&#039;re a new developer, now is the best time to learn shortcuts. Learning shortcuts as you learn FileMaker is the best way to do it.&lt;/p&gt;
&lt;p&gt;However if you&#039;re a more experienced developer and have spent years attached to the mouse, contextual menus, or inspector to do things, then you&#039;ve got a much tougher challenge ahead of you. Breaking years of habit can be hard to do, and you need to make a conscious effort to practice and use shortcuts.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/Shortcuts-Tired.png&quot; alt=&quot;Shortcuts Tired&quot; width=&quot;64&quot; height=&quot;64&quot;&gt;&lt;/p&gt;
&lt;p&gt;FileMaker provides a full list of &lt;a href=&quot;https://fmhelp.filemaker.com/help/18/fmp/en/index.html#page/FMP_Help/shortcuts-os-x.html&quot; target=&quot;_blank&quot;&gt;mac&lt;/a&gt;&lt;a href=&quot;https://fmhelp.filemaker.com/help/16/fmp/en/index.html#page/FMP_Help/shortcuts-os-x.html&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt; and &lt;a href=&quot;https://fmhelp.filemaker.com/help/18/fmp/en/index.html#page/FMP_Help%2Fshortcuts-windows.html%23&quot; target=&quot;_blank&quot;&gt;windows&lt;/a&gt; shortcuts on their help documentation. A lot of people will be familiar with some of the more frequently used shortcuts (Define Database, Open Script Workspace etc). However did you know that there are literally &lt;strong&gt;hundreds &lt;/strong&gt;of shortcuts!  &lt;/p&gt;
&lt;p&gt;We counted the total mac shortcuts available in FileMaker Pro, and there are around 260 give or take a few, that&#039;s quite a lot. Now, keep in mind that includes ones you might take for granted like cut/copy/paste, or arrow keys when in calculation dialogs to go to the start/end of a line - they&#039;re all considered shortcuts. &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;A real world example of the benefits &lt;/h2&gt;
&lt;p&gt;Enough preaching, time for a tangible example.&lt;/p&gt;
&lt;p&gt;Below we have two videos. These were made for a talk I gave at the &lt;a href=&quot;https://community.filemaker.com/en/s/news/a3r0H000000oF6UQAU/apac-developer-days-2018&quot; target=&quot;_blank&quot;&gt;APAC Developer Day&lt;/a&gt; last year about this very topic.&lt;/p&gt;
&lt;p&gt;To set the scene, we have a layout with some fields and labels, and a couple of other objects. The goal is to properly align everything nicely.  In the first video we use no keyboard shortcuts - just the inspector and contextual menus.  In the second video we use exclusively keyboard shortcuts.&lt;/p&gt;
&lt;p&gt;We display a timer in both videos. In the second video we also show on-screen the keyboard shortcuts used.&lt;/p&gt;
&lt;p&gt;First, no shortcuts: &lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;media center&quot;&gt;&lt;iframe width=&quot;459&quot; height=&quot;344&quot; src=&quot;https://www.youtube.com/embed/t-G7AC9yVTg?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; title=&quot;Layout Tidy Using No Shortcuts&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;and then with shortcuts:&lt;/p&gt;
&lt;p&gt;&lt;div class=&quot;media leftAlone&quot;&gt;&lt;iframe width=&quot;459&quot; height=&quot;344&quot; src=&quot;https://www.youtube.com/embed/cOVV-JxYx90?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; title=&quot;Layout Tidy Using Shortcuts&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Without using shortcuts we took 69 seconds, and using shortcuts the same actions took 45 seconds - a saving of 24 seconds. Or to put it another way we reduced the time by over 35%.&lt;/p&gt;
&lt;p&gt;This is just a one minute example. If you do this kind of thing for a job developing 6+ hours a day, you can equate that to over 2 hours of saved time.  Now that&#039;s an extreme example - you would have to be working exclusively in layout mode and doing a lot of manipulation to see that improvement, but this is a good illustration of how much time can be saved in increments over the course of a single day!&lt;/p&gt;
&lt;p&gt;More to the point, I think the most important area you can learn and use shortcuts is when in layout mode. So much of layout development is making minor adjustments and then previewing your work in browse mode. This refine/preview cycle can go on for hundreds of iterations when building a layout. The quicker you can do your refinements, the more previewing you can get done in the same amount of time. You&#039;ll quickly find yourself becoming a better designer as a result. &lt;/p&gt;
&lt;p&gt;And one final thing on the benefits. By using shortcuts you&#039;re not just getting faster at doing what you do. You will actually end up changing the way you develop. There&#039;s a tendency in developers to build something first, and refine or pretty it up later because that part of the task takes longer and is more tedious. By utilising extra shortcuts you&#039;ll find yourself doing refinements along the way rather than at the end (where they can often be forgotten about).&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Spot anything unusual in the video?&lt;/h2&gt;
&lt;p&gt;For the keen eye who knows their shortcuts you may have noticed in the second video a few shortcuts you may not find in the standard set that comes with FileMaker. These are custom shortcuts we have added into FileMaker to extend our full set, and add even more functionality and efficiency to development. Some extra ones in the video were:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Resize Selected Objects to Largest Width&lt;/li&gt;
&lt;li&gt;Align Selected Objects Vertically&lt;/li&gt;
&lt;li&gt;Align Selected Objects to Smallest Height&lt;/li&gt;
&lt;li&gt;Align Object Text to Top&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Adding Custom Shortcuts&lt;/h2&gt;
&lt;p&gt;In FileMaker you can actually add even more shortcuts to fill in the gaps where shortcuts are missing. There are a couple of ways you can do this.  For this article, you&#039;ll find our method in the example file that you can download below.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/CustomShortcuts.zip&quot; target=&quot;_blank&quot;&gt;Download the example file CustomShortcuts.zip&lt;/a&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p&gt;Our basic steps to add custom shortcuts is:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Define which shortcuts to add, and what the modifiers/keystroke will be.&lt;/li&gt;
&lt;li&gt;Generate some code to represent those shortcuts (automated in the example file)&lt;/li&gt;
&lt;li&gt;Paste that code into the FileMaker preferences (plist file)&lt;/li&gt;
&lt;li&gt;Restart FileMaker&lt;/li&gt;
&lt;li&gt;Use shortcuts&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;The FileMaker preferences file (also known as the plist file), is where all settings and defaults for the FileMaker program are kept. We can add custom shortcuts to this file.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Mac Only (for this article at least)&lt;/h2&gt;
&lt;p&gt;At this point because we&#039;re getting into discussing how to add custom shortcuts, we must stress that the example file is for mac users only. To this point I haven&#039;t found a good way to add custom shortcuts for FileMaker on windows.   If you have a good method for doing this please &lt;a href=&quot;mailto:daniel@teamdf.com&quot;&gt;get in touch&lt;/a&gt; and we&#039;ll update the article.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Code to go in the .plist file&lt;/h2&gt;
&lt;p&gt;We won&#039;t go into too much detail about the specifics around building your own shortcuts because this is all covered with instruction in the example file. However to touch briefly on what is involved, let&#039;s look at some sample code:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/_resampled/ResizedImage250311-Shortcuts-Code.png&quot; alt=&quot;Shortcuts Code&quot; width=&quot;250&quot; height=&quot;311&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;This code is for a handful of custom shortcuts. You can see the shortcuts defined as key/string pairs of tags. This looks very much like XML.  The key is the shortcut name (case sensitive and must exactly match the menu command in FileMaker). The string value is the shortcut representation.  The code uses some special symbols to represent modifier keys:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;@ for command&lt;/li&gt;
&lt;li&gt;~ for option&lt;/li&gt;
&lt;li&gt;^ for control&lt;/li&gt;
&lt;li&gt;$ for shift&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;the modifiers are followed by the keystroke. Note some shortcuts require special symbols to represent them, such as the arrow keys, backspace, delete key etc.  We list these special characters in the example file.&lt;/p&gt;
&lt;p&gt;The code is pasted into your FileMaker preferences file. After restarting FileMaker you should be able to use these. Here is an example of some custom shortcuts for layout object manipulation:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/_resampled/ResizedImage300156-Shortcuts-Example.png&quot; alt=&quot;Shortcuts Example&quot; width=&quot;300&quot; height=&quot;156&quot;&gt; &lt;/p&gt;
&lt;p&gt;The example file has 46 new custom shortcuts. All of them you&#039;ll find quite intuitive and similar to other existing keyboard shortcuts in the same area of FileMaker.  For example a lot of the shortcuts in the &quot;Manage..&quot; use command+shift as the modifiers. The custom shortcuts continue this trend so you can easily learn them:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/_resampled/ResizedImage300245-Shortcuts-Manage.png&quot; alt=&quot;Shortcuts Manage&quot; width=&quot;300&quot; height=&quot;245&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;You can also add shortcuts in System Prefs&lt;/h2&gt;
&lt;p&gt;On the mac you can add application specific shortcuts (for any app) via System Preferences -&amp;gt; Keyboard -&amp;gt; Shortcuts -&amp;gt; App Shortcuts.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/_resampled/ResizedImage300261-Shortcuts-Prefs.png&quot; alt=&quot;Shortcuts Prefs&quot; width=&quot;300&quot; height=&quot;261&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;The shortcuts you add directly into your plist file will appear here, and vice versa. We prefer modifying the plist because it allows you to easily keep your custom shortcuts, and transfer them to different computers if you need to. However this is a nice way to view all of the ones you have defined or make any minor refinements.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;Our Favourite Custom Shortcuts&lt;/h2&gt;
&lt;p&gt;Of the 46 custom shortcuts we use, there are a few standouts. These are ones either used most frequently, or quite unusual or interesting ways you can use shortcuts in FileMaker, we&#039;ll go through a few here.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Make Debugging Easier&lt;/h2&gt;
&lt;p&gt;FileMaker doesn&#039;t provide shortcuts to toggle the data viewer or script debugger, so why not add your own. These 2 tools are used so often in development it would be criminal not to use a shortcut!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/_resampled/ResizedImage299219-Shortcuts-Debugging.png&quot; alt=&quot;Shortcuts Debugging&quot; width=&quot;299&quot; height=&quot;219&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;h2&gt;Zoom to Actual Size&lt;/h2&gt;
&lt;p&gt;FileMaker provides a shortcut to zoom in (cmd+) and zoom out (cmd -), yet gives no shortcut to return to actual size, what gives? Let&#039;s just add our own. Most applications use cmd+0 as the standard, so we&#039;ll just use that, it&#039;s easy and intuitive for users and developers alike.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/_resampled/ResizedImage30086-Shortcuts-Zoom.png&quot; alt=&quot;Shortcuts Zoom&quot; width=&quot;300&quot; height=&quot;86&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;h2&gt;Layout object Manipulation&lt;/h2&gt;
&lt;p&gt;These are so critical. Completing the full set of layout manipulation shortcuts lets you never have to reach for the menus again. The best thing about these is they&#039;re intuitive and easy to learn if you already use the existing shortcuts (e.g. align edges)&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/_resampled/ResizedImage300156-Shortcuts-Example.png&quot; alt=&quot;Shortcuts Example&quot; width=&quot;300&quot; height=&quot;156&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;Developing with Custom Menus?&lt;/h2&gt;
&lt;p&gt;Quite often when developing you need to build custom menus for certain layouts. While the users might require these, they can be incredibly frustrating for a developer especially when common commands might be missing from them. Often you just want to revert to the standard menu set - so why not bind a key to the standard menus? This lets you quickly an easily change the menu set no matter where you are.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/_resampled/ResizedImage30090-Shortcuts-Menus.png&quot; alt=&quot;Shortcuts Menus&quot; width=&quot;300&quot; height=&quot;90&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;h2&gt;Previewing Data in Layout Mode&lt;/h2&gt;
&lt;p&gt;The option to toggle sample data in layout mode is a really useful tool but is often overlooked because it is hidden away in the menus.  Through using a shortcut key you can make this accessible and easy to toggle and add this valuable feature to your toolkit.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/_resampled/ResizedImage300394-Shortcuts-Sample.png&quot; alt=&quot;Shortcuts Sample&quot; width=&quot;300&quot; height=&quot;394&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;in fact you can add shortcuts for any items shown above.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;h2&gt;Some cool multi-shortcuts&lt;/h2&gt;
&lt;p&gt;Now for some cool stuff. In FileMaker there are certain menu commands that essentially do a similar thing, yet at any given point in time only one of them is able to be used.&lt;/p&gt;
&lt;p&gt;We&#039;re talking about the &quot;Setup…&quot; menu commands:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/_resampled/ResizedImage300239-Shortcuts-Setup.png&quot; alt=&quot;Shortcuts Setup&quot; width=&quot;300&quot; height=&quot;239&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;There are 8 different layout objects for which there is a setup dialog, however when working in layout mode you can only select one of these objects at a time for editing in the setup dialog.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;This allows us to define &lt;strong&gt;the exact same &lt;/strong&gt;shortcut for every single one. THey will never end up in conflict because only one will ever be enabled at any given time. How cool is that. It also means you only ever have to remember one shortcut.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;Shortcuts don&#039;t just have to be for menu commands...&lt;/h2&gt;
&lt;p&gt;Interestingly, we found shortcuts can be applied to a lot of menus in FileMaker, not just the standard ones at the top of your screen. Take this menu for example:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/_resampled/ResizedImage300421-Shortcut-TableOccurrences.png&quot; alt=&quot;Shortcut TableOccurrences&quot; width=&quot;300&quot; height=&quot;421&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Here we have a specify field dialog, and in it at the bottom is a special menu command to go to the Manage Database dialog. This is actually something we can add a shortcut to.  Note this differs from the menu command File -&amp;gt; Manage -&amp;gt; Database… (the name is different).&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;The benefit of adding a shortcut to this item is if you have a very long list of table occurrences, you can use the shortcut to immediately access field definitions and the graph without having to exit this dialog, or go to the very bottom to access the command. Groovy.  Now, you can always use the end key to jump to the bottom, followed by pressing enter, however this is a single shortcut that will instantly open the manage database dialog without the need for 2 key presses.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt; Work better in Script Workspace&lt;/h2&gt;
&lt;p&gt;How many times do you open the script step pane in the workspace just to look something up, and then want to get rid of it? How often do you need more space and want to collapse the script list (but easily get it back)?&lt;/p&gt;
&lt;p&gt;Now you can just by adding some intuitive shortcuts:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/_resampled/ResizedImage30074-Shortcuts-Script-Show.png&quot; alt=&quot;Shortcuts Script Show&quot; width=&quot;300&quot; height=&quot;74&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;These shortcuts are very easy to learn and intuitive.  Here you can also make use of a similar technique shown above with the object setup shortcuts.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;If the scripts pane is hidden, then the menu command is &quot;Show Scripts Pane&quot;. However if the scripts pane is showing, then the command changes to &quot;Hide Scripts Pane&quot;.  &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;At any given time only one of those two menu items appears in the menus, so you can safely attach the same shortcut key to both commands without fear of conflict:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/_resampled/ResizedImage29974-Shortcuts-Script-Hide.png&quot; alt=&quot;Shortcuts Script Hide&quot; width=&quot;299&quot; height=&quot;74&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;In Conclusion&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;I can&#039;t stress how great keyboard shortcuts are. I&#039;m a total fanboy and I hope you all become fanboys and fangirls of them too. You&#039;ll find through a bit of dedication and time to learn them, you&#039;ll rapidly become a far better and faster developer as a result.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;I encourage you also to make use of some of these additional custom shortcuts. There are some gaping holes in the standard set of shortcuts in FileMaker that fortunately we can patch with our own shortcuts quickly and easily.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Happy shortcutting!&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;Example File&lt;/h2&gt;
&lt;p&gt;We&#039;ve referenced the example file a few times in this article, you can download it here. The example file contains further information about custom shortcuts and a step by step guide to defining your own and implementing them.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;Download CustomShortcuts.zip&quot; href=&quot;https://www.teamdf.com/assets/blog-images/Keyboard-Shortcuts/CustomShortcuts.zip&quot; target=&quot;_blank&quot;&gt;Click to download example file CustomShortcuts.zip&lt;/a&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;Thank you Matt Petrowsky!&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;I wanted to give special mention to Matt Petrowsky from &lt;a href=&quot;https://www.filemakermagazine.com/&quot; target=&quot;_blank&quot;&gt;filemakermagazine.com&lt;/a&gt; who got me onto these custom shortcuts many years ago now. Since then I&#039;ve embraced them and used them daily and am a huge advocate for them.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Matt produced a database back in 2011 to help you build these shortcuts and implement them. While the file may no longer work in later versions of FileMaker, I encourage you to check out his site and the page for his solution. I drew a lot of inspiration from his work!&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;a href=&quot;https://filemakerstandards.org/display/dt/Enhanced+Macintosh+Keyboard+Shortcuts&quot; target=&quot;_blank&quot;&gt;You can find his original solution here&lt;/a&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 02 Jul 2019 07:53:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/take-the-short-cut/</guid>
		</item>
		
		<item>
			<title>Elemental has Landed</title>
			<link>https://www.teamdf.com/blogs/elemental-has-landed/</link>
			<description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;Elemental is here! This is my first foray into building a product/resource that is much larger and more expansive than my standard demo files you&#039;ll find on articles.  It&#039;s the main reason why the blog has been quiet these last couple of months as I&#039;ve been spending all my spare time on this project.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;If you want to check it out before reading, you can download a copy at &lt;a href=&quot;https://www.elemental-fm.com&quot; target=&quot;_blank&quot;&gt;https://www.elemental-fm.com&lt;/a&gt; &lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;h3 class=&quot;p1&quot;&gt;So what is it?&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;Elemental is more a resource than a product. Maybe you noticed over the last couple of years a trend toward more design and user interface based articles  such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.teamdf.com/blogs/beautiful-menus/&quot; target=&quot;_blank&quot;&gt;sliding drawers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.teamdf.com/blogs/beautiful-menus/&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://www.teamdf.com/blogs/dynamically-resizing-backgrounds/&quot; target=&quot;_blank&quot;&gt;resizing backgrounds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.teamdf.com/blogs/building-a-super-slick-search-ui/&quot; target=&quot;_blank&quot;&gt;search UI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.teamdf.com/blogs/better-breadcrumbs/&quot; target=&quot;_blank&quot;&gt;breadcrumbs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.teamdf.com/blogs/swipe-out-iphone/&quot; target=&quot;_blank&quot;&gt;swiping UI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;etc..&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This is mostly because design and building solutions that are both usable and visually appealing really floats my boat. The user experience is paramount here and anything that can be done to improve the users enjoyment of using a solution is vitally important. Just think how many hours a day people spend using a solution that you might have built - you want it to be as fun as possible.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;That&#039;s what Elemental is about. My goal is to provide UI resources that you can incorporate into your own solution to improve user experiences, be it through better user interface, or just purely a better visual design.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;h3 class=&quot;p1&quot;&gt;How much does Elemental cost?&lt;/h3&gt;
&lt;p&gt;Elemental is and always will remain free to the community. A lot of what I have done is writing code to help integrate with various API services, or make it easy to use freely available resources in your own solutions.&lt;/p&gt;
&lt;p&gt;While I ask no fee to purchase Elemental, my site does have a &lt;a href=&quot;https://www.elemental-fm.com/donate&quot; target=&quot;_blank&quot;&gt;donate&lt;/a&gt; option. Building this does take a lot of time and effort. I would really love to continue building on Elementals feature set which is why I have added this option. You are able to help make a contribution toward the continued development of Elemental.  You can also just offer a donation if you really like the product and want to help me out, but this is not expected.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;What&#039;s in Elemental? &lt;/h3&gt;
&lt;p&gt;In this first version I&#039;ve got 5 sections...&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Avatars&lt;/h3&gt;
&lt;p&gt;An avatar is something you&#039;d typically find on the web. Most sites you sign up for have a profile photo you can upload. Some offer a randomly generated avatar if you do not provide one.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Elemental/_resampled/ResizedImage600351-Elemental-1.png&quot; alt=&quot;Elemental Avatars&quot; width=&quot;600&quot; height=&quot;351&quot;&gt;&lt;/p&gt;
&lt;p&gt;I&#039;ve collated basically every restful API service out there that offers various avatar generators - 23 in total.  They&#039;re all slightly different, each offering a different feature-set of options that you can customise.&lt;/p&gt;
&lt;p&gt;Most work on unique generation based on a seed you provide. A seed is something generally unique to a user. Most of the time it will be the name of an individual, but you can just as easily use the primary key UUID, or whatever you like.&lt;/p&gt;
&lt;p&gt;The avatar generator will take that seed and hash it to produce a unique avatar at the other end.&lt;/p&gt;
&lt;p&gt;In Elemental you&#039;ll find a script group named &quot;Avatar Generators&quot;. These are built to be standalone scripts you can copy/paste into your own solution to implement an avatar generator. There are just a couple of places in the script you&#039;ll need to fix up for your own solution:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The bottom of the script has the section where the avatar is returned and set into a container (or text field for SVG) you&#039;ll need to point this to your own container/text field.&lt;/li&gt;
&lt;li&gt;Some scripts rely on a custom function @validate_input to make sure items passed are valid for the API. If the script uses this you&#039;ll need to import it into your solution.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;And that&#039;s about it.  We pass all parameter options that the API can accept to the script using JSON functions. You&#039;ll see at the top of the script all parameters are parsed.&lt;/p&gt;
&lt;p&gt;Some API&#039;s will return the avatar as an SVG, which for us is kind of useless because container fields don&#039;t display SVG&#039;s (although you can render this in a web viewer and that is what we&#039;ve done in Elemental for previewing the avatar). Fear not! Through some magic we&#039;ve got a SVG to PNG converter built into Elemental which works all within a single web viewer off the side of the layout. Feel free to explore how this works. We&#039;ll cover this more in an upcoming article.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Placeholders&lt;/h3&gt;
&lt;p&gt;These are quite similar to the Avatars. We integrate with API services that provide placeholder images. These are great if you need an image of certain dimensions, colour or type to act as a placeholder. Perhaps you have a product database where you need a placeholder image, or you expect the user to insert an image of a specific size - you can integrate with a placeholder API that provides you an image showing dimensions.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Elemental/_resampled/ResizedImage600351-Elemental-2.png&quot; alt=&quot;Elemental Placeholders&quot; width=&quot;600&quot; height=&quot;351&quot;&gt;&lt;/p&gt;
&lt;p&gt;We&#039;ve got a few fun placeholders in there too....&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;SVG Icons&lt;/h3&gt;
&lt;p&gt;This one might prove most useful to the most number of developers. These SVG icons are from the Syncfusion MetroStudio suite of icons which are freely available. We&#039;ve downloaded them all, and ran them through some processing to make them FileMaker ready. You should just be able to put these straight into a button bar and they&#039;ll be sized and positioned correctly ready to be used. You&#039;ll find over 7,000 icons in this set.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Elemental/_resampled/ResizedImage600351-Elemental-3.png&quot; alt=&quot;Elemental Icons&quot; width=&quot;600&quot; height=&quot;351&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;SVG / GIF Animations&lt;/h3&gt;
&lt;p&gt;A little bit of movement never hurt anyone!  Add a bit of animation to your solution. These are a selection of around 20 loading style animations. These would be great if you have a Perform Script on Server that you are executing and need the user to wait to complete, or any other operation that takes a while to run. A bit of visual feedback is sometimes all a user needs to accept that there will be a wait time.&lt;/p&gt;
&lt;p&gt;GIF&#039;s have been included because these are universally compatible on both mac &amp;amp; windows.  &lt;/p&gt;
&lt;p&gt;The SVG animations use SMIL technology which works great on Mac&#039;s but be weary on windows, not all browser versions support this so you may need to use GIF&#039;s.&lt;/p&gt;
&lt;p&gt;These were obtained under free license from &lt;a href=&quot;https://loading.io&quot; target=&quot;_blank&quot;&gt;loading.io&lt;/a&gt; (but you can purchase many more).  They are fully customisable and we offer instruction in Elemental on how to do this.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Elemental/_resampled/ResizedImage600351-Elemental-4.png&quot; alt=&quot;Elemental Animations&quot; width=&quot;600&quot; height=&quot;351&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Elemental/Elemental-5.gif&quot; alt=&quot;Elemental Animated Ball&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Gradients&lt;/h3&gt;
&lt;p&gt;Either love &#039;em or hate &#039;em, gradients are included :) We&#039;ve collated over 330 different examples of gradients from &lt;a href=&quot;https://gradientjoy.com/&quot; target=&quot;_blank&quot;&gt;GradientJoy&lt;/a&gt; that you can browse through and pick your favourite to use. Hex color codes are included so you can easily build your own in FileMaker.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Elemental/_resampled/ResizedImage600351-Elemental-6.png&quot; alt=&quot;Elemental Gradients&quot; width=&quot;600&quot; height=&quot;351&quot;&gt;   &lt;/p&gt;
&lt;h3&gt;Other Cool Stuff&lt;/h3&gt;
&lt;p&gt;Elemental has been built not just with some cool resources, but I want the overall solution to be considered a resource in and of itself. In it you&#039;ll find some other interesting little nuggets. Here&#039;s a hint of what they are and where to find them:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Elemental theme provided fully styled&lt;/li&gt;
&lt;li&gt;HTML5 Color pickers are used in some avatar/placeholder examples (where the OS version supports them)&lt;/li&gt;
&lt;li&gt;The Jdenticon Avatar has a double-range slider control (again if your OS supports it!)&lt;/li&gt;
&lt;li&gt;About/Acknowledgement pages contain animated SVG icons - these are done entirely with CSS animations on a static SVG. To discover how it is done check the custom function @svg_animate. This was a feature I hoped to flesh out a bit more in this version but it might have to wait to the next one.&lt;/li&gt;
&lt;li&gt;SVG to PNG/JPG conversion using some javascript in a web viewer and nothing more - check Avatar/Placeholder examples where it is used&lt;/li&gt;
&lt;li&gt;plus lots more!&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Elemental/Elemental-7.png&quot; alt=&quot;Elemental Color Picker&quot; width=&quot;574&quot; height=&quot;600&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Elemental/_resampled/ResizedImage600171-Elemental-8.png&quot; alt=&quot;Elemental Slider&quot; width=&quot;600&quot; height=&quot;171&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;In Conclusion&lt;/h3&gt;
&lt;p&gt;Building Elemental has been a labour of love. Most evenings over the last 2 months have been spent working on this instead of having a life! I hope you all enjoy it and find something in there you can use, no matter how small, or at the very least to just be inspired to think more about design or the user experience - if I can achieve that then my work here is done :)&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Mon, 17 Jun 2019 18:58:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/elemental-has-landed/</guid>
		</item>
		
		<item>
			<title>FileMaker 18 Release</title>
			<link>https://www.teamdf.com/blogs/filemaker-18-release-2/</link>
			<description>&lt;p&gt;FileMaker Inc have released the major annual update to the entire FileMaker platform today bringing a bunch of under-the-hood improvements and a few quite valuable, though generally quite technical new features. There are new versions of:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;FileMaker Pro Advanced &lt;/li&gt;
&lt;li&gt;FileMaker Server*&lt;/li&gt;
&lt;li&gt;FileMaker Go&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;*The Server update includes a new version of WebDirect too — better, faster, stronger.&lt;/p&gt;
&lt;h3&gt;Should You Update?&lt;/h3&gt;
&lt;p&gt;In short &lt;strong&gt;&lt;em&gt;Yes!&lt;/em&gt;&lt;/strong&gt; ...but not necessarily immediately — here’s how we see it:&lt;/p&gt;
&lt;h4&gt;On Desktop, iPad and iPhone&lt;/h4&gt;
&lt;p&gt;We think you’ll be fine to go ahead and update the FileMaker Pro Advanced app on your computers and iOS devices right away — the business world is getting used to updating software regularly and even automatically now which you see with most cloud software.&lt;/p&gt;
&lt;h3&gt;On Server&lt;/h3&gt;
&lt;p&gt;We’re a little more cautious on FileMaker Server, where we reckon on waiting at least a couple of weeks to see if any issues emerge: FileMaker Server has had some substantial changes in how it works and while these have been tested extensively for many months now, there’s nothing like the real-world to turn up issues in software.&lt;/p&gt;
&lt;p&gt;We’ll be progressively upgrading our own servers in coming days so that we too get some real world miles under our belts and can advise you.&lt;/p&gt;
&lt;p&gt;That said, if you’re suffering from bottlenecks on the server then the good news is that 18 brings some huge improvements to multitasking, which basically means the server can better handle lots of users and tasks at once. In which case, let’s get on and upgrade you as soon as possible—just drop us a line asap.&lt;/p&gt;
&lt;h3&gt;&lt;span style=&quot;font-size: 1em;&quot;&gt;Mix and Match&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;You can mix and match too — you don’t have to update for FileMaker Server immediately, and nor is it necessary for everyone in your organisation to update their apps at once.&lt;/p&gt;
&lt;p&gt;In fact, it’s also possible to keep both FM17 and 18 on your device or computer, so you can try 18 and still fall back to 17 if there is anything misbehaving. (And in which case, let us and FileMaker know — use &quot;Feedback&quot; under the Help menu.)&lt;/p&gt;
&lt;p&gt;To be clear though, in the long run though you’ll want everyone in the organisation on the same version and we always recommend staying up with the current version for robustness, security and to ensure you have the latest capabilities available. Also please bear in mind that the new version is not extra licenses — you’re not permitted to use your previous version for other users; please ensure you are licensed for the correct number of users.&lt;/p&gt;
&lt;h3&gt;What’s New?&lt;/h3&gt;
&lt;p&gt;Aside from the Server architecture, which is in fact one of the biggest and best things in our view, here’s what else is new:&lt;/p&gt;
&lt;p&gt;For developers:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;New commands for reading and writing text files&lt;/li&gt;
&lt;li&gt;A new “while” construct for loops in calculations — Wahoo! Now we don’t have to think about recursion in order to create functions that work through piece of data. &lt;/li&gt;
&lt;li&gt;Full XML / text dump of a database file — great for version control and change tracking.&lt;/li&gt;
&lt;li&gt;Script error logging&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;New capabilities:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Support for more barcode types&lt;/li&gt;
&lt;li&gt;Start-up Restoration — FileMaker files can now automatically recover themselves after a hardware or software crash on server.&lt;/li&gt;
&lt;li&gt;Auto-open a particular database app on launch — simpler and easier for people who’re using one primary application within FileMaker.&lt;/li&gt;
&lt;li&gt;Improvements to the “Data API”, allowing other apps better access to data stored in your FileMaker solution&lt;/li&gt;
&lt;li&gt;Vastly improved data import tool&lt;/li&gt;
&lt;li&gt;Enhancements to security, especially plugins and external access&lt;/li&gt;
&lt;/ul&gt;&lt;h3&gt;Insecure Plugins &lt;/h3&gt;
&lt;p&gt;When you first launch FileMaker 18 you may well get warnings like this for each of the plugins you use:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/fm18-release/_resampled/ResizedImage600283-plugin-warning.png&quot; alt=&quot;plugin warning&quot; width=&quot;600&quot; height=&quot;283&quot;&gt;&lt;/p&gt;
&lt;p&gt;The reason is that FileMaker now requires code to be &quot;signed&quot; by the developer, which simply ensures that it hasn&#039;t been hacked or modified. It&#039;s best practice and all apps are like that nowadays so it makes sense that the plugins should be too. You can go ahead and &quot;Load plugin&quot; for now, and I&#039;d be inclined to tick the &quot;Always load this plugin&quot; option too, otherwise you are going to be prompted every time you open FileMaker 18. &lt;/p&gt;
&lt;p&gt;That said, the correct and proper solution is to go and get the latest version of the plugin from whomever made it — all plugin developers should have released an update which is signed and secured in the correct way by now or very soon. If you&#039;re using our Reactor plugin, the latest version can be found on our &lt;a title=&quot;Latest Reactor plugin download.&quot; href=&quot;https://www.fusionplugins.com/products/reactor/try/Fusion_Reactor_Core.zip&quot; target=&quot;_blank&quot;&gt;fusionplugins.com&lt;/a&gt; site.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Moving On:&lt;/h3&gt;
&lt;p&gt;FileMaker, as with most software makers nowadays are pushing more forward rather than maintaining a lot of backward capability. Not only does this make life a lot easier for the developer, it also ensures the latest robustness and security. It’s an important move and we fully support it — for us, maintaining old versions and having to work in them when clients don’t stay current means inefficiency and frustration.&lt;/p&gt;
&lt;p&gt;Plus with the move to ongoing subscription licenses means you’re always entitled to run the current version, and it’s easier just to stay current than lag and then have to catch up.&lt;/p&gt;
&lt;h3&gt;And… What are we losing in FM18?&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;macOS High Sierra or better is now required&lt;/li&gt;
&lt;li&gt;Peer to Peer sharing is “deprecated” and permitted for testing purposes only*&lt;/li&gt;
&lt;li&gt;Swedish language version of FM Server is being dropped&lt;/li&gt;
&lt;li&gt;No new app icon — this version retains the same icon as FileMaker 17&lt;/li&gt;
&lt;/ul&gt;&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/fm18-release/_resampled/ResizedImage126118-fmpa18icon.jpg&quot; alt=&quot;fmpa18icon&quot; width=&quot;126&quot; height=&quot;118&quot;&gt;&lt;/p&gt;
&lt;p&gt;And some of the older licensing options &lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovukz87zz89zz86zz66z7ez84zgz68zz75zjffhz83z54a9cvz65zz81zz78zrz66z3mz85z&quot;&gt;have now ended: the transition to a simple per user license continues and we think this is a great idea, ultimately making licensing simpler and keeping it fair. &lt;/span&gt;&lt;/p&gt;
&lt;div&gt;*Peer to peer sharing refers to being able to open a database on your computer and let others connect to it, thus “saving” you having to run the database on server. It’s kinda convenient but not very robust or secure way to run a business at all. Given that FileMaker user licensing includes server (in fact you’re permitted to run 3!) we believe this is a good move. It is still useful in some cases, particularly when developing a new database and wanting to connect from an iOS device directly to the database on your machine as you’re building it, and that use case is still supported and permitted.
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;</description>
			<pubDate>Thu, 23 May 2019 12:34:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-18-release-2/</guid>
		</item>
		
		<item>
			<title>FileMaker 18 Release</title>
			<link>https://www.teamdf.com/blogs/filemaker-18-release/</link>
			<description>&lt;p&gt;FileMaker Inc have released the major annual update to the entire FileMaker platform today bringing a bunch of under-the-hood improvements and a few quite valuable, though generally quite technical new features. There are new versions of:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;FileMaker Pro Advanced&lt;/li&gt;
&lt;li&gt;FileMaker Server*&lt;/li&gt;
&lt;li&gt;FileMaker Go&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;*The Server update includes a new version of WebDirect too — better, faster, stronger.&lt;/p&gt;
&lt;h2&gt;Should You Update?&lt;/h2&gt;
&lt;p&gt;In short yes, but not necessarily immediately — here’s how we see it:&lt;/p&gt;
&lt;h4&gt;On Desktop, iPad and iPhone&lt;/h4&gt;
&lt;p&gt;We think you’ll be fine to go ahead and update the FileMaker Pro Advanced app on your computers and iOS devices right away — the business world is getting used to updating software regularly and even automatically now which you see with most cloud software.&lt;/p&gt;
&lt;h4&gt;Mix and Match&lt;/h4&gt;
&lt;p&gt;You can mix and match too — you don’t have to update for FileMaker Server immediately, and nor is it necessary for everyone in your organisation to update their apps at once. In fact, it’s also possible to keep both FileMaker 17 and 18 on your device or computer, so you can try 18 and still fall back to 17 if there is anything misbehaving. (And in which case, let us and FileMaker know — there’s a feedback option under the Help menu.)&lt;/p&gt;
&lt;p&gt;To be clear though, in the long run though you’ll want everyone in the organisation on the same version and we always recommend staying up with the current version for robustness, security and to ensure you have the latest capabilities available. Also please bear in mind that the new version is not extra licenses — you’re not permitted to use your previous version for other users; please ensure you are licensed for the correct number of users.&lt;/p&gt;
&lt;h4&gt;On Server&lt;/h4&gt;
&lt;p&gt;We’re a little more cautious on FileMaker Server, where we reckon on waiting at least a couple of weeks to see if any issues emerge: FileMaker Server has had some substantial changes in how it works and while these have been tested extensively for many months now, there’s nothing like the real-world to turn up issues in software.&lt;/p&gt;
&lt;p&gt;We’ll be progressively upgrading our own servers in coming days so that we too get some real world miles under our belts and can advise you.&lt;/p&gt;
&lt;p&gt;That said, if you’re suffering from bottlenecks on the server then the good news is that FileMaker 18 brings some huge improvements to multitasking, which basically means the server can better handle lots of users and tasks at once. In which case, let’s get on and upgrade you as soon as possible—just drop us a line asap.&lt;/p&gt;
&lt;h2&gt;What’s New?&lt;/h2&gt;
&lt;p&gt;Aside from the Server architecture, which is in fact one of the biggest and best things in our view, here’s what else is new:&lt;/p&gt;
&lt;h4&gt;For developers:&lt;/h4&gt;
&lt;ul&gt;&lt;li&gt;New commands for reading and writing text file&lt;/li&gt;
&lt;li&gt;A new “while” construct for loops in calculations — Wahoo! Now we don’t have to think about recursion in order to create functions that work through piece of data.&lt;/li&gt;
&lt;li&gt;Full XML / text dump of a database file — great for version control and change tracking.&lt;/li&gt;
&lt;li&gt;Script error logging&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;New Capabilities:&lt;/h4&gt;
&lt;ul&gt;&lt;li&gt;Support for more barcode types&lt;/li&gt;
&lt;li&gt;Start-up Restoration — FileMaker files are now automatically recovered after a hardware or software crash.&lt;/li&gt;
&lt;li&gt;Auto-open a particular database app on launch — simpler and easier for people who’re using one primary application within FileMaker&lt;/li&gt;
&lt;li&gt;Improvements to the “Data API”, allowing other apps better access to data stored in your FileMaker solution (what are they?)&lt;/li&gt;
&lt;li&gt;Vastly improved data import tool&lt;/li&gt;
&lt;li&gt;Enhancements to security, especially plugins and external access&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;Moving On:&lt;/h4&gt;
&lt;p&gt;FileMaker, as with most software makers nowadays are pushing more forward rather than maintaining a lot of backward capability. Not only does this make life a lot easier for the developer, it also ensures the latest robustness and security. It’s an important move and we fully support it — for us, maintaining old versions and having to work in them when clients don’t stay current means inefficiency and frustration. Moreover the move to ongoing subscription licenses means you’re always entitled to run the current version, and it’s easier just to stay current than lag and then have to catch up.&lt;/p&gt;
&lt;h2&gt;And… What are we losing in FileMaker 18?&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;macOS High Sierra or better is now required&lt;/li&gt;
&lt;li&gt;Peer to Peer sharing is “deprecated” and permitted for testing purposes only*&lt;/li&gt;
&lt;li&gt;Swedish language version of FileMaker Server is being dropped&lt;/li&gt;
&lt;li&gt;No new app icon — this version retains the same icon as FileMaker 17&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;p&gt;And some of the older licensing options (the Volume Licensing Agreements) have now ended: the transition to a simple per user license continues and we think this is a great idea, ultimately making licensing simpler and keeping it fair.&lt;/p&gt;
&lt;p&gt;*Peer to peer sharing refers to being able to open a database on your computer and let others connect to it, thus “saving” you having to run the database on server. It’s kinda convenient but not very robust or secure way to run a business at all. Given that FileMaker user licensing includes server (in fact you’re permitted to run 3!) we believe this is a good move. It is still useful in some cases, particularly when developing a new database and wanting to connect from an iOS device directly to the database on your machine as you’re building it, and that use case is still supported and permitted.&lt;/p&gt;
&lt;p&gt;This does mean though that very small operations, say 2 - 3 users, need to purchase the 5 user license — think of it as “Up to 5 users”. That might mean an increase in cost for some unfortunately. That said, we reckon FileMaker is very good value — it works out at $17 per user for 5 users with no additional cost for the server software nowadays (that used to be more than $1500 itself), and if you are just a two person operation it’s $50 per user per month.&lt;/p&gt;</description>
			<pubDate>Thu, 23 May 2019 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-18-release/</guid>
		</item>
		
		<item>
			<title>A Variable Way of Writing Recursion</title>
			<link>https://www.teamdf.com/blogs/a-variable-way-of-writing-recursion/</link>
			<description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;Recursion can be a complex and often intimidating part of FileMaker development for many. Wrapping your head around what it is and how it works is something even a seasoned developer can struggle with from time to time - just ask anyone who has sat the certification exam!&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;In this article we start by offering a brief introduction as to what recursion is by way of a simple example, before digging into the main reason for this article which is to present an alternative way to write your custom functions that is much simpler and easier to understand and follow.  If you are already caught up on what recursion is and how it works, then feel free to skip down this introduction and get stuck into the more interesting stuff further down the article. Otherwise enjoy this introduction to recursion :)&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;So let&#039;s go!&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;h3 class=&quot;p1&quot;&gt;Recursion is really just a loop&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;Yup, that&#039;s about it. We use recursion to simulate a looping construct when required in a calculation. FileMaker has no loop function at this point in time and so we rely on recursion to achieve the same effect. Think of it as being the ugly awkward half brother to a FileMaker scripted loop.  A scripted loop can be used to loop and process records, or values stored within variables among other things. Recursive functions typically are used to loop through a list of values while performing actions on that list. They can also be used to transform values, or build lists of values.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Of course they are used for much more but in the world of FileMaker development most recursive functions you will come across tend to involved processing of multiple values, such as a list.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;h3 class=&quot;p1&quot;&gt;You write recursive functions using a Custom Function&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;In FileMaker, we use the Custom Function feature to write recursive custom functions. A custom function is purely a function you entirely declare and write yourself. They need not be recursive, but given we have access to write functions, we can easily write them to be recursive if need be.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;You will find custom functions in FileMaker under the &quot;File&quot; menu -  File -&amp;gt; Manage -&amp;gt; Custom Functions.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;  &lt;/p&gt;
&lt;h3 class=&quot;p1&quot;&gt;Writing Custom Functions&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;Note that in FileMaker Pro 16 and earlier, this feature is only available to users of FileMaker Pro Advanced. While a standard copy of FileMaker Pro can execute a custom function, you cannot write them. With the release of FileMaker Pro 17, there is no longer a separate version of Advanced, and so you can write these functions using FileMaker Pro. You just have to make sure you enable the &quot;Use Advanced Tools&quot; option which is set in the FileMaker Pro preferences.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;h3 class=&quot;p1&quot;&gt;Okay, so recursion is like a loop... but how? &lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;a href=&quot;https://techterms.com/definition/recursion&quot; target=&quot;_blank&quot;&gt;Techterms.com&lt;/a&gt; has a nice and simple definition of recursion:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span&gt;Recursion is a process in which a function calls itself as a subroutine. This allows the function to be repeated several times, since it calls itself during its execution. Functions that incorporate recursion are called &lt;/span&gt;&lt;a href=&quot;https://techterms.com/definition/recursivefunction&quot;&gt;recursive functions&lt;/a&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p class=&quot;p1&quot;&gt;The key here is that the function &lt;strong&gt;calls itself&lt;/strong&gt;. Each time a function calls itself again, you can think of it as progressing to the next item - or drawing an analogy to a scripted loop it would be akin to moving on to the next record to process.  If we wanted to loop over a list of 10 items doing something to each, then the function would call itself 9 times (the first time the user calls it, and the other 9 times the function calls itself.).&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Another way to look at it is to think of it a bit like the Droste effect. I&#039;m sure you have all seen pictures similar to that below, it is a good way to think about recursion. You can read more about the &lt;a href=&quot;https://en.wikipedia.org/wiki/Droste_effect&quot; target=&quot;_blank&quot;&gt;Droste Effect here&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Variable-Recursion/VariableRecursion-1.png&quot; alt=&quot;VariableRecursion 1&quot; width=&quot;327&quot; height=&quot;400&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;h3 class=&quot;p1&quot;&gt; A simple example of recursion&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt; Here we have a simple function &lt;strong&gt;_factorial (_integer )&lt;/strong&gt;.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Variable-Recursion/VariableRecursion-2.png&quot; alt=&quot;VariableRecursion 2&quot; width=&quot;656&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; When this function is passed a number it will return the product of the integer and all integers below it, ending at the number 1.  For example _factorial (4) will return the result of 24. This is done by multiplying 4 * 3 * 2 * 1.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;The function first takes the parameter and makes it an absolute number - purely done to ensure we don&#039;t end up with a negative number parameter. &lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Recursive functions have an exit condition. This is a check to determine whether recursion is going to end or continue. It&#039;s exactly like the &quot;Exit loop If&quot; script step.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Each time the function is called, it will be being passed the next lowest number. The exit condition is when we are passed the number 1.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;If we have not yet been passed the value &quot;1&quot;, the function will multiply the integer passed by the result of the function called again (with 1 less as its parameter).&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;If you are still not following, have a look at this graphic:&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Variable-Recursion/VariableRecursion-3.png&quot; alt=&quot;VariableRecursion 3&quot; width=&quot;660&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: left;&quot;&gt;Here we are showing each row as a subsequent recursive call to the function.  The first time the function is called it is passed the value 4.   The exit condition is checked &quot;is 4 equal to 1?&quot;. Because the answer is false, we multiply 4 by the result of a recursive call.  Now imagine repeating this but for the function with the parameter of 3. This is illustrated on row 2. We repeat the exit condition which is still false, and so the result of this call is 3 multiplied by the function call again with the parameter of 2.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: left;&quot;&gt;Once more we repeat this until row 4 where the exit condition is true - 1 is equal to 1. The result of this is simply to return the number 1.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: left;&quot;&gt;So the result of 1 is passed back up to row 3 and used as the result. Row 3 is equal to 2 * 3.  This is passed up to row 2.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: left;&quot;&gt;Row 2&#039;s result is 3 * 2 * 1, and this is passed right back up to the first row.  &lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: left;&quot;&gt;You can see this in the result column, results of each function call are passed back up the recursive chain to the original function call, and it is here that we can fully evaluate the result.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Clear as mud? Good!  However if you are still struggling, at this point we recommend you download the accompanying example file for this article. You&#039;ll find a link at the bottom of the page. The example file includes a step by step guide to following the recursive function along with illustrations. You can also look at the function yourself in the unlocked file, to get a feel for how it works.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;   &lt;/p&gt;
&lt;h3 class=&quot;p1&quot;&gt;Let&#039;s take this further using variables&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;As we have seen, one of the most common ways in which recursion is done, is to process a value at each iteration, and then pass a modified version of the parameter to the subsequent recursive call. This is normally done by removing elements from a list, or maintaining a counter parameter which is incremented with each subsequent call so that each recursive step knows what position in a list it is processing.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Modification of lists such as chopping off values, or obtaining left/right values, can be quite an expensive and time consuming operation when done hundreds of times. Ideally we want to keep any parameter we use in an unmodified state and reference positions within it using a counter, it&#039;s a much more efficient way to process.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;But what if we don&#039;t want to pass counters as parameters, can we do this? Can we use a local variable as a counter? Furthermore how far can we take the usage of local variables to improve readability and simplicity of the function? Turns out we can take it quite far.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;  &lt;/p&gt;
&lt;h3 class=&quot;p1&quot;&gt;The key - variables persist from one recursive call to the next&lt;/h3&gt;
&lt;p&gt;That&#039;s right. You can define a local variable in one recursive call, and the value of that will be accessible to all subsequent recursive calls. This makes them very handy for transferring of information from one call to the next without using function parameters.  Think of them as storage lots that you can place information in to refer to throughout the function.&lt;/p&gt;
&lt;p&gt;Now we are going to utilise this fact to show an alternative way to write a more complex function.&lt;/p&gt;
&lt;p&gt;It is important to also note however that sometimes the method we&#039;ll show is not the best method. Often if recursion is simple enough, then just go with the simplest way to write it. Using variables is a good technique to improve readability for other developers, and can improve performance through minimal list manipulation functions, but go with what works best for you.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Example: _RemoveValues function&lt;/h3&gt;
&lt;p&gt;(Note you can find all examples from this article in the example file, linked to at the bottom).&lt;/p&gt;
&lt;p&gt;Time to take things up a notch. This function is defined as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;_RemoveValues ( _listA ; _listB )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It will take 2 return delimited lists as its parameters. The function is to return all values in _listA which &lt;strong&gt;do not exist&lt;/strong&gt; in _listB.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Variable-Recursion/VariableRecursion-4.png&quot; alt=&quot;VariableRecursion 4&quot; width=&quot;624&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;The way in which the function is written above is a pretty typical style that you might find in a lot of recursive functions.  It begins with the exit condition which is when the first list is empty.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;If there are values in _listA to process, it checks if the first value in that list is present in _listB. If so, it keeps it, otherwise it discards it. It does this by either getting the 1st left value from _listA, or the 0th value of _listA (in other words nothing).&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;To that value, it appends the result of the recursive call, however the parameter to this call is _listA without the left-most value present (as we just processed that one).&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;You&#039;ll note we are using 2 rather costly functions here - LeftValues and RightValues. These are inefficient function calls when dealing with larger lists.   Consider a _listA with a thousand items. We will be doing a thousand recursive calls, however each time we do that recursion we are running the RightValues function to strip out the left-most value, that&#039;s a lot of calls !&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Now let&#039;s look at it rewritten with variables&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Here is our alternative approach to writing the same function but this time using local variables and a standardised approach to the functional structure: &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Variable-Recursion/VariableRecursion-5.png&quot; alt=&quot;VariableRecursion 5&quot; width=&quot;715&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;There&#039;s quite a lot going on here to talk about. First thing to note is yes there are more lines of code here even without comments included. While there are more lines of code, it actually makes for a more readable function overall, as well as helping to better lay out a  more simplified approach to thinking about recursion. This approach is more like a scripted loop, where you do not need to think as much about the complex nature of recursive calls.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Structurally the function follows this standard layout:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;A counter is defined, as well as an exit counter value.&lt;/li&gt;
&lt;li&gt;Use however many variables (both local or within a Let statement) you require to be clear and readable.&lt;/li&gt;
&lt;li&gt;Use a local variable to maintain your final result value.&lt;/li&gt;
&lt;li&gt;Define your exit condition. When evaluated to true, clear all used local variables, and return your result value.&lt;/li&gt;
&lt;li&gt;If exit condition is not met, simply call the function again with the exact same parameters.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;One of the key differences here between this and a standard method of recursion is that we don&#039;t bother updating passed parameters to the recursive call. They can remain exactly the same -  no modification to them is required. We also do not require a counter parameter - this is maintained through a local variable.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;A note about the exit condition and variables&lt;/h3&gt;
&lt;p&gt;Upon reaching your exit condition, it is highly recommended that you clear all your local variables. This is because if you do not do so, their values will persist in the data viewer after the function finishes. This state is known as the 0 script state, and is a state where local variables can exist if defined outside the scope of a script - such as here in the function. In the interests of tidiness clear them when you&#039;re done. One of the reasons why we prefix all of our variables with an underscore when defined in a function is so that we know they were defined from a function. Normal script variables if defined should not be defined with the underscore. This is another way to ensure there is no conflict between variables defined in a function that may not be cleared, and those that get defined in a script.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Defining a counter and exit value&lt;/h3&gt;
&lt;p&gt;The first step in our function is to establish a counter, and an exit value.  The counter will be incremented each time the function is called in order to track our position in the recursion. The exit counter value tells us when to stop processing. Usually we know when this will be before we begin because it usually corresponds with the size of a list we are processing.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Variable-Recursion/VariableRecursion-6.png&quot; alt=&quot;VariableRecursion 6&quot; width=&quot;507&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;You&#039;ll note the first check is whether we have a counter value at all - this will ensure that the very first time the function is called we set an initial counter value of 1.  After that, each subsequent recursive call will see a value in our counter, and so increment it instead of initialising it.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;The same goes for our exit variable. On first call it will be empty so we set it to the size of our listA. Subsequent calls we do not modify it. This only needs to be set once.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt; &lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;Defining processing variables&lt;/h3&gt;
&lt;p&gt;Processing variables help us store values that will be carried from one recursive call to the next. For these we use local variables. If we require variables that need not be transferred from one call to the next, we instead use Let statement variables, whose scope is only that of the current function call.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Variable-Recursion/VariableRecursion-7.png&quot; alt=&quot;VariableRecursion 7&quot; width=&quot;574&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p&gt;In our example each successive function call will work with a specific value in our list. We use our counter to tell what value that is, and we use GetValue to obtain it. GetValue is a far more efficient function call than Left/RightValues.&lt;/p&gt;
&lt;p&gt;We do our check to see whether our value is in ListB or not, in the same way we did in our earlier function definition.&lt;/p&gt;
&lt;p&gt;Finally, we have a result variable - $_return - which we will store what our end result will be. This value persists from one function call to the next.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;The exit condition&lt;/h3&gt;
&lt;p&gt;Here is our exit condition:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Variable-Recursion/VariableRecursion-8.png&quot; alt=&quot;VariableRecursion 8&quot; width=&quot;625&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;The exit condition is almost always the same - it&#039;s when our counter reaches our exit value. At this point in time we need to do a couple of things:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Clear the local values we defined&lt;/li&gt;
&lt;li&gt;Store our return value in a Let variable&lt;/li&gt;
&lt;li&gt;Clear our return variable&lt;/li&gt;
&lt;li&gt;Return the result&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Steps 2 and 3 are a bit of a quirk. Our result is stored in a local variable, but we cannot clear this variable before we return it as a result. To work around this, we store it in a Let variable and return that instead. the Let variable is automatically cleared when the function ends.  Using the Let function allows us to clear all used variables used in a nice concise manner.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;And finally, the recursive call&lt;/h3&gt;
&lt;p&gt;In our recursive function definition, the actual act of recursion is reduced to somewhat of an afterthought. We don&#039;t need to think about it, or worry about what we pass it. We just call it.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Variable-Recursion/VariableRecursion-9.png&quot; alt=&quot;VariableRecursion 9&quot; width=&quot;356&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Pros and Cons of this method&lt;/h3&gt;
&lt;p&gt;As mentioned earlier, this is an alternative approach to writing a recursive custom function but not to be considered the correct way. There is nothing wrong with writing it however you wish. There are pros and cons with using this method. Some pros are:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Improved readability - useful if other developers must interpret your code&lt;/li&gt;
&lt;li&gt;Simplicity through closely resembling a scripted loop&lt;/li&gt;
&lt;li&gt;No need to modify parameters passed through each subsequent call&lt;/li&gt;
&lt;li&gt;No need for state-tracking parameters such as counters (done in variables)&lt;/li&gt;
&lt;li&gt;Easy to follow.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Some cons however are:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;You need to clear variables when done&lt;/li&gt;
&lt;li&gt;There is a risk variables could interfere with other processes if not cleared&lt;/li&gt;
&lt;li&gt;No guarantee this is a supported FileMaker feature, no guarantee it won&#039;t be deprecated in future.&lt;/li&gt;
&lt;li&gt;Perhaps performance hit through act of using local variables as opposed to purely Let statement? Unsure.&lt;/li&gt;
&lt;li&gt;May not play nice if your recursive function calls itself multiple times within each call (e.g. some sorting functions).&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The choice is yours. If this works for you then by all means embrace it and use it. We certainly have. But not all functions are the same and some other approaches to writing them may work better for you. Our aim here is that this method is clear to read and follow and might help developers feel less anxious about writing complex recursive custom functions.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Example file!&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;As with all of our articles we produce we like to provide a detailed example file to go along with it. It’s not enough to just read how something is done, you should be able to see it in action and explore how it works yourself. Please find attached the example file below.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;Variable Recursion sample file&quot; href=&quot;https://www.teamdf.com/assets/blog-images/Variable-Recursion/VariableRecursion.zip&quot; target=&quot;_blank&quot;&gt;Click to download example file!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/[sitetree_link,id=]&quot; target=&quot;_blank&quot;&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Fri, 22 Mar 2019 07:22:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/a-variable-way-of-writing-recursion/</guid>
		</item>
		
		<item>
			<title>Easily View Microsoft Office Files in FileMaker</title>
			<link>https://www.teamdf.com/blogs/easily-view-microsoft-office-files-in-filemaker/</link>
			<description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;When it comes to viewing Microsoft Office files within FileMaker, this has always been quite a sore point for developers. Unlike images, video files, audio files, and PDF files, we cannot directly view these file formats within container fields.  Developers tend to resort to exporting the files to disk and auto-opening them locally on the users machine. This however requires that the user have a copy of Microsoft Word, Office, or PowerPoint installed in order to view the file they wish to see. This is not always the case.&lt;/p&gt;
&lt;p&gt;In this article we&#039;re going to show how you can add Excel, Word or PowerPoint document viewing to any existing FileMaker solution in about 10 minutes, the setup couldn&#039;t be simpler!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Viewing Files Online - Using the Office App Viewer&lt;/h3&gt;
&lt;p&gt;Microsoft has a range of apps within its office 365 offering. Examples like Word, Excel, Powerpoint are so commonplace in industry today that almost everyone at some stage needs to view a doc file, or open a spreadsheet in Excel. Microsoft also makes these apps available online in the cloud via their 365 service. Users can keep their documents online in their MS OneDrive, and use online tools to view documents entirely within the browser.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/office-viewer/OfficeViewer-1.png&quot; alt=&quot;OfficeViewer 1&quot; width=&quot;660&quot;&gt;&lt;/p&gt;
&lt;p&gt;But did you know that they also have an online file viewer, which is freely available for anyone to use, no account required? This will render any Word, Excel or PowerPoint presentation providing that file is hosted online and the URL is accessible to the file viewer tool.&lt;/p&gt;
&lt;p&gt;Using this fact we can utilise the viewer in order to view documents stored directly in our own solutions. We just need to get the file online so that the viewer can render it for us. No more viewing of a document in FileMaker and just seeing this:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/office-viewer/_resampled/ResizedImage31084-OfficeViewer-2.png&quot; alt=&quot;OfficeViewer 2&quot; width=&quot;310&quot; height=&quot;84&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Getting your files online&lt;/h3&gt;
&lt;p&gt;The first obstacle to overcome is getting your container data online so that the office viewer can render it.  Now there are obviously numerous ways you can do this, such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Host via third party service (which we will do)&lt;/li&gt;
&lt;li&gt;Use your own web hosting server (good as you can secure it and control access to just the viewer)&lt;/li&gt;
&lt;li&gt;Hack around with Apache/IIS to directly host externally stored container data - yes it can be done though not recommended!&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;For this example we&#039;re going to use a really simple online file hosting service called &lt;a href=&quot;https://file.io&quot; target=&quot;_blank&quot;&gt;file.io&lt;/a&gt;. The goal here is to upload container fields to this service, and use the resulting hosted URL to pass to the office viewer for display.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;File.io - Pros and Cons&lt;/h3&gt;
&lt;p&gt;File.io is a great little service for hosting files. One of its key benefits is that it is a &lt;strong&gt;single-view only&lt;/strong&gt; service. When a file is hosted there, the URL is only valid to be viewed once only. After that single viewing occurs the file is deleted and the URL is removed. This is perfect for our use because we don&#039;t want that file to hang around on a server somewhere, nor do we require the URL after we view it.&lt;/p&gt;
&lt;p&gt;While that all sounds good, you have to be very careful when dealing with any third party service especially when they will be hosting your files. You may have sensitive information in your files you do not wish to put in the public domain. While secure, the files will still reside temporarily on someone else&#039;s server, and while the URL is a one-time view, you can never fully trust that.&lt;/p&gt;
&lt;p&gt;We are using this service for the demo but you should consider a more secure method of hosting your container data online if you intend to use this service. A good method would be to host them on your own server, and only allow the office viewer URL access.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Uploading files to File.io using Insert from URL&lt;/h3&gt;
&lt;p&gt;The file.io api is really simple, no keys are required, it&#039;s a simple CURL post of your file to their server, and in return you are given some simple JSON. Included in that result is the URL to your file.&lt;/p&gt;
&lt;p&gt;You can find this script in the example file included at the bottom of this article. It is recommended you download it and have a look through as you read.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/office-viewer/OfficeViewer-3.png&quot; alt=&quot;OfficeViewer 3&quot; width=&quot;660&quot;&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Here&#039;s the code above. What we do is first put the container data into a variable $file. This makes the subsequent steps a bit easier and clearer.&lt;/p&gt;
&lt;p&gt;Next, We calculate a local variable name, which we store in $VariableName. Why do we do this? Well this comes down to how posting of a file works using CURL, in conjunction with what the file.io api is expecting us to give them. This will be more apparent in the next step:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Evaluate ( &quot;Let ( &quot; &amp;amp; $VariableName &amp;amp; &quot; = $file ; 1 ) &quot; )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We are evaluating a calculation string here where we are setting our variable to the file contents that is stored in $file.  As an example if our file name was &quot;test_file.doc&quot; , then the name of the variable we are setting would be $test_file.doc , and the value of this would be that of the file itself.  We use a LET statement to do this as it allows us the ability to soft-code the variable name without having to explicitly define it.&lt;/p&gt;
&lt;p&gt;Why must we do this? Because in the following POST to file.io, we send the file using the &quot;-F&quot; command:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/office-viewer/OfficeViewer-4.png&quot; alt=&quot;OfficeViewer 4&quot; width=&quot;660&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;When we use a FileMaker variable in a CURL request, the name of the variable is important. File.io is using the variable name as the name of the file itself, and FileMaker in turn is passing the actual content of that variable to file.io - the file itself.  If we were to use some other variable name e.g. &quot;test&quot; then the resulting file uploaded would be called &quot;test&quot;.  The Microsoft office viewer would not recognise this as a valid file format and so fail to display it.  This is why variable name is important to be given the same name as the actual file we want to view.&lt;/p&gt;
&lt;p&gt;Once our request is posted off to file.io, we simply parse out the &quot;link&quot; key value from the JSON response.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/office-viewer/OfficeViewer-5.png&quot; alt=&quot;OfficeViewer 5&quot; width=&quot;484&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Rendering in a web viewer&lt;/h3&gt;
&lt;p&gt;Once we have the URL to our file, the rest is easy. The office viewer simply follows a simple url format which accepts the files URL as a parameter: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p class=&quot;p1&quot;&gt;http://view.officeapps.live.com/op/view.aspx?src=[OFFICE_FILE_URL]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p class=&quot;p1&quot;&gt;We just replace [OFFICE_FILE_URL] with the one returned from file.io. We then display this in a web viewer.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;h3 class=&quot;p1&quot;&gt;How does it look - Word&lt;/h3&gt;
&lt;p&gt;This is what the viewer looks like for our 3 main file formats. Firstly a Word document:&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/office-viewer/OfficeViewer-6.png&quot; alt=&quot;OfficeViewer 6&quot; width=&quot;660&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Not too shabby! The document is strictly read-only so no editing is allowed. Some of the options listed in the toolbar and menus are not available but others are, things that work include:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Accessibility Mode - a nicer full screen experience&lt;/li&gt;
&lt;li&gt;Save to Onedrive (provides a sign in option) not fully tested!&lt;/li&gt;
&lt;li&gt;Print&lt;/li&gt;
&lt;li&gt;Search within document&lt;/li&gt;
&lt;li&gt;View document comments&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;There are buttons to &quot;Download&quot; and &quot;Download as PDF&quot; but these do not seem to work in the web viewer. However, the Print option does. The print option should open a new tab in your browser (so outside of FileMaker) and give you a PDF version that is printable. From here you can print or save as PDF.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3 class=&quot;p1&quot;&gt;How does it look - Excel&lt;/h3&gt;
&lt;p&gt;Here is a simple Excel spreadsheet:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/office-viewer/OfficeViewer-7.png&quot; alt=&quot;OfficeViewer 7&quot; width=&quot;660&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Again, pretty good all things considered. Once again read only, but you can clearly see cells/columns and it looks very much like excel. Again options you can make use of include:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Viewing multiple sheets within the file&lt;/li&gt;
&lt;li&gt;Summing/counting columns - totals are shown in bottom toolbar&lt;/li&gt;
&lt;li&gt;Save to oneDrive&lt;/li&gt;
&lt;li&gt;Print - opens in browser as PDF&lt;/li&gt;
&lt;li&gt;Find within sheet&lt;/li&gt;
&lt;li&gt;View comments&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Same again as the document, download buttons don&#039;t work.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;How does it look - PowerPoint&lt;/h3&gt;
&lt;p&gt;Lastly we have a PowerPoint presentation:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/office-viewer/OfficeViewer-8.png&quot; alt=&quot;OfficeViewer 8&quot; width=&quot;660&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Features include:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Navigate through slides&lt;/li&gt;
&lt;li&gt;Toggle reading / slideshow view&lt;/li&gt;
&lt;li&gt;View associated slide notes&lt;/li&gt;
&lt;li&gt;Start slide show (opens in browser, slide show includes animations)&lt;/li&gt;
&lt;li&gt;Save to oneDrive&lt;/li&gt;
&lt;li&gt;Print to PDF (via browser)&lt;/li&gt;
&lt;li&gt;View slideshow comments&lt;/li&gt;
&lt;li&gt;Accessibility mode&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;What about Google?&lt;/h3&gt;
&lt;p&gt;Google has its own similar offering based on its Google Docs service. Again it works in the same way office viewer does - it&#039;s just a URL that accepts another file URL to render.&lt;/p&gt;
&lt;p&gt;Google actually has quite a bit of benefit over Microsoft when it comes to viewing other file types. Google offers a far wider range of file types to preview. This is really handy for some industries such as graphic design, because Google allows viewing of things like Adobe Illustrator, CAD, and other graphical formats.  Google also allows preview of CSS, JavaScript and HTML files which would come in handy for some.&lt;/p&gt;
&lt;p&gt;There is however a big drawback to Google, and why we haven&#039;t sung its praises in this article to this point.  Unfortunately it doesn&#039;t work very well with our file.io service we are using.&lt;/p&gt;
&lt;p&gt;When Google Docs is rendering a file URL, it must be accessing that URL more than once. File.io only allows access one time, and so Google Docs fails to render most file formats for this reason. Now, this is purely a limitation of file.io so if you host files using any other method you are likely to be able to use Google perfectly fine, in which case this may be the better option for you.&lt;/p&gt;
&lt;p&gt;Google renders its previews as a PDF in almost all instances (exception being audio/video)..&lt;/p&gt;
&lt;p&gt;As of writing this article it would appear only the Word Document format reliably works with file.io and so that has been included in the Demo.&lt;/p&gt;
&lt;p&gt;File formats that Google accepts includes the following:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Image files (.JPEG, .PNG, .GIF, .TIFF, .BMP)&lt;/li&gt;
&lt;li&gt;Video files (WebM, .MPEG4, .3GPP, .MOV, .AVI, .MPEGPS, .WMV, .FLV)&lt;/li&gt;
&lt;li&gt;Text files (.TXT)&lt;/li&gt;
&lt;li&gt;Markup/Code (.CSS, .HTML, .PHP, .C, .CPP, .H, .HPP, .JS)&lt;/li&gt;
&lt;li&gt;Microsoft Word (.DOC and .DOCX)&lt;/li&gt;
&lt;li&gt;Microsoft Excel (.XLS and .XLSX)&lt;/li&gt;
&lt;li&gt;Microsoft PowerPoint (.PPT and .PPTX)&lt;/li&gt;
&lt;li&gt;Adobe Portable Document Format (.PDF)&lt;/li&gt;
&lt;li&gt;Apple Pages (.PAGES)&lt;/li&gt;
&lt;li&gt;Adobe Illustrator (.AI)&lt;/li&gt;
&lt;li&gt;Adobe Photoshop (.PSD)&lt;/li&gt;
&lt;li&gt;Tagged Image File Format (.TIFF)&lt;/li&gt;
&lt;li&gt;Autodesk AutoCad (.DXF)&lt;/li&gt;
&lt;li&gt;Scalable Vector Graphics (.SVG)&lt;/li&gt;
&lt;li&gt;PostScript (.EPS, .PS)&lt;/li&gt;
&lt;li&gt;TrueType (.TTF)&lt;/li&gt;
&lt;li&gt;XML Paper Specification (.XPS)&lt;/li&gt;
&lt;li&gt;Archive file types (.ZIP and .RAR)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;So in Summary..&lt;/h3&gt;
&lt;p&gt;We&#039;ve shown a really quick and easy way to view office based files from FileMaker. We have however shown you must think carefully about how you use this because both google and Microsoft require a publicly available URL that it can access in order to render the file, so think long and hard about how you handle this requirement.&lt;/p&gt;
&lt;p&gt;Good luck!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Inspiration for this Article&lt;/h3&gt;
&lt;p&gt;While searching for a way to view spreadsheets in FileMaker for a client, it was this following site I came across which gave the answer:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/tzmartin/1cf85dc3d975f94cfddc04bc0dd399be&quot; target=&quot;_blank&quot;&gt;https://gist.github.com/tzmartin/1cf85dc3d975f94cfddc04bc0dd399be&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/tzmartin/1cf85dc3d975f94cfddc04bc0dd399be&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;Many thanks to that sites publisher &lt;a href=&quot;http://twitter.com/tzmartin&quot; target=&quot;_blank&quot;&gt;tzmartin&lt;/a&gt; for providing this invaluable information.  You will also find on his site information about how you can do this within an iframe, and how you can use both Google and Microsoft to view files stored directly on their respective cloud offerings - Google Docs, and OneDrive.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;As with all of our articles we produce we like to provide a detailed example file to go along with it. It’s not enough to just read how something is done, you should be able to see it in action and explore how it works yourself. Please find attached the example file below. This article is based on the example file. As always, this is a free download, and we won&#039;t make you sign up to download :)&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/office-viewer/OfficeViewer.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Thu, 28 Feb 2019 10:22:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/easily-view-microsoft-office-files-in-filemaker/</guid>
		</item>
		
		<item>
			<title>DIY: Tempting Templates</title>
			<link>https://www.teamdf.com/blogs/diy-tempting-templates/</link>
			<description>&lt;p&gt;If you want to build your own app for your business, then FileMaker is just the platform: powerful, yet accessible enough for those focussed on solving problems, especially if you have a bent for code. But where do you begin?&lt;/p&gt;
&lt;p&gt;In this article Stu takes a look at the latest template files from FileMaker Inc., files that get you up and running with a basic working solution, but they&#039;re open for you to then add-on and customise:&lt;/p&gt;
&lt;h2&gt;New And Improved&lt;/h2&gt;
&lt;p&gt;FileMaker have just released a series of three new templates that allow users the ability to have a &lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m h-rsquo&quot;&gt;starting point in terms of a featured solution.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We think these are a great idea, and are a real step up on what was on offer in the former starter solutions. They meet some really core needs for some organisations/businesses and for quite a number, may well be all they need.&lt;/p&gt;
&lt;p&gt;The three templates are:&lt;/p&gt;
&lt;ul class=&quot;listtype-bullet listindent1 list-bullet1&quot;&gt;&lt;li&gt;
&lt;p&gt;Memberships&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Job Tracking&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Event Management&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;In each case, an organisation could pick up on these and use them to manage their member base, job management and events respectively. The basic requirements are covered and all you need are some FileMaker licenses, somewhere to host the database, and you&#039;re away.&lt;/p&gt;
&lt;p&gt;What makes us happy, as professional developers, is that it gives those of you taking the DIY approach a sound starting point, so that if you come to us for help or to pick up where you&#039;ve left off, the foundations are both standardised and well structured! &lt;/p&gt;
&lt;p&gt;These templates allow you to get a clean, basic app in place, and then build in the features unique to your organisation, industry or way of doing things. There are also a bunch of ready made add-ons, tutorials and guides accessible from the FileMaker site to help you along the way — &lt;a title=&quot;FileMaker Inc web site templates page&quot; href=&quot;https://www.filemaker.com/templates/&quot; target=&quot;_blank&quot;&gt;www.filemaker.com/templates&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And of course we&#039;re very happy to help with guidance, one-on-one tuition, or to pick up where you leave off to carry on development. &lt;/p&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;p&gt;Looking a little more in-depth at each of the templates:&lt;/p&gt;
&lt;h3&gt;&lt;span class=&quot;ace-all-bold-hthree&quot;&gt;Memberships&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;This one is ideally suited to the organisation that needs to manage a membership base along with campaigns/donations.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/tempting-templates/_resampled/ResizedImage600436-memberships-home.png&quot; alt=&quot;memberships home&quot; width=&quot;600&quot; height=&quot;436&quot;&gt;&lt;/p&gt;
&lt;p&gt;The core features are:&lt;/p&gt;
&lt;ul class=&quot;listtype-bullet listindent1 list-bullet1&quot;&gt;&lt;li&gt;
&lt;p&gt;Member details including name, address, contact details, whether they are active or inactive, along with your interactions with them&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Building a campaign and tracking the donations against a target&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Viewing and exporting all campaign and donation data&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This is a great entry level way to manage a membership, but we can already see that you would want to hook this into a website &lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m h-lparen&quot;&gt;(so donations can be taken online), more reporting features, user management etc.&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;&lt;span class=&quot;ace-all-bold-hthree&quot;&gt;Job Tracking&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;Like the membership template this one includes all the things you need to track jobs, all within a single well build database.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/tempting-templates/_resampled/ResizedImage600436-job-tracking-home.png&quot; alt=&quot;job tracking home&quot; width=&quot;600&quot; height=&quot;436&quot;&gt;&lt;/p&gt;
&lt;p&gt;The core features are:&lt;/p&gt;
&lt;ul class=&quot;listtype-bullet listindent1 list-bullet1&quot;&gt;&lt;li&gt;
&lt;p&gt;A basic CRM to allow you to list all staff and clients&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The ability to setup a job, which in this template they are based on a building/construction business&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Setup jobs and tasks and assign staff to each&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Have staff track their time entries and mark whether they are billable or non billable&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;View all time logged against a job or task&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/tempting-templates/_resampled/ResizedImage600513-job-tracking-detail.png&quot; alt=&quot;job tracking detail&quot; width=&quot;600&quot; height=&quot;513&quot;&gt;&lt;/p&gt;
&lt;p&gt;With job tracking being one of the primary types of solution we build for clients, we know this template will be popular. It&#039;ll probably get you to a point where you want a lot more, such as an iOS app &lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m h-lparen&quot;&gt;(using FileMaker Go) to allow staff to track their work while out on the road or worksite, more reporting,  the ability to record material costings, and so forth, which would all make this a more fully featured application.&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;&lt;span class=&quot;ace-all-bold-hthree&quot;&gt;Event Management&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Managing an event from start to finish is a huge job, and all to often done via a stack of spreadsheets. Having an orderly way to manage an event will take away a big headache and allow you to focus on the more important tasks at hand.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/tempting-templates/_resampled/ResizedImage600436-events-home.png&quot; alt=&quot;events home&quot; width=&quot;600&quot; height=&quot;436&quot;&gt;&lt;/p&gt;
&lt;p&gt;The core features are:&lt;/p&gt;
&lt;ul class=&quot;listtype-bullet listindent1 list-bullet1&quot;&gt;&lt;li&gt;
&lt;p&gt;Add an event including the the date and location&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add sessions, with date and start/finish times&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Manage all attendees to the event&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a registration list that can be exported as a PDF&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Once again this template is a great start, and the features included may be all that is required for an organisation to run an event. Taking it the next step further, you could add web integration so attendees could view and book sessions. You may also have different sessions at different locations, have a limit on how many people can attend any session, have the ability to manage payments &lt;span class=&quot; author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qovvlz122zoz74zz67zcb2z74zz85zz80zz79zcz65zez66z8z71z2nhqok1z90zz71zg6m h-lparen&quot;&gt;(if it’s a paid event).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As you can see by the above, these templates are a good starting point and they may meet all the needs of some organisations. Or it might be that you want to further develop them yourself, in which case FileMaker have given guidance on how these can be extended further.&lt;/p&gt;
&lt;p&gt;So we say give them a try, see what you think (you can use the FileMaker trial license to start with), if you need a hand down the track do &lt;a title=&quot;Contact Us page&quot; href=&quot;https://www.teamdf.com/contact-us/&quot; target=&quot;_blank&quot;&gt;reach out to us&lt;/a&gt;, we would love to discuss your requirements.&lt;/p&gt;</description>
			<pubDate>Thu, 07 Feb 2019 12:04:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/diy-tempting-templates/</guid>
		</item>
		
		<item>
			<title>Scheduling With DayBack</title>
			<link>https://www.teamdf.com/blogs/scheduly-scheduling/</link>
			<description>&lt;p&gt;Scheduling is one of those perennial problems that businesses face when allocating jobs and resources. It’s deceptively simple to do on paper or a whiteboard when you have just a few people or resources to organise…&lt;/p&gt;
&lt;p&gt;But ramp that up to say 40 technicians across multiple locations and two countries, and you have a much trickier challenge. Handling jobs and resources is the sort of thing that&#039;s ideal for FileMaker, but it needs a calendar-style interface. A calendar is a great way to visualise what’s going on and makes interaction easy because you can drag jobs to allocate them.&lt;/p&gt;
&lt;h2&gt;Boom! A Calendar&lt;/h2&gt;
&lt;p&gt;You can’t do that sort of complex dynamic user interface with FileMaker alone so implementing a calendar as an add-on is the only way to do it. While we have a great resource calendar with our &lt;a title=&quot;Reactor plugin website&quot; href=&quot;https://fusionreactor.com&quot; target=&quot;_blank&quot;&gt;Reactor plugin&lt;/a&gt;, we decided to use the DayBack calendar from &lt;a title=&quot;Seedcode website&quot; href=&quot;http://seedcode.com&quot; target=&quot;_blank&quot;&gt;Seedcode&lt;/a&gt; for this project because it has a few key features that fit this project better.&lt;/p&gt;
&lt;p&gt;Like our calendar, DayBack is essentially a web page, embedded into the FileMaker layout within a web viewer. In saying that, the web page doesn’t come from a remote web server, but is generated directly within FileMaker on the user’s machine.&lt;/p&gt;
&lt;p&gt;Integrating such complex controls with FileMaker via the web viewer is a powerful and very smooth way of bringing in extra functionality and it feels like it’s just a normal part of the screen — below you can see the calendar and native FileMaker fields together on the one screen:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/scheduling/_resampled/ResizedImage600436-technician-scheduling.png&quot; alt=&quot;technician scheduling&quot; width=&quot;600&quot; height=&quot;436&quot;&gt;&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;Tailor Made&lt;/h2&gt;
&lt;p&gt;We needed to be able to schedule technicians to jobs in various locations, and convey that information to them individually, while maintaining a single centralised overview in the job database app.&lt;/p&gt;
&lt;p&gt;To do that the scheduling screen allows administrators and managers to tailor the view to groups of technicians, jobs, and days. You can choose which techs to show and which days you need to see, and if you choose to view more than fits on screen you can page through the technicians with forward and back arrows. This means each branch can focus on their own techs or subgroups of techs as need be.&lt;/p&gt;
&lt;p&gt;On the calendar there’s a special column labelled “none”, where jobs sit until they are allocated: simply drag a job from the “none” column onto a technician to assign the work.&lt;/p&gt;
&lt;p&gt;Technicians have differing background colours indicating the type of equipment they have, which affects the type of jobs they can be assigned — that feedback guides the user and avoids frustration… and having the overview of a group of techs at once means you can see at a glance what you’ve got to work with and who’s available.&lt;/p&gt;
&lt;p&gt;Speaking of availability, the scheduler also shows when people are unavailable because of leave or travel periods. Another nice feature is that some jobs require overnight stays, so the calendar is also used as a way to record that information which means that each technican can easily find their accommdation details when needed.&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;Integration With Google Calendars&lt;/h2&gt;
&lt;p&gt;Behind the scenes the scheduling calendar is integrated with the Google Calendar API so that each technician can have their own personal Google Calendar where their appointments are shown, including job notes and accommodation details for those overnight stays. This also means they can tailor the calendar behaviour such as colours, views and notifications to suit how they work.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/scheduling/_resampled/ResizedImage600527-google-calendar-view.png&quot; alt=&quot;google calendar view&quot; width=&quot;600&quot; height=&quot;527&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Tue, 22 Jan 2019 17:54:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/scheduly-scheduling/</guid>
		</item>
		
		<item>
			<title>Modal Magic</title>
			<link>https://www.teamdf.com/blogs/modal-magic/</link>
			<description>&lt;h2&gt;Introduction to Modal Dialogs&lt;/h2&gt;
&lt;p&gt;What is a &quot;modal dialog&quot;? When we talk about dialogs we’re actually talking about windows in the FileMaker sense. They could be a card window, or they could be a regular dialog window, or even a floating window or FileMakers own modal window style. Modal refers to a window state where the window cannot be dismissed without the user explicitly making a decision that will lead to the closing of that window.&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;Example File&lt;/h2&gt;
&lt;p&gt;Rather than wait til the end to check out the demo, we strongly recommend you download and explore the example file as you read. This will help you follow along with the content of the article and help you to understand what we are talking about. The demo file contains a lot of examples and information relevant to the remainder of the article, and you’ll find it easier to follow along the article with the demo file open so that you can explore as you read.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;Modal Magic Demo file&quot; href=&quot;https://www.teamdf.com/assets/blog-images/modal-magic/ModalMagic.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;FileMaker&#039;s “Card” Window&lt;/h2&gt;
&lt;p&gt;A simple modal dialog just opens and sits there forcing the user to do something. No scripts are running, and it’s up to the user to click a button or do something that has been scripted to carry out an action and close the window. The user is unable to move to any other window in the solution before dealing with the modal dialog. Think of a card window that opens showing the user some preferences. The user can do things on that layout, but has been given a close button to dismiss it. The card window is modal in a sense that the user cannot interact with the underlying parent window. Card windows are modal to the parent window only.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/modal-magic/window-style-1.png&quot; alt=&quot;window style 1&quot; width=&quot;457&quot; height=&quot;79&quot;&gt;&lt;/p&gt;
&lt;h2&gt;FileMaker&#039;s “Dialog” Modal Window&lt;/h2&gt;
&lt;p&gt;Other modal dialogs such as FileMakers “Dialog” window option, are more modal to the entire solution. When a dialog window is created, the user cannot move to any other window in the solution while the dialog window is open. FileMaker Dialogs are useful but they do suffer from a couple of drawbacks which we don’t like.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/modal-magic/window-style-2.png&quot; alt=&quot;window style 2&quot; width=&quot;471&quot; height=&quot;79&quot;&gt;&lt;/p&gt;
&lt;p&gt;Firstly, any script that you execute from within a FileMaker dialog window must reside within the current file. You are unable to run a script in an external file. In some solutions this is a deal breaker. You are also unable to spawn any other temporary windows for the purposes of carrying out actions in a script, you literally are locked into a single window.&lt;/p&gt;
&lt;p&gt;It is for these reasons we never use FileMakers dialog window option.&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;Different Uses of Modal Dialogs&lt;/h2&gt;
&lt;p&gt;We’ve touched upon a couple of uses of modal dialogs already. One may be used simply to have the user locked into a window, such as editing critical preferences. You would not wish for these to accidentally be left open in a window on-screen. By making it modal, the user must close in order to continue using the solution.&lt;/p&gt;
&lt;p&gt;Another typical use to replace FileMakers custom dialog script step in favour of a more appealing dialog built using a layout. A script is run and a modal dialog window is opened showing the user a nice dialog in which they have to make a decision. Based upon the decision they make, a different process is performed.&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;Script Execution and Modal Dialogs&lt;/h2&gt;
&lt;p&gt;This last use raises an interesting question. If we are using modal dialogs in scripts, such as replacing a custom dialog, then surely the user decision in that script should be then used in the remainder of the script that initiated it?&lt;/p&gt;
&lt;p&gt;To show what we mean, lets look at a diagram:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/modal-magic/_resampled/ResizedImage60064-script-flow-diagram-1.png&quot; alt=&quot;script flow diagram 1&quot; width=&quot;600&quot; height=&quot;64&quot;&gt;&lt;/p&gt;
&lt;p&gt;We have a script that is run, and that script at some point in its execution requires a user input to be made. To do this it opens a new modal dialog. This could be either a card window or a dialog window. The user makes a decision, which the script then continues execution with.&lt;/p&gt;
&lt;p&gt;But wait, something is not quite right here? If the script opens a new window waiting for the user to do something, what happens to the execution of the script?&lt;/p&gt;
&lt;p&gt;There are 2 possible scenarios here. The first is that upon opening the modal window the script ceases execution, leaving the user on the modal window. The user might then do some input, or click a button. The script that they execute in the window might be responsible for continuing the execution of the original script.&lt;/p&gt;
&lt;p&gt;Another scenario is that the initial script upon opening the modal window enters a paused state. The script is still running but stuck until resumed. Upon the user making a decision in the modal window, the script is resumed and can continue execution.&lt;/p&gt;
&lt;p&gt;It is this second method that we prefer, and love to develop with. There are a number of reasons why we prefer this method which we’ll cover next.&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;But first, lets talk about reusability&lt;/h2&gt;
&lt;p&gt;Reusability of modal dialogs is an absolutely critical concept we need to talk about, and it is where modal dialogs become really powerful. Think of a modal dialog as a function. You call a function, you pass it some information and then the function does some calculations and returns a result.&lt;/p&gt;
&lt;p&gt;Modal dialogs can be the same. You initiate a modal dialog. The user does some stuff in the dialog, and the dialog returns a result. Through designing modal dialogs in this fashion, you can build a dialog that can be reused multiple times your solution. The dialog becomes something you invoke whenever required to obtain a certain value.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;A classic reusability example&lt;br&gt;Let’s look at a really simple example of a modal dialog being reused. Let’s say you have a table of contacts in your solution, and in your solution there are multiple different scripts that require you to select a contact. One example might be if you create a job, and in order to dos you must know which contact the job is for. Another might be raising an invoice, a quote, or establishing a relationship between two contacts. All of these processes require a contact to be chosen (or added if they do not exist).&lt;/p&gt;
&lt;p&gt;In all of these scripts we write, we could program different dialogs in which the user selects a contact, or we could build a single modal dialog - known as a “Contact Picker” purely for this purpose, and reuse it in all our scripts.&lt;/p&gt;
&lt;p&gt;The contact picker is invoked by a script to launch it. The user can then do a search in the picker, or perhaps they can choose to add a new contact. The result of the picker is to simply return the ID of a contact chosen - that’s it. If nothing is returned, we assume the user cancelled and did not select a contact.&lt;/p&gt;
&lt;p&gt;Now, if we could invoke this in every other script that requires a contact, we have a nice reusable dialog to suit all situations where a contact is required.&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;Building a Reusable dialog&lt;/h2&gt;
&lt;p&gt;Reusable code is nothing new, nor is reusable dialogs of this fashion. People have been building them many years. However most of the modal dialogs we have seen in other solutions typically involve a certain process mentioned earlier where once the modal dialog is opened, script execution terminates, and is then reestablished upon user decision.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/modal-magic/_resampled/ResizedImage600112-script-flow-diagram-2.png&quot; alt=&quot;script flow diagram 2&quot; width=&quot;600&quot; height=&quot;112&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here, our initial script A is run. Perhaps this is for creating a job lets say. It requires a contact to be chosen, so opens the modal contact picker dialog. Script A then terminates and is no longer running. The user selects a contact in the dialog and upon doing so, it begins execution of another script, B.&lt;/p&gt;
&lt;p&gt;There is one big issue here - how does script B know that Script A was initially running and required the contact ID? Moreover, how does script A continue its original execution now that it has terminated?&lt;/p&gt;
&lt;p&gt;There are various ways around this. One such way is that B is a decision script, and we store which process was initially running (ie Create Job) in a global variable. Script B checks this, and knows that prior to the dialog being invoked, the “Create Job” process was running, and so returns the contact ID chosen back to this script.&lt;/p&gt;
&lt;p&gt;Even in doing so however, any state that was in script A was lost the second it was terminated (unless everything was stored in global variables).&lt;/p&gt;
&lt;p&gt;It’s all a bit of a mess, and the more times you use the contact picker dialog in more scripts, the more checks and branches you end up with having to cater for and the more scripts you have to restore.&lt;/p&gt;
&lt;p&gt;Fortunately there is a far easier way to structure your modal dialogs.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;Never stop your script running!&lt;br&gt;The simple solution is to never stop your initial script running. Once the modal dialog is invoked, your script enters a paused state, and just sits there… waiting. It is waiting for your modal dialog to finish, and return back to your initial script the contact ID. Once that happens, your script simply carries on and uses the chosen contact ID as required. So easy!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/modal-magic/_resampled/ResizedImage60071-script-flow-diagram-3.png&quot; alt=&quot;script flow diagram 3&quot; width=&quot;600&quot; height=&quot;71&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here’s what it looks like. So much simpler and easier to understand. The other major benefit is that because your script does not terminate all variables and state you have defined in the script is still there just waiting. There is no need to create a script that is responsible for figuring out what was originally running before the modal dialog, because it is still running!&lt;/p&gt;
&lt;p&gt;&lt;br&gt;So, how do we do this?&lt;br&gt;It’s easier than you think. There is a really basic structure to the modal process that we use. First, lets look at what Script A might look like:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/modal-magic/script-1.png&quot; alt=&quot;script 1&quot; width=&quot;497&quot; height=&quot;217&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is the typical structure of our initiating script. It calls our modal picker script, and immediately it grabs the result and deals with it. But in reality it’s not immediate. Our picker script can take quite some time to return that result, depending on how long the user farts about in selecting a contact! The key is that the modal script will enter a paused state waiting for the user to do whatever it is they need to do.&lt;/p&gt;
&lt;p&gt;Here is the basic structure of our modal script:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/modal-magic/_resampled/ResizedImage600211-script-2.png&quot; alt=&quot;script 2&quot; width=&quot;600&quot; height=&quot;211&quot;&gt;&lt;/p&gt;
&lt;p&gt;We initiate the modal dialog, and then we enter this special loop. Inside the loop the script is paused.&lt;/p&gt;
&lt;p&gt;The next line of code looks really out of place - how can we be obtaining a script result when no script was called? I hear lots of heads scratching here. Well, the thing that makes this all possible is the fact that any script the user calls now through clicking a button on the layout can return its result back to this script. So for example if the user clicks on a contact, or clicks a cancel button, whatever that script exits with is passed back here!&lt;/p&gt;
&lt;p&gt;There is one thing that all scripts the user runs must do however. They must be set to resume the currently running script - that being our modal script.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/modal-magic/button-setup-dialog.png&quot; alt=&quot;button setup dialog&quot; width=&quot;280&quot; height=&quot;386&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is what one such button on the layout looks like. We’re running a special script called “Modal Decision”. We are passing the script a parameter that tells it what the user has clicked. Note that the option to Resume current script is used. If you don’t want a button or script run in the modal dialog to continue execution of the modal dialog, simply set it to keep the current script paused.&lt;/p&gt;
&lt;p&gt;In this case, we’re passing our decision script a selected contact ID.&lt;/p&gt;
&lt;p&gt;Here is our Modal Decision script:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/modal-magic/script-exit.png&quot; alt=&quot;script exit&quot; width=&quot;385&quot; height=&quot;26&quot;&gt;&lt;/p&gt;
&lt;p&gt;Couldn’t be simpler! We just spit back out exactly what we got in. This tells our modal script what their decision was.&lt;/p&gt;
&lt;p&gt;Recall back in our modal script. Once this script resumes it too returns the user decision, which is the contact ID. This ID thus flows back to our original script, where it is picked up and dealt with in script A that continues execution, so simple and elegant!&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;Why do we need the loop?&lt;/h2&gt;
&lt;p&gt;You’ll note that we have a loop in our modal script. In the example we just showed the loop is irrelevant and not used. But there are times when the user may make a decision in the modal dialog that requires some checks to be carried out before their decision is accepted.&lt;/p&gt;
&lt;p&gt;Going back to our contact picker example, what if our dialog has the ability for the user to enter some details for a brand new contact? We might use global fields to allow user input. We may however have some requirements that a contact name is specified, or that an email address entered is in a valid format. These are checks that must be done before user decision is accepted.&lt;/p&gt;
&lt;p&gt;It is in this loop that we can carry out those checks. When the user decision is received, we can carry out checks, and only if all checks are successful do we exit the script with the result. If checks fail, the loop simply repeats, putting the user back into the paused state, thus waiting for them to remedy their errors.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/modal-magic/script-3.png&quot; alt=&quot;script 3&quot; width=&quot;546&quot; height=&quot;494&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is one such example. The user has chosen to add a new contact, and we can assume they have attempted to fill out some global fields for the new contacts details. Upon resuming, this script does a check - have they entered a name for the new contact? If not, a custom dialog is shown to the user saying they need to enter a name, and they are taken back to the name field.&lt;/p&gt;
&lt;p&gt;If that check does not happen, the alternative is to create the contact, and return the new contacts ID as the result. The new contact ID goes back to the original script. &lt;/p&gt;
&lt;h2&gt;So in Summary&lt;/h2&gt;
&lt;p&gt;Here is the basic flow of process for our modal structure:&lt;/p&gt;
&lt;p&gt;1. Script A begins execution&lt;br&gt; 2. Executes Modal Script&lt;br&gt; 3. Modal script initialises dialog and pauses in a loop&lt;br&gt; 4. User interacts with dialog, eventually making a decision&lt;br&gt; 5. Decision is returned back to modal script to resume execution&lt;br&gt; 6. Modal Script carries out checks, processes decision, and returns result if all checks are valid&lt;br&gt; 7. Result returned back to Script A&lt;br&gt; 8. Script A continues processing using the information returned from modal dialog.&lt;/p&gt;
&lt;p&gt;We hope that this is pretty straightforward and easy enough to follow. The 3 main keys to this process are:&lt;/p&gt;
&lt;p&gt;1. Entering a paused state in the modal script&lt;br&gt; 2. Being able to detect what action user has done in modal script, by way of retrieving a script result&lt;br&gt; 3. Being able to resume execution and return result back to originating script&lt;/p&gt;
&lt;h2&gt;A gotcha bout closing the modal window&lt;/h2&gt;
&lt;p&gt;With this method, one thing you may need to pay attention to is how a user cancels the modal dialog. A button is the easiest way, and have that button return a decision of “Cancel” back to your modal script to handle as required.&lt;/p&gt;
&lt;p&gt;Because our modal dialog is paused, the standard “X” in the top left corner of the window to close will not work, nor will the standard close menu item. To work around this, you can add a custom menu to the modal layout. If you override the close menu item with your own decision script (the exact same one you would attach to your cancel button in the dialog) then you can work around this and close the dialog by using the menu item, or shortcut.&lt;/p&gt;
&lt;p&gt;However because modal windows are designed to be modal, we would recommend the user have to explicitly press a cancel button if they wish to cancel the process.&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;Other benefits of this modal method&lt;/h2&gt;
&lt;p&gt;We have already covered the main reasons why this method of implementing a modal dialog is great - simple, reusable, and no need to terminate your parent script However one thing that is also great is something we touched upon right at the start of the article. Recall that FileMaker “Dialog” modal window is unable to execute scripts in other files while open? Well with this method you can do that, as well as spawn new temporary windows for use in your scripts, all while keeping the window truly modal.&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;Example File&lt;/h2&gt;
&lt;p&gt;As with all of our articles we produce we like to provide a detailed example file to go along with it. It’s not enough to just read how something is done, you should be able to see it in action and explore how it works yourself. Please find attached the example file below.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;Modal Magic Demo file&quot; href=&quot;https://www.teamdf.com/assets/blog-images/modal-magic/ModalMagic.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 13 Nov 2018 08:23:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/modal-magic/</guid>
		</item>
		
		<item>
			<title>Workplace Innovation Platform</title>
			<link>https://www.teamdf.com/blogs/workplaceinnovationplatform/</link>
			<description>&lt;p&gt;At the recent FileMaker DevCon conference in Grapevine, Texas, there was a very special announcement.&lt;/p&gt;
&lt;p&gt;Over the past few years FileMaker has been working to find a category that best explains what it is and what it does.&lt;/p&gt;
&lt;p&gt;For a long time it has sat in the &#039;no code - low code&#039; category, which is all good and well, but for those who want to really extend FileMaker to its full potential, you really do need to know how to code.&lt;/p&gt;
&lt;p&gt;So the announcement at DevCon centred around a new category that best suits and explains FileMaker, and that is the &#039;&lt;a title=&quot;Workplace Innovation Platform&quot; href=&quot;https://www.filemaker.com/workplace-innovation/&quot; target=&quot;_blank&quot;&gt;Workplace Innovation Platform&lt;/a&gt;’..&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;div class=&quot;media leftAlone&quot;&gt;&lt;iframe width=&quot;660&quot; height=&quot;371&quot; src=&quot;https://www.youtube.com/embed/sKYxgK1jzCI?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; title=&quot;Your Workplace Innovation Platform&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;At Digital Fusion we love it, we believe it really symbolises what FileMaker is all about, and we are passionate about taking this category forward.&lt;/p&gt;
&lt;p&gt;We are all about innovation, so to extend this into a category really helps with how we promote FileMaker to our current clients, but also how we can project it to new and interested clients.&lt;/p&gt;
&lt;p&gt;Along with the new category name, FileMaker have come up with a lot of new branding material, along with some cool advertisements.&lt;/p&gt;
&lt;p&gt;These are being showcased in the US and in other regions around the world, but you will potentially see them pop up on your YouTube and other social media feeds.&lt;/p&gt;
&lt;p&gt;If you do miss them, we have embedded them below…&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;iframe src=&quot;https://www.youtube.com/embed/Ll21pItAZ88?rel=0&quot; width=&quot;560&quot; height=&quot;315&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/KR943kRQ-nc?rel=0&quot; width=&quot;560&quot; height=&quot;315&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/89T51PLL__o?rel=0&quot; width=&quot;560&quot; height=&quot;315&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;</description>
			<pubDate>Sat, 10 Nov 2018 00:18:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/workplaceinnovationplatform/</guid>
		</item>
		
		<item>
			<title>Better Breadcrumbs</title>
			<link>https://www.teamdf.com/blogs/better-breadcrumbs/</link>
			<description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;Breadcrumb menus are great. They tell the user a lot about where they are within a solutions hierarchy.&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;They also provide a really quick and easy way to navigate up/down that hierarchy if needed. In the FileMaker world, people have been making breadcrumb menus in various forms for a while, the most common implementation is that of a repeating fields, button bars, or in the case of vertical menus, a portal.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;And while all of these methods are workable, they tend to have limitations when it comes to 2 aspects - the visual quality of the menu, and the ability to customise and extend the menu. So what do we mean by these?&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;We’ll start off by giving an example of a breadcrumb menu built using a button bar, discuss some of its limitations, and then present our alternative implementation using a tab control object.&lt;/p&gt;
&lt;h3&gt;Example file time!&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;Rather than wait til the end to check out the demo, we strongly recommend you download and explore the example file as you read. This will help you follow along with the content of the article and help you to understand what we are talking about.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;Download the demo file&quot; href=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/BetterBreadcrumb.zip&quot; target=&quot;_blank&quot;&gt;BetterBreadcrumbs.zip&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;h3&gt;A typical breadcrumb menu&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;Here is an example of a standard breadcrumb menu. This is a location based menu, as the items in the menu are locations within the solution the user can navigate to.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/Breadcrumbs-1.jpg&quot; alt=&quot;Breadcrumbs 1&quot; width=&quot;500&quot; height=&quot;179&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;The user currently resides at the right-most location in the menu, and as you scan to the left you can work your way back up the navigation hierarchy all the way to home screen. These navigation elements are clickable, so the user is free to traverse back up the hierarchy to any point they wish.&lt;/p&gt;
&lt;h3&gt;Building this in FileMaker&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;Many peoples first instinct would be to use a button bar to design and build a breadcrumb menu. It has a number of properties that suit a breadcrumb menu:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Multiple segments, each could be a step in the hierarchy&lt;/li&gt;
&lt;li&gt;Clickable, as each segment is essentially a button&lt;/li&gt;
&lt;li&gt;You can calculate the text to appear in each segment.&lt;/li&gt;
&lt;/ul&gt;&lt;p class=&quot;p1&quot;&gt;But here’s the problem. Button bars are of a fixed width, and the segments within the button bar are all proportional in width to the overall width of the bar itself. So if you have a 100pt wide button bar, with 10 segments, then each segment will be 10 pts wide. If you extend the width of the bar to 200pts, then each segment grows to 20pts in width. You have no control over the width of each individual segment.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;So what does this mean for us in real terms?&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/Breadcrumbs-2.png&quot; alt=&quot;Breadcrumbs 2&quot; width=&quot;444&quot; height=&quot;84&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Here is a crack at building a breadcrumb menu with a button bar. The issue we have is that each segment has a variable amount of text, yet we can only have a single width per segment. Add to this the fact that typical breadcrumb menus have a divider between each element, and you end up with a pretty average looking menu.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/Breadcrumbs-3.png&quot; alt=&quot;Breadcrumbs 3&quot; width=&quot;383&quot; height=&quot;77&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;This is what it looks like in layout mode, to further illustrate whats going on.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Now, we have seen people come up with attempts to work around this fixed width segment issue. Some involve creating button bar segments based on calculations, where the text inside each segment is padded with spaces to make it a certain width, while others involve starting off with hundreds of small segments, and programmatically removing certain segments and padding others. The simple fact is these are all complex and a real pain to work with, and you still do not achieve a really beautiful result.&lt;/p&gt;
&lt;h3&gt;What about a tab control?&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;What’s that, I hear you ask? A tab control? Surely a tab is the last object you’d think of to build a breadcrumb menu right? Well maybe, but the fact is tab controls are the perfect layout object for building them (short of an actual breadcrumb menu layout object!). &lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;The reason why tab controls are so great for this, is the simple fact that the width of each tab control name is variable in width. This means it doesn’t matter how much or how little text goes into each tab name, they won’t all end up the same width.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/Breadcrumbs-4.png&quot; alt=&quot;Breadcrumbs 4&quot; width=&quot;501&quot; height=&quot;64&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;This is a tab control, designed to look like a breadcrumb menu. Looks pretty nice doesn’t it. Notice how all of the spacing between the dividers and the items are all consistent.&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;So how is this done?&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/Breadcrumbs-5.png&quot; alt=&quot;Breadcrumbs 5&quot; width=&quot;565&quot; height=&quot;54&quot;&gt;&lt;br&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Here is the same tab control object highlighted in layout mode.&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;The height of the overall object has been reduced such that there is actually no content space, it’s just the height of the tab names themselves. We aren’t going to be using this object for placing other objects in, we are only concerned with the names.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Let’s look at the tab control setup next.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/Breadcrumbs-6.png&quot; alt=&quot;Breadcrumbs 6&quot; width=&quot;573&quot; height=&quot;459&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Interesting! What we can see here is that the odd positions in the tab control are given the names of the items in the menu. Whilst the even positions are used for dividers. This is a key concept in our technique for building the menu - odd spaces are for items, even spaces are for separators.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;The above setup is kind of useless in an actual solution because it is so hard-coded. Ideally you want the menu to be dynamic, and have elements add/remove as you traverse up/down the navigation hierarchy of your solution, but at this point we’re simply showing you the building blocks for how we structure the object.&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;We use the “Label width + Margin of” option for tab width, this allows tabs to grow as more text is added, whilst maintaining an even spacing between items and dividers. We are using an ascii character of a right arrow for the divider.&lt;/p&gt;
&lt;h3&gt;Formatting items&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;You’ll note that the first three items in the menu are underlined. This is to give visual indication to the user that these are clickable. The right-most element is not underlined, suggesting that is the screen they are current on, and there is no need for them to click that link.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Visual design is achieved through conditional formatting of each individual tab control. In this very basic example, the condition for the first 3 items is simply “true” and we format them to underlined. Again in reality we want to be a bit more dynamic in our conditional formatting, which we’ll cover later.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;For a navigation breadcrumb, you may actually wish to simply go with a hard-coded menu such as the one above, and just adjust its display for each layout it appears on, and indeed this may be the easiest implementation.&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;Other implementations may require a more soft-coded dynamic approach.&lt;/p&gt;
&lt;h3&gt;A simple example&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;In the example file we start off with a simple wizard example. Here we use a breadcrumb menu to indicate position in a step by step wizard.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/_resampled/ResizedImage600200-Breadcrumbs-7.png&quot; alt=&quot;Breadcrumbs 7&quot; width=&quot;600&quot; height=&quot;200&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;This wizard has 5 steps, and the user will work their way through the wizard, and continue to the next section by clicking a button. The menu itself is not clickable, it exists purely as a visual aid to inform the user of their progress in the wizard.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;We use the tab control for display of the menu, and we are using a slide-control beneath it for the wizard itself. So, the slide control has 5 panels and each panel is named Wizard_1 through Wizard_5.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;The tab control setup is as follows:&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/Breadcrumbs-8.png&quot; alt=&quot;Breadcrumbs 8&quot; width=&quot;573&quot; height=&quot;459&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Pretty simple stuff. Again odd positions for items, even positions are separators. Because the size of this wizard is known, we only need to add however many tabs are required for each step. &lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Navigation through the wizard is done by running a script.&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;The script takes as a parameter a direction, be it forward or back. Depending on which direction, it updates the value of a global variable $$WIZARD_POSITION. We use this global variable to help us know which step of the wizard we are on.&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;The script then simply navigates to the next or previous slide panel.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;The breadcrumb menu now has to update visually to reflect the users position also. We know the position of the user based on the number in the global variable which will be between 1 and 5.&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;The visual updating is done via conditional formatting, so let&#039;s take a look at that:&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/Breadcrumbs-9.png&quot; alt=&quot;Breadcrumbs 9&quot; width=&quot;173&quot; height=&quot;35&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;This is really easy. What we are looking at is the conditional formatting rule for the second position “Your Details”.&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;We’re saying that if the user is at this position, or has gone past this position already, that it should be coloured.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/_resampled/ResizedImage600198-Breadcrumbs-10.png&quot; alt=&quot;Breadcrumbs 10&quot; width=&quot;600&quot; height=&quot;198&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Here the user is on step 4 “Interests”, and so the conditional formatting of items 1 through 4 are evaluated to true, and are coloured bold and green.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;For the dividers, they are irrelevant in our example, so we can either always evaluate their conditional formatting to true (and assign them some property, in this case grey colour), or you can leave them without conditional formatting, in which case they will inherit the default formatting of the tab control object.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;In this example, you’ll note that the text is black, and the dividers are grey, so we have a difference in formatting of the 2 types of tabs. In the interests of simplicity, we make the default tab text colour black, and we have applied conditional formatting to all dividers, to change them to grey.&lt;/p&gt;
&lt;h3&gt;Adding action to navigation items&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;More often than not, you want the user to be allowed to click an item in the navigation menu and run a script accordingly. We can achieve this in tab controls by using the OnPanelSwitch object trigger.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;a&gt;&lt;/a&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/_resampled/ResizedImage600202-Breadcrumbs-11.png&quot; alt=&quot;Breadcrumbs 11&quot; width=&quot;600&quot; height=&quot;202&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Here is the same wizard, although this time all sections can be navigated to at any point in time.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;We start by altering the formatting so that all objects are underlined to begin with, indicating that they can be clicked.&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;The other conditional formatting properties are the same as in the previous example, if the user is on a position, or that position is to the left of where the user currently is, we make it bold and green.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;If we apply an OnPanelSwitch trigger to the tab control object,&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;then our script will run regardless of which tab is chosen.&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;An important piece of information we will use in the script is the position of the tab the user has clicked. This can be found by evaluating the first value in the function &lt;strong&gt;Get ( TriggerTargetPanel )&lt;/strong&gt;.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;There are 2 possible situations here. Firstly, the user may have clicked a divider. Our script will still run in this instance, so we must handle this situation. Recall all even positions are dividers, so we can check whether the clicked position is even. If it is then we return a FALSE result from the script, and the divider tab is not navigated to.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;The only other scenario is the user has clicked on an actual item that they can navigate to. This will be an odd number.&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;We must translate this number into the actual wizard position. We need to do this because of the dividers, they offset the clicked item.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;To illustrate this consider clicking on “Immediate Family”. You know that this is the third position in the wizard, but it is actually the 5th position in the tab control. So we need to write a translation between the position chosen and the wizard position. It’s pretty straightforward and simply &lt;strong&gt;Ceiling ( $PositionClicked / 2 )&lt;/strong&gt;.&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;In our example, this would be 5/2 = 2.5, and taking the ceiling of this gives us a wizard position of 3.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Now that we know the wizard position, it’s just a case of setting our location to that value, and going to that sliding panel object, all done !&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;You can indeed write your own script to cater for any positional click in your menu, regardless of what you are using your menu for.&lt;/p&gt;
&lt;h3&gt;Abstracting item names into a table&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;Often times your wizard or menu items will exist in a table as records because you need to customise them, or build different menus for different purposes. In this example we’re going to show that you can still use the breadcrumb menu in this fashion.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/Breadcrumbs-12.png&quot; alt=&quot;Breadcrumbs 12&quot; width=&quot;388&quot; height=&quot;156&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/_resampled/ResizedImage600198-Breadcrumbs-13.png&quot; alt=&quot;Breadcrumbs 13&quot; width=&quot;600&quot; height=&quot;198&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Here is a table of records, each for a different section in the breadcrumb menu, and below is the breadcrumb menu.&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;The 2 important bits of information in the table are the name of the item, and its position in the menu.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;The beauty of using a tab control really stands out when using an abstracted menu like this. The menu will simply expand to accommodate variable lengths of text. In order for things to work smoothly there are just two things you need to be aware of:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Make the initial width of the tab object wide enough to cater for a worst case scenario length of menu.&lt;/li&gt;
&lt;li&gt;Add enough tab control objects so that you are sure you have enough menu positions to cater for all the items that may end up in the menu.&lt;/li&gt;
&lt;/ul&gt;&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/_resampled/ResizedImage573459-Breadcrumbs-14.png&quot; alt=&quot;Breadcrumbs 14&quot; width=&quot;573&quot; height=&quot;459&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Here is the tab control setup of this abstracted menu. Wow things are really getting interesting now!&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;What you see there is a custom function which we have named @BREADCRUMB. It takes 2 parameters. The first is a keyword identifying which records in our wizard setup table to retrieve, and the second is the order number to retrieve. The 5 items in our table are all of type “Abstracted”, and are all numbered 1 through 5.&lt;span class=&quot;Apple-converted-space&quot;&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/_resampled/ResizedImage60044-Breadcrumbs-15.png&quot; alt=&quot;Breadcrumbs 15&quot; width=&quot;600&quot; height=&quot;44&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Here’s the custom function. It’s a simple executeSQL query where we retrieve names of items based on their type and order number, again nothing magical here just standard FileMaker.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;The rest of the implementation is no different to our other examples. Conditional formatting for the items, and a script trigger for navigation.&lt;/p&gt;
&lt;h3&gt;Abstracting the formatting as well as the names&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;In this last example we show how you can tailor the formatting of individual items in the menu as well as their names. Now you could achieve this with conditional formatting again, but if you want a specific item to have a specific formatting you may wish to abstract this into a table of records to be based on actual items, rather than position in the menu.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;This is a very similar example to the one above, with a slight exception that we have an additional field in our table containing an RGB function for the colour we want our item to be.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/Breadcrumbs-16.png&quot; alt=&quot;Breadcrumbs 16&quot; width=&quot;394&quot; height=&quot;161&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Here is the tab control setup for this example:&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/_resampled/ResizedImage573459-Breadcrumbs-17.png&quot; alt=&quot;Breadcrumbs 17&quot; width=&quot;573&quot; height=&quot;459&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;We have added in 9 different tabs here. In fact we add more than required in case more are needed. Because the items are abstracted to a menu, but adding more tabs, we ensure we don’t have to come back and potentially add more in future.&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;The other interesting thing to notice here is that we no longer are adding dividers into the even positions. It’s all just calls to a custom function called @BREADCRUMB_Formatted.&lt;span class=&quot;Apple-converted-space&quot;&gt;  &lt;/span&gt;This function is identical in behaviour to the earlier one, but this function does a couple more things&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;If the order number passed through is even, it returns the divider character&lt;/li&gt;
&lt;li&gt;If the order number passed through is odd, it obtains the name of that item from corresponding record.&lt;/li&gt;
&lt;li&gt;It also obtains the formatting properties from the record, and applies them to the name, using the &lt;strong&gt;Evaluate&lt;/strong&gt; function.&lt;/li&gt;
&lt;li&gt;It also determines using the wizard position $$WIZARD_POSITION whether to format the item, or whether to not format&lt;/li&gt;
&lt;/ul&gt;&lt;p class=&quot;p1&quot;&gt;So in this case, we are not using conditional formatting to determine whether to format an item or not, it is entirely done within the custom function. The formatting properties we use comes from the record itself.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/_resampled/ResizedImage600207-Breadcrumbs-18.png&quot; alt=&quot;Breadcrumbs 18&quot; width=&quot;600&quot; height=&quot;207&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;The end result of this is that because we are only displaying text for items, we have full formatting control over how that looks using the text formatting functions. Here we are using slightly different colours for each item.&lt;/p&gt;
&lt;h3&gt;Tabs are awesome&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;The tab control object is just one of those cool objects that just keeps giving. We really love these breadcrumb menus and feel they have a really useful place in solutions. They can also be now made to look really professional and behave just like a breadcrumb menu should as well as being very easy to customise and format.&lt;/p&gt;
&lt;h3&gt;Example file again!&lt;/h3&gt;
&lt;p class=&quot;p1&quot;&gt;As with all of our articles we produce we like to provide a detailed example file to go along with it. It’s not enough to just read how something is done, you should be able to see it in action and explore how it works yourself. Please find attached the example file below.&lt;/p&gt;
&lt;p class=&quot;p1&quot; style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;Download the demo file&quot; href=&quot;https://www.teamdf.com/assets/blog-images/Better-Breadcrumbs/BetterBreadcrumb.zip&quot; target=&quot;_blank&quot;&gt;Breadcrumbs.zip&lt;/a&gt;&lt;/p&gt;
&lt;h2 class=&quot;p1&quot; style=&quot;text-align: left;&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;We&#039;d like to thank Greig Jackson here at Digital Fusion for coming up with this method — nice work!&lt;/p&gt;</description>
			<pubDate>Thu, 04 Oct 2018 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/better-breadcrumbs/</guid>
		</item>
		
		<item>
			<title>FileMaker Developer Certification</title>
			<link>https://www.teamdf.com/blogs/filemaker-developer-certification/</link>
			<description>&lt;p&gt;A little known fact about being part of the FileMaker community is that a large number of developers go through a rather rigorous FileMaker Certification exam. And that exam has to be sat each year for each new version of FileMaker.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/certification/_resampled/ResizedImage660374-certified-teaser-1.jpg&quot; alt=&quot;certified teaser 1&quot; width=&quot;660&quot; height=&quot;374&quot;&gt;&lt;/p&gt;
&lt;p&gt;At Digital Fusion we strongly believe that all our developers need to be current in the latest version of certification. That&#039;s important for many reasons:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;It shows our clients we&#039;re professional and know our stuff&lt;/li&gt;
&lt;li&gt;It encourages each developer to closely review each new version&lt;/li&gt;
&lt;li&gt;It shows that we measure up against the bar FileMaker has set&lt;/li&gt;
&lt;li&gt;It helps us ensure we are all on the same page&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The exam isn’t easy either — even when you’ve done it several times! And it’s fair to say everyone gets a bit nervous in the lead up. To give you an idea of what it consists of, there are about 60 questions to be answered over a two hour period, examining all different aspects of the productline covering everything from programming techniques to design to server and security. It’s pretty thorough and detailed. &lt;/p&gt;
&lt;p&gt;When we are employing new team members, we don’t specify that they must be certified, but we do expect that they have a crack at it fairly on so they/we can benchmark their knowledge. It can take 2 or 3 attempts before they nail it and can call themselves a FileMaker certified developer.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/sitewide-assets/_resampled/ResizedImage428126-certified-17-logo-4clr-258x60.png&quot; alt=&quot;certified 17 logo 4clr 258x60&quot; width=&quot;428&quot; height=&quot;126&quot;&gt;&lt;/p&gt;
&lt;p&gt;Developers by nature are a competitive sort so when a new certification exam is released, there is a bit of gamesmanship as to who goes first, who gets the best result. This is all very friendly but does mean there is good banter around the office.&lt;/p&gt;
&lt;p&gt;“Being a certified FileMaker developer shows that you are a capable and competent developer who can utilise all of the features in the FileMaker product family to their fullest potential” Daniel, now certified in versions 8 to 17!&lt;/p&gt;
&lt;p&gt;“Being a certified FileMaker developer brings my lanyard one step closer to the floor at DevCon&quot; Paul Thomas - FileMaker Certified Developer version 16-17&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/certification/_resampled/ResizedImage342456-lanyard.jpg&quot; alt=&quot;lanyard&quot; width=&quot;342&quot; height=&quot;456&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Sat, 22 Sep 2018 00:20:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-developer-certification/</guid>
		</item>
		
		<item>
			<title>FileMaker 14 Support Ending</title>
			<link>https://www.teamdf.com/blogs/filemaker-14-comes-to-an-end/</link>
			<description>&lt;div&gt;
&lt;p class=&quot;ApplePlainTextBody&quot;&gt;As of the 21st of September, 2018, FileMaker, Inc. will discontinue the ongoing support of the FileMaker 14 platform.&lt;/p&gt;
&lt;h4 class=&quot;ApplePlainTextBody&quot;&gt;What does this mean?&lt;/h4&gt;
&lt;p class=&quot;ApplePlainTextBody&quot;&gt;Firstly and probably most importantly, there will be no ongoing support or updates for the software. This means that if a bug is found (although unlikely) then it won’t be fixed, the software will remain as it is now.&lt;/p&gt;
&lt;/div&gt;
&lt;p class=&quot;ApplePlainTextBody&quot;&gt;Other things will happen, you will no longer be able to buy a license for 14 and you will not be able to downgrade to 14. Although these likely won&#039;t effect the vast majority of our clients, there are times when we come across old versions of databases that need assistance.&lt;/p&gt;
&lt;h4 class=&quot;ApplePlainTextBody&quot;&gt;What should you do if you&#039;re currently using 14 still?&lt;/h4&gt;
&lt;p class=&quot;ApplePlainTextBody&quot;&gt;The simple answer is that you should be upgrading, preferably to FileMaker 17, the current version available.&lt;/p&gt;
&lt;p class=&quot;ApplePlainTextBody&quot;&gt;The benefits of upgrade are well worth the costs (if any), you will experience greater speeds, you will take advantage of superior security, and you get to add features to your solution such as connecting external apps using the data API.&lt;/p&gt;
&lt;p class=&quot;ApplePlainTextBody&quot;&gt;While there is no change of format — a FileMaker 14 database can be hosted on and accessed by FileMaker 17 without modification — you may need to make the jump to having your own dedicated server. That&#039;s because if you&#039;ve got your databases hosted on a shared server, it will be no newer than FileMaker 14, and FileMaker 17 can not access files on 14 server. The reason for this change is that for security and licensing reasons FileMaker Inc. disallowed shared hosting from FileMaker 15 onwards. Moving to your own server is probably going to cost more and we&#039;re happy to advise on the options such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Your own server on premise&lt;/li&gt;
&lt;li&gt;A dedicated server in the cloud (e.g. Amazon Web Services)&lt;/li&gt;
&lt;li&gt;FileMaker Cloud&lt;/li&gt;
&lt;/ul&gt;&lt;p class=&quot;ApplePlainTextBody&quot;&gt;Moving to a dedicated server is not a bad thing, in the security of your database will be greatly enhanced.&lt;/p&gt;
&lt;p class=&quot;ApplePlainTextBody&quot;&gt;If you are still on FileMaker 14 and below, do get in touch with us and we can build a plan to get you upgraded. We are happy to offer advice on whats needed, including what FileMaker licensing best suits your organisation.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Thu, 13 Sep 2018 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-14-comes-to-an-end/</guid>
		</item>
		
		<item>
			<title>Building a Multilingual App</title>
			<link>https://www.teamdf.com/blogs/building-a-multi-lingual-application/</link>
			<description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Multilingual&lt;/em&gt; - what do we mean by that?  Well, “multi” means more than one, and “lingual” has its origins in the Latin word “lingua”, meaning language… err in other words we’re talking about a single solution that can speak more than one language :)&lt;/p&gt;
&lt;h3&gt;&lt;span style=&quot;font-size: 1.17em;&quot;&gt;Why would you want many languages?&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;In most cases, a solution is developed using the most common language of the user of that solution. But what if the solution has many users across many geographic regions and who speak many different primary languages?  &lt;/p&gt;
&lt;p&gt;Being able to present a solution to a user in their native language is a real benefit and widens the market for a solution that you may sell as a product, or indeed any solution you develop to be used in many countries. Even within a single country many languages can be spoken so being able to give users the freedom to select their language of choice is going to greatly improve their &lt;em&gt;user experience&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Is this for everyone?&lt;/h3&gt;
&lt;p&gt;In short, no. Building a multi-lingual solution takes time and planning. Once the key framework is in place for adding multiple languages it can be quite efficient to develop with but it will always be a slower to build than if you just ripped into development using a single language.&lt;/p&gt;
&lt;p&gt;You need to think carefully about whether the solution you intend to build will ever potentially be used by individuals who may have a different native language to the one the solution is developed in, and whether you want to make that investment up front. It is much harder to make an existing solution into a multi-lingual one than it is to begin a solution from scratch to be multi-lingual.&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;Before we get into things, grab the example file!&lt;a title=&quot;Multilingual Demo File&quot; href=&quot;https://www.teamdf.com/assets/blog-images/multilingual/MultiLingual.zip&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For the remainder of this article we are going to use the associated example file as our reference.  I strongly recommend you download the example file and have a look (and read) through it as you read this article. The example file includes many different scenarios that you will encounter in building a multi-lingual solution and also contains a lot of helpful information about each.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;&lt;a title=&quot;MultiLingual Demo File&quot; href=&quot;https://www.teamdf.com/assets/blog-images/multilingual/MultiLingual.zip&quot; target=&quot;_blank&quot;&gt;MultiLingual.zip&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;The first table is Languages&lt;/h3&gt;
&lt;p&gt;It’s pretty straightforward really. Each record in the language table is, yup you guessed it, a language. &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600364-01-languages-table.png&quot; alt=&quot;01 languages table&quot; width=&quot;600&quot; height=&quot;364&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can see above we have established three languages in our example. The information we capture is again very simple: name, abbreviation, icon and a flag field indicating whether this is the primary language in the solution. It is really up to you the developer as to how you decide which language a user is to use.  Almost certainly this would involve having a User table, where each user stores their individual preference for what language they want to display the solution in upon opening the solution. If it is a brand new user however, or if the user has made no preference, then the default language can be used and set on startup.&lt;/p&gt;
&lt;h3&gt;The next table is Phrases&lt;/h3&gt;
&lt;p&gt;Think of a &lt;em&gt;phrase&lt;/em&gt; as having no associated language, it is merely some form of written text within your solution, that you are going to be required to translate into a language. For example, a particular phrase may be a label for a name field, it may be a label on a button, a tab control, or it may be an item in a value list.&lt;/p&gt;
&lt;p&gt;Phrases can also be for specific records. You may for example have a table in which you have records for your solutions navigation - each record being a link to a screen in your solution. These are going to need to be translated, so phrase records can be setup and linked directly to each record. We’ll cover more on these later, but for now think of a phrase as purely something to be translated.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600290-02-phrases-table.png&quot; alt=&quot;02 phrases table&quot; width=&quot;600&quot; height=&quot;290&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here in the table above we have the phrases setup in the example file. By looking at this you may start to have some light bulbs going off as to how we are going to achieve multilingual functionality through global variables.&lt;/p&gt;
&lt;p&gt;In our phrase table we have essentially 3 different category fields named type, category and sub category. The description is purely for our own purposes to help the developer identify what the phrase is actually pertaining to.&lt;/p&gt;
&lt;p&gt;The variable name that you see is a calculation and we build the name based upon the users nominated type, category and sub category.&lt;/p&gt;
&lt;p&gt;We should point out here that this method of categorising your phrases is just one such way in which you can do this. This part of the process is entirely up to you the developer as to how you want to identify phrases, and thus how your variables are going to be named. You may simply want 2 categories, you may want none, or you may end up with more, it’s up to you.&lt;/p&gt;
&lt;h3&gt;Variable Names are really important!&lt;/h3&gt;
&lt;p&gt;So if you haven’t clicked by now, each phrase has an associated global variable name. The way in which we will do multiple languages, is to store into these global variables the translation of the phrase in that of the users chosen language.&lt;/p&gt;
&lt;p&gt;This method requires that variable names be used throughout your solution, from calculations on button bars and tab controls, to merge fields on your layout, to within calculations and scripts - there is an element of hard coding throughout your solution of variable names.&lt;/p&gt;
&lt;p&gt;We do this primarily for readability.  Looking in the data viewer will give you the full list of all of the language based variables used so you can easily reference them. It also makes it easy when looking at layouts and calculations to ensuring you are using a correct global variable for a given purpose. At the end of the day, hard coding is going to be done, so we may as well make these as readable as possible.&lt;/p&gt;
&lt;p&gt;But the drawback to this is that you must make sure you name your variables in such a way that you are happy with them, and that you are not going to go back and change the naming down the track. If you end up recategorising your phrases, it will mean you have to change variables names accordingly in your solution, which can be difficult if you don’t know where they are used. Applications like BaseElements and FMPerception can help with this.&lt;/p&gt;
&lt;p&gt;If you wanted to make a modification to the framework, there is no reason why you couldn’t simply name your global variables by using a Unique record identifier (UUID) of the phrase record instead. The benefit is variable names won’t change as the UUID won’t change, but the drawback is your global variables become unintelligible and you cannot simply look at them to know what they are. That is why we go with human readable names.&lt;/p&gt;
&lt;p&gt;The key takeaway here is to get your categorisation and naming convention correct early so that you&#039;re happy with it... and that you won’t change it!&lt;/p&gt;
&lt;h3&gt;And Finally, Translations&lt;/h3&gt;
&lt;p&gt;The final table we are going to require is called Translations.  The translation table is simply a join table between Languages and Phrases. Each Phrase is going to have 1 Translation record per language.  The translation record will store the actual translation of the phrase into the nominated language, and that’s pretty much it.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600342-03-translations.png&quot; alt=&quot;03 translations&quot; width=&quot;600&quot; height=&quot;342&quot;&gt;&lt;/p&gt;
&lt;p&gt;In our example file, we define are translations using a specially constructed portal as shown above. The portal is filtered based upon the user choosing a nominated language from a drop down above. What the portal shows is actually phrase records, but inside it we place a translation field. We have constructed a special relationship with “allow creation of records in this table via this relationship” enabled. This makes it really easy for us to define the translations for every phrase for a chosen language.  We simply change the drop-down to the next language and then we can create our translation records for that language.&lt;/p&gt;
&lt;p&gt;Above we display the type of phrase record, its descriptions and categories, and its variable name so that we clearly know what it is we are translating. &lt;/p&gt;
&lt;h3&gt;Putting it all together - the basics of the framework&lt;/h3&gt;
&lt;p&gt;So that’s about it really for the table structure of our framework, it simply consists of 3 tables - Languages, Phrases, and Translations.&lt;/p&gt;
&lt;p&gt;The next stage of the framework is defining all of our phrase global variables for a given language, so lets look at how we achieve this.&lt;/p&gt;
&lt;h3&gt;How variables are defined&lt;/h3&gt;
&lt;p&gt;We saw earlier that global variable names are defined on the phrase table.  It’s a calculation, and we are using our category names to define our variable name. We also strip out any spaces or illegal characters from the variable name, replacing with underscores.&lt;/p&gt;
&lt;p&gt;When your solution is opened, as part of the startup procedure, we will be required to define all of our global variables and give them a value for a given language. So we should at the very least know the language we want to use - this will either be the system default language, or a language based on user preference.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/04-variables.png&quot; alt=&quot;04 variables&quot; width=&quot;413&quot; height=&quot;81&quot;&gt;&lt;/p&gt;
&lt;p&gt;In our example file we have 3 key scripts responsible for management of languages.  The first “Load Language” is really the only script you require. You pass it the primary key ID of a language to load, and it does so.  The other two scripts are helper sub-scripts.&lt;/p&gt;
&lt;p&gt;The basic process of Load Language is:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Obtain a list of all of the variable declarations for given language&lt;/li&gt;
&lt;li&gt;Evaluate these declarations, thus loading them as actual global variables.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;And that’s all, pretty simple really.&lt;/p&gt;
&lt;h3&gt;Variable Declarations&lt;/h3&gt;
&lt;p&gt;So, we know the language we want, and so using this knowledge we can find all translation records for that language.  On each translation record we have 2 special calculation fields, named variable_set and variable_clear. &lt;/p&gt;
&lt;p&gt;What these calculation fields are defining is a string which represents either setting the global variable to the value of the translation record, or simply setting the global variable to empty.&lt;/p&gt;
&lt;p&gt;As an example, here is the variable_set calculation:&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;PHRASES::variable &amp;amp; &quot; = &quot; &amp;amp; Quote ( value ) &amp;amp; &quot; ;&quot;&lt;/p&gt;
&lt;p&gt;We grab the associated variable name from the phrase, stick in an “=“ sign, and then he translated value in quotes, followed by a semicolon.  This is exactly how we would write it if we were defining this global variable in a LET Statement, and in fact that is exactly what we are going to do. We are going to build up a Let statement containing all of our global variables declared to their translated values, and then run that statement using the “Evaluate” function.&lt;/p&gt;
&lt;p&gt;This is what the 2 helper scripts achieve, they help retrieve all of the required variable declarations, and then build the LET statement before finally executing it.&lt;/p&gt;
&lt;p&gt;How it actually achieves that is something we’ll leave up to you all to explore in the example file. The scripts are designed to help load all the variables successfully. One limitation is that of the size of a calculations definition. To overcome this for large solutions which may have thousands of translations, we chunk declarations into no more than 500 at a time, so that we never hit the limit of a calculations definition.&lt;/p&gt;
&lt;h3&gt;To cut a long story short, this is what we get…&lt;/h3&gt;
&lt;p&gt;After calling our Load language script, what we end up with is something like this:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600656-05-variables-view.png&quot; alt=&quot;05 variables view&quot; width=&quot;600&quot; height=&quot;656&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is our data viewers current tab, and inside it you can see all of our global variables loaded up with words.  Note that we use the LANG prefix on all global variables that are to do with the language of the solution, this just helps us keep them all grouped together. &lt;/p&gt;
&lt;p&gt;We also store the ID of the selected language in a special global $$LANGUAGE.SELECTED_ID . This has benefits later on which help us overcome some other challenges with multi-lingual implementation, so it is important to know at all times what the current language is.&lt;/p&gt;
&lt;p&gt;There are also some special META variables defined. This is loading in information about the current language which we may wish to display on-screen to the user. They’re loaded in as variables in case they ever need to be used, but they are not critical.&lt;/p&gt;
&lt;h3&gt;What are these?&lt;/h3&gt;
&lt;p&gt;You may note that at the bottom of the list of global variables are some odd looking variable names:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600148-05-variables-unusual.png&quot; alt=&quot;05 variables unusual&quot; width=&quot;600&quot; height=&quot;148&quot;&gt;&lt;/p&gt;
&lt;p&gt;They certainly are not the categories we have defined for our phrases, so what are they?&lt;/p&gt;
&lt;p&gt;These are special translations that are not for text that may appear on a layout directly (such as a label, tab or button).  They are translations for words that exist in records within the solution.  In fact this is one of the challenges of a multi-lingual solution that must be overcome - there are often times that data residing on records within a solution need to be translated.&lt;/p&gt;
&lt;h3&gt;What type of record data are we talking about?&lt;/h3&gt;
&lt;p&gt;It is very important here to make a distinction about what kind of record data we’re talking about translating. We are NOT talking about user-entered record data. We have no control over what data a user will type into a text field for example, and so we simply cannot provide translations for every possible thing they may type, that is ludicrous!&lt;/p&gt;
&lt;p&gt; What we are talking about here is record data that we know exactly what it is, and that will not change.  Typically this is record data for use in value lists for example, or record data for user interface purposes, such as a navigation portal.  Both of these examples are covered in the example file using this method, and we’ll talk about these a bit more later.&lt;/p&gt;
&lt;h3&gt;Defining a “Record” type Phrase.&lt;/h3&gt;
&lt;p&gt;Previously we were just talking about phrases for standard text in your solution on layouts, buttons and so forth. They were defined using categories.  Record phrases however are defined using the Primary Key ID of the record that is being translated, along with a special keyword to identify what it is on that record we are translating. Our phrase table has a type field named “phrase_type” that is set to either “Variable” or “Record” which helps us define what type of phrase it is. &lt;/p&gt;
&lt;p&gt;For record based phrases, we still use the category fields, but instead, our primary category is the ID of the record being translated, and the sub category is keyword to help identify what on that record is being translated. The keyword is important because there may be times where a record has more than one field that requires translation ,so the keyword helps create different variable names for each field being translated on that record.&lt;/p&gt;
&lt;h3&gt;Okay, time for a quick recap!&lt;/h3&gt;
&lt;p&gt;We’re about halfway through now, so lets just quickly recap what we have covered:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;3 tables - Languages, Phrases, and Translation&lt;/li&gt;
&lt;li&gt;For a given language, we generate global variables, 1 per phrase, that contain the translated word for chosen language&lt;/li&gt;
&lt;li&gt;We can then use these global variables throughout solution where required, e.g. labels, buttons, tabs, calculations, scripts etc.&lt;/li&gt;
&lt;li&gt;We have special global variables that are tied to a record/field to be translated (more on this shortly).&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; So it all boils down to a pretty simple framework really.&lt;/p&gt;
&lt;h3&gt;Let’s see it in action&lt;/h3&gt;
&lt;p&gt;Here’s an example of a layout that uses the global variables:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600284-06-layout.png&quot; alt=&quot;06 layout&quot; width=&quot;600&quot; height=&quot;284&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can see some merge-variables used for the field labels. The buttons (which are button bar segments) have calculated values set to global variables. The tab names are calculated global variables. And even the merge field contact_display_title makes use of a global variable.&lt;/p&gt;
&lt;p&gt;This is a great example actually of how we achieve multi-language in calculations. Lets look at that calculation in more detail:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage60098-07.png&quot; alt=&quot;07&quot; width=&quot;600&quot; height=&quot;98&quot;&gt;&lt;/p&gt;
&lt;p&gt;We have a contact chosen. We start by getting their name.  We also grab the translation of a special phrase used if no contact name is provided.  Next, we take another phrase we use for the string, and we replace a piece of defined placeholder text &amp;lt;&amp;lt;NAME&amp;gt;&amp;gt; with a value, that is either the contacts name, or our special “no name” phrase.&lt;/p&gt;
&lt;p&gt;If we look at the phrase definitions used:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600106-08.png&quot; alt=&quot;08&quot; width=&quot;600&quot; height=&quot;106&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can see in the first phrase we have our &amp;lt;&amp;lt;NAME&amp;gt;&amp;gt; placeholder. This is how we can insert actual record data into a translated piece of text.&lt;/p&gt;
&lt;p&gt;The second translation is what we will display if a contact has not been given a name.  Here is what it looks like in browse mode:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600247-09.png&quot; alt=&quot;09&quot; width=&quot;600&quot; height=&quot;247&quot;&gt;&lt;/p&gt;
&lt;p&gt;Pretty cool huh?!&lt;/p&gt;
&lt;h3&gt;Keeping data-entry as simple and universal as possible&lt;/h3&gt;
&lt;p&gt;Now we are going to get into some of the more challenging aspects of multi-lingual solutions, the first of which is value lists.&lt;/p&gt;
&lt;p&gt;But before we get stuck in we need to be clear in our understanding of what is translatable in a solution, and what is not.  Earlier we stated that no user-entered record data will be translated and we stand by that. You simply cannot provide a translation for what a user will type in as data on a record. For example, if you have an english-speaking user enter contact names, then those contact names are almost certainly going to be in english. If you have a Chinese person enter contact names, then they’re going to enter them in Chinese. Differences in the languages of entered data is something you just have to live with in a solution.&lt;/p&gt;
&lt;p&gt;There are some situations however, with careful planning that you can avoid these conflicts by being smart about the format of data that users are entering. So what do we mean by this?&lt;/p&gt;
&lt;p&gt;Lets say you have a field in your database called “Test Complete”. This is a straightforward boolean field with either a yes or no response. The user chooses a value using a value list.&lt;/p&gt;
&lt;p&gt;One way of data entry would be to provide the user with a value list of “Yes” and “No”. These are english words, and if you do that then the user is actually entering english words in as data onto that record. Then, what if a Chinese person then wants to enter data? Will they know the meaning of Yes and No in the value list? &lt;/p&gt;
&lt;p&gt;The solution to this problem is to at all possible opportunities come up with a universally recognised method of data entry that has the same underlying meaning across all languages.&lt;/p&gt;
&lt;p&gt;In this case, don’t use words. Instead, use a check-box. Store a “1” as a yes response, and store an empty value as a “No” response. Present it as a check-box to the user. Everyone understands the concept of a ticked box meaning “Yes” versus an unticked meaning “No” regardless of their language of choice.&lt;/p&gt;
&lt;p&gt;By providing the user with a visual means of data entry, like a check-box, versus a textual means of data entry like words, it means the method of entry becomes universally accepted and understood, and you remove any confusion you would otherwise have by presenting words to the user. The users need never see the actual underling fields value, providing it is always visually presented in a universally accepted format.&lt;/p&gt;
&lt;h3&gt;For times when this is not possible, a value list is required&lt;/h3&gt;
&lt;p&gt;Check-boxes are the main example for where you can universalise data entry. Another would be using colours for things like a priority value. But generally you will have to display a value list to the user for the purposes of selecting a value.  So how do we present a value list in a users native language?&lt;/p&gt;
&lt;p&gt;One problem we have in FileMaker is that if a value is chosen in one language, then the value will not appear in a value list based on a different language.  &lt;/p&gt;
&lt;p&gt;The solution is to think about storing where possible the primary key record ID’s, instead of the actual textual value.&lt;/p&gt;
&lt;p&gt;Here is a great example of this - selecting a country.  A country will always be the same country regardless of its name - the name is just a means to identify it. So if you need to select a country on a record, why not just create a table of countries, and store the ID of that country record?  This is another way in which you can universalise the data entered. A primary Key is a primary key in any language, and in most solutions we develop users will never be exposed to a primary key value anyway, to them it is meaningless.&lt;/p&gt;
&lt;p&gt;If value lists become tools for selecting primary key IDs, then what the user actually see is purely a visual component, and something we can manipulate to display in the users chosen language, and that is exactly what we do!&lt;/p&gt;
&lt;p&gt;Again, it is important to note, we’re talking here about record data that is known, and not likely to change or be modified by a user. We can easily build a table of countries and base a value list off that.  If instead we were to build a value list of contacts names and IDs, then we cannot translate contact names, and so a user in any language will always see just the names as they were entered onto contact records.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600196-10.png&quot; alt=&quot;10&quot; width=&quot;600&quot; height=&quot;196&quot;&gt;&lt;/p&gt;
&lt;p&gt;In our example file, we have a table of countries on the left. Each country has an ID, and a name. The name in this case is purely to help identify the record, and is likely to be in the developers native language. We won’t actually be using the country name on this record for display in a value list, instead we’ll be displaying a translation of that name instead.&lt;/p&gt;
&lt;p&gt;The table on the right is phrases, and we have 1 phrase record per country record. We link the phrase record to the country record through the countries primary key.  We are using a keyword “country” as the phrase identifier.&lt;/p&gt;
&lt;p&gt;We define translations for the phrases in the exact same way we did previously:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600193-11.png&quot; alt=&quot;11&quot; width=&quot;600&quot; height=&quot;193&quot;&gt;&lt;/p&gt;
&lt;p&gt;But in this case you’ll note we are dealing with phrases that are of type “record”.  The variable name contains the countries primary key value, and a keyword “country”.&lt;/p&gt;
&lt;h3&gt;Defining the Value List&lt;/h3&gt;
&lt;p&gt;This is not trivial unfortunately, and it’s a bit of extra leg-word to get the value list properly setup, but once done, it is really cool, promise!&lt;/p&gt;
&lt;p&gt;Think about what the value list actually needs to contain:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The ID’s of Country records&lt;/li&gt;
&lt;li&gt;Displaying the translated value, from the translation records. &lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The country ID resides on Phrase records, and the names reside on translation records. So in our definition of the value list, we need to relate to all phrase records that are for countries, and then relate to the translations for the selected language.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600591-13.png&quot; alt=&quot;13&quot; width=&quot;600&quot; height=&quot;591&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is the first relationship, from our base table occurrence (which could be anything really), to phrases.  We have 2 predicates. The first is finding all phrase records for a specific set of primary key values (country IDs), and the second is linking to the specific keyword which is “Country”.&lt;/p&gt;
&lt;p&gt;In fact, this is a bit overkill. If we wanted, we could actually just relate on the keyword “country” providing it is unique.   However the reason we do it as above is by relating to a specific set of records matching on ID’s, we don’t necessarily have to have a value list based on every phrase record for countries. We could control which countries are in our value list based on which ID’s we have on the left hand side of the relationship.&lt;/p&gt;
&lt;p&gt;In this case however the field “country_ids” on the left is basically a return-delimited list of every country primary key ID.&lt;/p&gt;
&lt;p&gt;Okay, so we have now a relationship to all phrase records for countries.  This serves as the basis of the first field in our value list. We will be using “category_primary” as the first field. Recall this field actually contains the country ID.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600591-14.png&quot; alt=&quot;14&quot; width=&quot;600&quot; height=&quot;591&quot;&gt;&lt;/p&gt;
&lt;p&gt;Next, we have a relationship to translations.  We first match on phrase so that we are only getting translations for the given phrase record. We then must filter further to the specific translation record for the language the user is currently viewing the solution in.&lt;/p&gt;
&lt;p&gt;Recall earlier we defined a global variable $$LANGUAGE_SELECTED_ID. We are now going to use that in the calculation field _CURRENT_LANGUAGE. This calculation simply contains a reference to the global variable.  Each time the language is changed by the user, the value of this calculation changes, and thus the relationship to specific translations changes to just those for the user chosen language.&lt;/p&gt;
&lt;p&gt;Here is our value list definition:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600649-15.png&quot; alt=&quot;15&quot; width=&quot;600&quot; height=&quot;649&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the first value is the country ID, second value is the associated translated country name for the users chosen language. &lt;/p&gt;
&lt;p&gt;We only show the displayed value, the user has no reason to see the ID or care that they are actually selecting an ID.&lt;/p&gt;
&lt;p&gt;Putting it all together here is what it looks like, first in English:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/16.png&quot; alt=&quot;16&quot; width=&quot;410&quot; height=&quot;129&quot;&gt;&lt;/p&gt;
&lt;p&gt;and then in German:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/17.png&quot; alt=&quot;17&quot; width=&quot;427&quot; height=&quot;134&quot;&gt;&lt;/p&gt;
&lt;p&gt;Note that regardless of the language chosen, the actual country chosen remains ticked in the value list and is displayed to the user in their chosen language.&lt;/p&gt;
&lt;h3&gt;Phew! We made it!&lt;/h3&gt;
&lt;p&gt;Value lists are tricky, and are indeed what we believe to be the most tricky part of a multi lingual solution. But they are possible and once you get the hang of how it works actually quite easily to setup and use.&lt;/p&gt;
&lt;p&gt;The next example is very similar to value lists as it involves displaying record data however this time it is not data the user is going to be entering into a field, it’s purely a visual/user interface thing. &lt;/p&gt;
&lt;h3&gt;Translating data in records for layout display&lt;/h3&gt;
&lt;p&gt;Often we’ll want to translate record data to the user where the record data is used as part of the interface. A classic example is building a portal-based navigation system, where the labels of screens will exist as data in a table.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/18.png&quot; alt=&quot;18&quot; width=&quot;216&quot; height=&quot;226&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is a simple portal containing records from a Navigation table. Each record corresponds to a layout in the solution the user can go to, or a function the user can do, such as logout.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600230-19.png&quot; alt=&quot;19&quot; width=&quot;600&quot; height=&quot;230&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is our table setup and phrase setup. This is identical to that of the value list setup. We have a navigation table on the left. The screen name here is purely for the developer to help identify what record is what.&lt;/p&gt;
&lt;p&gt;The phrase table on the right has 1 phrase record per navigation record, with an identifier “navigation”, and description. &lt;/p&gt;
&lt;p&gt;Now, you may wonder why even bother with a navigation table, why not just put your navigation directly into the phrase table? Well there is no reason as to why you couldn’t do this. You could simply treat the “Navigation” records in the phrase table as your actual navigation records. The reason why we don’t do this is we wan’t to keep the language, phrase and translation tables purely for multi-lingual purposes. We don’t want to clutter them with user interface elements or value list data. This is why in both the value list and this example we still have a separate table containing value list data and record display data.&lt;/p&gt;
&lt;p&gt;Anyways, back to the example!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600276-20.png&quot; alt=&quot;20&quot; width=&quot;600&quot; height=&quot;276&quot;&gt;&lt;/p&gt;
&lt;p&gt;Once again, the exact same setup of translations as before, we just choose a language and define the translation. Note the variable names here again contain the navigation ID and keyword.&lt;/p&gt;
&lt;h3&gt;Making use of having the ID in the variable name&lt;/h3&gt;
&lt;p&gt;We now finally can make use of having the record ID’s contained within the variable name. In the value list example while we still had variables declared for countries, we didn’t actually use them for the purposes of the value list. However in this instance we are going to make use of them. &lt;/p&gt;
&lt;p&gt;Given a navigation record, we know what its ID is.  We also know that it is for navigation. These 2 pieces of information should allow us to calculate what the global variable name associated with the record is. We know all language variables begin with $$LANG. We also know that the ID follows this in the variable name, and we know the Navigation keyword is on the end.&lt;/p&gt;
&lt;p&gt;To help us obtain the correct global variable, we have built a custom function, named &lt;strong&gt;@LANGUAGE_GetRecordTranslation&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600442-21.png&quot; alt=&quot;21&quot; width=&quot;600&quot; height=&quot;442&quot;&gt;&lt;/p&gt;
&lt;p&gt;This function receives 2 parameters - the ID and the keyword identifier.&lt;/p&gt;
&lt;p&gt;The function recreates what the name of the corresponding global variable should be, and then returns its value by evaluating it.&lt;/p&gt;
&lt;p&gt;We know that all spaces and hyphens are replaced with underscores when the variables are defined, so we build these same rules into this custom function to help reconstruct the variable name.&lt;/p&gt;
&lt;p&gt;And that’s it, pretty simple!  We can use this custom function in a calculation field directly on the Navigation table, and here it is:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/multilingual/_resampled/ResizedImage600322-22.png&quot; alt=&quot;22&quot; width=&quot;600&quot; height=&quot;322&quot;&gt;&lt;/p&gt;
&lt;p&gt;We run the custom function, telling it the navigation ID, and the keyword “Navigation”, and it will in turn give us the translated name of the navigation record, in the users currently selected language, brilliant!&lt;/p&gt;
&lt;h3&gt;That concludes the technical stuff&lt;/h3&gt;
&lt;p&gt;Congratulations, you made it! Pat yourself on the back!  We hope that wasn’t too confusing for you.  The basic concept of the framework is simply to follow, it’s just setting a bunch of words into global variables and then using those variables in your solution.&lt;/p&gt;
&lt;p&gt;The two gotcha areas are value lists, and translating data on records, but we have found ways to solve both of these issues.  In building real world multi-lingual solutions these were the only 2 complications and so we don’t anticipate many other issues….&lt;/p&gt;
&lt;p&gt;However…..&lt;/p&gt;
&lt;p&gt;There are actually other things you need to consider in building a multi-lingual solution. These are non-technical but you must be aware of them and be thinking about them as you develop.&lt;/p&gt;
&lt;h3&gt;No two words are created equal&lt;/h3&gt;
&lt;p&gt;In english, the word “Settings” is 8 characters long. In German - according to Google Translate - it is 17 ! (die Einstellungen)&lt;/p&gt;
&lt;p&gt;The implication of this is that if you are placing any text on your layout you must consider the variable widths of words in different languages.  If you place a label to the left of a field, then that label may look fine in English, but in German you may find the label is longer, and overlaps the field.  &lt;/p&gt;
&lt;p&gt;You need to be smart about text placement. For labels, consider placing them above the field instead of to the left. By placing them above, you are giving yourself much more room to accommodate labels that are wider or shorter in different languages. &lt;/p&gt;
&lt;h3&gt;Don’t rely on an online translator service&lt;/h3&gt;
&lt;p&gt;For this example file, we used Google Translate. Almost certainly the words are not 100% correct for the German and Spanish translations and for that we apologise. If you are building a real world multi-lingual solution, we could encourage you to enlist the help of someone who speaks the language that you are translating into, to assist with the translations. There is no substitute for someone who knows the language.&lt;/p&gt;
&lt;h3&gt;Plan your phrase naming convention early&lt;/h3&gt;
&lt;p&gt;This was touched upon earlier but needs to be reiterated. Make sure you come up with a good naming convention for your phrases early on in development that you are happy with. These serve the basis of your global variable names that you are going to be hard-coding throughout your solution, so make sure you don’t need to change their names down the track!&lt;/p&gt;
&lt;h3&gt;And finally, have fun!&lt;/h3&gt;
&lt;p&gt;Building a multi-lingual solution is challenging but incredibly rewarding. There is no sweeter feeling than selecting a different language and seeing your entire solution instantly change before your eyes, it is simply magic. Enjoy the process!&lt;/p&gt;
&lt;h3&gt;Extra Bonus - Making your Framework even better&lt;/h3&gt;
&lt;p&gt;If your solution runs server-side, consider making use of this when it comes time to load in your global variables. Depending on the size of your solution, retrieving all of the global variable declarations can be time consuming. This part of the process can quickly be handled by server using the Perform Script on Server script step. Ask server to get you a list of the required variable declarations so that you can load them in locally.  This will help improve the speed of selecting a different language.&lt;/p&gt;
&lt;p&gt;The scripts in this example file have PSOS capabilities built into them and are controlled by passing through a parameter to the script to indicate you want to use server-side processes.&lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;If you made it all the way here without having downloaded and looked at the example file then hats off to you, it must have been a tough read!  You can download the example file below which we would strongly encourage. It’s always better to see something in action and then figure out how it works than to try and read how it works before diving in.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;&lt;a title=&quot;MultiLingual Demo File&quot; href=&quot;https://www.teamdf.com/assets/blog-images/multilingual/MultiLingual.zip&quot; target=&quot;_blank&quot;&gt;MultiLingual.zip&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Sat, 01 Sep 2018 09:23:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/building-a-multi-lingual-application/</guid>
		</item>
		
		<item>
			<title>R&amp;D Tax Credits in New Zealand</title>
			<link>https://www.teamdf.com/blogs/r-and-d-tax-credits-in-new-zealand/</link>
			<description>&lt;p&gt;&lt;span&gt;There’s no doubt that a huge opportunity exists in many businesses to dramatically improve productivity, or even completely disrupt an industry, by using technology and innovation. Doing so takes vision and guts, of which we have plenty in NZ.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; However “Vision and Guts” aren’t quite enough — you’ll undoubtedly need some Money…&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/r-and-d-tax-credits/_resampled/ResizedImage659426-finding-money.png&quot; alt=&quot;finding money&quot; width=&quot;659&quot; height=&quot;426&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Spare capital is in notoriously short supply especially if you’re a startup or small company with modest means, but those are exactly the kinds of businesses that are hungry for growth and looking for opportunities. In fact I think this is where true entrepreneurship lurks…&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Enter a new government keen to stamp their mark on the landscape and lift NZ’s meagre level of investment in R&amp;amp;D (1.28% of GDP). The aim doesn’t particularly ambitious though: over 10 years the hope is to raise that level of investment to 2% of GDP, which is still well below the OECD average of 2.38%. In a nutshell we invest about half as much as our peers and even with 10 years of ramping that up we’re still not expecting meet the average!&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/r-and-d-tax-credits/_resampled/ResizedImage659459-r-and-d-spending.png&quot; alt=&quot;r and d spending&quot; width=&quot;659&quot; height=&quot;459&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;So to help kick things along they’re bringing in a new &lt;/span&gt;&lt;span&gt;R&amp;amp;D Tax Rebate&lt;/span&gt;&lt;span&gt; that takes effect from 1 April 2019. It works like this, I believe:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px; padding-right: 30px;&quot;&gt;&lt;span&gt;You can claim 12.5% of the value spent on a specified R&amp;amp;D project as a tax rebate. So you spend $100,000 on investigating and building an innovative new &quot;Thingamabob&quot; and you get to take $12,500 off your tax bill, which is quite nice.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;While the government is committed to making the scheme happen from that date, exactly what it will look like isn’t entirely locked down yet. There’s a &lt;a href=&quot;http://www.mbie.govt.nz/info-services/science-innovation/funding-info-opportunities/rd-tax-incentive/research-and-development-tax-incentive/rd-incentive-discussion-document.pdf&quot;&gt;&lt;span&gt;discussion paper&lt;/span&gt;&lt;/a&gt; that has been made publicly available and from that will come further discussion and possibly some changes before it’s drafted into the laws of the land.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;R&amp;amp;D Discussion Paper&quot; href=&quot;http://www.mbie.govt.nz/info-services/science-innovation/funding-info-opportunities/rd-tax-incentive/research-and-development-tax-incentive/rd-incentive-discussion-document.pdf&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/r-and-d-tax-credits/r-d-discussion-paper-cover.png&quot; alt=&quot;r d discussion paper cover&quot; width=&quot;300&quot; height=&quot;406&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;span&gt;Custom Software Development?&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;We’re particularly interested in the whole concept because we think a lot of projects your projects with us might qualify — after all what we do is build innovative new technological solutions that help business take on the world. Most projects we do involve determining a new approach (your research and ideas), and development on our part. As the owners of such projects, it would of course be you, our clients, that get the rebate — but that’s good for us too because it reduces the real cost of taking the plunge. &lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;&lt;span&gt;Things To Know&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;While the scheme is still only in proposal form we can see a few catches and things to bear in mind — here are 5 key aspects to keep in mind:&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;&lt;span&gt;1. Scientific Method&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span&gt;The current proposal includes a requirement that projects should adhere to “the scientific method”, which as I understand it means: &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;span&gt;“A systematic progression of work, that proceeds from hypothesis to experiment, observation and evaluation, and to logical conclusions.” &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Basically, a fair degree of discovery as you try things is to be expected and worked through in a logical way. The outcomes are somewhat uncertain at the beginning and will depend on what’s learned along the way&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Each project we work on is innovative and different, and they always evolve and change with testing and trial — which does seem to fit the definition of the “scientific method”.&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;&lt;span&gt;2. Minimum Spend $100k&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span&gt;Another catch is that you need to spend $100,000 in a financial year to qualify. That said there is also mention that certain suppliers might be deemed “Approved Research Providers” and that when using such a supplier you may still be able to claim the rebate without necessarily spending the $100k minimum. &lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;&lt;span&gt;3. Special Treatment for Software &lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span&gt;The paper is also a little vague on software R&amp;amp;D projects specifically:  &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/r-and-d-tax-credits/_resampled/ResizedImage550144-software-notes.png&quot; alt=&quot;software notes&quot; width=&quot;550&quot; height=&quot;144&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I think that’s a positive sign though because when clearly around half the R&amp;amp;D spend is going on software it needs to be well defined and clear what types of software development and which parts of the activity will qualify. &lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;&lt;span&gt;4. For Profitable Companies Only?&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span&gt;Another thing to bear in mind is that this type of funding is not a capital-injection and there’s an obvious rub with it right from the outset: you need to have tax to pay (i.e. be making a profit) in order to receive the benefit. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;So as it stands this scheme is not going to suit the innovative high growth startup type business that takes several years of mad growth before turning a profit. However the plan is to address that issue the following year (2020) but for now finding a way to provide benefit to non-profitable companies is in the too hard basket. &lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;&lt;span&gt;5. Qualifying Expenditure &lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span&gt;The discussion paper gives a couple of ways of defining what type of expenditure might be able to be included, but the good thing is that it looks like it will include both your own in-house costs, especially direct wages and resources used, plus external contractors such as us.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;&lt;span&gt;Conclusion&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;While we don’t profess to be experts and would advise you seek legal or financial advice before making any bets on this, we think the ideas here are an interesting start for at least one approach. What would also help would be the ability to fully expense R&amp;amp;D investments, particularly in software development of course, in the year they’re incurred. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;My take on it is that this scheme will make some modest benefits available to a much wider group of companies than the previous systems, but it’s not startling — more &lt;strong&gt;“useful and encouraging”&lt;/strong&gt;, which is probably ideal because what we really need is to build a culture of reinvesting in our businesses to improve and grow through productivity and innovation not just more man-power and number 8 wire.&lt;/span&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 18 Jun 2018 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/r-and-d-tax-credits-in-new-zealand/</guid>
		</item>
		
		<item>
			<title>FileMaker 17 Released</title>
			<link>https://www.teamdf.com/blogs/filemaker-17-released/</link>
			<description>&lt;p&gt;It’s that time of year again — when FileMaker Inc bestow upon the world the latest major update to the database platform we know and love. Funny how quickly this has become a practice: the annual update cycle… and personally I think it’s a great thing because not only can we plan for it reliably, but it also ensures the platform keeps moving forward at a steady pace. &lt;/p&gt;
&lt;p&gt;No doubt there are a few key questions in your mind if you’re running a business on a FileMaker database application, like:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Why upgrade?&lt;/li&gt;
&lt;li&gt;What’s new this year?&lt;/li&gt;
&lt;li&gt;Will there be any issues?&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;So let&#039;s take a look...&lt;/p&gt;
&lt;h2&gt;Why upgrade? &lt;/h2&gt;
&lt;p&gt;First off, with most people on a subscription type license now there’s no extra cost to upgrade, meaning there’s no financial reason not to. &lt;/p&gt;
&lt;p&gt;Importantly, new versions always include a lot of non-critical fixes and functional enhancements that don’t really make the headlines. A number of minor issues surface through the year and these get rolled into the next major release. &lt;/p&gt;
&lt;p&gt;Each new version always brings under the hood tweaks that make it faster, more robust and secure too — and those are qualities that we’re always looking at now with cloud hosting and access over the internet being the norm. &lt;/p&gt;
&lt;p&gt;So our advice? Keep with the times! &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;What’s new this year?&lt;/h2&gt;
&lt;p&gt;So aside from the general improvements and keeping up with the times, what is actually new this year? Well the definitive list of new features can be found here: &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;New Features in FileMaker 17&quot; href=&quot;https://fmhelp.filemaker.com/help/17/fmp/en/index.html#page/FMP_Help%2Fnew-features.html%23ww1133564&quot; target=&quot;_blank&quot;&gt;https://fmhelp.filemaker.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And we’d like to highlight a few that we think are the top 5 most important:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage143132-migration.png&quot; alt=&quot;migration&quot; width=&quot;143&quot; height=&quot;132&quot;&gt; &lt;/p&gt;
&lt;h4&gt;1. Data Migration Tool&lt;/h4&gt;
&lt;p&gt;This is going to make deploying a database update 100x easier! &lt;/p&gt;
&lt;p&gt;With the “DMT” you can develop separately from your production or live database, then complete testing (and fixing!), before deployment. Moreover deployment can be achieved without having to write complex data import scripts — scripts which often take hours or even days to complete on big databases.&lt;/p&gt;
&lt;p&gt;DMT opens up a world of opportunities because FileMaker solutions can now be productised more easily: if you’ve got hundreds of people (or even just 2) using copies of your database app, then there needs to be an easy way to issue and update and this tool helps solve that problem. &lt;/p&gt;
&lt;p&gt;It’s also going to be handy when fixing damaged databases because we can very quickly grab an empty clone (FileMaker Server should be set up to create a backup clone each night), then use the DMT to rapidly copy data from the corrupt database into the good clone. The DMT will fix broken records if it can.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage16180-sensors.png&quot; alt=&quot;sensors&quot; width=&quot;161&quot; height=&quot;80&quot;&gt;&lt;/p&gt;
&lt;h4&gt;2. Access to more sensors in iPhones and iPad&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;It’s almost scary how much your phone can know about the environment it’s in — from how many steps you’ve taken, to which direction it’s facing and whether it’s accelerating due to gravity, i.e. about to bounce on the concrete. I say ‘almost’ scary because thankfully Apple have built in protocols to ensure these sensors can only be accessed by apps if you allow them, and the good news is we can now access a whole lot more of the sensors from FileMaker database apps.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Aside from being a bit of fun, a key way to make mobile apps more usable is to have the application automatically read as much data as it can — Location is of course a good starting point, but we can now determine altitude, speed and acceleration, air pressure, step counts, and battery level.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage142120-notification.png&quot; alt=&quot;notification&quot; width=&quot;142&quot; height=&quot;120&quot;&gt;&lt;/p&gt;
&lt;h4&gt;&lt;span style=&quot;font-size: 1em;&quot;&gt;3. Notifications for iPhone and iPad&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Another handy features is the ability for apps to queue up notifications on the device — much like calendar reminders.&lt;/p&gt;
&lt;p&gt;Paired with the GeoFencing functionality this can be used to alert the user when they enter or leave an area or approach an iBeacon (useful for locating very specific points or objects).&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage144144-data-api.png&quot; alt=&quot;data api&quot; width=&quot;144&quot; height=&quot;144&quot;&gt;&lt;/p&gt;
&lt;h4&gt;4. Data API — with scripts&lt;/h4&gt;
&lt;p&gt;FileMaker has always offered a really good number of ways to connect with the outside world, and now with the “FileMaker Data API” — first introduced in a cut down beta form last year, fully fledged and ready for use we have THE industry standard way to make FileMaker data available to other services including a website. &lt;/p&gt;
&lt;p&gt;The Data API now supports scripts and images, for example if you have a website that needs to upload an image to FileMaker then run a script to process that it can all be done through this standardised and secure interface to the world. &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage122122-padlock.png&quot; alt=&quot;padlock&quot; width=&quot;122&quot; height=&quot;122&quot;&gt;&lt;/p&gt;
&lt;h4&gt;5. Account Lockout &lt;/h4&gt;
&lt;p&gt;This is an important security enhancement because it helps stop automated ‘cracking’ attempts, a real risk when you have a database app hosted in the cloud or available over the public internet. &lt;/p&gt;
&lt;p&gt;Basically all it does is lock the account (user name) being attempted if several password attempts fail in quick succession. After a few minutes, it’ll reset and you can try again if you’re legitimately trying to get in… &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Will there be any issues upgrading?&lt;/h2&gt;
&lt;p&gt;We’re not anticipating any problems at all, particularly for people switching up from FileMaker 16, but being a new release we generally recommend customers sit tight for a couple of weeks just to see if anything emerges before running the updates.&lt;/p&gt;
&lt;p&gt;We’ll be emailing all our customers with the news of the release and advice on when to go ahead and upgrade… each case might be slightly different so if you&#039;re in any doubt, give us a bell and we can advise...&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a title=&quot;Email Digital Fusion support&quot; href=&quot;mailto:support@teamdf.com&quot;&gt;support@teamdf.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Wed, 16 May 2018 02:51:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-17-released/</guid>
		</item>
		
		<item>
			<title>Introducing Paul Thomas</title>
			<link>https://www.teamdf.com/blogs/introducing-paul-thomas/</link>
			<description>&lt;p&gt;&lt;img class=&quot;right&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/paul-thomas-intro/paul-with-dog-260.jpg&quot; alt=&quot;paul with dog 260&quot; width=&quot;260&quot; height=&quot;304&quot;&gt;&lt;/p&gt;
&lt;p&gt;It’s not every day that we get to take on a new developer with a wealth of experience, so when one comes knocking at your door, you sit up and pay attention.&lt;/p&gt;
&lt;p&gt;This is what happened when our latest team member, Paul Thomas came knocking and we jumped at the chance to take him on.&lt;/p&gt;
&lt;p&gt;Paul (or PT as he is referred to around the office) comes to us with over 10 years FileMaker experience at AA Tourism.&lt;/p&gt;
&lt;p&gt;Being the sole developer at AA Tourism meant that he was a ‘jack of all trades’ which lends itself nicely to the sort of role he will have at Digital Fusion. We will be able to call upon his skills in designing and developing iOS apps in FileMaker Go, beautiful desktop apps in FileMaker Pro, and giving access to core user groups via FileMaker WebDirect.&lt;/p&gt;
&lt;p&gt;Outside of work, Paul is married with three children, two dogs and like most developers, gaming is top of the list of hobbies.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/paul-thomas-intro/paul-with-family-660.jpg&quot; alt=&quot;paul with family 660&quot; width=&quot;660&quot; height=&quot;440&quot;&gt;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot;&gt; &lt;em&gt;Welcome aboard Paul!&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 16 Jan 2018 14:34:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/introducing-paul-thomas/</guid>
		</item>
		
		<item>
			<title>Swipe Out!</title>
			<link>https://www.teamdf.com/blogs/swipe-out-iphone/</link>
			<description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;In our &lt;a title=&quot;Beautiful and Easy Drawer Menus blog article&quot; href=&quot;https://www.teamdf.com/blogs/beautiful-menus/&quot;&gt;previous article&lt;/a&gt;, we built beautiful drawer menus for desktop and iOS. These menus were horizontal in that they would slide in from either the left or right side of screen. This is achieved either through using a slide panel object, or through layout transition effects available in FileMaker Go (if you wish to have your menu as a separate layout). The sliding panel layout object gives us the power to use left/right swipe gesturing to close (or open) the menu.&lt;/p&gt;
&lt;p&gt;But what about vertical menus? That being a menu that slides up from the bottom of screen. In FileMaker Go you can achieve this effect through using the ‘Slide in from Bottom’ layout transition - brilliant! The user can then press a close button on the menu to reverse the process through using a ‘Slide out to Bottom’ transition effect, returning the user to their original layout.&lt;/p&gt;
&lt;p&gt;However one key element is missing from this equation which provides a much more intuitive and native iOS feel to this menu - the ability to swipe-down on the screen with your finger in order to dismiss the menu. In our horizontal menus, left and right swiping can be utilised through a panel control, but how do we achieve swipe down (or up for that matter)?&lt;/p&gt;
&lt;h3&gt;&lt;span&gt;First attempt using a sliding panel&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;When this challenge initially arose my first thought was to just use a sliding panel again. It already has swipe gesture, so surely there is a way to ‘flip it on its side’, right?&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/swipe-out/_resampled/ResizedImage660688-screenshot-1.png&quot; alt=&quot;screenshot 1&quot; width=&quot;660&quot; height=&quot;688&quot;&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately not! The rotate option is not supported for slide panels in FileMaker Pro - dang! But wait! All layout objects are just somes FileMaker XML and CSS underneath it all, so what if I could just modify that XML to add my own rotation?  To do this, I used &lt;a title=&quot;FileMaker Clip Manager&quot; href=&quot;https://www.myfmbutler.com/en/products/clip-manager-for-mac/6&quot; target=&quot;_blank&quot;&gt;myFMButler Clip Manager&lt;/a&gt; to retrieve and modify the XML:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/swipe-out/_resampled/ResizedImage659449-screenshot-2-xml-editor.png&quot; alt=&quot;screenshot 2 xml editor&quot; width=&quot;659&quot; height=&quot;449&quot;&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The rotation attribute can be seen above, we just modify it from 0 to 900 in order to rotate 90 degrees.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/swipe-out/_resampled/ResizedImage660576-screenshot-3.png&quot; alt=&quot;screenshot 3&quot; width=&quot;660&quot; height=&quot;576&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Voilà! Now we’re cooking! But does it work? Well yes and no. It works in the sense that you can click the dots to navigate the panels and you can script moving between panels. However actually putting anything useful inside the panel becomes a nightmare. If you copy/paste something simple like a label inside the panel, you’ll note it immediately rotates 90 degrees also to be in the same orientation as the panel. You can then rotate it again to have it correctly oriented. This is fine for simple things, but for more complex menus this becomes a real challenge to have the objects properly rotated and positioned.&lt;/p&gt;
&lt;p&gt;And then there is the positioning of objects. Using the keyboard it is somewhat manageable but given the rotation of the panel, all the directions are also rotated. So the up arrow moves an object right, the right arrow moves it down, and so on. But once you reach for the mouse and drag the object, then things reach a whole other level of weird as illustrated in this short video below.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;/p&gt;&lt;div class=&quot;media center&quot;&gt;&lt;iframe width=&quot;660&quot; height=&quot;371&quot; src=&quot;https://www.youtube.com/embed/0UOaQazPs0Y?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; title=&quot;Rotated Slide Panel&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;/p&gt;
&lt;p&gt;So basically the panel was a no go. Couple with the fact that when the panel was tried in FileMaker Go, the swipe gestures were still left &amp;amp; right even after it was rotated - the final nail in the coffin.&lt;/p&gt;
&lt;h3&gt;Back to the drawing board…&lt;/h3&gt;
&lt;p&gt;So now what? How else can we do a swipe down gesture? Other possibilities arose such as using the onGestureTap trigger, but this only capture finger taps, not swipes.  &lt;/p&gt;
&lt;p&gt;Then I thought of this:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/swipe-out/screenshot-4.gif&quot; alt=&quot;screenshot 4&quot; width=&quot;588&quot; height=&quot;439&quot;&gt;&lt;/p&gt;
&lt;p&gt;It’s called the rubber band effect, and is an effect that has been in FileMaker Pro/Go for a few versions now. (FULL DISCLOSURE: I am completely ignorant of FileMaker on Windows so have no idea if this is present there).&lt;/p&gt;
&lt;p&gt;In FileMaker when using a scrolling device in FileMaker Pro or your finger in FileMaker Go, you can effectively drag the layout down/up beyond its normal position. When you release your scrolling device, the layout ‘bounces back’ to its original position. A seemingly useless artefact of the operating system one would presume, particularly when it relates to FileMaker Pro and seemingly has no use.  This rubber band scrolling was first introduced with the original iPhone (you can read all about it on &lt;a title=&quot;The &amp;quot;rubber band&amp;quot; effect on iPhone&quot; href=&quot;https://www.cultofmac.com/489256/bas-ording-rubber-band-effect-iphone/&quot; target=&quot;_blank&quot;&gt;Cult of Mac&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;In more recent times however this rubber band effect has been utilised as a method to perform some secondary action in iOS apps. Most notable of those is to refresh the current view. Apps like Instagram, Facebook and Strava to name a few all utilise this swipe-down-and-release to refresh the current page.&lt;/p&gt;
&lt;h3&gt;But can we use it in FileMaker?&lt;/h3&gt;
&lt;p&gt;That was the 64 million dollar question. This is as close (currently) to a swipe-down effect as we have. Can it be utilised to somehow perform a script when the user swipes down to produce the rubber band effect?&lt;/p&gt;
&lt;p&gt;To make any use of it, we need to be able to detect when the rubber band effect is being performed, and secondary to that, we need to be able to control at which point during the effect we should be triggering a script to perform an action, in this case closing the menu.&lt;/p&gt;
&lt;h3&gt;GetLayoutObjectAttribute provides the solution&lt;/h3&gt;
&lt;p&gt;Our trusted friend - GetLayoutObjectAttribute - comes through in the clutch for us yet again. This handy function can tell us some useful properties of layout objects. In this case we use the “Top” coordinate property of a layout object.&lt;/p&gt;
&lt;p&gt;On our layout, we place an object. It doesn’t really matter where on the layout it is placed, or what type of object it is. Give that layout object a name. Now we can use GetLayoutObjectAttribute ( “ObjectName” ; “Top” ) to determine where that object is relative to the top of the window.&lt;/p&gt;
&lt;p&gt;The key point here is that the top attribute of a layout object changes during the rubber band effect. As the layout is moved down the screen, all of the top coordinates of objects on the layout increase. Conversely, they decrease as the layout is swiped up - even into negative coordinates for those that go above the top of the screen.&lt;/p&gt;
&lt;p&gt;So to recap: When you first go to the layout, the object will have a top coordinate. Then, as you drag the layout down, the top coordinate of that object increases. Are you beginning to see how this can be useful?&lt;/p&gt;
&lt;h3&gt;An onTimer pulls everything together&lt;/h3&gt;
&lt;p&gt;Knowing that the top coordinate increases is not quite enough. We need some means by which to detect when the top coordinate hits a given value, and to run a script at that point. There is no such thing as “onRubberBandEffect” trigger sadly! &lt;/p&gt;
&lt;p&gt;To do this we use an onTimer script. When the user first enters the menu layout, we install an onTimer to run every 0.1 seconds.  This script is tasked with checking the top coordinate of our special object and waiting for it to reach a certain value. When that value is reached the script performs the desired action - in this case closing the menu.&lt;/p&gt;
&lt;p&gt;For all of this to work smoothly, our onTimer script should not reference, or set any record data. It should also be doing no heavy lifting such as refreshing the window or committing records. These actions would cause slight pauses in the script execution and create a bad user experience because the user will see that there is something running in the background.&lt;/p&gt;
&lt;p&gt;Fortunately in this case our script can be very light weight - all it does is evaluate the GetLayoutObjectAttribute function, and check to see if it is at a given value, if not, it does nothing. Given this is so quick and low cost, the user has no visual indication that a script is running at all which is exactly what we want!&lt;/p&gt;
&lt;h3&gt;What does our onTimer script do?&lt;/h3&gt;
&lt;p&gt;The purpose of the onTimer script is pretty simple, and can be summarised as below:    &lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;span&gt;When the menu loads, store the layout objects top coordinate for future use&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Subsequently, compare the current top coordinate of the object with its original coordinate&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;When the top coordinate hits a nominated value greater than the original coordinate, close the menu&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;And that’s it, pretty simple!&lt;/p&gt;
&lt;p&gt;&lt;span&gt;To illustrate what the top coordinate is doing, have a look at the video below which shows our demo file in action. As we drag down with our finger, you’ll see the top coordinate value at the top of screen increase. When it hits our designated position, we close the menu, and thats all there is to it!&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;/p&gt;&lt;div class=&quot;media center&quot;&gt;&lt;iframe width=&quot;660&quot; height=&quot;371&quot; src=&quot;https://www.youtube.com/embed/_OuVIHnOZqY?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; title=&quot;Rubber Band Dragging&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Well, not quite all there is to it, there is one more thing&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;Not all layouts exhibit the rubber band effect. Your layout has to be setup in just the right away in order to produce the rubber band effect. The rubber band effect only appears when the layout is scrollable and so if your layout dimensions are too perfect (i.e. they match exactly your devices dimensions) then you may not end up with any scrolling at all.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The answer is to make your layout just slightly taller than the default height by a few points. Not enough to give any hint of a scroll bar, but just enough to introduce the rubber band effect. You don’t need this on every layout, just those where you want to utilise this technique.&lt;/span&gt; &lt;/p&gt;
&lt;h3&gt;&lt;span&gt;Other potential uses&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;I hope this article has sparked some other ideas and potential uses for you. One such idea we thought of would be to replicate a native applications use of the rubber band effect to carry out a refresh action. You may be developing an offline solution which pulls data from a remote location, or your layout might simply require a ‘refresh window’ every so often to keep it up to date. &lt;/p&gt;
&lt;p&gt;&lt;span&gt;Native apps tend to put an icon in the refresh area that reveals itself during the rubber band effect. Can we do the same in FileMaker? Well surprisingly again the answer is yes!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/swipe-out/_resampled/ResizedImage660489-screenshot-5-demo-file.png&quot; alt=&quot;screenshot 5 demo file&quot; width=&quot;660&quot; height=&quot;489&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This grey area shown above that reveals itself during the effect is actually the ‘layout background’ style.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/swipe-out/screenshot-6-inspector.png&quot; alt=&quot;screenshot 6 inspector&quot; width=&quot;270&quot; height=&quot;530&quot;&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It is accessed by making sure no other object or part is selected on your layout. Options are fairly limited and you only really have a fill option. One of the fill options however is to use an image. If you use an image as your layout background then this image reveals itself as you drag down on the layout!&lt;/p&gt;
&lt;p&gt;Simply set your background image to one with a reload icon positioned at the top of it, and this should appear as you drag. In the video below we show what this looks like. Our background image is relatively the same size as our device screen. Most of the image is a transparent png, with a little refresh icon at the top of the image.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;/p&gt;&lt;div class=&quot;media center&quot;&gt;&lt;iframe width=&quot;660&quot; height=&quot;371&quot; src=&quot;https://www.youtube.com/embed/dWNjByt_jUI?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; title=&quot;Layout Background Icon&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Pretty nifty huh?&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;span&gt;Finally a nice wee gem in the Demo file&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;I’ve included a bonus technique inside the demo file (completely unrelated but equally awesome). The technique is very simple and is an easy way to render SVG animations inside a web viewer.  Check out &lt;a title=&quot;Link to loading.io website&quot; href=&quot;http://loading.io/&quot; target=&quot;_blank&quot;&gt;http://loading.io&lt;/a&gt; to accompany this - a very awesome website with some amazing tools to use in conjunction with this technique. Give your solutions a bit more vibrancy and visual feedback.&lt;/p&gt;
&lt;h4&gt;Demo file&lt;/h4&gt;
&lt;p&gt;No weetbicks article would be complete without a demo file to accompany it. You can download the demo file below. Once you’ve read the article everything should be fairly straightforward and make sense. Just note that to really get the most out of demonstrating the technique you should be using it on an iPhone or iPod touch. While Macs also have the rubber band effect, it doesn’t really work that great on a laptop or desktop - this really is an iOS technique only.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://www.teamdf.com/assets/Uploads/swipe-out.zip&quot; target=&quot;_blank&quot;&gt; Click here to download the demo file&lt;/a&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;/p&gt;</description>
			<pubDate>Wed, 13 Dec 2017 04:39:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/swipe-out-iphone/</guid>
		</item>
		
		<item>
			<title>Master and Apprentice - Queenstown Marathon</title>
			<link>https://www.teamdf.com/blogs/master-and-apprentice-queenstown-marathon/</link>
			<description>&lt;p&gt;As the sales guy, I spread the myth that the developer sorts are just geeks, who at the whiff of fresh air or sunlight head back inside to keep coding.&lt;/p&gt;
&lt;p&gt;On the contrary though, at Digital Fusion there’s an underbelly of rebel runners and none more so than the godfather, Stephen Baker.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;right&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/qt-marathon/stephen-running.png&quot; alt=&quot;Stephen running&quot; width=&quot;248&quot; height=&quot;450&quot;&gt;&lt;/p&gt;
&lt;p&gt;To sum up Steve, some say he runs more kilometres in a day than he speaks words. If you follow him on Strava you will see that pretty much everyday he’s out there pounding the pavement. With 10 Marathons already under his belt it’s fair to say he’s truly a master of the marathon. &lt;/p&gt;
&lt;p&gt;In the Apprentice corner you find myself, having run a couple of half marathons and the full once, albeit very slowly. But around six months ago, this was all about to change with the apprentice signed up to take on the master, namely both of us running the &lt;a title=&quot;Link to the Official Queenstown Marathon web site&quot; href=&quot;https://queenstown-marathon.co.nz&quot; target=&quot;_blank&quot;&gt;Queenstown Marathon&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The apprentice decided that to conquer the beast would take skill, resolve, and someone else telling him what to do. I enlisted the help of two coaches based out of Sydney and got to work.&lt;/p&gt;
&lt;h3&gt;Training&lt;/h3&gt;
&lt;p&gt;From a shocking first five km run, I gradually pulled myself up to some level of fitness. Six months is a long time to keep running, particularly when you have a coach tracking everything you do. Keeping yourself honest is one thing; keeping a coach happy is another altogether.&lt;/p&gt;
&lt;p&gt;Well after much training and getting up to the ridiculous level of running 35km’s (in the rain no less), the time was ripe to dethrone the master. But….&lt;/p&gt;
&lt;p&gt;Three weeks out I pulled up lame, having blown my right calf muscle. Many physio appointments later it was decided that there was no way the calf could withstand a four hour run so I sadly withdrew my entry from the marathon. The folk that run the Queenstown Marathon kindly offered to downgrade me to the 10km which I thought would at least be a nice walk around the lakes of Queenstown.&lt;/p&gt;
&lt;p&gt;The master had shown the apprentice that it was indeed a marathon and not a sprint.&lt;/p&gt;
&lt;h3&gt;Race Day&lt;/h3&gt;
&lt;p&gt;So come last Saturday, the two of us made the trek down to Central Otago, donned our Team DF running kit, and set out on our respective runs through the stunning Queenstown scenery, along with close to 10,000 other runners! &lt;/p&gt;
&lt;p&gt;From my perspective, I started on the basis that if I could feel my calf hurting I would pull up and walk the remainder of the event. Fortunately there was no pain and I managed to run the whole way, in what was quickly becoming a very warm day.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/qt-marathon/_resampled/ResizedImage600455-stuart-running.png&quot; alt=&quot;stuart running&quot; width=&quot;660&quot; height=&quot;500&quot;&gt;&lt;/p&gt;
&lt;p&gt;Steve set out on the marathon around 8am and word got out fairly early that Queenstown wasn’t going to be offering up any “personal bests”. At 26°C and no wind at 9am, there were plenty of people struggling. The good news was the Steve finished the event and retained his rightful title of DF’s Master of Marathons, knocking off his 11th Marathon in a respectable time. &lt;/p&gt;
&lt;p&gt;All up the event was awesome, in quite possibly the most beautiful place in the world. I think the master and the apprentice both have unfinished business so this blog post might need a little updating in 12 months.  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/qt-marathon/done-running.jpg&quot; alt=&quot;Medal and Shoes — Done Running!&quot; width=&quot;338&quot; height=&quot;370&quot;&gt;&lt;/p&gt;
&lt;p&gt;Editors note: As you’ll note in the photo of Stu, seen zooming past other runners, he nailed the 10k run, finishing 8th in his class. Well done both of you — you’re an inspiration to the rest of us.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;</description>
			<pubDate>Tue, 21 Nov 2017 15:54:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/master-and-apprentice-queenstown-marathon/</guid>
		</item>
		
		<item>
			<title>Zero to App in 3 Weeks</title>
			<link>https://www.teamdf.com/blogs/quick-we-need-an-app/</link>
			<description>&lt;h2&gt;&lt;span style=&quot;font-size: 1.5em;&quot;&gt;The Back Story&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;Danny Hui is a man on a mission, and it’s an incredibly special mission that is very close to his heart.&lt;/p&gt;
&lt;p&gt;When you have a child with disabilities, you look for ways to make their lives easier and better, as well as yours as a parent.&lt;/p&gt;
&lt;p&gt;Danny and his wife Jess have gone to extraordinary lengths to offer their son Monty, the opportunities that most children would have, like walking unassisted or running around a park — the simple daily activities we take for granted that are huge challenges.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;Monty Hui&quot; src=&quot;https://www.teamdf.com/assets/blog-images/sameview/_resampled/ResizedImage659367-monty.png&quot; alt=&quot;Monty Hui&quot; width=&quot;659&quot; height=&quot;367&quot;&gt;&lt;/p&gt;
&lt;p&gt;With challenges like this it&#039;s a team effort to get the best outcomes, from advisors to family caregivers, all offering their advice around the best approach and what to expect. In one of our first discussions with Danny, he mentioned they have something like 20 different points of contact that are regularly consulting on their son: doctors, therapists, grandparents, the list goes on.&lt;/p&gt;
&lt;p&gt;What Danny very quickly realised is that with such a big team comes a mismatch of communication. Not everyone has the same information; there’s no one place to gather and share knowledge and progress; and it’s just too easy to find that not everyone involved is on the same page.&lt;/p&gt;
&lt;p&gt;A prime example centres around Danny&#039;s son heading to school next year: he needs to get a chair, but because he’ll be at school, there&#039;s an array of people who need to approve the type of chair that would be best for Monty’s needs, from the school principal, to therapists, everyones input needs to be factored in. And the way that it’s always been done is to have all the details about the chair in a folder, and you cart this around the different therapists and meetings…&lt;/p&gt;
&lt;h2&gt;&lt;span style=&quot;font-size: 1.5em;&quot;&gt;The Front Story&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;So if the above is the back story, you can guess what Danny has set out to do, which is nicely encapsulated in his company name — introducing:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/sameview/_resampled/ResizedImage37560-sameview-logo.png&quot; alt=&quot;sameview logo&quot; width=&quot;375&quot; height=&quot;60&quot;&gt; &lt;/p&gt;
&lt;p&gt;&lt;span&gt;Danny had the idea that if he built an app, then everyone would have the same view of what care and requirements are needed, how his son was progressing, and of his therapy and action plans.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So he got to work, giving up his full time job to take on something he is immensely passionate about. He entered the world of “&lt;a title=&quot;Link to a definition of Social Enterprise&quot; href=&quot;https://en.wikipedia.org/wiki/Social_enterprise&quot; target=&quot;_blank&quot;&gt;Social Enterprise&lt;/a&gt;” and envisioned an app to help track and share information for Monty and others like Monty.&lt;/p&gt;
&lt;p&gt;As part of his research, he realised that he needed to get something up and running quickly which he could get in the hands of families to start testing. How these families used the app would help make design decisions for further development.&lt;/p&gt;
&lt;p&gt;The question then became: How can you design and develop a mobile app fast, and deploy it to a group of people with minimal fuss?&lt;/p&gt;
&lt;p&gt;As a long term user and advocate of FileMaker, he started considering this as a rapid development platform. He approached Digital Fusion in May 2017 to discuss the project and get our thoughts on moving forward.&lt;/p&gt;
&lt;p&gt;We were blown away by the thought and consideration that Danny had already put into planning the app. Our part was to take these initial ideas and work them into a practical solution through an initial Analysis and Design phase.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Wireframes for a “minimum viable product” were drawn up, discussed, changed, and finally locked in. A plan was put in place for development that would see the app up and running quickly, but which was also very flexible to make sure we could make changes as feedback was received.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;img class=&quot;center&quot; title=&quot;sameview app screenshots&quot; src=&quot;https://www.teamdf.com/assets/blog-images/sameview/_resampled/ResizedImage659369-app-views.png&quot; alt=&quot;sameview app screenshots&quot; width=&quot;659&quot; height=&quot;369&quot;&gt;&lt;/p&gt;
&lt;p&gt;FileMaker Go makes for a brilliant platform to develop an iOS app quickly. Not only is it econmic to develop with, but we were able to get it out to the families quickly for testing.&lt;/p&gt;
&lt;p&gt;We also used FileMaker Pro and FileMaker Server to host the central database behind the app, and to provide management tools such as usernames and password administration, usage tracking, and overall giving Danny the ability to self manage the app.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;sameview backend admin app&quot; src=&quot;https://www.teamdf.com/assets/blog-images/sameview/admin.png&quot; alt=&quot;sameview backend admin app&quot; width=&quot;660&quot; height=&quot;343&quot;&gt;&lt;/p&gt;
&lt;p&gt;The end result is now being tested by facilities across Australia and Danny continues to look at modelling the business side of the app.&lt;/p&gt;
&lt;p&gt;What would have cost a lot of money to build as a native iOS app (think 100’s of thousands of dollars and many months) was developed in FileMaker at a fraction of the cost and time. &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Kicker&lt;/h2&gt;
&lt;p&gt;All the while we have been discussing and developing Danny&#039;s app, he has been part of the Optus Future Makers programme. The programme is focused around innovators who have an idea or business that will benefit disadvantaged youth.&lt;/p&gt;
&lt;p&gt;It’s a pretty special opportunity that Optus offers, with full day workshops to teach the innovators ways to bring their ideas to life. There is the added benefit that they award funding to some of these innovators, with the chance to then go onto the APAC regional section as part of a SingTel (the big Singaporian telecommunications company) accelerator programme.&lt;/p&gt;
&lt;p&gt;Well, we are super stoked to announce that Danny was successful, in fact very successful in the programme, and was awarded entry into the APAC region Future Makers programme along with a substantial fund for further developing his product. &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;Danny Hui — Optus Future Maker&quot; src=&quot;https://www.teamdf.com/assets/blog-images/sameview/_resampled/ResizedImage659438-danny.jpeg&quot; alt=&quot;Danny Hui — Optus Future Maker&quot; width=&quot;659&quot; height=&quot;438&quot;&gt;&lt;/p&gt;
&lt;p&gt;The money is going to substantially help Danny and Jess realize their dreams by removing some of the financial pressures of self-funded app developement.&lt;/p&gt;
&lt;p&gt;Digital Fusion are immensely proud to have worked with Danny, he is a very special person whose work will make disability care more coordinated, easier for everyone and ultimately bring better outcomes to many families. &lt;span style=&quot;font-size: 10px;&quot;&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 14 Nov 2017 17:26:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/quick-we-need-an-app/</guid>
		</item>
		
		<item>
			<title>Team DF Goes Racing</title>
			<link>https://www.teamdf.com/blogs/team-df-racing/</link>
			<description>&lt;p&gt;&lt;span&gt;Have you ever wanted to live out your childhood dream of racing a car around a track at very fast speeds?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Well our CEO, Craig Saunders, had that dream and last year decided to give it a crack with the advent of an entry level series called the &quot;2K Cup&quot;&lt;/p&gt;
&lt;p&gt;The key thing about this series is in the name: &#039;2K&#039; means your car must be able to be bought for $2000 or less on the open market. Sure, you can (and should) add a roll cage and safety kit, but performance modifications are prohibited to keep the cost down.&lt;/p&gt;
&lt;p&gt;Well the 2016 season passed and Craig found himself enjoying the sport, and the company of other petrol heads, so when the series sponsorship was up for grabs he raised his hand. He reckoned that after the first season he could clearly see that he wasn&#039;t going to win personally, so by getting &quot;Digital Fusion&quot; onto every car in the series we could be sure of sponsoring the winning car. (You can see why he&#039;s the boss.)&lt;/p&gt;
&lt;p&gt;We are now pleased to announce that the South Island version of the sport is called the &lt;strong&gt;Digital Fusion 2K Cup:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;Digital Fusion 2K Cup Banner&quot; src=&quot;https://www.teamdf.com/assets/blog-images/2kcup-intro/_resampled/ResizedImage65880-2kcup-banner.png&quot; alt=&quot;2kcup banner&quot; width=&quot;658&quot; height=&quot;80&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;This means Digital Fusion branding is splashed over all the cars, and our message to &quot;Get Ahead&quot;, whether that be through racing or through better business software, is being spread to the masses.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;2K Cup racing - Get Ahead&quot; src=&quot;https://www.teamdf.com/assets/blog-images/2kcup-intro/_resampled/ResizedImage660440-2kcup-side.jpg&quot; alt=&quot;2kcup side&quot; width=&quot;960&quot; height=&quot;640&quot;&gt;&lt;/p&gt;
&lt;p&gt;And what would motorsport be without a team? So we have nabbed a young whipper snapper from &lt;a title=&quot;Website for Custom D&quot; href=&quot;https://customd.com&quot; target=&quot;_blank&quot;&gt;Custom D&lt;/a&gt; and have him driving in a Team DF car. (Incidentally, Custom D did the graphic design for the car, which we think is a pretty cool way to use our logo huh?)&lt;/p&gt;
&lt;p&gt;So if you ever find yourself at a loose end over summer, and you are in the South Island of New Zealand, do head out to your local circuit and give Craig and Josh a cheer.&lt;/p&gt;
&lt;div class=&quot;captionImage center&quot; style=&quot;width: 660px;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;2K Cup cars - Craig and Josh&quot; src=&quot;https://www.teamdf.com/assets/blog-images/2kcup-intro/_resampled/ResizedImage660440-2kcup-craig-and-josh.jpg&quot; alt=&quot;2kcup craig and josh&quot; width=&quot;660&quot; height=&quot;440&quot;&gt;&lt;h3 class=&quot;caption center&quot;&gt;Update — March 2018&lt;/h3&gt;
&lt;p class=&quot;caption center&quot;&gt;Craig&#039;s finally had a tidy enough run to actually publish an in-car video of one the races — in this it&#039;s a handicap start too, where the slowest cars get a head start:&lt;/p&gt;
&lt;p class=&quot;caption center&quot;&gt;&lt;div class=&quot;media leftAlone&quot;&gt;&lt;iframe width=&quot;660&quot; height=&quot;371&quot; src=&quot;https://www.youtube.com/embed/hvmRvbKP_MA?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; title=&quot;2K Cup SI Race 4 March 2018&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p class=&quot;caption center&quot;&gt; &lt;/p&gt;
&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Fri, 27 Oct 2017 07:54:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/team-df-racing/</guid>
		</item>
		
		<item>
			<title>Tesla Roadtrip DevCon 2017</title>
			<link>https://www.teamdf.com/blogs/tesla-roadtrip/</link>
			<description>&lt;p&gt;&lt;span&gt;The 2017 FileMaker DevCon was held in Phoenix Arizona, a few hundred miles inland from Los Angeles, where flights from NZ land, so rather than catch another flight I figured a drive would be more interesting…&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;I&#039;m Thinking...&lt;/h2&gt;
&lt;p&gt;I’ve always been a “petrol head”, I love cars, driving and high performance engines, but now the with the rise of the electric vehicle I have a new perspective on things… &lt;/p&gt;
&lt;p&gt;&lt;span&gt;It has occurred to me that the internal combustion engine really is a kludge — a work around, an extremely complex, highly refined, remarkably engineered work-around to convert explosions into motive power. To see what I mean think about the systems that a petrol engine needs to work successfully: fuel, lubrication, cooling, transmission, exhaust, crank and electrical. In fact you have to have an electric motor just to get things started.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The modern combustion engine is a marvel to behold, an engineering and manufacturing triumph, but wow is it complex!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/tesla-roadtrip/_resampled/ResizedImage408276-M3-V8.png&quot; alt=&quot;M3 V8&quot; width=&quot;408&quot; height=&quot;276&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The electric motor on the other hand is dead simple. Some magnets and coils of wire, feed in an electric current and you get rotational motion.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So I believe the days of combustion engines — for main stream transport anyway, are numbered. We already have viable electric cars that perform well — fantastically well in fact — and can achieve a decent range between charges… there’s the rub though, with charging taking up to several hours. So petrol engines still have that ace up their sleeves — the 5 minute “recharge”. But when you factor in the advances coming in batteries and charging… in a few years those issues will be gone: range will double or better and much faster charging rates look like being possible. In fact I think battery technology is like the silicon chip: it’s probably the key driver of much of the technological innovation we see now — they’re everywhere, enabling devices and sensors to pervade our lives, whether we like it or not.&lt;/p&gt;
&lt;p&gt;So that brings me to some real questions: When do you switch? How good are the best electric cars now? And what is it like to have to recharge your car on a road trip?&lt;/p&gt;
&lt;h2&gt;&lt;span style=&quot;font-size: 1.5em;&quot;&gt;Road Trip!&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;I figured the best way to find out for myself would be a road trip — a pretty decent trip, not just some city driving and a quick blast through the hills, but an 1300 kilometre return trip from LA to Phoenix in a &lt;strong&gt;Tesla Model X&lt;/strong&gt;. Through a scorching desert where you &lt;strong&gt;will die&lt;/strong&gt; if stranded. Or if the aircon stops.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/tesla-roadtrip/_resampled/ResizedImage650317-desert-road.jpg&quot; alt=&quot;desert road&quot; width=&quot;650&quot; height=&quot;317&quot;&gt;&lt;/p&gt;
&lt;h3&gt;&lt;span style=&quot;font-size: 1.5em;&quot;&gt;Turo&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;First problem: how do you hire one?&lt;/p&gt;
&lt;p&gt;A quick check of the mainstream rental companies revealed… nothing. But then a web search revealed Turo, a new way of renting cars from private individuals — essentially this is AirBnB for cars, and the result is a huge variety of vehicles including some very exotic and unusual options…&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/tesla-roadtrip/_resampled/ResizedImage649212-turo-cars.png&quot; alt=&quot;turo cars&quot; width=&quot;649&quot; height=&quot;212&quot;&gt;&lt;/p&gt;
&lt;p&gt;Signing up for Turo, uploading my NZ drivers license and getting ready to hire was a breeze — a hell of a lot easier than signing up with any of the old school rental companies, that is for sure. I can see yet another big industry disruption going down here — watch out car rental companies.&lt;/p&gt;
&lt;p&gt;So I found a very nice 2016 Tesla Model X 90D. The choices available meant I could even find a colour and interior combo I liked, complete with the rather unique 6 seat configuration. Sweet!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/tesla-roadtrip/seat-config.png&quot; alt=&quot;seat config&quot; width=&quot;476&quot; height=&quot;237&quot;&gt;&lt;/p&gt;
&lt;h2&gt;&lt;span&gt;UX&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;To use the language of our industry, what was the User Experience (UX) like? i.e. What was it like to drive? &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Quite simply the Model X is a beautiful machine to drive, with strong acceleration even at higher highway speeds (80-90 mph) and power that is instant and smooth. And it steers and handles with precision and confidence — our driving was city streets and freeways, but I’m betting it would’ve felt sublime carving out some twisty back roads too (i.e. New Zealand). &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It’s true, there is no visceral V8 tearing apart the airwaves like my M3 but… it just doesn’t matter. I think until you’ve experienced it you can’t really understand this. Don&#039;t get me wrong the sound of the M3 is just fantastic, but the Tesla doesn&#039;t lack for not having it — in the same way petrol cars didn&#039;t need the sound of hooves, electric cars just don&#039;t need to roar.&lt;/p&gt;
&lt;h2&gt;Baptism by Fire&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;So it turns out that heading out into that lovely scorching desert with limited range and big distances between chargers might’ve been slightly foolhardy, at least for the inexperienced EV driver.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The trip computer calculates your journey nicely — all you do is put in the destination and it tells you exactly where you’ll need to stop and how long for. It worked out the journey with a couple of stops of about 40 minutes, even though the journey could theoretically be done in one stop — that’s because the Superchargers “fill up” better for the first 3/4 of the battery capacity so it’s not worth waiting for a complete top up. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;HOWEVER, if you leave with ‘just the right amount’ and then drive this car with any sort of vigor you will find that the range you thought you had, rapidly disappears. This can be a problem.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Tesla has your back though, and it’ll start pointing this fact out: “Stay below 70 mph to get to your destination” … at first I didn’t take that too seriously, I could see that the battery range was still greater than the distance left…&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;However continuing to drive briskly and with some incline or altitude or heat, or maybe a combination of all of the above, led to “Stay below 65 mph”. This brought on a fair dose of Range Anxiety. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I slowed down, moved to the slow lane and watched the big rigs I&#039;d passed earlier haul ass on the Model X. Argh.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Pulling in to Quartzite, small town in the middle of the desert, things were getting pretty marginal and life support systems were on the verge of shutdown. Dire:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/tesla-roadtrip/_resampled/ResizedImage60047-range-anxiety.png&quot; alt=&quot;range anxiety&quot; width=&quot;600&quot; height=&quot;47&quot;&gt;&lt;/p&gt;
&lt;p&gt;My passenger, fellow FileMaker developer CJ from LA, came with the bright idea that we install an exercycle in the passenger footwell to generate some extra power. Fortunately Quartzite has a Tesla Super Charging station.&lt;/p&gt;
&lt;h2&gt;Destination&lt;/h2&gt;
&lt;p&gt;On arrival at the JW Marriott Desert Ridge Resort in Phoenix, the Tesla was again down to the last few miles so my first question to the bellhop was “What are your charging options?”, to which he replied “$29 for valet…” — “Er, no mate. I mean electricity, where can I plug in?” The answer I was surprised to learn was “no where”. At least not at the hotel. Turns out that’s a bit of a problem…&lt;/p&gt;
&lt;p&gt;Over the next few days I had to take the Tesla over the road to the shopping mall (which is about a kilometer away) and plug it in. The first place I took it to charged $1.50 an hour, which seemed OK, though I didn’t realise it went up to $5/hour after the first 3 hours, so I ran up a $20 bill and only half filled the car — the shopping mall chargers are way way slower than the Tesla Super Charger stations. &lt;/p&gt;
&lt;p&gt;I found another charger a bit further down the road at another shopping mall car park — this time free, but with a 3 hour limit. So over the next 3 days I took the car there several times and gradually built up a decent charge. This was painful. Especially the walk back to the Marriott in that 40°C (104°F) plus heat. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Not being able to charge overnight at your destination is a killer.&lt;/strong&gt; If we’d needed to go any distance each day, say a trip to Sedona or the Grand Canyon we’d be SOL. The nearest Tesla Super Charger was about 40 minutes away on the other side of Phoenix so a visit there was out of the questions too. I have to say that I was very surprised that a top notch hotel like the JW Marriott wasn’t equipped for electric vehicles. In fact the bellhop said they’d had 5 Teslas arrive that day alone! So what did those drivers do for charging I wonder?&lt;/p&gt;
&lt;h2&gt;Range Anxiety Max&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;Somehow I failed to learn from my journey out to Phoenix and on the way back I made the same mistake charging up to just the minimum amount of time recommended. After gather just enough electrons I then proceeded to nail it up the on-ramp and we headed briskly down the freeway. Within about 20 minutes the car came up with some bad news: You do not have enough charge to reach your destination.” WTF? This was a bit concerning because rather than needing to drive slower to get to the destination at Coachella, we simply were not going to make it. Basically it was telling us we were screwed.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;After a quick team discussion we figured that we didn’t need to turn back yet — we hadn’t reached a point of no return — so we’d try a bit of Daniel’s cycling expertise and tucked in behind a truck to draft along at a modest speed for a while. I’d also figured out how to make the autopilot follow closely to maximise the draft effect (knowing that the autopilot would brake quickly enough if need be!)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;font-family: -webkit-standard;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/tesla-roadtrip/_resampled/ResizedImage400453-drafting.jpg&quot; alt=&quot;drafting&quot; width=&quot;400&quot; height=&quot;453&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Peak Time Traffic&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;Arriving into LA at 5 PM on a Friday afternoon was always bound to involve a spot of commuter traffic. Turns out autopilot is very handy in this situation, bringing the car to a complete stop then driving off with the cars in front, even if you’ve dozed off in the meantime — saves a lot of embarrassment. Just kidding, but actually it was good as long as you didn’t want to change lanes — to carve your way through traffic, such as you might want to do when you’re running late to get to the airport, you really need to take charge and drive it yourself. &lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;&lt;span style=&quot;font-size: 1.5em;&quot;&gt;So… Would I Buy One?&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;Yes I would &lt;em&gt;but&lt;/em&gt; I don’t quite think they’re for everyone yet: the Tesla range are still very expensive cars and there desperately needs to be either a very quick way to charge or charging points everywhere you might stop for the night. My problem is that I just can’t bring myself to part with the M3 yet.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Fri, 22 Sep 2017 19:37:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/tesla-roadtrip/</guid>
		</item>
		
		<item>
			<title>Beautiful and Easy Drawer Menus for Desktop and Go</title>
			<link>https://www.teamdf.com/blogs/beautiful-menus/</link>
			<description>&lt;h2&gt;Stepping up your design game&lt;/h2&gt;
&lt;p&gt;FileMaker is no longer simply a database development tool.&lt;/p&gt;
&lt;p&gt;With FileMaker edging closer every day to being a fully fledged mobile and desktop application platform, as developers we should be striving to build the best user experience possible. That means building controls that both look and behave to the same standards as if they were developed in any other platform.&lt;/p&gt;
&lt;p&gt;Until recently this has been quite a challenge in FileMaker. We have been restricted by controls that were limiting in their functionality, and often needing to resort to plugins or simply putting things in the too hard basket.&lt;/p&gt;
&lt;p&gt;It is my belief that as FileMaker developers we should no longer be settling for &quot;just good enough&quot;. We need to step our game up and become great designers and developers of applications, not just databases.  If we can build controls that are easy to drop into a solution and use (even if they are complex underneath it all) then we should be doing this for the betterment of the user experience. After all - what we build is for people to use all day every day.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Sliding Drawer Menus&lt;/h2&gt;
&lt;p&gt;&lt;a title=&quot;Sliding Drawers&quot; href=&quot;https://www.teamdf.com/blogs/a-sliding-drawer-that-opens-and-closes-on-mouse-over/&quot; target=&quot;_blank&quot;&gt;We have covered these types of menus in the past&lt;/a&gt;. A couple of years ago I wrote an article about how they can be built using sliding panels. That article went a little over the top by having the menu open/close simply on a mouse-over action through the use of a plugin and tooltips. The technique while workable had some limitations - the plugin on FileMaker Go and WebDirect being one of them.&lt;/p&gt;
&lt;p&gt;Recently I began development on a large client solution and decided to overhaul this technique and make it both easier to implement, and more usable and reliable.  The menu was to work on both FileMaker Pro and in FileMaker Go.&lt;/p&gt;
&lt;p&gt;I wanted the drawer to look and feel as native as possible, and leverage all the tools that FileMaker provides to give the user the most native experience.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/beautiful-drawers/_resampled/ResizedImage600404-project.png&quot; alt=&quot;project&quot; width=&quot;600&quot; height=&quot;404&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Jump right in and have a look!&lt;/h2&gt;
&lt;p&gt;We always try to build easy and user friendly demo files for our articles and this one is no different. You can download the demo file that accompanies this article below. Have a play round, explore, learn how it works. Make sure to try it on all platforms such as FileMaker Pro, iPad, and iPhone.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/Uploads/BeautifulMenus.zip&quot; target=&quot;_blank&quot;&gt; Download the Demo File!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Basic Structure for the Menu&lt;/h2&gt;
&lt;p&gt;The menu setup is quite simple.  It comprises of a sliding panel object with 3 panels:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The first panel (default) is empty and unused, it just happens to be the one the user ends up on by default.&lt;/li&gt;
&lt;li&gt;The second panel (on) is the panel that contains the actual menu and contents.&lt;/li&gt;
&lt;li&gt;The third panel (off) is again an empty panel, but is used to close the menu via a swipe gesture on FileMaker Go.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;So that&#039;s it, pretty simple huh! This panel object can be placed on your layout wherever you want the menu to be (typically the left edge). There are a few other design considerations for the panel:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;It has no fill colour so that you can see the underlying layout&lt;/li&gt;
&lt;li&gt;The navigation dots are hidden as they are not required.&lt;/li&gt;
&lt;li&gt;Swipe gestures are enabled so that the user can close it via swipe on FileMaker Go&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;A single script for opening and closing&lt;/h2&gt;
&lt;p&gt;There is a single script responsible for either opening the menu, or closing it. Under normal circumstances, the script does not accept a parameter, and the default action is to toggle the menu on or off.&lt;/p&gt;
&lt;p&gt;The script keeps track of whether the menu is open or closed by way of defining a global variable - $$MENU.STATE.  When it has a value of 1, the menu is on, otherwise it is off.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The basic way we open and close&lt;/h2&gt;
&lt;p&gt;Recall our object has three panels. When using a left of screen based navigation the following actions are done to open and close the menu. First, for opening:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The script goes to the third (off) panel&lt;/li&gt;
&lt;li&gt;It then animate going back to the second (on) panel.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;and to close:T&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The script goes to the third (off) panel.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Our demo file is built on the basis of the menu opening from the left of screen. If you instead wanted a right of screen menu, you simply reverse these actions. To open the menu you would start on the first panel and go to the second. To close, you go to the first panel. In fact, the right-of screen menu only requires 2 panels, not three.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The beauty and power lies within Script Triggers&lt;/h2&gt;
&lt;p&gt;While the above menu script &amp;amp; processes are great, they are for toggling a menu on and off through using an action such as the user pressing a menu button on the screen.  But you can take this so much further and make the menu so much more usable by leveraging script trigger functionality.&lt;/p&gt;
&lt;p&gt;Consider other ways the usability could be enhanced:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;What about opening the menu using the right-arrow key?&lt;/li&gt;
&lt;li&gt;What about closing the menu using the left-arrow key?&lt;/li&gt;
&lt;li&gt;What about using escape to close the menu if it is open?&lt;/li&gt;
&lt;li&gt;What about using a swipe-gesture to close the menu?&lt;/li&gt;
&lt;li&gt;What about tapping on an area outside of the menu to close it?&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;We can do all this, and it&#039;s easy!&lt;/p&gt;
&lt;p&gt;The first three actions can all be done by using an onLayoutKeystroke script trigger with a corresponding script. These are leveraged for FileMaker Pro where keystrokes are used.  In the demo file this script is provided and used.  The script needs to check a few things, but its basic operation is:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;If the user has the mouse cursor in a field, or a layout object such as a button has focus, it will not trigger the menu.&lt;/li&gt;
&lt;li&gt;Otherwise, if the user pressed the left arrow key, close the menu.&lt;/li&gt;
&lt;li&gt;If the user pressed the right arrow key, open it&lt;/li&gt;
&lt;li&gt;If the user pressed escape key, close it&lt;/li&gt;
&lt;li&gt;Otherwise just let the keystroke proceed as normal.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;So simple and yet so effective!  Check the demo file and try these for yourself.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Taking it to the next level with FileMaker Go.&lt;/h2&gt;
&lt;p&gt;The sliding drawer while a great desktop control, really shines on the iPad and iPhone due to these devices limited screen real estate and extra usability features we can leverage. It is a control you commonly see in a lot of native iOS applications, so users are familiar with how it works, and there is a certain level of expectation also that goes along with a drawer as to its behaviour.&lt;/p&gt;
&lt;p&gt;The following FileMaker tools have been leveraged to give the complete user experience:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The existing panel control &amp;amp; navigation script&lt;/li&gt;
&lt;li&gt;Enabling of Gesture Swipes on the panel object&lt;/li&gt;
&lt;li&gt;The onPanelSwitch Script trigger to capture the user swipe &amp;amp; direction&lt;/li&gt;
&lt;li&gt;The onGestureTap layout level script trigger to capture user tap on screen.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The onPanelSwitch script trigger captures the target destination panel. If the menu is open (on panel #2) and the user has swiped to the third panel #3, then they have swiped their finger to the right in a motion where the expectation is they are minimizing the drawer.  Great! We can just run our navigation script to toggle the menu to close, done!&lt;/p&gt;
&lt;p&gt;It is also interesting to note that swipe gestures work on the mac desktop in FileMaker Pro if you use a trackpad or mouse capable of having swipe gestures.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Tap tap tap!&lt;/h2&gt;
&lt;p&gt;For the onGestureTap script trigger, it&#039;s a little more complicated, but once you understand how this trigger works it&#039;s simple!&lt;/p&gt;
&lt;p&gt;The function Get ( TriggerGestureInfo ) returns us lots of useful information about the users tap:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;The string &quot;tap&quot; indicating a tap was done - we don&#039;t care about this.&lt;/li&gt;
&lt;li&gt;A value containing how many fingers were used - we will only trigger with 1 finger.&lt;/li&gt;
&lt;li&gt;The X coordinate in the document where the gesture occurred - we want this!.&lt;/li&gt;
&lt;li&gt;The Y coordinate in the document where the gesture occurred - we don&#039;t care about this.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;The importing aspect here is whether the user tapped with one finger, and where in the horizontal axis of the layout did they tap.&lt;/p&gt;
&lt;p&gt;Why do we care about where they tapped? If you look at the behaviour of most sliding drawers on iOS, a tap within the menu does not close it, yet a tap on screen outside of the menu area will close. So that is the behaviour to be replicated.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;How to tell if the user tapped off the menu&lt;/h2&gt;
&lt;p&gt;Again, more simple leveraging of the tools at our disposal. &lt;/p&gt;
&lt;p&gt;The panel object has been defined, and all the panels are named. So the GetLayoutObjectAttribute function can be used to get all the information needed:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;GetLayoutObjectAttribute ( &quot;menu.on&quot; ; &quot;right&quot; ) gives the right-edge coordinate of the menu, where &quot;menu.on&quot; is the panel object name.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;So knowing the right edge of the menu and knowing the coordinate where the user tapped, the script simply needs to compare the two values. When the user tapped a coordinate greater than the right edge we know they tapped outside of the menu.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Some other considerations when implementing&lt;/h2&gt;
&lt;p&gt;This menu works great and it&#039;s a beautiful modular control you can throw on your layouts. With just a few scripts and controls you can have it up and running in your own solution. To make it more usable, consider building the contents of the menu via a context which is universal (accessible from all other layout contexts). This allows you quick copy/paste of the control onto other layouts for use and you don&#039;t need to worry about changing field and portal references.&lt;/p&gt;
&lt;p&gt;Because the panel control sits on your layout, it can be often annoying trying to work in layout mode with it present. There are 2 options at your disposal:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Just drag it off the edge of the layout while developing, OR&lt;/li&gt;
&lt;li&gt;Use the new layout object inspector in FileMaker 16 to hide the object while in layout mode. &lt;/li&gt;
&lt;/ul&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/beautiful-drawers/_resampled/ResizedImage452523-object-inspector.png&quot; alt=&quot;object inspector&quot; width=&quot;452&quot; height=&quot;523&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Remember, the panel control should be at the top of your layouts ordering so that it sits on top of everything else - you don&#039;t want other underlying layout objects to appear in front of it!&lt;/p&gt;
&lt;p&gt;Finally, it is recommended to use a fill coloured rectangle to replicate the actual menu background, as opposed to simply filling the colour of the panel itself.  In our example, we have attached a single &quot;Exit Script&quot; script step to this rectangle object.&lt;/p&gt;
&lt;p&gt;This is done so that if the user is clicking or tapping on the menu, they are not inadvertently clicking on any underlying field on the layout. If you do not do this, there is potential for unexpected actions such as entering a field or clicking a button under the menu object, as shown below.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/beautiful-drawers/demo-1.png&quot; alt=&quot;demo 1&quot; width=&quot;586&quot; height=&quot;548&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; Panel is not the front-most object&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/beautiful-drawers/demo-webdirect.png&quot; alt=&quot;demo webdirect&quot; width=&quot;553&quot; height=&quot;453&quot;&gt; &lt;/p&gt;
&lt;div class=&quot;captionImage leftAlone&quot; style=&quot;width: 553px; text-align: center;&quot;&gt;&lt;span style=&quot;text-align: center;&quot;&gt;The navigation is not a button, so the user can click behind it&lt;/span&gt;&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;p&gt;While we are forever getting closer to perfect implementation in all circumstances, there are still some limitations to this technique. One of which is FileMaker&#039;s inability for objects to span vertically across layout parts. If your layout uses a top navigation or header, then putting this control in that part will not work as it chops off once it hits the part below.  Actually in the solution I developed for this was the case, but it was quite easy to simply sit the navigation below the top navigation part in the body and it still works great.&lt;/p&gt;
&lt;p&gt;This control doesn&#039;t work in list view or table view for similar reasons to those mentioned above. Hopefully one day FileMaker will give us horizontal layout parts so that the side of our layouts are a separate space for controls such as these.&lt;/p&gt;
&lt;p&gt;Finally, the navigation control works great in WebDirect, but it comes with a caveat. In WebDirect, any object overlaying another will prevent the underlying object from being clickable as a button, or enterable as a field. In this case, the navigation panel sits at the front of the layout object ordering, preventing the user from clicking what lies underneath. In order to implement for webdirect, introduce a hide condition on the panel. Recall the use of the global variable $$MENU.STATE to keep track of whether the menu is open or closed. Simply add the hide condition of &quot;not $$MENU.STATE&quot; to work around this issue.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Demo File Download&lt;/h2&gt;
&lt;p&gt;The demo file has been built to work on both FileMaker Pro, iPad and iPhone. If opening on a phone, it should open on a separate appropriately sized layout. On the iPad and Desktop, you&#039;ll end up on a larger layout.  This demo is suitable for FileMaker Pro and FileMaker Go versions 15-16.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/Uploads/BeautifulMenus.zip&quot; target=&quot;_blank&quot;&gt;Download the Demo File!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Feedback and comments are always appreciated!&lt;/p&gt;</description>
			<pubDate>Tue, 18 Jul 2017 09:17:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/beautiful-menus/</guid>
		</item>
		
		<item>
			<title>Intro to FileMaker Cloud</title>
			<link>https://www.teamdf.com/blogs/filemaker-cloud/</link>
			<description>&lt;p&gt;&lt;span&gt;If you’re dialed in to FileMaker Inc for the Asia Pacific region you’ve probably heard that “FileMaker Cloud” is now available — Wahoo! &lt;/span&gt;Here&#039;s one now:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/FileMaker-Cloud-Intro/_resampled/ResizedImage600144-fm-cloud-horz.png&quot; alt=&quot;fm cloud horz&quot; width=&quot;600&quot; height=&quot;144&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;But what is it exactly? What does it mean for you if you’re a business owner?&lt;/p&gt;
&lt;p&gt;Quite simply FM Cloud is a service where your databases are hosted in a data centre (a big warehouse full of computers) for you, and you&#039;re billed monthly based on how many connections you want and how much you use the service.&lt;/p&gt;
&lt;h3&gt;Cloud&lt;/h3&gt;
&lt;p&gt;“Cloud” does not mean it’s on the web. There’s a bit of confusion in the world — actually there’s a lot of confusion in the world…. but lets stick to FileMaker:&lt;/p&gt;
&lt;p style=&quot;padding-left: 30px;&quot;&gt;&lt;em&gt;The term “Cloud” in this case simply refers to the data and application                         &lt;/em&gt;&lt;em&gt;being hosted in a cluster of computers that are managed for you. &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this case the “cloud” is Amazon Web Services (AWS), one of the leading providers of such cloud infrastructure globally, which means they’re extremely good at providing a robust yet flexible service. We’ve been hosting FileMaker solutions on AWS for several years now so we know a lot about how it works and just how easy and reliable it is.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/FileMaker-Cloud-Intro/AmazonWebservices-Logo.png&quot; alt=&quot;AmazonWebservices Logo&quot; width=&quot;300&quot; height=&quot;113&quot;&gt;&lt;/p&gt;
&lt;p&gt;FM Cloud is a bundled service that includes both the computer power you need for hosting, plus the FM Server software, backup and administration tools. You still connect to it using FileMaker Pro on your desktop/laptop computer, or through WebDirect (if your app has been designed for it), or FileMaker Go.&lt;/p&gt;
&lt;h3&gt;Some big wins&lt;/h3&gt;
&lt;p&gt;Hosting solutions in the cloud has some major advantages over hosting on your own server on your premises. It really simplifies deployment and management and lets us all concentrate on the business end of the solution:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;You’re no longer responsible for the physical computer hardware: that’s &lt;strong&gt;taken care of for you&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;&lt;/li&gt;
&lt;li&gt;It’s &lt;strong&gt;scaleable&lt;/strong&gt;: if you need more power or more storage, it’s simply a matter of reconfiguring the server through a web page.&lt;br&gt;&lt;br&gt;&lt;/li&gt;
&lt;li&gt;Cloud hosting makes it easy to &lt;strong&gt;access your apps from anywhere&lt;/strong&gt; — they’re no longer trapped inside your network.&lt;br&gt;&lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Super security&lt;/strong&gt;: AWS data centres are so secure no-one knows exactly where they are*, plus they have back-up power generation, multiple high bandwidth connections to the internet and are fully climate controlled. &lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;(* While that&#039;s what we&#039;ve been told, we&#039;re picking someone must know where the servers are...)&lt;/p&gt;
&lt;p&gt;The only real drawback is that you might see a performance reduction if you currently run a server in-house simply because data has to travel a lot further when the server is not in your office. Performance will depend a bit on how far you are from the data centre and what type of internet connection you have. FM Cloud for our region is hosted in Sydney which pretty much means you’ll get good to great performance from anywhere in Australia or New Zealand that has broadband.&lt;/p&gt;
&lt;h3&gt;Is it right for us?&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Essentially FileMaker Cloud is fairly similar to the service we’ve been providing our customers who host with AWS, but there are a few technical differences and these affect whether or not FM Cloud is going to be right for you.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/FileMaker-Cloud-Intro/_resampled/ResizedImage728296-contemplate.jpg&quot; alt=&quot;contemplate&quot; width=&quot;728&quot; height=&quot;296&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FM Cloud uses FileMaker Server 15&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We don’t see that as a big disadvantage but there are performance gains to be had with 16, and of course new features like PDF printing and the new data API. This also explains why the icon is pink/purple vs the blue/purple FileMaker now sports.&lt;/p&gt;
&lt;p&gt;We have no doubt that FM Cloud will be updated to use FileMaker Server v16 at some point in the near future. Even with the server being 15 you can still use FileMaker Go or FileMaker Pro 16 to connect to it to get most of the advantages of the latest FileMaker version.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FM Cloud does not support Custom Web Publishing (PHP and XML)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If your database has a web site attached using PHP then it won’t be able to be hosted with FM Cloud. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Server-side Plugins May Not Be Compatible&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;FM Cloud runs on a Linux operating system so you need to have special versions of any plugins on the server in order to be able to use them. Many of the solutions we’ve built use our Xero plugin, BaseElements and Sendmail: we don’t have versions of these plugins suitable for FM Cloud at this time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No Scheduled Scripts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Scripts that automatically run at predetermined times on the server can&#039;t be setup or used in FM Cloud — in most cases re-thinking how those operations are carried out should be doable.&lt;/p&gt;
&lt;p&gt;For a more thorough and direct comparison FileMaker have produced a very useful table that shows how &lt;a title=&quot;Comparison of FileMaker Server with FM Cloud&quot; href=&quot;http://www.filemaker.com/products/filemaker-cloud/compare.html&quot; target=&quot;_blank&quot;&gt;FileMaker Server compares with FileMaker Cloud&lt;/a&gt; — bear in mind they compare FM Cloud to FM Server on premise, but there is also a third and very popular choice which gives the best of both worlds, i.e. a &lt;a title=&quot;Custom Configured and Fully Managed Hosting Services&quot; href=&quot;https://www.teamdf.com/what-we-do/hosting/&quot;&gt;custom configured cloud server&lt;/a&gt; with FileMaker Server installed. &lt;/p&gt;
&lt;h3&gt;So in a &lt;a title=&quot;Our Nutshell CRM and Job Tracking solution&quot; href=&quot;https://www.teamdf.com/products/nutshell/&quot;&gt;Nutshell&lt;/a&gt;…&lt;/h3&gt;
&lt;p&gt;Despite some limitations FM Cloud is a superb product and we’d be more than happy to talk to you about whether or not it might make sense to move your solution onto this platform. &lt;/p&gt;
&lt;p&gt;And if the turn-key FM Cloud service doesn’t work for you we can essentially provide you with a very similar service, using AWS to configure a FileMaker 16 Cloud-based server running on Windows.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 11 Jul 2017 12:12:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-cloud/</guid>
		</item>
		
		<item>
			<title>DevDays - 5 Go Wild In Sydney!</title>
			<link>https://www.teamdf.com/blogs/devdays-5-go-wild-in-sydney/</link>
			<description>&lt;p&gt;We had a tonne of fun being a part of the Asia Pacific FileMaker Developer Days mini-conference held in Sydney last week. There were over 100 developers from around the region, many travelling in from as far away as Malaysia, Perth and New Zealand.&lt;/p&gt;
&lt;p&gt;FileMaker Inc. brought in &lt;a title=&quot;Andrew Paulsen on LinkedIn&quot; href=&quot;https://www.linkedin.com/in/andrewjamespaulsen/&quot; target=&quot;_blank&quot;&gt;Andrew Paulsen&lt;/a&gt;, one of the key product architects on the FileMaker Pro team, and &lt;a title=&quot;Brad Freitag on LinkedIn&quot; href=&quot;https://www.linkedin.com/in/bradfreitag/&quot; target=&quot;_blank&quot;&gt;Brad Freitag&lt;/a&gt;, Vice President of Worldwide Sales. And of course the local Asia Pacific team were there with &lt;a title=&quot;David Borgnis alter-ego&quot; href=&quot;https://www.youtube.com/watch?v=MS1WJBZ8Bd4&quot; target=&quot;_blank&quot;&gt;David Borgnis&lt;/a&gt; organising and MC&#039;ing the whole event — thanks David!&lt;/p&gt;
&lt;p&gt;From Digital Fusion we sent five staff, with four them involved in presentations — the fifth was there to hold placards up to encourage suitable audience reactions.&lt;/p&gt;
&lt;h3&gt;Incredibly Informative...&lt;/h3&gt;
&lt;p&gt;The conference coincided with the release of FileMaker 16 so we&#039;ll lay claim to leading the world in getting into some serious discussions of the new features.&lt;/p&gt;
&lt;p&gt;A number of speakers noted that the 16 release is quite developer centric with features such as the new RESTful data API, new window controls and the new object inspector. Even so there&#039;s a lot of features that will affect users too — a lot of discussion was on how these things will help us build better user experiences into our FileMaker applications and make it easier to fit in to the world of web services smoothly. &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/devdays-2017/_resampled/ResizedImage677167-theatre-from-the-back.png&quot; alt=&quot;theatre from the back&quot; width=&quot;677&quot; height=&quot;167&quot;&gt;&lt;/p&gt;
&lt;p&gt;Andrew spoke a lot about FM16 features and product direction, as well as two of the best sessions we&#039;ve ever seen (including those &quot;under the hood&quot; sessions at &lt;a title=&quot;FileMaker DevCon&quot; href=&quot;http://www.filemaker.com/learning/devcon/index.html&quot; target=&quot;_blank&quot;&gt;DevCon&lt;/a&gt;) on performance optimisation — very informative and directly applicable to the work we&#039;re doing.&lt;/p&gt;
&lt;p&gt;Brad covered some of the sales and marketing strategy that&#039;s driving FileMaker nowadays and it was interesting to see how they&#039;re comparing against some of the new comers in the space such as Google AppMaker. FileMaker is a far more mature product and doesn&#039;t require buy in to the Google realm. However having these new players in the field helps validate and grow general awareness of the need for rapid, robust business app development tools.&lt;/p&gt;
&lt;p&gt;It&#039;s also very reassuring to hear how FMI recognise FileMaker as more of a software development platform than the simpler &quot;desktop database&quot; that it used to be.&lt;/p&gt;
&lt;h3&gt;...Highly Entertaining&lt;/h3&gt;
&lt;p&gt;Another highlight was developer Salvatore from Goya showing us how to send photos of objects off to an Amazon Artificial Intelligence service (using the API tools) which would then return the contents of the picture as text — send it a picture of a cup on a table and it&#039;ll come back with &quot;Cup&quot;; he sent off a photo of a glass of beer and it came back with &quot;Glass of Orange Juice&quot;. He&#039;s one of the funniest developers we&#039;ve heard and his ability to entertain while telling us about such a dry subject is gold. &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/devdays-2017/beer.png&quot; alt=&quot;beer&quot; width=&quot;250&quot; height=&quot;304&quot;&gt;&lt;/p&gt;
&lt;p&gt;And to keep that theme running, we sponsored some drinks and food at the end of the first day to help spur the creative juices and socialisation amongst the FBA community that were present... if you weren&#039;t there you missed out on a free beer on DF so don&#039;t let that happen again will you?&lt;/p&gt;
&lt;h3&gt;Something For Everyone&lt;/h3&gt;
&lt;p&gt;The two days were targeted seprately to cater to two different audiences, with Monday being for FileMaker Business Alliance (FBA) members, and the Tuesday for all-comers such as &quot;citizen&quot; developers and non-FBA developers.&lt;/p&gt;
&lt;p&gt;We were lucky enough to get four of our team onto the speaking schedule with...&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Daniel and Craig with &quot;Making the most of new features for a better user experience&quot;&lt;/li&gt;
&lt;li&gt;James and Craig on &quot;Stand Alone Apps: App creation and deployment using the iOS SDK&quot;&lt;/li&gt;
&lt;li&gt;Cath going it alone with &quot;Wonders of WebDirect: Success stories from the frontline&quot;&lt;/li&gt;
&lt;/ul&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/devdays-2017/_resampled/ResizedImage505336-cath-presenting.png&quot; alt=&quot;cath presenting&quot; width=&quot;505&quot; height=&quot;336&quot;&gt;&lt;/p&gt;
&lt;p&gt;Not only was it a great experience for our team to be part of the conference, they thoroughly enjoyed being able to share their knowledge. I think it&#039;s a bit of a buzz to nail a presentation in front of a big audience... and these are knowledgeable peers with plenty of questions!&lt;/p&gt;
&lt;p&gt;&lt;span&gt;And what would a conference be without the company branded top plus obligatory photo (in this case we got the team mid-Conga):&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;Team DF staff in company colours – Craig, Cath, Morgan, James, Daniel&quot; src=&quot;https://www.teamdf.com/assets/blog-images/devdays-2017/_resampled/ResizedImage711352-conga.png&quot; alt=&quot;conga&quot; width=&quot;711&quot; height=&quot;352&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Wed, 17 May 2017 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/devdays-5-go-wild-in-sydney/</guid>
		</item>
		
		<item>
			<title>Dynamically Resizing Backgrounds That Don&#039;t Distort</title>
			<link>https://www.teamdf.com/blogs/dynamically-resizing-backgrounds/</link>
			<description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;If background images are used sensibly, they can provide a beautiful backdrop to areas of your solution, such as a login screen, splash screen, or indeed the entire solution. FileMaker allows the user stretch the window both horizontally and vertically in any ratio they wish. Anchoring has allowed us to try and compensate for this in our designs, but often images suffer because they are themselves a fixed aspect ratio, and deviating from that ratio will either stretch and distort the image if &#039;maintain aspect ratio&#039; is off, otherwise result in blank space around the image edge if aspect ratio is on - both options are not ideal for a background image.&lt;/p&gt;
&lt;p&gt;In this article we present a technique that allows you to resize an image and have it re-generate a thumbnail version upon resizing of the layout. This thumbnail version is a cropped version of the original, but respects the original image&#039;s aspect ratio.  If you choose your image sensibly, you can make a layout background that looks great no matter what dimensions your window is set to.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;What is the issue here?&lt;/h2&gt;
&lt;p&gt;It all comes down to aspect ratio.  I&#039;m sure you&#039;ve all come across this issue at some point or another when developing: You have a container on a layout, and as you resize the layout, the image becomes stretched and distorted:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/Stretch.gif&quot; alt=&quot;Stretching an image&quot; width=&quot;600&quot; height=&quot;251&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage238154-Screen-Shot-2017-03-20-at-5.58.11-PM.png&quot; alt=&quot;Stretch Settings&quot; width=&quot;238&quot; height=&quot;154&quot;&gt;&lt;/p&gt;
&lt;p&gt;So here we have a container where we have set it to reduce or enlarge to fit, and we don&#039;t maintain proportions (the aspect ratio). This is good in that it fills the entire container, but bad in that the image looks terrible when stretched.&lt;/p&gt;
&lt;p&gt;Aspect ratio is just the ratio of width to height of an image.  Typical aspect ratios such as 16:9 simply mean that if the width of the image was 16 centimetres for example, then the height would be 9. If the width were 32, the height would be 18, and so on.&lt;/p&gt;
&lt;p&gt;So how about turning on maintaining original proportions (aspect ratio): &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/Stretch2.gif&quot; alt=&quot;Stretch with aspect ratio maintaining&quot; width=&quot;600&quot; height=&quot;251&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now we have the image looking good, but the rest of the container cannot be occupied by anything in order for us to keep aspect ratio.  This would be fine if our container was displaying something like a persons photo, or a company logo.  However in this article we want a container that is going to be used as a background image. Imagine using the above as a background, who wants massive areas of nothing in the background?  Conversely who wants a horrible distorted image.  Is there a nice middle-ground here?&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Requirements for our background image&lt;/h2&gt;
&lt;p&gt;First, let&#039;s define a few rules for what will make a successful background image:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;We don&#039;t want the image to zoom if possible (so no pixelation)&lt;/li&gt;
&lt;li&gt;We don&#039;t want the image to stretch or distort (so no breaking of aspect ratio)&lt;/li&gt;
&lt;li&gt;We don&#039;t want any large borders around the image (so fill the entire layout object)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Prevention of Pixelation when Zooming&lt;/h2&gt;
&lt;p&gt;This is an issue that would occur if the dimensions of our FileMaker Window were greater than the original image dimensions. If we wish to satisfy conditions 2 and 3, we can&#039;t make the image larger than it&#039;s original dimensions, this results in pixelation of the image - you simply cannot make an image bigger than it actually is without sacrificing quality of the image.&lt;/p&gt;
&lt;p&gt;The solution to this one then is pretty straightforward, make sure your background image you use has a dimension that is sufficiently large so that it is unlikely your user will be able to resize their FileMaker window larger than the images dimensions.&lt;/p&gt;
&lt;p&gt;on iOS this is fine, you know what dimensions you can work with as it&#039;s constrained by the size of the device screen. Similarly on monitors you are constrained in window size to the monitor size, however different users can be on different monitors so you must choose wisely.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Prevention of Distortion and Borders&lt;/h2&gt;
&lt;p&gt;The way we prevent distortion of the background image, while keeping it filling the layout object, is best illustrated with a diagram: &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600311-One.png&quot; alt=&quot;One&quot; width=&quot;600&quot; height=&quot;311&quot;&gt; In this example the green rectangle represents the dimensions of our background image. The blue rectangle is our screen dimensions.&lt;/p&gt;
&lt;p&gt;Both image and screen have the same aspect ratio of 2:1 and so in order to fully occupy the screen, we simply generate a thumbnail image 1/2 the size of the original image, it should fit it nicely.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600313-Screen-Shot-2017-03-20-at-6.22.03-PM.png&quot; alt=&quot;Screen Shot 2017 03 20 at 6.22.03 PM&quot; width=&quot;600&quot; height=&quot;313&quot;&gt;&lt;/p&gt;
&lt;p&gt;This one is a bit trickier. Our screen is now 600x200,  which is an aspect ratio of 3:1.  To demonstrate how we will scale down our background image to fill this screen size, we&#039;ll use this crudely put together FileMaker layout and the GIF below!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://i.imgur.com/mjf9kCV.gif&quot;&gt;http://i.imgur.com/mjf9kCV.gif&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PRO DEVELOPER TIP:  When resizing layout objects in layout mode, if you hold the cmd+shift keys while resizing, the image is resized respecting it&#039;s original aspect ratio. That is how in the above GIF I am able to resize it correctly. (also of note, holding option+drag will constrain the object to the same width and height when resizing...)&lt;/p&gt;
&lt;p&gt;We must maintain aspect ratio of the background image, so the first step is scaling the background down to a size where the largest dimension of the screen is matched to that of the image. Our resulting image in green is now still in it&#039;s aspect ratio, but sized down.&lt;/p&gt;
&lt;p&gt;The second step is to center the image (in green) over our layout background (in blue).  This is actually achieved simply by setting the layout object properties to align centered both vertically and horizontally.  The final step is to ensure that the layout object is set to crop the image&lt;/p&gt;
&lt;p&gt;Here is another example:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600310-Screen-Shot-2017-03-20-at-6.31.24-PM.png&quot; alt=&quot;Screen Shot 2017 03 20 at 6.31.24 PM&quot; width=&quot;600&quot; height=&quot;310&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here the height is slightly more than the width of the screen. You might find a user doing this if the layout contains a portal or list and they want to maximise screen height, or if they are using portrait orientation on an iOS device.&lt;/p&gt;
&lt;p&gt;Here is the transformation that occurs:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://i.imgur.com/8Cq58lU.gif&quot;&gt;http://i.imgur.com/8Cq58lU.gif&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Much like the first example, this one is simply scaling the original image down to the maximum dimension. The difference here is the maximum dimension is the height, not the width. Scaling down stops at the point the height is reached.&lt;/p&gt;
&lt;p&gt;With the fact the background image is centered horizontally/vertically and cropped on the layout, the final effect is for the background image to be positioned centered in relation to the original image.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Wrapping it all up in a Custom Function&lt;/h2&gt;
&lt;p&gt;In order to generate the required thumbnail image, we need to know:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The width and height of the raw image&lt;/li&gt;
&lt;li&gt;The width and height of the layout background object&lt;/li&gt;
&lt;li&gt;The image to use&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The first point can be obtained using the GetContainerAttribute function, we can return the width and height of the image in the container.&lt;/p&gt;
&lt;p&gt;The second set of dimensions is obtained using the GetLayoutObjectAttribute function. With it, we can tell the dimensions of the layout background object at any point in time - recall that given the container is anchored and resizing, it&#039;s dimensions change as the window is resized.&lt;/p&gt;
&lt;p&gt;In the demo file you&#039;ll find a custom function called&lt;strong&gt; @IMAGE_bgThumbnail. &lt;/strong&gt;This takes as it&#039;s parameters the image to use in the thumbnail, and the object name on the layout that the thumbnail is to be sized for.&lt;/p&gt;
&lt;p&gt;If you want to find out exactly what the calculation is have a looksee in the function.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Getting things to work nicely&lt;/h2&gt;
&lt;p&gt;So you now have a custom function to use, and hopefully an image to use also. You can create a calculation function to produce the desired resulting container field to use for your background. Put this on your layout and you&#039;re all set, right?  &lt;/p&gt;
&lt;p&gt;Well not quite, there is a little matter of having the calculation refresh itself when the screen is resized.  The mere act of resizing a screen (and thus the background object) is not enough to force the redrawing of the thumbnail.&lt;/p&gt;
&lt;p&gt;To achieve this, we need to use an &lt;strong&gt;onLayoutResize&lt;/strong&gt; layout script trigger. The script that runs will be responsible for refreshing the background layout object.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage356335-Screen-Shot-2017-03-20-at-6.50.13-PM.png&quot; alt=&quot;Screen Shot 2017 03 20 at 6.50.13 PM&quot; width=&quot;356&quot; height=&quot;335&quot;&gt;&lt;/p&gt;
&lt;p&gt;The script itself is pretty basic, there are a few ways you can refresh the background object:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Refresh Window&lt;/li&gt;
&lt;li&gt;Refresh Object&lt;/li&gt;
&lt;li&gt;Freeze Window&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;We use Refresh object in the demo because it allows us to only refresh the background image, and not all other things on the layout.&lt;/p&gt;
&lt;p&gt;As an interesting side note, freeze window also works. We assume this is because if a freeze window step is used, then the script when it exits silently does a &#039;refresh&#039; window to bring the screen back to it&#039;s required current state. Quite nice to know!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://i.imgur.com/TuZSlw4.gif&quot;&gt;http://i.imgur.com/TuZSlw4.gif&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Here is an example from our demo file. In it, we are resizing the window to be wider horizontally. As we resize, we don&#039;t instantly see the thumbnail image resize - this occurs upon release of the mouse after resizing. At this point in time the script to refresh the object runs and we see the change.&lt;/p&gt;
&lt;p&gt;The end result image is a thumbnail that is not zoomed in, it is not stretched or distorted either. It is however cropped, but from the center of the image out.  If you choose your images wisely the end result is a nice alteration to the background image that the user should not notice much change in.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;What&#039;s the point?&lt;/h2&gt;
&lt;p&gt;User experience! If you present a background image to a user with large borders because you don&#039;t want to stretch your image, the user will notice.  Conversely if you present a stretched image, the user will notice. All of these add to a negative user experience. While background images aren&#039;t critical - and most of the time not actually useful - they do have their place in certain parts of a solution if used in a certain way, so you might as well make it the best experience possible.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Demo File&lt;/h2&gt;
&lt;p&gt;What good is an article like this without a demo file to accompany it right? Well here it is! No username and password, fully unlocked just go for it.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/Uploads/DynamicBackgrounds.zip&quot;&gt; DynamicBackgrounds.zip&lt;/a&gt;&lt;a href=&quot;https://www.teamdf.com/assets/Uploads/ModernSearchUI.zip&quot;&gt;&lt;br&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Mon, 20 Mar 2017 19:41:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/dynamically-resizing-backgrounds/</guid>
		</item>
		
		<item>
			<title>Building a Super Slick Search UI</title>
			<link>https://www.teamdf.com/blogs/building-a-super-slick-search-ui/</link>
			<description>&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Search is an integral part of any solution, and can take many forms. FileMaker provides us with a useful native find mode, along with quickfind. Often though this is unintuitive for users, or just does not fit in with the design of a solution. In this article we present a slick, great looking search box UI design pattern, and explain how it is built. We also incorporate a number of native FileMaker techniques to achieve this (no plugins here!).&lt;/p&gt;
&lt;p&gt;The primary focus of this article is on the construction of the UI design for our search box. Other techniques discussed involve using relationship level filtering of results (in a basic way) and having a timed delay on our search filter.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;A bit of Search Background&lt;/h2&gt;
&lt;p&gt;So, what does FileMaker offer in the way of searching? Well there is find mode obviously. Great power, but perhaps a little unintuitive for the average user, especially in this day of age where websites provide pretty commonplace design patterns for searching.  Quickfind is a much nicer alternative, combining an automated &#039;find mode&#039; search of sorts, with a single search box making it easier for users to search.&lt;/p&gt;
&lt;p&gt;Both find mode and quickfind rely on results being displayed in a found set.  If your solution is setup this way then great, you can stop here :) If you are into building solutions that don&#039;t feel like native FileMaker, and feel more like a native application, then read on.&lt;/p&gt;
&lt;p&gt;Portals have been used to display search results for a long time, it&#039;s no secret. No matter how you end up collating your results for display in a portal, the portal generally allows you to select a record to then navigate to. The benefit to portals is that they can be placed within a layout, for in-line results display. This is perfect for the modern solution where you may have a search box at the top of every screen.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Search Box Design&lt;/h2&gt;
&lt;p&gt;The inspiration for this design was partly borrowed from websites and how they achieve search boxes.  Two examples that come to mind are &lt;a href=&quot;http://www.imdb.com&quot; target=&quot;_blank&quot;&gt;imdb.com&lt;/a&gt; and &lt;a href=&quot;http://www.tv.com&quot;&gt;tv.com&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600249-Screen-Shot-2017-03-12-at-2.40.35-PM.png&quot; alt=&quot;imdb&quot; width=&quot;600&quot; height=&quot;249&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;When you begin searching at imdb, matching results drop down underneath the search box. The size of the box shrinks or grows depending on the results found. If too many are found, a link at the bottom is provided to view the full results.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage322405-Screen-Shot-2017-03-12-at-2.41.00-PM.png&quot; alt=&quot;tv.com&quot; width=&quot;322&quot; height=&quot;405&quot;&gt;&lt;/p&gt;
&lt;p&gt;TV.com is also very similar. Results drop down displaying an image, information, and a few links to useful pages. The box resizes again depending on results found.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Goal - Build This in FileMaker&lt;/h2&gt;
&lt;p&gt;That was the goal. How close to this look and feel can we achieve in FileMaker &lt;strong&gt;natively. &lt;/strong&gt;By that I mean no plugins, but I also mean no web viewers. I want this to be native to the point that making any changes to it&#039;s look and feel is achieved through using layout tools.&lt;/p&gt;
&lt;p&gt;SO how did we do?&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/Demo.gif&quot; alt=&quot;Demo&quot; width=&quot;323&quot; height=&quot;496&quot;&gt;&lt;/p&gt;
&lt;p&gt;What you are seeing above is all native FileMaker. In order to make this usable on different layouts, it had to be easy to transport anywhere, and hook up for any given search box. A few points on this:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;We give the appearance of a results box that shrinks in size as fewer results are found.&lt;/li&gt;
&lt;li&gt;We can display the number of results found, or 0 if none are found.&lt;/li&gt;
&lt;li&gt;Results are scrollable.&lt;/li&gt;
&lt;li&gt;Results dynamically show as the user types.&lt;/li&gt;
&lt;li&gt;The results box only shows after the user beings typing.&lt;/li&gt;
&lt;li&gt;The results box disappears if the user exits the search field.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Pretty cool huh? We think so!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Breaking it Down into Components&lt;/h2&gt;
&lt;p&gt;So what is actually going on here? Well, if you like to get stuck in and figure this out for yourself, there is a demo file at the bottom of this article you can grab and dissect til your hearts content. For those who would like a bit more information, read on.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage270332-Screen-Shot-2017-03-12-at-2.54.44-PM.png&quot; alt=&quot;Components&quot; width=&quot;270&quot; height=&quot;332&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is our search box setup in layout mode. We have numbered 6 key components to the search which we&#039;ll go through step by step to understand what they are and their role in creating the interface. Briefly what we have is:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The search box&lt;/li&gt;
&lt;li&gt;A button bar&lt;/li&gt;
&lt;li&gt;A top horizontal line&lt;/li&gt;
&lt;li&gt;A middle horizontal line&lt;/li&gt;
&lt;li&gt;A bottom horizontal line&lt;/li&gt;
&lt;li&gt;A single sliding panel&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; And of course a portal to show the results.&lt;/p&gt;
&lt;p&gt;We make use of the hide layout object condition to create the illusion of a box that shrinks in size as results are refined. Our lines are shown or hidden according to a set of rules to achieve this. The sliding panel is used to enclose all the objects we wish to hide en-masse (it&#039;s just an easy way to manage them).&lt;/p&gt;
&lt;p&gt;Next we&#039;ll look at each object in a bit more depth.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;But First Some Naming Conventions&lt;/h2&gt;
&lt;p&gt;The interface has a number of components, but two of them contain object names which are key. We use a naming convention for these:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The search box can be named anything you want, but we&#039;ve called it &quot;search&quot;&lt;/li&gt;
&lt;li&gt;The sliding panel used to enclose the rest of the search UI is named &amp;lt;searchfield&amp;gt;.panel. So in our case, it is called &quot;search.panel&quot;. We use this convention so that scripts can determine what the object panel name is based on the search fields object name. It saves any hard-coding or parameter passing of object names.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Search Box&lt;/h2&gt;
&lt;p&gt;There really isn&#039;t much to the search box. It&#039;s just a global field we placed on the layout to accept user input. We format it to look how we want.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage29447-Screen-Shot-2017-03-12-at-3.00.22-PM.png&quot; alt=&quot;search box&quot; width=&quot;294&quot; height=&quot;47&quot;&gt;&lt;/p&gt;
&lt;p&gt;The magic is applied to the search box through script triggers:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage280244-Screen-Shot-2017-03-12-at-3.00.37-PM.png&quot; alt=&quot;Screen Shot 2017 03 12 at 3.00.37 PM&quot; width=&quot;280&quot; height=&quot;244&quot;&gt;&lt;/p&gt;
&lt;p&gt;Quite a few aren&#039;t there? Fear not,  only half of the triggers are concerning the user interface.  The onObjectEnter and onObjectExit triggers are for deciding whether the results are to be shown or hidden. We always hide when the search box is exited, but we only show once the user begins typing. the onObjectKeystroke trigger is part responsible for searching, and part responsible for refresh of whether to show/hide results.&lt;/p&gt;
&lt;p&gt;We will cover how the searching is done later on in the article.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Button Bar Calculation for Results Display&lt;/h2&gt;
&lt;p&gt;While this isn&#039;t absolutely necessary, it&#039;s a really nice touch to tell the user how many results are found, and more specifically if nothing is found. We use a button bar so that we can place the calculation for display direct on the layout in this object.&lt;/p&gt;
&lt;p&gt;We won&#039;t bother showing that calculation here, you can check it out for yourself in the demo. Basically it looks at how many records are found through the relationship to our results, and displays a text string based on that number, pretty simple stuff.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Top Horizontal Line&lt;/h2&gt;
&lt;p&gt;Now things get interesting! Our interface has 3 key horizontal lines which we&#039;ll call top, middle and bottom.  The purpose behind all three is to show one of the 3 at any given point in time, hiding the other 2. The lines act as the bottom of the results box. There are three scenarios for when these lines show.&lt;/p&gt;
&lt;p&gt;In the case of our top line, this will act as the bottom of our results box if there are NO results. In this case, we just show the &quot;no results found&quot; display text, and our box ends there. &lt;/p&gt;
&lt;p&gt;So conversely we hide this line when there ARE results.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Middle Horizontal Line&lt;/h2&gt;
&lt;p&gt;So now that we know our lines are to show the bottom of the box, can you think of when we would have this middle line act as the bottom of the box? I&#039;ll give you a clue, this line sits within a portal row at the bottom of the row.&lt;/p&gt;
&lt;p&gt;Got it yet? How about if we only had 3 results found? Or 2? or 1?  yes! This line is used as the bottom of our box when we have fewer results found than the number of default rows of our portal.&lt;/p&gt;
&lt;p&gt;In our demo file, our portal is setup to show 7 rows. If we only find 3 results, then we want the bottom of our box to end at the bottom of the third row.&lt;/p&gt;
&lt;p&gt;So, our rule for this line is that it is to be shown if there are results found, and where there are fewer results than our portal default.  Or the converse of this: We hide it when the results are more than the number of portal rows.&lt;/p&gt;
&lt;p&gt;Because this line sits inside the portal, we don&#039;t need to bother with the condition of whether there are results or not, this is going to be hidden if there are no results. However it will display on every portal row for which we have results, hence we must hide it on all bar one.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Bottom Horizontal Line&lt;/h2&gt;
&lt;p&gt;Ok so hopefully with top and middle out of the way, the reason for the bottom line should be obvious. If we have lots of results (more than the number of portal rows by default) then we want the results box to be the bottom of the portal. So this line sits just underneath the bottom of the portal.&lt;/p&gt;
&lt;p&gt;If there are more results found than the portals default, we show this line, otherwise we hide it.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;The Results Panel&lt;/h2&gt;
&lt;p&gt;This is a transparent, no bordered single panel control. We use this so that we can enclose everything else inside it, and then we can just apply a single hide condition to the panel to show/hide everything inside.&lt;/p&gt;
&lt;p&gt;The design for our results panel dictates that if the user is not inside the search box, then we will not show any results display. If the user is inside the search box, we only show results content if they have typed at least one character, otherwise we show nothing.&lt;/p&gt;
&lt;p&gt;Showing or Hiding of the results panel is done by way of scripts that execute when the user both exits and enters the search field.  Recall our panel has an object name, so showing/hiding of this is performed by simply refreshing the panel object (which triggers it&#039;s hide condition to run).&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Still with us?&lt;/h2&gt;
&lt;p&gt;Good! We&#039;re almost there. Hopefully you can follow the reason behind the design components and why we show/hide certain elements under certain conditions. But how do we hide things?&lt;/p&gt;
&lt;p&gt;We wanted this solution to be completely transportable and applicable to any other search box in your solution with as minimal effort as possible. To that end, we built a custom function in which all logic for showing/hiding UI components is contained.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage184209-Screen-Shot-2017-03-12-at-3.25.54-PM.png&quot; alt=&quot;custom function&quot; width=&quot;184&quot; height=&quot;209&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is our custom function called @SEARCH_ShowHide.  The function takes 4 parameters:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;_searchObjectName:  This is the object name of our search box&lt;/li&gt;
&lt;li&gt;_hideObject: This is a keyword that identifies which of the 4 hiding components we are trying to hide (top/middle/bottom line or panel).&lt;/li&gt;
&lt;li&gt;_displayRows: How many rows does our results portal show by default&lt;/li&gt;
&lt;li&gt;_resultsKey: This is a reference through to a primary key on our results table, and we use this to determine various bits of information around how many results were found.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;When we setup a hide condition on one of our 4 main hiding elements, we simply reference this custom function. Here is an example of the hide condition on the &lt;strong&gt;middle horizontal line&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;@SEARCH_ShowHide ( &quot;search&quot; ; &quot;line_middle&quot; ; 7 ; Interface_CUSTOMERS__results::id_customer )&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We have told it the name of our search box, what component we are hiding, how many portal rows we have for results, and what the results primary key is.&lt;/p&gt;
&lt;p&gt;We&#039;re not going to post all the code for the custom function here, you can look for yourself within the Demo File, but we&#039;ll point out a couple of things:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;We count the number of results using Count function. This can often be not ideal especially if large numbers of results are found. You can always replace this with our technique &lt;a href=&quot;https://www.teamdf.com/blogs/a-lightning-fast-alternative-to-the-count-function/&quot; target=&quot;_blank&quot;&gt;found here in an earlier article&lt;/a&gt; by adding a foundcount calculation to your table. We opted to not do this here in order to keep the solution free of needing to add extra fields to your tables.&lt;/li&gt;
&lt;li&gt;We make use of the dual nature of custom function parameters being both a value AND a reference to a field (big thanks to Wim Decorte of Soliant for his &lt;a href=&quot;http://www.soliantconsulting.com/blog/2013/11/custom-function-parameters-value-or-reference&quot; target=&quot;_blank&quot;&gt;brilliant and invaluable article on the technique here&lt;/a&gt;). Using this technique we can count records within the custom function.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;So Putting it all Together Again&lt;/h2&gt;
&lt;p&gt;Here&#039;s what is going on:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;User enters into search field. If there is a search, we run a script to show the results panel if not we keep it hidden.&lt;/li&gt;
&lt;li&gt;User beings searching. We show the results panel. Hide conditions determine the size of the results box&lt;/li&gt;
&lt;li&gt;The user clicks upon a search result to navigate away, or exits the search field. We run a script to hide the results panel.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;When you put it like that it&#039;s really quite simple. There are a number of components but on their own they&#039;re all pretty simple and easy to see what role they play.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Applying to your own Solutions&lt;/h2&gt;
&lt;p&gt;Building this into your own solution is simple. If you already have results being shown in a portal, then you&#039;re all set. Just paste into your solution and change the following:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Change the parameters in the hide conditions on the 4 main objects to suit your solution&lt;/li&gt;
&lt;li&gt;Make sure your table has a primary key (a unique value) to use, if not then shame on you!&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;A note on Portal Filtering versus Relationship Filtering&lt;/h2&gt;
&lt;p&gt;This demo file has used filtering of results at the relationship level, and we do not use portal filtering. Digital Fusion has always had a policy of using relationship filtering where possible due to substantial performance gains to be had when working with larger data sets.&lt;/p&gt;
&lt;p&gt;That is not to say portal filtering is bad, nor we never use it. For this demo, if you wish to use portal filtering then you will need to make a few modifications to the solution. Our demo checks the number of records found through the relationship to determine the number of results, and apply hide conditions accordingly. &lt;/p&gt;
&lt;p&gt;The number of results found through portal filtering is a little different to obtain, as the relationship record count may differ from the portal record count. One technique you can use is to add a COUNT summary field to the results table, and place this inside the portal with an object name attached. You can then use GetLayoutObjectAttribute ( &quot;ObjectName&quot; ; &quot;Content&quot; ) to obtain the found count. This can be inserted into the hide custom function in place of where we count records found.&lt;/p&gt;
&lt;p&gt;We won&#039;t go into much more detail into this here, suffice to say it is a change that can be made to use this technique with portal filtering.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Delaying the Search for Performance&lt;/h2&gt;
&lt;p&gt;Our search box uses script triggers to carry out when the reevaluation of the relationship occurs. This is a pretty common technique used to produce dynamic search results for years in FileMaker, ever since v10 introduced triggers.&lt;/p&gt;
&lt;p&gt;We take this one step further. The traditional approach is to refresh search results after each keystroke. This can suffer from performance issues, specifically when there are many results found, or the user is over a WAN connection. THe user often finds themselves being unable to continue typing their search term while they wait for results to load. This can compound itself when results begin showing immediately after the first character is typed - as often the most results found are at this point in the process.&lt;/p&gt;
&lt;p&gt;Our solution is to introduce a short timed delay before filtering occurs. We use an onTimer to control this delay.  Every time the user enters a keystroke, we reset the onTimer which resets the delay. Once the user ceases typing, the delay occurs and after that the onTimer script runs, which carries out the search.&lt;/p&gt;
&lt;p&gt;To give a basic illustration, consider the user typing the word &quot;David&quot; into a search box:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&quot;D&quot; is typed, an onTimer is started at 0.5 seconds&lt;/li&gt;
&lt;li&gt;&quot;A&quot; is typed quickly after, the onTimer is reset back to 0.5&lt;/li&gt;
&lt;li&gt;&quot;V&quot; is typed, slower this time, but still only 0.3 seconds after the &quot;A&quot;. The onTimer is reset to 0.5&lt;/li&gt;
&lt;li&gt;&quot;I&quot; is typed quickly, again the onTimer reset back to 0 .5&lt;/li&gt;
&lt;li&gt;&quot;D&quot; is typed, the user is done typing. The onTimer delay expires after 0.5, and the script runs,carrying out the filtering.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;If the user stopped typing at the &quot;V&quot;, then filtering would occur there. If they continued typing the rest of the word, filtering would again occur 0.5 seconds after the last &quot;D&quot; was entered.&lt;/p&gt;
&lt;h4&gt;Going back a couple of years now..&lt;/h4&gt;
&lt;p&gt;We actually wrote an article on this technique a few years back now. &lt;a href=&quot;https://www.teamdf.com/blogs/building-a-timed-delay-search-filter-for-wan-performance/&quot; target=&quot;_blank&quot;&gt;You can read it here&lt;/a&gt;. The general techniques in that article are exactly the same as they are in our demo file now. In our current demo file we have simplified some things such as script parameters just to make this file easier to understand.&lt;/p&gt;
&lt;h4&gt;Using escape key as a quick clear&lt;/h4&gt;
&lt;p&gt;Because this technique uses an onLayoutKeystroke trigger after each keystroke, we can intercept certain characters and change the resulting behaviour. This is exactly what we have done when we detect the escape character is pressed by the user in the search field. In this case, we clear the search field contents. This is a nice intuitive way to clear the field rather than providing an X icon.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;What about Relationship Filtering?&lt;/h2&gt;
&lt;p&gt;This is another one of those &quot;many ways to skin a cat&quot; things in FileMaker. Some prefer using portal filters, others relationship level filtering. At the relationship level, some build big keys, while others opt for exact matches.&lt;/p&gt;
&lt;p&gt;Exact matches in this case are pretty useless, and keys that are built are often big and cumbersome.&lt;/p&gt;
&lt;p&gt;A few years ago now, &lt;span&gt;Danny Kohn on &lt;/span&gt;the webiste &lt;a href=&quot;http://filemakerinspirations.com/&quot; target=&quot;_blank&quot;&gt;FileMakerInspirations.com&lt;/a&gt; wrote a very insightful article into this problem, and posed a technique using the ≤ and ≥ predicates of relationships, and the sort ordering of text in FileMaker to achieve a relationship filtering technique that results in a very lightweight key field.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://filemakerinspirations.com/2009/01/google-like-search-through-relationship-filtering/&quot; target=&quot;_blank&quot;&gt;You can read his article in full here&lt;/a&gt;. It covers the technique really well and so we won&#039;t go into much more detail on it in this article, suffice to say our demo file makes use of this technique.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Demo File&lt;/h2&gt;
&lt;p&gt;What good is an article like this without a demo file to accompany it right? Well here it is! No username and password, fully unlocked just go for it.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/Uploads/ModernSearchUI.zip&quot;&gt; ModernSearchUI.zip &lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Mon, 13 Mar 2017 11:02:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/building-a-super-slick-search-ui/</guid>
		</item>
		
		<item>
			<title>Options for distributing FileMaker apps</title>
			<link>https://www.teamdf.com/blogs/options-for-distributing-filemaker-apps/</link>
			<description>&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;One of the coolest things that has happened with FileMaker over the last couple of years is the ability to take a FileMaker App and put it through the SDK (Software Development Kit) treatment. The end result is a standalone iOS app that comes with all the features you would expect out of apps in this day and age.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;We have already written on why we think this is cool along with very detailed instructions on how to do this yourself but the missing link was how do you then distribute you app to your clients, co-workers etc.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;The following blog post outlines some of the options currently available at the time of writing*&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;h2 class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Custom B2B Distribution&lt;/span&gt;&lt;/h2&gt;
&lt;h4 class=&quot;p2&quot;&gt;Key Points&lt;/h4&gt;
&lt;ul&gt;&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Custom B2B distribution is exclusively available for purchase through “Volume Purchase Program”&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;The app is hosted and distributed by Apple&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;It gives exclusive access for business members that you identify in iTunes Connect&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Customers sign in and purchase their apps on the Volume Purchase Program store&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;There is no minimum price for the app&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;There is no facility to directly transfer to or from the app store. This means it will always remain a B2B app&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Any updates you wish to make are the same as for app store&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;You may use “Promo Codes”. This way the app can be given to people NOT in the list of Apple ID’s that is used for distribution, for a limited amount of time.&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Volume Purchase Program available in Canada, UK, France, Italy, Germany, Spain, Japan, Australia, New Zealand and USA.&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Can be used with Mobile Device Management &lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;The general public cannot see the listing.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p class=&quot;p2&quot;&gt; &lt;/p&gt;
&lt;h4 class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Costs&lt;/span&gt;&lt;/h4&gt;
&lt;p class=&quot;p1&quot;&gt;The cost associated with getting your app into the B2B programme are $299 per year for an Enterprise Developer Licence and the App store margin is 30%&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;h4 class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;How it works&lt;/span&gt;&lt;/h4&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;After you complete your enrolment in the Apple Developer Program, make sure your tax and banking information is set up in iTunes Connect&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;(&lt;a href=&quot;https://developer.apple.com/programs/enroll/&quot;&gt;&lt;span class=&quot;s3&quot;&gt;Learn about enrolment&lt;/span&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;Next up you need develop and test the application that will solve a problem for your customers.&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;You then selecting your pricing options which could be free or at any price tier you select. &lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Once you identify your customers and release date, you’re all set&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;(&lt;a href=&quot;http://www.apple.com/itunes/go/itunesconnect/manageusers/&quot;&gt;&lt;span class=&quot;s3&quot;&gt;Sign in to iTunes Connect&lt;/span&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Finally you need to select the custom B2B distribution option in iTunes Connect. If your app contains sensitive data, provide sample data and authentication for our review team.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p3&quot;&gt;&lt;span class=&quot;s4&quot;&gt;(&lt;a href=&quot;https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/About.html&quot;&gt;&lt;span class=&quot;s3&quot;&gt;iTunes Connect Developer Guide&lt;/span&gt;&lt;/a&gt;) (&lt;a href=&quot;https://developer.apple.com/app-store/review/guidelines/&quot;&gt;&lt;span class=&quot;s3&quot;&gt;App Store Review Guidelines&lt;/span&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt; &lt;/p&gt;
&lt;h4 class=&quot;p2&quot;&gt;What business customers need to do&lt;/h4&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Once your customer has a volume purchasing account with Apple, they can easily buy apps that meet their business needs, and get custom B2B apps you’ve built for them&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;(&lt;a href=&quot;http://www.apple.com/business/vpp/&quot;&gt;&lt;span class=&quot;s3&quot;&gt;Learn more about the VPP for Business&lt;/span&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Custom B2B apps will appear in your customer&#039;s Volume Purchase Program account. Customers select the app and enter the quantity they want to purchase&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;(&lt;a href=&quot;http://vpp.itunes.apple.com/us/store&quot;&gt;&lt;span class=&quot;s3&quot;&gt;Volume Purchase Program store&lt;/span&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Your business customers can use third-party Mobile Device Management (MDM) solutions to help manage and distribute their apps. Or they can provide redemption codes to their users via email or an internal website&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;(&lt;a href=&quot;http://www.apple.com/iphone/business/it/management.html&quot;&gt;&lt;span class=&quot;s3&quot;&gt;Learn more about Mobile Device Management&lt;/span&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt; &lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage302302-noun-17542.png&quot; alt=&quot;B2B Apps&quot; width=&quot;302&quot; height=&quot;302&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt; &lt;/p&gt;
&lt;h4 class=&quot;p2&quot;&gt;Technical&lt;/h4&gt;
&lt;ul&gt;&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;You cannot submit the same app to app store. You can generate a new appID for it if you want to do this though.&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Must provide test login for Apple&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Promo codes must be requested from Apple.&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Business needs a “DUNS” number to use the volume purchase program. This is installed by emailed URL or use a licence code&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Can be used with Mobile Device Management ( MDM )&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;This can be installed using Apple Configurator&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;The configurator can be used to redeem codes against the device, not the Apple ID. This is the only way to do this&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;If using Supervised Devices, the Apple configurator can be used to activate single app mode ( for iOS 6.0 or greater ) &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p class=&quot;p2&quot;&gt; &lt;/p&gt;
&lt;h2 class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;App Store Distribution&lt;/span&gt;&lt;/h2&gt;
&lt;h4 class=&quot;p2&quot;&gt; &lt;span class=&quot;s1&quot;&gt;Key Points&lt;/span&gt;&lt;/h4&gt;
&lt;ul&gt;&lt;li&gt;The app is available to general public&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Apple provides the distribution service – The App Store. It is highly available and well understood by users&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;The App Store promotes your company on a highly visible marketplace&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;The App Store approval process is required for initial app deployment and app updates. This can often be the tricky part of getting an app into the App Store and it could take you a number of attempts to be successful. The approval process can take a few days or a few weeks.&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;The App Store provides information about your app including a description of the app’s features, screenshots and an indication when the app is updated.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p class=&quot;p2&quot;&gt; &lt;/p&gt;
&lt;h4 class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Costs&lt;/span&gt;&lt;/h4&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;You will need to get yourself an Apple Developers Licence which cost $99 per year and like the B2B option, Apple takes a store margin of 30%&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt; &lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage300300-noun-201546.png&quot; alt=&quot;App Store&quot; width=&quot;300&quot; height=&quot;300&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt; &lt;/p&gt;
&lt;h2 class=&quot;p2&quot;&gt;Ad Hoc Distribution&lt;/h2&gt;
&lt;p class=&quot;p2&quot;&gt;This options is predominantly used for testing purposes and can only be distributed on up to 100 iOS devices.&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Some of the other details that surround the Ad Hoc option are:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;span class=&quot;s1&quot;&gt;Devices must be manually registered using their UDID&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Devices can be removed/replaced once each membership year&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;The App Store approval process is not required&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;The general public cannot see the listing, purchase or install the app&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;The related developer provisioning profile expires in one year - meaning that it can only be used on a given device for a year.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;span class=&quot;s1&quot;&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage300300-noun-323511.png&quot; alt=&quot;Ad Hoc&quot; width=&quot;300&quot; height=&quot;300&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt; &lt;/p&gt;
&lt;h2 class=&quot;p4&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Enterprise In House Distribution&lt;/span&gt;&lt;/h2&gt;
&lt;p class=&quot;p2&quot;&gt; &lt;span class=&quot;s1&quot;&gt;The final option is to distribute it on on an in house enterprise method. This is not curated by Apple and may not be used outside of your business.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt; &lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage300300-noun-284801.png&quot; alt=&quot;Enterprise&quot; width=&quot;300&quot; height=&quot;300&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt; &lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;*We are in a time when things move very quickly so we have attempted to be as accurate as possible at the time of writing. We can’t offer any guarantee the above options or the processes you go through are accurate moving forward.&lt;/span&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 31 Oct 2016 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/options-for-distributing-filemaker-apps/</guid>
		</item>
		
		<item>
			<title>A marriage made of dreams, code and custom T-Shirts.</title>
			<link>https://www.teamdf.com/blogs/a-marriage-made-of-dreams-code-and-custom-t-shirts/</link>
			<description>&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Some say you make your own luck and this story shows there is at least a kernel of truth in that, but I can’t help also feeling that sometimes you just get lucky. This is the story of how I landed my dream job at DF.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;From an early stage in my FileMaker development trajectory I had identified Digital Fusion as a standard setting team to watch and learn from. It was a bitter sweet day when I found a job advertisement online for a new developer to join the DF ranks. At least they were hiring so there was hope one day, but I knew I still had too much to learn. However, perhaps my biggest hurdle  was that I was based and committed in my home on the outskirts of Brisbane , Queensland, while the nearest DF office is in Sydney.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;A Brisbane based, developer,  mentor and friend of mine was aware I was looking at shifting my career into full-time FileMaker consultancy. He’d been approached about a project he couldn’t take on and put my name forward.&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;Enter the T-Shirts. Located near Brisbane Airport, at Eagle Farm, Queensland, QTCo or &lt;a href=&quot;http://www.qtco.com.au/&quot; target=&quot;_blank&quot;&gt;Queensland T-Shirt Company&lt;/a&gt;, is a leading Australian supplier of branded products for business and promotional use. They can source and brand pretty much anything and everything but also have dedicated in-house apparel and screen-printing business units. Excitingly, they also run one of the most significant ‘direct to garment’ (DTG) printing enterprises in the Southern Hemisphere.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600305-direct-to-garment-t-shirt-printer-dtg-machine-tee.jpg&quot; alt=&quot;direct to garment t shirt printer dtg machine tee&quot; width=&quot;600&quot; height=&quot;305&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;The team at QTCo had the kind of problem you hope for in business. A significant international client, offering a large increase in sales , beyond your current system’s capacities to deliver.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;The client is an international, web based, marketplace for artists. Products such as T-shirts are produced ‘on demand’ when an order is placed and shipped direct to consumers by local ‘fulfiller’ partner enterprises.  They had their eye on QTCo to be the Australasian fulfiller for printed garments, but QTCo needed to develop solutions to  integrate with the client’s automated ordering system, manage inventory and print workflow using barcode scanners and automatically create shipping labels and submit manifests to Australia Post for delivery.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;I needed help with some of the web integration elements of the project so I reached out to Stuart Woodhouse and suggested Digital Fusion might work with me on it. Along the way, we discovered we work very well together. &lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;One day, while watching the latest bag of printed shirts getting packed and shipped from QTCo, it occurred to me there may be a way to stay in Brisbane AND work with the team at Digital Fusion all the time.  So I suggested DF may like to look at taking me on in Queensland with a view to better supporting and growing their client base here. I’m still waiting on my finder’s fee for head hunting myself, but otherwise I think this plan ticks all my boxes.&lt;/span&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 17 Oct 2016 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/a-marriage-made-of-dreams-code-and-custom-t-shirts/</guid>
		</item>
		
		<item>
			<title>Sortable - A Developers Journey</title>
			<link>https://www.teamdf.com/blogs/sortable-a-developers-journey/</link>
			<description>&lt;p&gt;What follows is a tale of a developer. Like many tales it twists and turns, guiding the protagonist to embark on a journey of discovery. This journey of discovery is not conducive to a linear tale, but the richest of experiences is always a product of re-evaluation, self-discovery and enlightenment.&lt;/p&gt;
&lt;p&gt;One of the great things about FileMaker is its willingness to bring other friends to the party; it doesn’t restrict us to a proprietary end-to-end environment. There are many great ways to introduce integrations and other technologies. The most powerful of which has got to be plugins.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;A FileMaker plugin is a file, created in C or C++, given the appropriate extension. The plugin can then be loaded into FileMaker Pro to expand the set of functions available. There are also third party plugins that allow you to develop your own plugins in PHP or Java.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Or, we can develop our own plugins using our very own Reactor! But more on that later... &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;While the FileMaker platform allows us to build and deploy powerful business applications extremely quickly, it doesn’t give us the degree of control that allows us to build ‘anything’ in FileMaker Pro natively.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;  &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sortable/_resampled/ResizedImage173173-digger.png&quot; alt=&quot;digger&quot; width=&quot;173&quot; height=&quot;173&quot;&gt;&lt;/p&gt;
&lt;p&gt;But this is a good thing!&lt;/p&gt;
&lt;p&gt;Because were that not the case, we wouldn’t be able to build and deploy applications as quickly as we can.&lt;/p&gt;
&lt;p&gt;However, FileMaker Pro is happy to hand the job onto someone else. There are two ways to use develop a client-side interface using web technologies; in a WebViewer, and using Reactor.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sortable/_resampled/ResizedImage226179-keys.png&quot; alt=&quot;keys&quot; width=&quot;226&quot; height=&quot;179&quot;&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;&lt;span&gt;The Mission&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;There have been many moments when building portals in FileMaker Pro that this developer wished they could drag around portal rows to re-sort them. It occurred to me that building a portal in HTML+JS could allow me to manipulate the portal anyway I desired. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;&lt;span&gt;The WebViewer&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;I got to work. With a basic knowledge of HTML+CSS+JS I put together a web-based portal, and transformed it into a custom function. The custom function was passed in a Javascript array of IDs and sort orders, as well as the script to run when the sort order changed. The sort order was changed when the portal rows were dragged up or down - using JQuery’s incredible UI Library. When running the script it would pass as a parameter the ordered set of record IDs. It worked.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;&lt;span&gt;The Problem&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;While it worked, it wasn’t very modular. I had to encode the data into a Javascript array, and decode it at the other end. It was working around FileMaker rather than working with it. It would be difficult to take it out of this solution, and pop it into another one.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sortable/_resampled/ResizedImage127127-puzzle.png&quot; alt=&quot;puzzle&quot; width=&quot;127&quot; height=&quot;127&quot;&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;&lt;span&gt;The Solution&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;“Why don’t you just use Reactor?” I was asked by one of my fellow colleagues.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sortable/_resampled/ResizedImage140140-confused.png&quot; alt=&quot;confused&quot; width=&quot;140&quot; height=&quot;140&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span&gt;That quip gave me pause. While I certainly knew of Reactors existence, I had never had first-hand experience of developing for Reactor and how powerful it truly was.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;font-size: 10px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sortable/reactorize-1.gif&quot; alt=&quot;reactorize 1&quot; width=&quot;235&quot; height=&quot;74&quot;&gt;&lt;/h2&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Reactor? What&#039;s that?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://fusionplugins.com&quot;&gt;&lt;span class=&quot;s1&quot;&gt;fusionplugins.com&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At Digital Fusion, we pride ourselves on our Fusion Reactor plugin. Most plugins are developed to perform a certain task or reach a certain goal; be that to integrate with your accounting package, or to perform file operations on a local disk. The Fusion Reactor plugin provides a gateway. What lies beyond that gateway is entirely up to you - the developer. &lt;a href=&quot;http://fusionplugins.com&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;JavaScript is really the only way to create new and unique UI controls (widgets) for FileMaker applications.&lt;/p&gt;
&lt;p&gt;The combination of HTML5, CSS3 and Javascript has provided an almost unlimited palette with which to build web applications; if you can dream it, you can do it. Anything you can conceive of in a software application can be built using this combination of technologies. &lt;/p&gt;
&lt;p&gt;Reactor is a plugin developed by some wizards at Digital Fusion Ltd, well before my time. Basically it’s a plugin that allows us to build our own plugins using front-end web technologies. Reactor allows us to install and run these things called BlackBoxes. Far from a flight-data recovery tool (which I should avoid dwelling on - as I write this from 35,000 feet over the Tasman sea) it is a web app. I was able to write the source for the web app, and deploy it into a BlackBox that could then be installed onto any machine that has Reactor installed.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;&lt;span&gt;Where’s the Reaction?&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;So far, no different. We’ve basically done what we did with the WebViewer and custom function. Where Reactor really adds value is the way it can talk with the database. The Reactor toolbox contains a suite of tools that facilitate communication between our Javascript and our FileMaker data. No more did this developer have to parcel up their data in a form the Javascript can understand, and un-parcel it when it’s done. Any transactions with the FileMaker data could take place within the Javascript itself. It was now completely modular and fully portable.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Like all great tales, the Sortable application basically boiled down to three acts:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sortable/_resampled/ResizedImage135135-books.png&quot; alt=&quot;books&quot; width=&quot;135&quot; height=&quot;135&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;&lt;span&gt;Act I: Retrieve the data&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;When the application is loaded it downloads the records - it knows what records to download and display in the portal because we pass through a table occurrence with field name as one of the parameters - this takes into account the relationship to that table occurrence. In the Javascript, we can pull through any fields we wish; such as current sort values, UID, type, value 1, value 2, image, etc. These are all set up as parameters as well.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sortable/_resampled/ResizedImage600361-code.png&quot; alt=&quot;code&quot; width=&quot;600&quot; height=&quot;361&quot;&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;&lt;span&gt;Act II: Manipulate the front-end&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;The next step is to write the Javascript, so that an HTML element can be dragged about a list of HTML elements. This is remarkably easy to do using the JQuery UI Library, we just need to instantiate the Sortable class, and tell it what to do when an element is dragged to a different location.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;&lt;span&gt;Act III: Preserve the new sort order&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;So far, all we have done is move objects about a portal. The next step is to actually have it do something. When the element is dragged to a different location, we call an asynchronous function. This is really nice because the users experience is truly seamless. We loop through every item in the portal, updating the FileMaker Pro data with the new sort order. We do this by calling a script, passing through the UID of the record, as well as the new sort order.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sortable/_resampled/ResizedImage359349-list.png&quot; alt=&quot;list&quot; width=&quot;359&quot; height=&quot;349&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;&lt;span&gt;Where To From Here?&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;I emerged triumphant. I had achieved my goal in developing a solution that was modular and portable, and learned a lot of about a powerful tool that paved a new way to a world of exciting possibilities. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sortable/_resampled/ResizedImage600481-screenshot-correct.png&quot; alt=&quot;screenshot correct&quot; width=&quot;600&quot; height=&quot;481&quot;&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span&gt;In particular, I&#039;m very keen and excited to explore other great front-end augmentations and features that can be made possible with other components of the JQuery UI library. Sortable is just one of them:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href=&quot;https://jqueryui.com/&quot;&gt;https://jqueryui.com&lt;/a&gt;&lt;/span&gt; &lt;/p&gt;
&lt;p&gt;&lt;span&gt;Interactions and Widgets&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;span&gt;Draggable - drag object around an area with the mouse&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Droppable - drag objects and drop them onto/within other objects, activating an action&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Resizeable - change the size of an object using the mouse&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Selectable - click-and-drag the mouse to select multiple items (could be an awesome alternative to sortable where multiple rows in a portal can be selected with the mouse)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Accordian - headings that can collapse more detailed information&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Auto-complete - predict user input in text fields&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Button - enhances buttons, to make them fully customisable&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Dialog - produce a customised dialog that can be moved and closed&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Menu - create fully customised menus, including disabled items, nested items, able to be navigated by both keyboard and mouse&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Progress Bar - customised progress bar of a pending process or action&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Select Menu - similar to popup fields in FMP, but with icons and grouping&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Slider - customisable slider to set numerical values&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Spinner - customisable spinner to increment/decrement numerical values&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Tabs - fully customisable tabs. Can open tabs on hover rather than click, can add/remove/sort tabs as user, etc&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Tooltip - many awesome customisations for tooltips, beyond what might be termed as conventional&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;&lt;span&gt;Effects&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;We can use the JQuery UI suite to add classes to objects, therefore adding effects. For example, we can animate an object to transition from one color to another, animate the easing of an object (gradually show/remove), or animate any effect at all such as bouncing, dropping, shaking, pulsating, etc.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Effects such as these are all over the web to augment the users experience, and using Reactor they can be added to any FileMaker Pro application to do the same!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Fri, 07 Oct 2016 08:06:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/sortable-a-developers-journey/</guid>
		</item>
		
		<item>
			<title>Introducing Morgan Chance</title>
			<link>https://www.teamdf.com/blogs/digital-fusion-opens-in-queensland/</link>
			<description>&lt;p&gt;For a number of years now, Digital Fusion have had a large number of clients in Brisbane and the greater Queensland region.&lt;/p&gt;
&lt;p&gt;These clients have been looked after by our sales and development teams, with a short skip and jump up from Sydney.&lt;/p&gt;
&lt;p&gt;But now we are pleased to announce that we have a full time staff member based in Brisbane and he will be focusing on just the Queensland region (we feel it&#039;s time to repay the love)&lt;/p&gt;
&lt;p&gt;Morgan Chance starts with us at the beginning of October and will have many hats to wear.&lt;/p&gt;
&lt;p&gt;As well as being our client manager for Queensland, he will be working with clients as our business analyst plus taking on FileMaker development projects.&lt;/p&gt;
&lt;p&gt;Morgan comes to us with an incredibly interesting background, so we asked him to write us a bio on what he&#039;s got up to through the years....&lt;/p&gt;
&lt;p&gt;Prior to graduating with a veterinary science degree, Morgan worked in a variety of industries including food animal production (farming), veterinary retailing and nursing, transportation, merchandising and printing. On completing his studies he began several years of rural, mixed animal veterinary practice in a predominantly beef cattle region of Northern New South Wales.&lt;/p&gt;
&lt;p&gt;In preparation for a sea change, Morgan completed a high school science teaching diploma and moved his large family to the Island paradise ‘North Stradbroke Island’ in South East Queensland.&lt;/p&gt;
&lt;p&gt;High school teaching led Morgan to engage with a local university marine research station where he settled into a role managing science education field activities. Along the way Morgan established a house call veterinary service for Island residents.&lt;/p&gt;
&lt;p&gt;Struggling with his data needs in this service, Morgan discovered FileMaker and found it such a user friendly and accessible platform he started using it to develop solutions at the research station as well.&lt;/p&gt;
&lt;p&gt;Recently, he has been working on production floor, order and logistics automation systems for a rapidly expanding international garment printing enterprise.&lt;/p&gt;
&lt;p&gt;Morgan enjoys exploring business systems, imagining future potentials and especially loves those eureka moments when a challenging business requirement crystallises into a design solution.&lt;/p&gt;
&lt;p&gt;As a footnote, we thought we had done well by employing our first Australian staff member in a while, only to discover that Morgan was born in Auckland. His redeeming grace is he only lived there for the first few months of his life.&lt;/p&gt;</description>
			<pubDate>Tue, 20 Sep 2016 08:49:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/digital-fusion-opens-in-queensland/</guid>
		</item>
		
		<item>
			<title>FileMaker Certification</title>
			<link>https://www.teamdf.com/blogs/new-blog-post/</link>
			<description>&lt;p&gt;With every release of a new version of FileMaker, we like to get our developers certified, both as a way to upskill our team, but also to show our passion for FileMaker.&lt;br&gt;&lt;br&gt;FileMaker 15 was released earlier this year, and soon after the certification exam was released. &lt;br&gt;&lt;br&gt;Passing the exam is not easy, it involves quite a bit of study on our developers behalf, and the pressure to pass is high, particularly when you are last to sit the exam.&lt;br&gt;&lt;br&gt;We are now proud to say that all eight of our developers are FileMaker 15 certified.&lt;br&gt;&lt;br&gt;As our company motto goes….  FileMaker - We know it. We love it. We live it&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 13 Sep 2016 08:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/new-blog-post/</guid>
		</item>
		
		<item>
			<title>Tiki Tour To DevCon</title>
			<link>https://www.teamdf.com/blogs/tiki-tour/</link>
			<description>&lt;p&gt;Tiki Tour: New Zealand slang for&lt;span&gt; taking the &lt;/span&gt;scenic route&lt;a class=&quot;spf-link&quot; href=&quot;http://www.urbandictionary.com/define.php?term=scenic+route&quot; data-hasqtip=&quot;91&quot;&gt;&lt;/a&gt;&lt;span&gt; to a destination.&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;A British Experience&lt;/h2&gt;
&lt;p&gt;About 9 months ago, I made the decision that I needed to be at one of the biggest music festivals in the world - the &lt;a title=&quot;Glastonbury Festival Official Site&quot; href=&quot;http://www.glastonburyfestivals.co.uk&quot; target=&quot;_blank&quot;&gt;Glastonbury festival&lt;/a&gt; in Somerset. I was also one of the lucky souls of Team Digital Fusion that would be attending DevCon in 2016, so I thought I could make the most of this, and line a personal holiday up with DevCon, which one might term a Working Holiday.&lt;/p&gt;
&lt;h3&gt;Glastonbury Festival of Music and Mud&lt;/h3&gt;
&lt;p&gt;Well, I am now on the other side. And I can say that it was amazing fun, I shall always look upon it fondly, and I NEVER want to do it again. EVER.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Getting in was pretty delayed, but people had it much worse. I think it must’ve been worse the day after we arrived. It’s a 3.5 hour ride in from London, and it took about 7-8 hours.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Tiki-Tour-To-DevCon/_resampled/ResizedImage600800-glastonbury.png&quot; alt=&quot;glastonbury&quot; width=&quot;600&quot; height=&quot;800&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Musical highlights were definitely Coldplay, Madness, Muse and this incredible Beatles cover band I happened to stumble onto on the last afternoon. People seemed to really enjoy Adele, which I did attend, but not really my thing. I left half-way through to see the Bowie Tribute Laser Show. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Festival highlights were just the overall vibe of the festival, it really is incredible. 170,000 people crammed into a farm, which is set up as a commune, but with heavy capitalist influences. Everywhere you turn is somewhere you can buy food and/or alcohol. Any sort of shop you can imagine is represented as well. Moving between the main stages is akin to getting around downtown Sydney or London during rush hour.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The mud. I will never forget the mud. It’s not an object, or even an adjective. It’s a medium through which the whole festival exists. I was expecting there to be some mud around, but in reality, the mud was good enough to host a festival for us. However, I have since learned that due to the torrential rain leading up to the festival, 2016 was the muddiest Glastonbury ever.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;And now it’s all over. People I was there with are already making plans to do it all again next year. Nope. Never again. 10 stars. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Tiki-Tour-To-DevCon/_resampled/ResizedImage600600-sunset.png&quot; alt=&quot;sunset&quot; width=&quot;600&quot; height=&quot;600&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;So on with my holiday. Though I have written tomorrow off for recovery and laundry. Mud is in EVERYTHING.&lt;/p&gt;
&lt;p&gt;With Glastonbury done and dusted I still had a couple of weeks before DevCon — this left me with a bit of a dilemma. I would be based in London for the most part, but the thought of keeping my sightseeing to London would be a bit restrictive, and not quite sufficient to fill up two weeks. I was keen to see more of the country, but wasn’t keen on spending a fortune to do it - nor coming up with the logistics of doing so...&lt;/p&gt;
&lt;div&gt;
&lt;h2&gt;Enter Contiki Tours!&lt;/h2&gt;
&lt;p&gt;Contiki Tours is an organisation that carries out tours for people aged 18-35 of Europe, USA, Canada, Asia, Australia and New Zealand.&lt;/p&gt;
&lt;p&gt;It was actually set up by a Kiwi, John Anderson. John Anderson set off for a big OE in England, but found he was too short of money for everything he wanted to see. So he devised a cheeky scheme, and advertised a new tour for Australasians with only a few seats left available. He heard back from 11 people excited to join this very popular ‘tour’, and were more than happy to pay to join the trip. So he worked out the total costs for the trip, charged each applicant an equal share, and bought a van. Having secured himself a free place on this tour as the tour guide, he could now begin his OE. He was completely unable to maintain the facade of being an experienced tour guide, so he quickly confessed his inexperience to the group, and they all shared in the responsibilities and duties - including the driving! It is from this that Contiki Tours grew into the massive operation it is today. However it’s a bit more professional these days, and the trip managers are much better informed!&lt;/p&gt;
&lt;p&gt;When I was discussing the gap in my trip with a friend, they floated the idea that perhaps I could do a Contiki tour. I looked into it, and it seemed perfect. I could see England and Scotland in the time-frame I had available, and I didn’t need to do anything beyond paying the fee and turning up. Everything is pre-arranged.&lt;/p&gt;
&lt;p&gt;Somehow, I managed to set it up to do a tour of England at a time they were facing dual crises. Not only did the Brexit decision get announced a week before my trip, England were eliminated from the UEFA Euro playoffs - in a shock loss to Iceland. But they are a hardy bunch, and it didn’t impact my trip at all (other than a slight improvement in the buying power of my NZ dollars).&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Tiki-Tour-To-DevCon/alarm.png&quot; alt=&quot;alarm&quot; width=&quot;203&quot; height=&quot;176&quot;&gt;&lt;/p&gt;
&lt;p&gt;At 6.30am I turned up at the meeting place, and after some formalities (showing passports, travel insurance, next of kin, etc) we were off on the road - the road to Liverpool. What I found remarkable was that most everybody was in the same boat as me. They were travelling alone.&lt;/p&gt;
&lt;p&gt;There were very few friends amongst the group - at that stage anyway. Ironically, I believe that creates a friendlier environment, because everybody is that much keener to make new friends. For the first leg of our drive to Liverpool, we were pretty much left to be - or rather to sleep.&lt;/p&gt;
&lt;h3&gt;Curve Ball&lt;/h3&gt;
&lt;/div&gt;
&lt;p&gt;Then after we stopped for lunch, the trip manager pulled out a curve ball I was not expecting. We were to undergo a speed-dating inspired method of getting to know each other. Anybody in the aisle seat would move forward to the next person asking a set of questions to get to know them until the buzzer went off, and they’d move to the next person. The questions were of standard fare; what’s your name, what do you do, is this your first tour, etc. As an introvert, I found this positively terrifying and I just conducted it in a similar manner to the dentist - of just getting through to the other end.&lt;/p&gt;
&lt;p&gt;But the energy of the bus completely changed after that. I don’t think it’s because you learn more about the other people in the trip - I forgot everything instantly. But what I think it does do, is just loosen everybody up. I discovered throughout the rest of the trip that most people hated it - but afterwards everybody was laughing and chatting in a way they weren’t doing before hand. Well played Contiki.&lt;/p&gt;
&lt;p&gt;So that set the tone for the trip. From London we saw Liverpool, York, Lake District, Edinburgh, Scottish Highlands, West Highlands and Glasgow. The weather was absolutely appalling for the beginning of summer - but living in New Zealand I’ve learned that if you get upset at disjointed expectations about weather you’ll drive yourself nuts. Anyway, it added to the trip - to get the authentic British summer weather. &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Tiki-Tour-To-DevCon/_resampled/ResizedImage600400-terrified.png&quot; alt=&quot;terrified&quot; width=&quot;600&quot; height=&quot;400&quot;&gt;&lt;/p&gt;
&lt;div&gt;
&lt;h3&gt;Roomies&lt;/h3&gt;
&lt;p&gt;Something I was particularly anxious about was sharing a room. I am a snorer, and like all snorers I have a bit of anxiety about how it affects others. Contiki do offer a single room for the hotels you stay at, but the cost didn’t really make it worth it for me. So I mentioned this to my room-mate the first night, and to my eternal relief he said he too was a snorer. Sharing a room with someone was something I found very strange at first, but after a couple of nights I had totally acclimatised and it didn’t bother me at all. Maybe I was very lucky to get a great room-mate I got along with really well. Also I think having a room-mate sort of stops either of you from sleeping in past the departure time. Two alarms are better than one!&lt;/p&gt;
&lt;p&gt;So for nine days we went from town to town, and saw some amazing things and went to some amazing places. Hadrian’s Wall, Edinburgh Castle (as well as countless other castles), the Edinburgh Dungeons - which were absolutely terrifying, the Lake District, York, the Cavern Club in Liverpool, the Isle of Skye, the Loch Ness...&lt;/p&gt;
&lt;h3&gt;The Loch Ness Challenge&lt;/h3&gt;
&lt;p&gt;Loch Ness posed the next step &#039;outside my comfort zone&#039;: The Loch Ness challenge — basically to jump into the Loch which might sound fine to those in warmer climes where summer is indeed the perfect time to jump into a lake. And we&#039;re pretty sure there is no &quot;nessy&quot; lurking in those unfathomable depths... However this Scotland, and it turns out Loch Ness is the same temperature all year around - a toasty 6 degrees, so being summer doesn&#039;t help.&lt;/p&gt;
&lt;p&gt;I had told people I’d do it, but the day leading up to it was cold and miserable, and I really didn’t want to. But I went with the flow and ended up jumping in. Then after I got out and dried myself someone said ‘Shall we do it again?’, so I dropped my towel, went back to the pier and did a majestic bomb into the water this time - not like my timid step off the edge I did with the first one. It was a fast recovery with another towel-dry and shot of whiskey.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Tiki-Tour-To-DevCon/jump.png&quot; alt=&quot;jump&quot; width=&quot;350&quot; height=&quot;305&quot;&gt;&lt;/p&gt;
&lt;div&gt;Before I knew it, the tour had come to an end. I had found that in the short space of nine days - which had gone by in a massive flurry, I had made some awesome new friends - the only stinger being that I’ll probably never see most (if not any) of them again. But that’s part and parcel of it, and can’t dwell on it too much. What made the end particularly difficult was that I had picked a modular trip. This meant that our of around 50 of us, 17 of us were dropping off, and the rest were continuing onto Ireland. I wouldn’t recommend a modular trip as most of the remaining people on the tour are now my friends on Facebook, and I keep seeing photos pop up of their amazing time in Ireland. For example, this came through a few hours ago:&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Tiki-Tour-To-DevCon/ireland.png&quot; alt=&quot;ireland&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Future Plans...&lt;/h3&gt;
&lt;p&gt;Unlike Glastonbury, I’m already making plans in my head to do another one - a proper big one, around the main tourist parts of Europe. Unfortunately I am approaching the dusk of the 18-35 year old range, so that leaves me with just a few years. So if you’re curious about it, I would say absolutely do it. And if you want to travel, see the world, and you’re not sure how, it’s perfect. Check their website to see what’s available, and you’ll have an absolute blast.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.contiki.com/&quot;&gt;https://www.contiki.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;They talk a lot about the Contiki Family you develop, and it does sound like marketing nonsense. But it’s true. Even after a relatively short tour such as mine, a group of complete strangers are transformed into close friends over just nine days. I have even caught up with a couple of them since the tour ended, for some sightseeing in London.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;</description>
			<pubDate>Wed, 13 Jul 2016 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/tiki-tour/</guid>
		</item>
		
		<item>
			<title>FileMaker iOS SDK - Part 4</title>
			<link>https://www.teamdf.com/blogs/building-and-testing-our-ios-app/</link>
			<description>&lt;h2&gt;Building an iOS App from a FileMaker Database&lt;/h2&gt;
&lt;p&gt;Welcome to the fourth and final part of the FileMaker iOS App SDK series. In the final part of the series I will take you through building and compiling the iOS App. If you haven&#039;t yet read through parts &lt;a title=&quot;FileMaker iOS SDK - Part 1&quot; href=&quot;https://www.teamdf.com/blogs/building-an-ios-app-from-your-custom-filemaker-go-app/&quot;&gt;1&lt;/a&gt;, &lt;a title=&quot;FileMaker iOS SDK - Part 2&quot; href=&quot;https://www.teamdf.com/blogs/setting-up-your-apple-developer-account/&quot;&gt;2&lt;/a&gt; and &lt;a title=&quot;FileMaker iOS SDK - Part 3&quot; href=&quot;https://www.teamdf.com/blogs/creating-the-project-directory/&quot;&gt;3&lt;/a&gt;; now would be a good time to go take a look.&lt;/p&gt;
&lt;h3&gt;Building the iOS App&lt;/h3&gt;
&lt;p&gt;We will start by opening the WindowFurnishing.xcodeproj file that we created in &lt;a title=&quot;FileMaker iOS SDK - Part 3&quot; href=&quot;https://www.teamdf.com/blogs/creating-the-project-directory/&quot;&gt;part 3&lt;/a&gt;. In the Xcode project window we’ll click the disclosure triangle next to Custom Application Resources and again next to Solution Files. The Solution Files directory is where the iOS App expects the FileMaker files to be.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/iOS-App-SDK/_resampled/ResizedImage600381-xcode-project.png&quot; alt=&quot;xcode project&quot; width=&quot;600&quot; height=&quot;381&quot;&gt;&lt;/p&gt;
&lt;p&gt;It’s important to note that each iOS app has its own documents directory in addition to the Solution Files directory. When the WindowFurnishing app is launched for the first time on iOS, the files from the Solution Files directory are copied to the WindowFurnishing app documents directory, from there the user adds / updates the data in the app documents directory files. When an iOS device is plugged into a computer with iTunes installed you can access the App documents directory by selecting the iOS device &amp;gt;&amp;gt; Apps and the app name in the File Sharing section.&lt;/p&gt;
&lt;p&gt;We will remove the PlaceHolder.fmp12 file by selecting it and pressing delete. We can copy our files into the Solution Files directory by dragging and dropping on the folder in the Xcode window.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/iOS-App-SDK/_resampled/ResizedImage600381-xcode-project-mcw.png&quot; alt=&quot;xcode project mcw&quot; width=&quot;600&quot; height=&quot;381&quot;&gt;&lt;/p&gt;
&lt;p&gt;With our files in place we need to tell the iOS App what file to open at launch. In the Custom Application Resources folder Click on the configFile.txt file and change the following line&lt;/p&gt;
&lt;pre&gt;launchSolution = PlaceHolder.fmp12&lt;/pre&gt;
&lt;p&gt;to&lt;/p&gt;
&lt;pre&gt;launchSolution = WindowFurnishing.fmp12&lt;/pre&gt;
&lt;p&gt;If we try and specify a file name in launchSolution that doesn’t exist the iOS App will fail to build. The launchSolution file name is also case sensitive, if we don’t get the casing correct the build will succeed but the iOS App will not launch the FileMaker solution.&lt;/p&gt;
&lt;p&gt;There are two further options in the config file that can be changed:&lt;/p&gt;
&lt;p&gt;helpURL - this is the URL to your apps support or help site, if this is left blank the help menu is removed from the app. If your custom files are being opened in Kiosk mode the help menu will not be available.&lt;/p&gt;
&lt;p&gt;alwaysOverwrite - this specifies whether the Solution Files are copied fresh into the apps document directory when the app launches. If this is set to 1 everytime we launch the WindowFurnishing app the Solution Files will be copied into the documents directory. This means that the files will “reset” at each launch. Setting this value to 1 is only recommended for testing purposes.&lt;/p&gt;
&lt;p&gt;We&#039;ll save our changes to the config file and continue on.&lt;/p&gt;
&lt;h3&gt;Creating and Adding images&lt;/h3&gt;
&lt;p&gt;We’ll now create and add some icons for our iOS App, icons and images need to follow the &lt;a title=&quot;Apple Guidelines for Icons and Images&quot; href=&quot;https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html#//apple_ref/doc/uid/TP40006556-CH27-SW1&quot; target=&quot;_blank&quot;&gt;Apple guidelines for icons and image sizes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Adding icons to our App is very straight forward through the drag and drop interface provided in Xcode, to access this interface click on the CustomAppAssets.xcassets folder. We can see there are three icons sets available for changing: AppIcon, LaunchImage and ObscureIcon.&lt;/p&gt;
&lt;p&gt;AppIcon - The app icon is the icon that we see on the iOS home screen. iOS devices will have different icon size requirements depending on model.&lt;/p&gt;
&lt;p&gt;LaunchImage - The launch image is used as a splash screen while the iOS app launches&lt;/p&gt;
&lt;p&gt;ObscureIcon - If our FileMaker app uses the fmreauthenticate extended privilege the iOS App will display a security shield over the content when the iOS App is moved into the background.&lt;/p&gt;
&lt;p&gt;Let&#039;s start by clicking on AppIcon and dragging our icons in for each of the devices and sizes required. Xcode will show a warning triangle in the title bar if we have used any incorrectly sized icons. Clicking on the warning triangle will present a dropdown showing the list of warnings. We will be able to build and test our iOS App with these warnings but there is no guarantee the icons will look as expected on all devices and versions of iOS.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/iOS-App-SDK/_resampled/ResizedImage600381-xcode-images.png&quot; alt=&quot;xcode images&quot; width=&quot;600&quot; height=&quot;381&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Changing the Settings of our iOS App&lt;/h3&gt;
&lt;p&gt;Before we can build and test our iOS App we need to change some settings. Our iOS App requires Data Protection to be enabled, a version number and a build number.&lt;/p&gt;
&lt;p&gt;We’ll start by enabling Data Protection. Click on the WindowFurnishing project and then click on capabilities in the main project window. We can see that Background Modes has already been turned on for us, we’ll find Data Protection in the list and click the toggle to turn it on.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/iOS-App-SDK/_resampled/ResizedImage600381-xcode-general-dataprotection.png&quot; alt=&quot;xcode general dataprotection&quot; width=&quot;600&quot; height=&quot;381&quot;&gt;&lt;/p&gt;
&lt;p&gt;Next we need to specify the version and build numbers for our iOS App, we’ll click on the General tab in the main project window to bring up these settings. In the Identity section add the version number and build number.&lt;/p&gt;
&lt;p&gt;Optionally we can specify a URL scheme for our iOS App. FileMaker Go uses fmp for its url scheme, we will have to use a unique URL scheme. We&#039;ll start by selecting the Info tab in the main project window, click on URL Types to open the drop down. We will create a URL scheme by clicking the plus button and entering mcw into the URL Schemes box, other apps and websites will be able to use mcw:// to interact with our app.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600410-xcode-info-urltypes.png&quot; alt=&quot;xcode info urltypes&quot; width=&quot;600&quot; height=&quot;410&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Other optional settings&lt;/h3&gt;
&lt;p&gt;Under the General tab in the main project window we can see there are a few other options that can be set, a few of these options can be safely changed. In the Deployment Info section we can make changes to the following options to suit our needs:&lt;/p&gt;
&lt;p&gt;Devices - We can choose the iOS devices our app runs on (iPhone, iPad or Universal).&lt;/p&gt;
&lt;p&gt;Device Orientation - We can choose to restrict which orientations are allowed for our iOS App, note that on devices that support full screen this setting will be ignored.&lt;/p&gt;
&lt;p&gt;Status Bar Style - We can choose to have the default style or use the light style status bar (this is the bar where the cell info, clock etc is located)&lt;/p&gt;
&lt;p&gt;Hide Status Bar - We can choose to hide the status bar in our app completely&lt;/p&gt;
&lt;p&gt;Requires Full Screen - If this option is checked our iOS App will not be able to be used in Slide Over or Split View.&lt;/p&gt;
&lt;p&gt;On the info tab in the Custom iOS Target Properties section we can also change the “Application supports iTunes file Sharing” option. This is set to Yes by default, if we change the value to No users will be prevented from accessing the app documents directory through iTunes.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/iOS-App-SDK/_resampled/ResizedImage600434-xcode-custom-properties.png&quot; alt=&quot;xcode custom properties&quot; width=&quot;600&quot; height=&quot;434&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Compiling and testing the iOS App&lt;/h3&gt;
&lt;p&gt;We are now ready to compile and test our iOS App. First we need to ensure that our device is plugged into our computer and unlocked. We will specify which device we will be testing on by selecting it in the Xcode window. Click on the device menu to bring up the dropdown. The devices menu lists the devices plugged into the machine as well as any iOS simulators that are installed (the latest devices are installed along with Xcode). We can use the simulators to test our app on device that we may not have physical access to.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/iOS-App-SDK/xcode-devices.png&quot; alt=&quot;xcode devices&quot; width=&quot;305&quot; height=&quot;271&quot;&gt;&lt;/p&gt;
&lt;p&gt;With our device selected we can go ahead and push the play icon in the title bar. A progress indicator will be displayed in the centre of the Xcode title bar indicating the Apps build progress. Once Xcode has finished building the iOS App it will be installed and launched automatically on our iPad.&lt;/p&gt;
&lt;p&gt;Xcode immediately puts our iOS App into debugging mode, we can stop Xcode from debugging our App by clicking on the debug menu and selecting the detach option at the bottom of the list. If we wish to re-enter debugging mode we can simply click on the debug menu and in the “Attach to Process” submenu select WindowFurnishing, it can take a few seconds for the process list to load.&lt;/p&gt;
&lt;p&gt;Congratulations, we have successfully compiled and built an iOS App from our custom FileMaker solution.&lt;/p&gt;</description>
			<pubDate>Thu, 12 May 2016 10:05:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/building-and-testing-our-ios-app/</guid>
		</item>
		
		<item>
			<title>FileMaker 15 released</title>
			<link>https://www.teamdf.com/blogs/filemaker-15-released/</link>
			<description>&lt;p&gt;Earlier today FileMaker released their latest version, FileMaker 15&lt;/p&gt;
&lt;p&gt;This is the first time that FileMaker have moved to their annual release pattern so you will start to see updates and patches more frequently.&lt;br&gt;&lt;br&gt;Firstly, this is a new full release right across the FileMaker product range. This means there is now FileMaker 15 for Server, Pro, Advanced, Go and WebDirect.&lt;br&gt;&lt;br&gt;Looking at some of the changes across these products….&lt;br&gt;&lt;br&gt;&lt;strong&gt;FileMaker Pro&lt;/strong&gt;&lt;br&gt;&lt;br&gt;There is now a new licensing model called - FileMaker for Teams (FLT). This is way licenses are shared across Pro, Go and WebDirect, all connecting to Server. Further details will come from FileMaker around this but there could be use cases where it’s advantageous for you to switch licensing plans.&lt;br&gt;&lt;br&gt;With FileMaker 15 there is now an improved way to update an application. It is now much simpler to now update your version of FileMaker to the latest patches/versions, this can all be done within the application when a new version is available, just click the prompt to download and install in a single step. You no longer have to go to the FileMaker website and download very large update files.&lt;br&gt;&lt;br&gt;One of the big gains in FileMaker 15 is around performance. - solutions will perform better than ever. Information in portals will now load independently of the rest of the screen you are viewing, so you can continue to work while portals load their data.&lt;br&gt;&lt;br&gt;&lt;strong&gt;FileMaker Go&lt;/strong&gt;&lt;br&gt;&lt;br&gt;Touch ID - Allows you to use the Touch ID scanner to log into your FileMaker Go solutions&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600350-Screen-Shot-2016-05-12-at-7.44.11-AM.png&quot; alt=&quot;Screen Shot 2016 05 12 at 7.44.11 AM&quot; width=&quot;600&quot; height=&quot;350&quot;&gt;&lt;br&gt;&lt;br&gt;iBeacon support - FileMaker Go can now support interaction with iBeacons, useful for detecting when your device is close to a beacon, which beacon is closest, and designing your solution to make use of this information, for example your solution could know whereabouts in a large warehouse you may be at any given time. If you are new to iBeacons check out the following article ... &lt;a href=&quot;http://www.ibeacon.com/what-is-ibeacon-a-guide-to-beacons/&quot; target=&quot;_blank&quot;&gt;iBeacons explained&lt;/a&gt;&lt;br&gt;&lt;br&gt;Better integration with other apps on the device, the ability for things such as images, movies, music, to be shared amongst other applications on the device, e.g. DropBox, PDF readers, printers, email etc.&lt;br&gt;&lt;br&gt;&lt;strong&gt;FileMaker WebDirect&lt;/strong&gt;&lt;br&gt;&lt;br&gt;More refinements and improvements to the platform including better performance.  FileMaker WebDirect now offers support for Android browsers meaning WebDirect now works across most platforms (via browser)&lt;/p&gt;</description>
			<pubDate>Wed, 11 May 2016 11:02:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-15-released/</guid>
		</item>
		
		<item>
			<title>FileMaker iOS SDK - Part 3</title>
			<link>https://www.teamdf.com/blogs/creating-the-project-directory/</link>
			<description>&lt;h2&gt;Building an iOS App from a FileMaker Database&lt;/h2&gt;
&lt;p&gt;Welcome to Part 3 of the FileMaker iOS App SDK series, in this article I will take you through creating the project directory that will house our app settings and files. In part &lt;a title=&quot;FileMaker iOS SDK - Part 1&quot; href=&quot;https://www.teamdf.com/blogs/building-an-ios-app-from-your-custom-filemaker-go-app/&quot;&gt;1&lt;/a&gt; and &lt;a title=&quot;FileMaker iOS SDK - Part 2&quot; href=&quot;https://www.teamdf.com/blogs/setting-up-your-apple-developer-account/&quot;&gt;2&lt;/a&gt; we highlighted some considerations that need to be made when developing our solution for iOS, setup our Apple Developer account, added an App ID, created a provisioning profile and setup Xcode ready for developing our App.&lt;/p&gt;
&lt;p&gt;We will be building an iOS App from the WindowFurnishing solution we have built for &lt;a title=&quot;McKenzie and Willis&quot; href=&quot;http://www.mckenzieandwillis.co.nz&quot; target=&quot;_blank&quot;&gt;McKenzie and Willis&lt;/a&gt;. You can read a case study on the McKenzie and Willis project &lt;a title=&quot;McKenzie and Willis case study&quot; href=&quot;https://www.teamdf.com/our-work/mckenzie-and-willis/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Signup for a FileMaker Developer Subscription&lt;/h3&gt;
&lt;p&gt;Before we can create a project directory we need to purchase a &lt;a title=&quot;FileMaker Developer Subscription&quot; href=&quot;https://store.filemaker.com/US/ENG/RTL/product/view/group/FDS/&quot; target=&quot;_blank&quot;&gt;FileMaker Developer Subscription&lt;/a&gt; and download the iOS App SDK.&lt;/p&gt;
&lt;h3&gt;Create a Project Directory&lt;/h3&gt;
&lt;p&gt;The iOS App project directory contains the required files and iOS frameworks for our App. We’ll start by extracting the iOS App SDK to the desktop on our Mac. Once that&#039;s done we’ll open the terminal application located in /Applications/Utilities/ or by typing terminal into a Spotlight search. Using the terminal we will change our working directory to the iOS App SDK directory, the easiest way to do this is to type cd followed by a space then drag and drop the iOS App SDK folder in to the terminal window, pressing return / enter will execute the command.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/iOS-App-SDK/_resampled/ResizedImage489342-terminal-cd-iosappsdk.png&quot; alt=&quot;terminal cd iosappsdk&quot; width=&quot;489&quot; height=&quot;342&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now that we are in the working directory for the iOS App SDK we can create our project directory by running the makeprojdir command with the required parameters:&lt;/p&gt;
&lt;pre&gt;./makeprojdir &amp;lt;NewAppDir&amp;gt; &amp;lt;appName&amp;gt; &amp;lt;bundleIdentifier&amp;gt;&lt;/pre&gt;
&lt;p style=&quot;padding-left: 30px; text-align: left;&quot;&gt;NewAppDir - This is where we will store the files required for the iOS App&lt;br&gt;appName - This is the name we will give our iOS App&lt;br&gt;bundleIdentifier - This is the identifier we used in &lt;a title=&quot;FileMaker iOS SDK - Part 2&quot; href=&quot;https://www.teamdf.com/blogs/setting-up-your-apple-developer-account/#Registering-our-App-ID&quot;&gt;Part 2 Registering our App ID&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;The command we will run in terminal to create our WindowFurnishing project directory will look like this:&lt;/p&gt;
&lt;pre&gt;./makeprojdir /Users/james/Desktop/McWApp/ WindowFurnishing com.mckenzieandwillis.windowfurnishing&lt;/pre&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/iOS-App-SDK/_resampled/ResizedImage489342-terminal-makeprojdir.png&quot; alt=&quot;terminal makeprojdir&quot; width=&quot;489&quot; height=&quot;342&quot;&gt;Once the command has completed an iOS App directory named McWApp will have been created for our Window Furnishing App. We&#039;ll take a quick look inside the project folder and examine its contents. The folder contains four items:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;app.entitlements&lt;/li&gt;
&lt;li&gt;iOSAppSDKResources&lt;/li&gt;
&lt;li&gt;WindowFurnishing&lt;/li&gt;
&lt;li&gt;WindowFurnishing.xcodeproj&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Do not modify the app.entitlements or iOSAppSDKResources, these contain important files required for the iOS App.&lt;br&gt;The WindowFurnishing folder will be used to store our custom App files (along side other automatically generated files).&lt;br&gt;The WindowFurnishing.xcodeproj is the Xcode project file, we can double click this to open our project in Xcode.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Continue reading with the &lt;a title=&quot;FileMaker iOS SDK - Part 4&quot; href=&quot;https://www.teamdf.com/blogs/building-and-testing-our-ios-app/&quot;&gt;fourth and final part&lt;/a&gt; in the iOS SDK series.&lt;/p&gt;</description>
			<pubDate>Thu, 28 Apr 2016 09:47:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/creating-the-project-directory/</guid>
		</item>
		
		<item>
			<title>FileMaker iOS SDK - Part 2</title>
			<link>https://www.teamdf.com/blogs/setting-up-your-apple-developer-account/</link>
			<description>&lt;h2&gt;Building an iOS App from a FileMaker Database&lt;/h2&gt;
&lt;p&gt;Welcome to Part 2 of the FileMaker iOS App SDK series, in this article I will take you through setting up Xcode and creating a provisioning profile for an iOS device. In &lt;a href=&quot;https://www.teamdf.com/blogs/building-an-ios-app-from-your-custom-filemaker-go-app/&quot;&gt;part 1&lt;/a&gt; I highlighted some of the considerations that need to be made when turning a custom FileMaker solution into an iOS App.&lt;/p&gt;
&lt;h3&gt;Register in the Apple developer program&lt;/h3&gt;
&lt;p&gt;First things first, we need to register in the Apple Developer program. Head over to the &lt;a title=&quot;Apple Developer Program&quot; href=&quot;https://developer.apple.com/programs/&quot; target=&quot;_blank&quot;&gt;Apple Developer Program page&lt;/a&gt; and click the &quot;Enroll&quot; button on the top right of the page. Log in with your Apple ID and follow through the prompts to enroll.&lt;/p&gt;
&lt;h3&gt;Download Xcode&lt;/h3&gt;
&lt;p&gt;We will need to download and install the latest version of Xcode, which is available from the &lt;a title=&quot;Xcode Download&quot; href=&quot;https://developer.apple.com/xcode/download/&quot; target=&quot;_blank&quot;&gt;Apple Developer website&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Setting up Xcode&lt;/h3&gt;
&lt;p&gt;Now that we&#039;re enrolled in the developer program we can start registering our App ID.&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Launch Xcode, click on the &#039;Xcode&#039; menu and open the preferences dialog.&lt;/li&gt;
&lt;li&gt;Click on the &#039;Accounts&#039; tab. In the bottom left hand corner of the window click the plus icon and select &#039;Add Apple ID...&#039;&lt;/li&gt;
&lt;li&gt;Sign into your Apple Developer account&lt;/li&gt;
&lt;li&gt;Once signed in select the &#039;Team Name&#039; and click on the &#039;View Details...&#039; button&lt;/li&gt;
&lt;li&gt;In the Signing Identities section click the &#039;Create&#039; button next to iOS Development.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/iOS-App-SDK/_resampled/ResizedImage600475-xcode-preferences-accounts-obfuscated.png&quot; alt=&quot;xcode preferences accounts obfuscated&quot; width=&quot;600&quot; height=&quot;475&quot;&gt; &lt;/p&gt;
&lt;h3&gt;&lt;a name=&quot;Registering-our-App-ID&quot;&gt;&lt;/a&gt;Registering our App ID&lt;/h3&gt;
&lt;p&gt;Registering our App ID with Apple will allow us to create a provisioning profile which will be used in building, testing and distribution of our iOS App.&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Log into the &lt;a title=&quot;Apple Developer&quot; href=&quot;https://developer.apple.com&quot; target=&quot;_blank&quot;&gt;Apple Developer Member Centre&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Click on &#039;Certificates, Identifiers &amp;amp; Profiles&#039;&lt;/li&gt;
&lt;li&gt;Under the iOS Apps heading click on &#039;Identifiers&#039;&lt;/li&gt;
&lt;li&gt;Click the plus button to register a new app ID, enter the App ID Description, Prefix and Suffix.&lt;/li&gt;
&lt;li&gt;In the App Services section tick &#039;Data Protection&#039; and ensure &#039;Complete Protection&#039; is selected&lt;/li&gt;
&lt;li&gt;Tick the box to enable iCloud.&lt;/li&gt;
&lt;li&gt;Click continue to review our App ID, finally click the &#039;Submit&#039; button to create the App ID.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/iOS-App-SDK/_resampled/ResizedImage600375-apple-register-app-id.png&quot; alt=&quot;apple register app id&quot; width=&quot;600&quot; height=&quot;375&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Registering our Device for testing&lt;/h3&gt;
&lt;p&gt;If we want to use an actual iOS device for testing we need to register the UDID (Unique Device Identifier) with Apple.&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Under Devices click on &#039;All&#039; and then click the plus button in the top right corner&lt;/li&gt;
&lt;li&gt;Enter the device name and UDID. We can copy and paste the UDID from Xcode.&lt;/li&gt;
&lt;li&gt;Ensure your device is plugged in to your Mac&lt;/li&gt;
&lt;li&gt;Click on the Window menu and select &#039;Devices&#039;.&lt;/li&gt;
&lt;li&gt;Select iOS device and copy the Identifier, paste this into the UDID field on the Apple Developer site.&lt;/li&gt;
&lt;li&gt;Click continue and then register to add your device&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/iOS-App-SDK/_resampled/ResizedImage600375-apple-register-device-id.png&quot; alt=&quot;apple register device id&quot; width=&quot;600&quot; height=&quot;375&quot;&gt; &lt;/p&gt;
&lt;h3&gt;Create and download the Provisioning Profile&lt;/h3&gt;
&lt;p&gt;Now that we’ve created our App ID we need to create and download our provisioning profile.&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Under Provisioning profiles click &#039;All&#039; then click the plus button in the top right corner&lt;/li&gt;
&lt;li&gt;Select &#039;iOS App Development&#039; and select the &#039;Distribution&#039; method required. Click continue.&lt;/li&gt;
&lt;li&gt;Select the &#039;App ID, Certificate and Devices&#039;. We’ll give our provisioning profile a name and finally click the generate button.&lt;/li&gt;
&lt;li&gt;Switch back to Xcode and open the preferences dialog&lt;/li&gt;
&lt;li&gt;Click on &#039;Accounts&#039; then click on &#039;View Details&#039;&lt;/li&gt;
&lt;li&gt;Click the &#039;Download&#039; button next to our newly created provisioning profile&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;img class=&quot;center&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/iOS-App-SDK/_resampled/ResizedImage600375-apple-register-provisioning-profile.png&quot; alt=&quot;apple register provisioning profile&quot; width=&quot;600&quot; height=&quot;375&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Continue reading on to &lt;a title=&quot;FileMaker iOS SDK - Part 3&quot; href=&quot;https://www.teamdf.com/blogs/creating-the-project-directory/&quot;&gt;Part 3&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Fri, 22 Apr 2016 09:55:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/setting-up-your-apple-developer-account/</guid>
		</item>
		
		<item>
			<title>Subscribe and Ye Shall Receive</title>
			<link>https://www.teamdf.com/blogs/sign-up-to-recieve-weetbicks-and-digital-fusion-blog-posts/</link>
			<description>&lt;p&gt;Be you a lover of Weetbicks blog posts on how to do fun and funky things using FileMaker or you want to keep up with news on the happenings at Digital Fusion we now have a way for you to keep up to date.&lt;br&gt;&lt;br&gt;You will see we have added an email subscription to our blog section.&lt;br&gt;&lt;br&gt;Add your email address and we will keep you in the loop when we post a new blog.&lt;br&gt;&lt;br&gt;We generally add a new post once a month so we promise you will not be bombarded with too many emails, we hate spam as much as you.&lt;/p&gt;</description>
			<pubDate>Wed, 20 Apr 2016 10:07:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/sign-up-to-recieve-weetbicks-and-digital-fusion-blog-posts/</guid>
		</item>
		
		<item>
			<title>FileMaker iOS SDK - Part 1</title>
			<link>https://www.teamdf.com/blogs/building-an-ios-app-from-your-custom-filemaker-go-app/</link>
			<description>&lt;h2&gt;Building an iOS App from a FileMaker Database&lt;/h2&gt;
&lt;p&gt;As you may be aware FileMaker Inc have given developers a toolset (&quot;SDK&quot;) for creating standalone apps for iPhone and iPad, from FileMaker databases. The process is a little tricky and there&#039;re plenty of things to be aware of...&lt;/p&gt;
&lt;h3&gt;But it&#039;s worth it!&lt;/h3&gt;
&lt;p&gt;The key thing is that once you&#039;ve got a standalone app, it&#039;s much easier for users to have your database as an app just like any other app, as an icon sitting on the iPhone or iPad rather than buried away under FileMaker Go. &lt;/p&gt;
&lt;p&gt;The other advantages are that it just looks and behaves like a standard native app. It opens quickly, with it&#039;s own splash screen and it&#039;s easier to install. In fact you can even sell (or give it away) through the App Store if you&#039;ve built something that you want to distribute widely. More on deployment and distribution options later.&lt;/p&gt;
&lt;p&gt;We&#039;ve turned several existing iOS solutions we&#039;ve built into standalone apps and based on that experience I&#039;ve put together four articles that go through the technical &quot;nuts and bolts&quot; of the process. As this is all still very new I may not have everything perfect - let me know if I’ve missed anything and I will update the article/questions as we go.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/iOS-App-SDK/scary.png&quot; alt=&quot;scary&quot; width=&quot;184&quot; height=&quot;162&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Things to be aware of&lt;/h2&gt;
&lt;p&gt;Before you start it&#039;s worth keeping in mind that there are things that will not work as they do in FileMaker Go so you may want to make a few changes to the solution...&lt;/p&gt;
&lt;h4&gt;No Exit&lt;/h4&gt;
&lt;p&gt;The Exit Application script step in FileMaker Go usually takes us back the files interface. In our custom iOS App the files interface does not exist. The effect that the Exit Application script step has is that it will still close our current file (and any hidden but referenced files) and immediately try to re-open the main file. The user will automatically be logged back in if they&#039;ve saved their password to the keychain or if the file is set to automatically log in with a specified account name and password, otherwise we are presented with the Log in dialog. Any OnFirstWindowOpen script triggers will run again once the login process has completed successfully.&lt;/p&gt;
&lt;h4&gt;App Version?&lt;/h4&gt;
&lt;p&gt;The Get ( ApplicationVersion ) function in FileMaker Go returns the string “Go_iPad 14.0.4”. When we run the Get ( ApplicationVersion ) function in our iOS App we were surprised to see it returned “Go_iPad 1.0.1”. 1.0.1 is a version number that is specified in the Version Number field in Xcode. This makes it difficult to determine if our Custom App is running in FileMaker Go or as our own iOS App. A simple work around is to use the Get ( ApplicationPath ) function and parse out the application name.&lt;/p&gt;
&lt;h4&gt;App Name&lt;/h4&gt;
&lt;p&gt;Using long application names will cause them to be truncated, for example the app name WindowFurnishing gets truncated to WindowFurni... iOS does not have a fixed maximum for the length of an app name, instead it will display as much of the name as it can. Using wide letters such as C, W, Z etc will reduce the available amount of space for our app name whereas using letters i, j, l etc will maximise the number of characters our app name can have. This limit differs depending on the device, an iPad allows for more visible width in an app name compared to an iPhone or iPod. A quick and easy way to see if an app name will fit completely on screen is to create an app folder and name it the same as our app.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/iOS-App-SDK/update-from-cloud.png&quot; alt=&quot;update from cloud&quot; width=&quot;200&quot; height=&quot;185&quot;&gt;&lt;/p&gt;
&lt;h4&gt;App Updates&lt;/h4&gt;
&lt;p&gt;The FileMaker files within a custom app are not automatically updated when the app is updated. The files are either left untouched or they are overwritten with the solution files included with the iOS app. Ideally the app should update leaving the users data intact. This can be achieved by using an additional helper file that downloads the updated FileMaker files and transferring the user data from the old version to the new version.&lt;/p&gt;
&lt;h4&gt;Open URL&lt;/h4&gt;
&lt;p&gt;As we know the FileMaker Go app has a url scheme that can be used to open files, run scripts and set variables. We do this by creating a link with a prefix of fmp. Our native app can take advantage of the url scheme as well; however, we can not use fmp as our prefix. When we setup our project in Xcode we have the ability to specify a prefix of our own choosing.&lt;/p&gt;
&lt;h3&gt;Continue reading&lt;/h3&gt;
&lt;p&gt;&lt;a title=&quot;FileMaker iOS SDK - Part 2&quot; href=&quot;https://www.teamdf.com/blogs/setting-up-your-apple-developer-account/&quot;&gt;Part 2&lt;/a&gt; on how to setup Xcode and create a provisioning profile.&lt;/p&gt;
&lt;p&gt;&lt;a title=&quot;FileMaker iOS SDK - Part 3&quot; href=&quot;https://www.teamdf.com/[sitetree_link,id=]&quot;&gt;Part 3&lt;/a&gt; on how to setup your project directory.&lt;/p&gt;
&lt;p&gt;&lt;a title=&quot;FileMaker iOS SDK - Part 4&quot; href=&quot;https://www.teamdf.com/blogs/building-and-testing-our-ios-app/&quot;&gt;Part 4&lt;/a&gt; on building, compiling and testing&lt;/p&gt;</description>
			<pubDate>Mon, 11 Apr 2016 11:13:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/building-an-ios-app-from-your-custom-filemaker-go-app/</guid>
		</item>
		
		<item>
			<title>Sending Email from FileMaker Using SparkPost</title>
			<link>https://www.teamdf.com/blogs/sending-email-from-filemaker-using-sparkpost/</link>
			<description>&lt;h3&gt; &lt;/h3&gt;
&lt;h3&gt;A bit of background&lt;/h3&gt;
&lt;p&gt;Back in 2014 we published &lt;a href=&quot;https://www.teamdf.com/blogs/sending-e-mail-from-filemaker-using-mandrill/&quot; target=&quot;_blank&quot;&gt;this article&lt;/a&gt; about a new service at the time called Mandrill. Mandrill is an email web service that you can use to send thousands of emails per month. The great thing about Mandrill was that although it had paid subscription options, their free offering was perfect for most FileMaker solutions required to send email. Because email was sent through an API, it also avoids many common SMTP issues that developers come across when trying to setup emailing from FileMaker.&lt;/p&gt;
&lt;p&gt;Recently however, &lt;a href=&quot;http://blog.mandrill.com/important-changes-to-mandrill.html?_ga=1.159381114.1732226726.1458090791&quot; target=&quot;_blank&quot;&gt;Mandrill has announced that it is incorporating Mandrill into its Mailchimp service&lt;/a&gt;, and it will become a paid add-on to MailChimp accounts.  This change will take effect from April 27th, 2016 and will affect all existing Mandrill users, and any FileMaker integrations that rely on it.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;How does this affect me?&lt;/h3&gt;
&lt;p&gt;If you are not a Mandrill user, there is no effect, and you can read this post at your leisure. If you do use Mandrill in your FileMaker solution you have cause for taking some urgent action. Here is what is changing:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Mandrill users will be required to have a paid monthly MailChimp account&lt;/h3&gt;
&lt;p&gt;The separate service known as Mandrill will cease to be its own standalone service and will become incorporated into MailChimp by the end of April. To begin this process, MailChimp is requiring you sign up for an account if not already, and link your existing Mandrill account to it.&lt;/p&gt;
&lt;p&gt;This in itself is not really a difficult task, sign up is very easy at &lt;a href=&quot;http://www.mailchimp.com&quot; target=&quot;_blank&quot;&gt;mailchimp.com&lt;/a&gt; and linking your account is easy too. You have until 27th of April to do this. The following is from Mandrill:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span&gt;The MailChimp team built Mandrill in 2012 as a transactional email tool. It was a startup within MailChimp that functioned as a completely separate product. Mandrill is now becoming an optional add-on to paid MailChimp accounts. This is a strategic change we’re making to close the gap between the two products. MailChimp is designed for marketing, and Mandrill is designed for transactional messages. Each is powerful on its own, and offering Mandrill as an add-on makes MailChimp even more powerful for our small business and e-commerce customers&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The real gotcha with the change is that your MailChimp account will be required to be a &lt;strong&gt;paid monthly account &lt;/strong&gt;by 27 April. Any free accounts will no longer be valid once your Mailchimp and Mandrill accounts are merged.&lt;/p&gt;
&lt;p&gt;Pricing is set to change and is not yet finalised on the website. The blog article on the subject details that you will pay a single consolidated monthly fee for both Mailchimp and Mandrill, and Mandrill credits will be sold in blocks of 25,000 emails at $20 per month starting price.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Your sending domains will need to be verified&lt;/h3&gt;
&lt;p&gt;Mandrill allowed you to send emails from any sending domain. A sending domain is the domain name that comes after the @ part of your email address. This made setup easy but it did mean that the service could be abused by spammers and spoofed email addresses acting as senders.&lt;/p&gt;
&lt;p&gt;MailChimp will require that all senders verify their domains. This is actually a good thing and not too difficult to do. Normally verifying your sending domain is done by adding a record into either your SPF or DKIM entries in your domain setup. Your domain provider will be able to assist and provide documentation on how you can do this.&lt;/p&gt;
&lt;p&gt;One thing to note here that is important is that you&#039;ll need your own verified sending domain and you will be unable to use public domains such as Gmail, Hotmail or Yahoo. For users of free email services such as these it may mean you are out of luck.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;SparkPost to the Rescue!&lt;/h3&gt;
&lt;p&gt;This is where &lt;a href=&quot;https://www.sparkpost.com/&quot; target=&quot;_blank&quot;&gt;SparkPost&lt;/a&gt; comes in. SparkPost is a new web service sending emails much like Mandrill, but SparkPost has a free email plan and is a great alternative for those who wish to not pay for Mandrill. SparkPost is recommended by Mandrill as the alternative for those who wish not to move to MailChimp, that&#039;s a good endorsement!&lt;/p&gt;
&lt;p&gt;Better still, SparkPost offer a &lt;a href=&quot;https://www.sparkpost.com/mandrill-migration-guide&quot; target=&quot;_blank&quot;&gt;Mandrill Migration Guide&lt;/a&gt; which will help anyone with the transition.&lt;/p&gt;
&lt;p&gt;SparkPost offers a free 100,00 emails a month plan (capped).&lt;/p&gt;
&lt;p&gt;They have a great and fully complete API and excellent developer support.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;A couple of Points about SparkPost&lt;/h3&gt;
&lt;p&gt;Sparkpost will require you to verify your sending domain using SPF/DKIM records, or verification through email. This is the same verification that Mandrill is enforcing, so Gmail/Hotmail/Yahoo users will be out of luck, but those with a legitimate sending domain will have no problem with this.&lt;/p&gt;
&lt;p&gt;SparkPost can send emails of up to 20mb in size (with attachments) which should pose no issues for most people.&lt;/p&gt;
&lt;p&gt;SparkPost also has a very in depth web based dashboard interface for tracking all mail sent, much like the Mandrill dashboard, and a number of features of Sparkpost are very similar to Mandrill.&lt;/p&gt;
&lt;p&gt;Even JSON for formulating an API request is very similar to Mandrill so you should have no trouble with the transition.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Migrating to SparkPost&lt;/h3&gt;
&lt;p&gt;To give some information about the migration from Mandrill to SparkPost, we have used our old Mandrill example file as the basis, and have modified it to work with SparkPost. You can download the old file below.&lt;/p&gt;
&lt;p&gt;The new file is also available here. Below we&#039;ll outline some of the important differences between the two that you&#039;ll need to be aware of when migrating.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/mandrill/Mandrill.zip&quot; target=&quot;_blank&quot;&gt;Mandrill Demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://share.teamdf.com/daniel/SparkPost.zip&quot; target=&quot;_blank&quot;&gt;SparkPost Demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Authentication Differences&lt;/h3&gt;
&lt;p&gt;When authenticating with Mandrill, your API key was passed as part of your JSON request posted to the API endpoint.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;Mandrill method of authentication&quot; src=&quot;https://www.teamdf.com/assets/Uploads/sparkpost-1.png&quot; alt=&quot;Mandrill method of authentication&quot; width=&quot;357&quot; height=&quot;228&quot;&gt;&lt;/p&gt;
&lt;p&gt;With SparkPost however you must first authenticate using your API key by way of setting a custom POST header prior to sending the JSON request. You also need to specify the content type of your request.  SparkPost will use XML by default so you must specify whether your request is to be in JSON or XML.&lt;/p&gt;
&lt;p&gt;To do this, we use the &lt;a href=&quot;http://www.goya.com.au/baseelements/plugin&quot; target=&quot;_blank&quot;&gt;BaseElements&lt;/a&gt; plugin from &lt;a href=&quot;http://www.goya.com.au&quot; target=&quot;_blank&quot;&gt;Goya&lt;/a&gt; once again. This contains functions for setting your custom headers.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;BE_HTTP_Set_Custom_Header ( &quot;Authorization&quot; ; &amp;lt;APIKEY&amp;gt; )&lt;/p&gt;
&lt;p&gt;BE_HTTP_Set_Custom_Header ( &quot;Content-Type&quot; ; &quot;application/json&quot; )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Using these two functions, you can authenticate and specify JSON.  These can be combined into a single &quot;Let&quot; statement when posting your request, they need not be specified in separate script steps, or as separate variables, just as long as they&#039;re defined prior to posting your request.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Request Differences&lt;/h3&gt;
&lt;p&gt;While the JSON formatting is very similar to Mandrill, SparkPost has slightly different naming for certain parts of the request such as recipients, but overall it is incredibly similar in how a request is formulated. The demo file contains an equivalent example to the Mandrill demo file, in that it is a template for sending an email to a single recipient with attachments and rich text.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://developers.sparkpost.com/api/&quot; target=&quot;_blank&quot;&gt;SparkPost API documentation&lt;/a&gt; is great and gives you all the information you&#039;ll need to customise the request to suit your needs. The key parts of the documentation around sending emails for you will be the &quot;Transmissions&quot; area and &quot;Recipients&quot; areas. The API can do all kinds of things such as manipulation of your settings, profile, recipient lists, webhooks etc, but a lot of that is not required for simply sending email.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;center&quot; title=&quot;SparkPost Request&quot; src=&quot;https://www.teamdf.com/assets/Uploads/Screen-Shot-2016-03-18-at-12.06.29-PM.png&quot; alt=&quot;SparkPost Request&quot; width=&quot;345&quot; height=&quot;294&quot;&gt;&lt;/p&gt;
&lt;p&gt;Above is a basic template for sending a SparkPost request. There are only minor changes to that of a Mandrill request, mainly around the structuring of recipients into an array.  The attachment code is basically the same.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Parsing the Result Returned&lt;/h3&gt;
&lt;p&gt;The format of the result returned by the API is different to that of Mandrill and so you will need to modify any functions you use to parse the response.  SparkPost responses come in one of two varieties. The first is an error that will be returned along with an error code and message describing the error. You will normally see this if you have an improperly formed JSON request, or are missing vital information in your request.&lt;/p&gt;
&lt;p&gt;If the JSON request is correct and an email is sent, you will receive a response that gives information about the number of recipients sent to successfully, or number that failed, along with the ID of the request.&lt;/p&gt;
&lt;p&gt;An example of an error message:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;{ &quot;errors&quot;: [ { &quot;message&quot;: &quot;required field is missing&quot;, &quot;description&quot;: &quot;content object or template_id required&quot;, &quot;code&quot;: &quot;1400&quot; } ] }&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a JSON error object containing an array of errors. Each object within the array contains 3 attributes about the error. &quot;Message&quot; is the name of the error, and &quot;Description&quot; will give you more information about what the problem is. &quot;Code&quot; is an error code you can use to look up more information on the error in the API documentation. If you have multiple errors you will receive this in an array.&lt;/p&gt;
&lt;p&gt;For a successful response, the format is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p class=&quot;p1&quot;&gt;{ &quot;results&quot;: { &quot;total_rejected_recipients&quot;: 0, &quot;total_accepted_recipients&quot;: 1, &quot;id&quot;: &quot;84290312071045307&quot; } }&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a results object that contains the total number of rejected recipients, total number of accepted, and the SparkPost ID.&lt;/p&gt;
&lt;p&gt;In our demo file we have included a very simplistic parsing function that will transform this into a return delimited list for easier FileMaker parsing. You can nominate which attribute to return, or passing an empty parameter to the function will return the full result. This is similar to the original parsing function in the Mandrill example file.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Rules around what is and is not Spam&lt;/h3&gt;
&lt;p&gt;If you find that your emails are not being delivered by SparkPost, it may be due to the rules around what SparkPost deems as suspicious or spam emails, and these may be different to Mandrill. SparkPost is quite strict around checking emails for potential spam. Subject lines, email content, recipients etc all contribute to whether the email will bounce or be delivered. &lt;/p&gt;
&lt;p&gt;Originally, our demo file had a test email with the subject line &quot;Hello There!&quot;.  While this worked fine in Mandrill, SparkPost considered this email spam. We have had to change the subject line for this example file as a result.  We recommend testing sending various emails after you switch to SparkPost to ensure they are successfully delivered, especially if you use preset templates.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Sending Email using the &quot;Insert from URL&quot; script step&lt;/h3&gt;
&lt;p&gt;In the Mandrill example file, reader and developer &lt;a href=&quot;https://twitter.com/IamSloper&quot; target=&quot;_blank&quot;&gt;Michael Sloper&lt;/a&gt; found a means to send requests to Mandrill in a URL format which allows you to use the Insert from URL script step. this was great because it removed the need for a plugin.&lt;/p&gt;
&lt;p&gt;We have been unable to find a suitable means to achieve this using SparkPost - to be fair we haven&#039;t really tried very hard!  We welcome anyone who can find a suitable means to integrate with SparkPost using the Insert from URL script step!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;In Conclusion&lt;/h3&gt;
&lt;p&gt;SparkPost is our preferred alternative to Mandrill because it offers the same free plans that Mandrill used to offer, and is very easy to switch to. Our Mandrill article was our most successful ever in terms of reader feedback, and we hope that this article prompts a similar level of discussion and sharing of ideas when it comes to SparkPost integration.&lt;/p&gt;
&lt;p&gt;Good luck!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;An important note on the API Key and Account used in the Demo file&lt;/h3&gt;
&lt;p&gt;Because SparkPost requires a valid sending domain for each account, the provided example file has been setup with a preset key on a demo SparkPost account we have created. This demo account has been verified to the sending domain &quot;weetbicks.com&quot; and we have setup a test email address &quot;sparkpost@weetbicks.com&quot; to act as the sender.&lt;/p&gt;
&lt;p&gt;You may find that your emails will not send if you use the demo file with a different sender email address. If you wish to do this you should create your own SparkPost account, and obtain your own API key and verified sending domain to use in the example file.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;We&#039;ve included a Demo file to help you get started on your road to SparkPost integration. You can download using the link provided.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/Uploads/Sparkpost.zip&quot; target=&quot;_blank&quot;&gt; Click here to download the Sparkpost example file.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can also check out our Mandrill example file for comparison below.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/mandrill/Mandrill.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the Mandrill example file.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Sat, 19 Mar 2016 08:58:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/sending-email-from-filemaker-using-sparkpost/</guid>
		</item>
		
		<item>
			<title>Custom App Success Guide - Number two</title>
			<link>https://www.teamdf.com/blogs/custom-app-success-guide-number-two/</link>
			<description>&lt;p&gt;Carrying on from Craig&#039;s post last month, FileMaker have now released their second guide in their Custom App Success series.&lt;/p&gt;
&lt;p&gt;This one takes you through a step by step guide on how to develop your own custom app.&lt;/p&gt;
&lt;p&gt;It makes for great reading with some awesome ideas particularly as it follows the &#039;plan guide&#039;. We are big believers in spending a lot of time in planning, the changes of success are greatly enhanced if you put the effort in at the beginning.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;This time FileMaker now require you register for the download, check it out here..&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://info2.filemaker.com/customapps_guide_create_lp.html?language=en#form&quot;&gt;Custom App Success - Create&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;And as always, if you need a hand with either creating or planning your app, the team at Digital Fusion are always here for support.&lt;/p&gt;</description>
			<pubDate>Tue, 08 Mar 2016 10:08:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/custom-app-success-guide-number-two/</guid>
		</item>
		
		<item>
			<title>The DIY Approach - Is it for you?</title>
			<link>https://www.teamdf.com/blogs/the-diy-approach-is-it-for-you/</link>
			<description>&lt;p&gt;Firstly, FileMaker is a fantastic tool that allows you to develop your own apps and use them in your workplace/workspace. There are thousands and thousands of businesses throughout the world that run on ‘homemade’ apps, which is awesome because it goes to show the power of FileMaker.&lt;br&gt;&lt;br&gt;There is also a plethora of help out there for you, including our own blog where we give tips and tricks to get your over any hurdles you might find as you progress through development. FileMaker themselves are bringing out ‘how to’ guides on the process of developing apps, starting with the very awesome ‘planning your app&#039;&lt;br&gt;&lt;br&gt;But sometimes the DIY approach doesn’t make sense.&lt;br&gt;&lt;br&gt;And this is where I hark back to my previous life as an account manager at British Airways.&lt;br&gt;&lt;br&gt;As you can imagine, working for British Airways, we were locked into the ‘beast’ of all systems when it came to IT (although I will say they were ahead of their game at the time)&lt;br&gt;&lt;br&gt;Being an outpost in NZ we thought there must be a better way to do some things, starting with being able to report on clients based on a monthly basis.&lt;br&gt;&lt;br&gt;We had the data but we just couldn’t pull it out of the system in a legible manner, nor display it in a way that made sense.&lt;br&gt;&lt;br&gt;So off to Excel I went, building a fairly crude ‘database’ that allowed us do things ‘our way’.&lt;br&gt;&lt;br&gt;This fairly simple database took me three solid days, with much frustration plus many interruptions of others to get their thoughts.&lt;br&gt;&lt;br&gt;If I look back now, what I achieved in three days would have been knocked off pretty quickly by our developers in a matter of hours.&lt;br&gt;&lt;br&gt;To look at this from a financial perspective, because at the end of the day tha&#039;ts the thing to weight up between the DIY/Paid approaches…&lt;br&gt;&lt;br&gt;Three days of my time = $2000&lt;br&gt;2-3 hours of developer time = $400-500&lt;br&gt;&lt;br&gt;There&#039;s also the fact that a developer will have done a far better job, the interface will be so much nicer, the structure of the app would withstand further development in the future, and the stress levels of myself would have been greatly removed.&lt;/p&gt;
&lt;p&gt;Case in point...&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600398-main-graphic-2x.jpg&quot; alt=&quot;main graphic 2x&quot; width=&quot;600&quot; height=&quot;398&quot;&gt;&lt;br&gt;&lt;br&gt;The point of this post is not to persuade you from giving the DIY approach a crack, by all means buy your FileMaker licenses, start developing and see how you get on.&lt;br&gt;&lt;br&gt;All is not wasted if you then come to us to have us add-on or develop a new app, we can use your work as a proof of concept and a template for our development.&lt;br&gt;&lt;br&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 24 Feb 2016 14:57:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/the-diy-approach-is-it-for-you/</guid>
		</item>
		
		<item>
			<title>20 Years Already</title>
			<link>https://www.teamdf.com/blogs/20-years-already/</link>
			<description>&lt;h3&gt;Time Flies...&lt;/h3&gt;
&lt;p&gt;In February 1996 I took the plunge and left a perfectly good salaried job to go and ‘do my own thing’. To be honest it was pretty scary — I remember the day I told my boss I was leaving, then having to go round to a friend&#039;s place to have a few drinks to settle the nerves.&lt;/p&gt;
&lt;p&gt;Well, there was no looking back and 20 years on I have to say it’s been a very exciting, very challenging, very rewarding… very silly idea.&lt;/p&gt;
&lt;p&gt;So I figure we’ve still got a lot to achieve but at 20 years now it’s probably a good point to take a moment to reflect on what happened and how we got to where we are.&lt;/p&gt;
&lt;h3&gt;WTF Was I Thinking?&lt;/h3&gt;
&lt;p&gt;In 1995 I reckoned that the internet, and in particular the “World Wide Web”, looked like a fairly promising development that might become popular. So I set out to create a company that brought technology together - that melded Content (in those days, “multimedia”), Software, and People… thus was born the name “Digital Fusion” and our stylish logo:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/20-years/dflogo-1996.png&quot; alt=&quot;dflogo 1996&quot; width=&quot;178&quot; height=&quot;288&quot;&gt;￼&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;The FileMaker Accident&lt;/h2&gt;
&lt;p&gt;While I set out to do web development, there actually wasn’t a huge demand for it at that moment, so when presented with an opportunity to create a business database in FileMaker I figured “Why not?” I had seen FileMaker a couple years earlier so I knew the basics, and as a programmer full of confidence, not knowing the language was no barrier whatsoever.&lt;/p&gt;
&lt;p&gt;I took on that job and built a document management system in a couple of days. Deployed it, and to my astonishment the solution was pretty much bug free… Happy Client. This is good I thought.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/20-years/_resampled/ResizedImage5052-good.png&quot; alt=&quot;good&quot; width=&quot;50&quot; height=&quot;52&quot;&gt;￼&lt;/p&gt;
&lt;p&gt;I’d been programming in much more powerful languages and I’d never taken FileMaker seriously: but it had just become a proper relational database, and it was beautifully consistent cross platform – so I could develop on a Mac and deploy to the masses of Windows 95 heathen.&lt;/p&gt;
&lt;p&gt;More importantly I had a bit of an epiphany: in FileMaker I suddenly had a platform that did less, but was better: faster to develop with, more robust and predictable… basically something you could count on and bet your business on.&lt;/p&gt;
&lt;p&gt;So on Day One, I had set up as a web developer and on Day Two I added FileMaker Development to the menu. We’ve had a few sidelines along the way, but to this day that’s what we do…&lt;/p&gt;
&lt;h2&gt;This Is 1996&lt;/h2&gt;
&lt;p&gt;But before I go too far let me reflect for a moment on the state of play in 1996:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;No broadband - internet was via dialup and clobbered your phone line&lt;/li&gt;
&lt;li&gt;There was no iPhone, iPod or iPad&lt;/li&gt;
&lt;li&gt;In fact there was no iMac even…&lt;/li&gt;
&lt;li&gt;and Steve Jobs was some pillock who&#039;d been tossed out of Apple long ago&lt;/li&gt;
&lt;li&gt;There was no “Cloud” computing&lt;/li&gt;
&lt;li&gt;No FaceBook or Instagram or Twitter&lt;/li&gt;
&lt;li&gt;No TradeMe or eBay&lt;/li&gt;
&lt;li&gt;No Google!&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;We did however have:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;HTML v2.0 (with tables for positioning, oh joy)&lt;/li&gt;
&lt;li&gt;Internet Explorer v2.0 - for both Mac and Windows!&lt;/li&gt;
&lt;li&gt;FileMaker v3.0&lt;/li&gt;
&lt;li&gt;Fax machines&lt;/li&gt;
&lt;li&gt;Michael Jackson&lt;/li&gt;
&lt;/ul&gt;&lt;p style=&quot;text-align: center;&quot;&gt;￼&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/20-years/michael-jackson.png&quot; alt=&quot;michael jackson&quot; width=&quot;306&quot; height=&quot;306&quot;&gt;&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;You’ve Got To Have A Steve&lt;/h2&gt;
&lt;p&gt;For a start it was just me… I’ve always believed in a fair bit of reading to both help with self development and for inspiration. After studying the history of Apple and watching what happened when Steve Jobs came back to Apple, it became clear that you need to have a Steve onboard: in August 1998 I hired my first employee, Stephen Baker, fresh out of university after a career change from making showers to IT… and two weeks later I headed off for a holiday and left him in charge.&lt;/p&gt;
&lt;p&gt;Steve, quietly spoken, resourceful and smart, held the fort with aplomb and was pivotal to those early days of growth. The first employee is essentially the doubling of your workforce, and as a startup with no capital to speak of, there isn’t time for a lot of training or any room for error. Steve’s a legend and a guru among clients and colleagues to this day; he’s even earned a certain reputation in the global FileMaker community…&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/20-years/steve-jedi.png&quot; alt=&quot;steve jedi&quot; width=&quot;250&quot; height=&quot;250&quot;&gt;￼&lt;/p&gt;
&lt;h6 style=&quot;text-align: center;&quot;&gt;(Credit to &lt;a title=&quot;Open Richard Carlton Consulting website in a new window&quot; href=&quot;http://http//rcconsulting.com&quot; target=&quot;_blank&quot;&gt;Richard Carlton Consulting&lt;/a&gt;)&lt;/h6&gt;
&lt;h2&gt;Growing Up&lt;/h2&gt;
&lt;p&gt;From there we grew steadily with my wife Raewyn joining the fun (now we had no external income!) and other staff gradually adding to the mix. Paul and Cath joined in 2002, and Julie came on as an administrator in 2004 when I finally realised developers make useless organisers and hate doing important things like sending invoices for the hard work we’ve done. Again we landed on our feet with good keen people who stayed the distance through the highs and lows, and who picked up the pieces I couldn’t get right. Eh Julie?&lt;/p&gt;
&lt;p&gt;I won’t bore you with the entire history of this little company but suffice to say over the years we’ve achieved some very fun things and built up some awesome friendships with the team (including the few who’ve managed to slip away from DF), the development community and with many of our clients—the loyalty of both clients and staff is pivotal for the long game and everyone benefits because we’re not having to pick up the pieces. The depth of those longer relationships and the knowledge is so very valuable. To you all a big Thank You!&lt;/p&gt;
&lt;p&gt;Team DF, circa 2008:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;￼&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/20-years/_resampled/ResizedImage600444-dfwebsite-2008.png&quot; alt=&quot;dfwebsite 2008&quot; width=&quot;600&quot; height=&quot;444&quot;&gt;&lt;/p&gt;
&lt;h2&gt;&lt;br&gt;Spinning Out&lt;/h2&gt;
&lt;p&gt;Perhaps the most disruptive thing we’ve done in this business is split it into two—kind of ironic for a business with “Fusion” in it’s name—but it’s been another challenging exciting change.&lt;/p&gt;
&lt;p&gt;Basically we became known for our FileMaker prowess and it stands out as a point of distinction, yet we’d also built up an incredibly capable web development team that was proving much harder to showcase and find recognition for. So… I decided that it was at a point where it needed to be a separate company, something far more than the web development arm of a FileMaker consultancy.&lt;/p&gt;
&lt;p&gt;This would enable the team on that side of the business to become a powerful web app design and development company in their own right, helping businesses transform the way they work through online tools and services, realizing the full opportunity of the web where form AND function changes the way we do business. Enter &lt;a title=&quot;Open Custom D website in another window&quot; href=&quot;http://customd.com&quot; target=&quot;_blank&quot;&gt;Custom D&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br&gt;&lt;a title=&quot;Open Custom D website in another window&quot; href=&quot;http://customd.com&quot; target=&quot;_blank&quot;&gt;￼&lt;/a&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/20-years/Custom-D-Logo-Main.png&quot; alt=&quot;Custom D Logo Main&quot; width=&quot;306&quot; height=&quot;89&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Onward and Upward&lt;/h2&gt;
&lt;p&gt;So what now? Well… onward and upward. I’ve got high hopes for the web team at &lt;a title=&quot;Open the Custom D web site in a new window&quot; href=&quot;http://customd.com&quot; target=&quot;_blank&quot;&gt;Custom D&lt;/a&gt; — it’s a challenging market to differentiate ourselves in but the opportunities are huge and as was the case in 1996 it’s where the most disruption and change is coming from, albeit on a totally different level now.&lt;/p&gt;
&lt;p&gt;Meanwhile at Digital Fusion the focus on FileMaker now gives us an unprecedented sense of purity and purpose. And with FileMaker Inc doing a most excellent job of evolving the product from “desktop database” to a powerful “Business App Development Platform”, the opportunities to help more businesses operate more effectively have expanded hugely. It still astounds me 20 years on, just how many businesses run on spreadsheets and paper with a fair bit of smoke and a few mirrors to make it all “work”!&lt;/p&gt;
&lt;p&gt;Anyway… I’ll update you on progress in another 20 years. At that point I fully expect we will have:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Autonomous, electric cars (combustion engines are obsolete)&lt;/li&gt;
&lt;li&gt;Hyperloops&lt;/li&gt;
&lt;li&gt;Prototype Fusion Reactors&lt;/li&gt;
&lt;li&gt;Home automation: robots, smart everything from your fridge to your lights&lt;/li&gt;
&lt;li&gt;Screens on walls. Anywhere and everywhere.&lt;/li&gt;
&lt;li&gt;Lightsabers&lt;/li&gt;
&lt;li&gt;FileMaker v35 will be nearing release with AI to do the development for you&lt;/li&gt;
&lt;li&gt;The Web will now be the &quot;vWeb&quot;, a virtual reality where we can live our entire lives without fear of sunburn&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;and of course:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Retirement will have moved out to 85&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;See ya there.&lt;/p&gt;</description>
			<pubDate>Tue, 23 Feb 2016 00:20:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/20-years-already/</guid>
		</item>
		
		<item>
			<title>Custom App Success Guide - Available Free</title>
			<link>https://www.teamdf.com/blogs/custom-app/</link>
			<description>&lt;p&gt;Thinking of building your own database app?&lt;/p&gt;
&lt;p&gt;Or wanting to know more about the process, especially what sort of things should be tackled in the design and planning stage?&lt;/p&gt;
&lt;p&gt;FileMaker Inc have published a very well put together &quot;How to&quot; guide. In fact this is the first in a 3 part series and is available now free from the &lt;a title=&quot;Download page for the Custom App Success Guide&quot; href=&quot;http://www.filemaker.com/plan/&quot; target=&quot;_blank&quot;&gt;FileMaker web site.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/news-custom-app-guide/_resampled/ResizedImage600338-sample-page.png&quot; alt=&quot;sample page&quot; width=&quot;600&quot; height=&quot;338&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Wed, 10 Feb 2016 23:57:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/custom-app/</guid>
		</item>
		
		<item>
			<title>FileMaker, AppMaker</title>
			<link>https://www.teamdf.com/blogs/filemaker-appmaker/</link>
			<description>&lt;h2 style=&quot;text-align: left;&quot;&gt;This Is Cool.&lt;/h2&gt;
&lt;p&gt;Earlier this month FileMaker Inc released a toolset to allow us to turn databases built for FileMaker Go into standard “apps” for iPhone and iPad.&lt;/p&gt;
&lt;p&gt;That is to say we can now turn a database into a standalone app which, just like any other app, can be downloaded and installed in one step. No FileMaker Go app needed.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/filemaker-appmaker/_resampled/ResizedImage25787-icons.png&quot; alt=&quot;icons&quot; width=&quot;257&quot; height=&quot;87&quot;&gt; &lt;/p&gt;
&lt;h2&gt;So What?&lt;/h2&gt;
&lt;p&gt;Well, what does this mean for you, in your business?&lt;/p&gt;
&lt;p&gt;If you’ve got an FileMaker Go solution, or considering having one built, we can turn it into one of these apps with a fairly modest amount of work so that you can set up new devices by simply installing a single application. No more needing to install FileMaker Go, then the database; no more creating an icon shortcut that jumps through Safari before opening your solution. Basically:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Simplified installation and setup&lt;/li&gt;
&lt;li&gt;Proper identity with your own app icon, lock screen&lt;/li&gt;
&lt;li&gt;Launching apps is fast and clean&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;There’re a few subtleties too like, the fact users can’t close the database and end up back at some dashboard of database templates that come with the standard FileMaker Go install. And if you’ve been using a special launcher icon, you might have noticed that iOS puts a link back to Safari in the top left of the screen – that can be confusing and users sometimes hit that by mistake and end up leaving the app. &lt;/p&gt;
&lt;p&gt;All round it’s just a big improvement in usability and deployment.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/filemaker-appmaker/_resampled/ResizedImage600627-iphone-apps.png&quot; alt=&quot;iphone apps&quot; width=&quot;600&quot; height=&quot;627&quot;&gt;&lt;/p&gt;
&lt;h2&gt;App Store?&lt;/h2&gt;
&lt;p&gt;But there’s something else this also means, and the implications could be huge…&lt;/p&gt;
&lt;p&gt;You can now create an app using FileMaker that can potentially be sold through the Apple App Store.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/filemaker-appmaker/_resampled/ResizedImage24284-app-store-icon.png&quot; alt=&quot;app store icon&quot; width=&quot;242&quot; height=&quot;84&quot;&gt;&lt;/p&gt;
&lt;p&gt;Granted, you’re going have to ensure it meets Apple’s strict guidelines for usability, design, content and so on. And it’ll need to work out of the box, whether or not the buyer has a FileMaker Server, at least to some degree. And turning something you’ve built or had built for your own use into a standardised solution takes a lot more work.&lt;/p&gt;
&lt;p&gt;But this opens the door for FileMaker apps to be distributed and used much more widely. And yet users may not even know they’re using something built with FileMaker—which is as it should be, after all, you don’t know what platform or programming language your current apps are written in do you?&lt;/p&gt;
&lt;p&gt;So with this SDK (Software Development Kit) there’s now an opportunity to productize FileMaker based solutions as apps like never before. And while I don’t think we should just jump in and try and produce every solution, there may be some nice opportunities.&lt;/p&gt;
&lt;h2&gt;The Thing I Love Most…&lt;/h2&gt;
&lt;p&gt;The very fact that FileMaker Inc have put this out reinforces the recognition that FileMaker is a software development tool — no, sorry that’s old school, I mean, “app development” tool and not just a “desktop database”. &lt;/p&gt;
&lt;p&gt;And I think the best term for it in our industry speak is, “Platform” - a platform for development, a platform for business solutions, a platform for innovation. It’s powerful, robust, flexible and offers true rapid development unlike anything else.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/filemaker-appmaker/_resampled/ResizedImage222193-love.png&quot; alt=&quot;love&quot; width=&quot;222&quot; height=&quot;193&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Fri, 29 Jan 2016 01:40:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-appmaker/</guid>
		</item>
		
		<item>
			<title>iPad Pro and FileMaker Go - A Marriage Made in Heaven</title>
			<link>https://www.teamdf.com/blogs/ipad-pro-and-filemaker-go-a-marriage-made-in-heaven/</link>
			<description>&lt;p&gt;A few weeks back Apple announced the &lt;a href=&quot;http://www.apple.com/ipad-pro/&quot; target=&quot;_blank&quot;&gt;iPad Pro &lt;/a&gt;and &lt;a href=&quot;http://www.apple.com/apple-pencil/&quot; target=&quot;_blank&quot;&gt;Apple Pencil&lt;/a&gt; which is both big in size but also processing power. At the point at writing, we are still a few weeks away from seeing these in in-store.&lt;/p&gt;
&lt;p&gt;This got us to thinking what will the ‘use cases’ be for our clients in terms of both developing for and using the Pro version of iPad.&lt;/p&gt;
&lt;p&gt;For a number the iPad mini is perfect but this mostly relates to the form factor, size really does matter when you are climbing up on &lt;a href=&quot;https://www.teamdf.com/work/synergy-building-consultants&quot; target=&quot;_blank&quot;&gt;people roofs&lt;/a&gt; or working in a panel shop.&lt;/p&gt;
&lt;p&gt;So conversely what will the additional real estate of the Pro offer clients and these are the four areas we have identified:&lt;/p&gt;
&lt;p&gt;1. Complex apps where you’re working with a lot of data - A number of our clients are required to entered and collate a large amount of data, think measuring a six bedroom house for all &lt;a href=&quot;https://www.teamdf.com/work/mckenzie-and-willis&quot;&gt;window coverings&lt;/a&gt; (curtains, blinds, curtain rods etc). Each room has to have exact measurements taken and stored. Having the larger screen will mean things are more tactile and the smaller details are not missed.&lt;/p&gt;
&lt;p&gt;2.  In house displays - One of our clients has iPads running FileMaker Go on the ‘shop floor’. Once again, with the larger display the visibility of items not the screen will be greatly enhanced. There’s also the option of having a split screen, so both Go and another app are visible at the same time.&lt;/p&gt;
&lt;p&gt;3. Apple Pen use - Where being able to draw or annotate is important or adds a lot of value. Think medical solutions where there’s an x-ray or body diagram that’s annotated or photos of damage or work to be be done where you can draw over the photo.&lt;/p&gt;
&lt;p&gt;4. &lt;a href=&quot;http://www.apple.com/smart-keyboard/&quot; target=&quot;_blank&quot;&gt;Smart Cover with Apple Keyboard&lt;/a&gt; - Apple are to produce a cover and keyboard that will essentially make the iPad into a tablet come laptop. It will give the user the best of both worlds and we can see that this will have some interesting areas for use with FileMaker. At the moment a number of clients have both a FileMaker Go and FileMaker Pro solution, potentially (and we say potentially, it will be interesting to explore) a solution can just be built in FileMaker Go. &lt;/p&gt;
&lt;p&gt;We are always amazed by what clients want and need iPads to do. With the addition of the Pro this will only advance the opportunities for us to develop, and our clients to use FileMaker Go on the iPads.&lt;/p&gt;</description>
			<pubDate>Sun, 03 Jan 2016 14:39:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/ipad-pro-and-filemaker-go-a-marriage-made-in-heaven/</guid>
		</item>
		
		<item>
			<title>iPad Pro and FileMaker Go - A Marriage Made in Heaven?</title>
			<link>https://www.teamdf.com/blogs/ipadproandfilemaker/</link>
			<description>&lt;p&gt;A few weeks back Apple announced the iPad Pro and Apple Pencil which is both big in size but also processing power. At the point of this writing, we&#039;re still a few weeks away from seeing these in in-store.&lt;/p&gt;
&lt;p&gt;This got us to thinking what will the ‘use cases’ be for our clients in terms of both developing for and using the Pro version of iPad.&lt;/p&gt;
&lt;p&gt;For a number the iPad mini is perfect but this mostly relates to the form factor, size really does matter when you are climbing up on &lt;a href=&quot;https://www.teamdf.com/work/synergy-building-consultants&quot; target=&quot;_blank&quot;&gt;people roofs&lt;/a&gt; or working in a panel shop.&lt;/p&gt;
&lt;p&gt;So conversely what will the additional real estate of the Pro offer clients and these are the four areas we have identified:&lt;/p&gt;
&lt;p&gt;1. Complex apps where you’re working with a lot of data - A number of our clients are required to entered and collate a large amount of data, think measuring a six bedroom house for all &lt;a href=&quot;https://www.teamdf.com/work/mckenzie-and-willis&quot;&gt;window coverings&lt;/a&gt; (curtains, blinds, curtain rods etc). Each room has to have exact measurements taken and stored. Having the larger screen will mean things are more tactile and the smaller details are not missed.&lt;/p&gt;
&lt;p&gt;2. In house displays - One of our clients has iPads running FileMaker Go on the ‘shop floor’. Once again, with the larger display the visibility of items not the screen will be greatly enhanced. There&#039;s also the option of having a split screen, so both Go and another app are visible at the same time.&lt;/p&gt;
&lt;p&gt;3. Apple Pen use - Where being able to draw or annotate is important or adds a lot of value. Think medical solutions where there’s an x-ray or body diagram that’s annotated or photos of damage or work to be be done where you can draw over the photo.&lt;/p&gt;
&lt;p&gt;4. &lt;a href=&quot;http://www.apple.com/smart-keyboard/&quot; target=&quot;_blank&quot;&gt;Smart Cover with Apple Keyboard&lt;/a&gt; - Apple are to produce a cover and keyboard that will essentially make the iPad into a tablet come laptop. It will give the user the best of both worlds and we can see that this will have some interesting areas for use with FileMaker. At the moment a number of clients have both a FileMaker Go and FileMaker Pro solution, potentially (and we say potentially, it will be interesting to explore) a solution can just be built in FileMaker Go.&lt;/p&gt;
&lt;p&gt;We are always amazed by what clients want and need iPads to do. With the addition of the Pro this will only advance the opportunities for us to develop, and our clients to use FileMaker Go on the iPads.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/542f9685-4a25-4ad8-8eb4-caa2ecd27771.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Fri, 06 Nov 2015 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/ipadproandfilemaker/</guid>
		</item>
		
		<item>
			<title>14 for 14: Reconnect with your Databases</title>
			<link>https://www.teamdf.com/blogs/14-for-14-reconnect-with-your-databases/</link>
			<description>&lt;h3&gt;Introductions first...&lt;/h3&gt;
&lt;p&gt;This is the first article written for Weetbicks by Craig Saunders - our Director and master chief (be nice in the comments section, he pays my wages! - Daniel)&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 101px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/82b7ca22-cd91-4ad3-822b-4664aabb94fa.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3&gt;  &lt;/h3&gt;
&lt;h3&gt;Let&#039;s Stick Together&lt;/h3&gt;
&lt;p&gt;New in FileMaker 14 is the automatic “reconnect to server” feature which I particularly love.&lt;/p&gt;
&lt;p&gt;Basically FileMaker reconnects you automatically if you’ve lost your connection to the server, such as when you close your laptop then open it up again some time or place later... With ‘reconnect’ FMP will carry on where you left off without the need to log in all over again.&lt;/p&gt;
&lt;p&gt;FileMaker Go has always had this great feature but as of FM14 it’s now in the desktop products too, i.e. FileMaker Pro 14 and FileMaker Pro Advanced 14. And it works with Server 13 or 14 so it’s an instant win even if you’re still running a 13 server.&lt;/p&gt;
&lt;p&gt;Reconnect might not sound like a major feature but it makes huge difference to performance over the internet and the resulting end user experience. Let me explain...&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;FileMaker is a Distributed Database&lt;/h3&gt;
&lt;p&gt;When you first connect to a solution the FileMaker Pro client downloads a large deal of information about the solution including the database schema (tables, fields and relationship graph) and layout and record information for the layout you first land on. Then as you browse records the data itself is also downloaded and ‘cached’ locally. Scripts, value lists, indexes and of course the layout information are also cached as you use the system.&lt;/p&gt;
&lt;p&gt;You see this quite dramatically when you run a report: the first time, a moderate report might take a minute or two to run. Run it again and it can be almost instant, such is the magic of caching.&lt;/p&gt;
&lt;p&gt;When you log out or disconnect, all that hard earned cache data is deleted—it’s a “temporary” working copy after all, right? But what if you could keep it...?&lt;/p&gt;
&lt;p&gt;Essentially reconnect does just that–allows you to keep the cache. In other words if you &lt;strong&gt;don’t&lt;/strong&gt; &lt;strong&gt;close&lt;/strong&gt; the database at the end of day or when you unplug, then FileMaker keeps the cache and can carry on at a later time — i.e. when you have an internet connection again.&lt;/p&gt;
&lt;p&gt;FileMaker’s distributed database technology handles the changes to... it could be a week or a month later when you reconnect, and FileMaker always knows which records, layouts etc, have changed and will update your cache as need be when you reconnect.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Bad Behaviour&lt;/h3&gt;
&lt;p&gt;In practice it’s not entirely “graceful” how this happens but it works fairly well and with a trick or two and some education for users it works like magic.&lt;/p&gt;
&lt;p&gt;Here’s what happens: When the connection is lost FileMaker will try to alert the user—on a Mac, the dock icon bounces a couple of times and this horrific message will confront you:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 467px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/265eeaf4-3493-446f-9bed-e71c3b9253ef.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;(I can see why the good folks at FMI felt the need to explain what’s going on here but that is a lot of information for a user to wrap their head around. It’d be a lot better if the message was worded according to the user privileges—if you don’t have access to Layout editing etc then that detail isn’t needed so it could be kept very simple.)&lt;/p&gt;
&lt;p&gt;Anyway the correct answer is “Reconnect” which basically means “Yeah, carry on, as you were.”&lt;/p&gt;
&lt;p&gt;Actually if you just leave it alone the dialog will go away and it’ll reconnect by itself if it can or just keep trying quietly in the background ad nauseam.&lt;/p&gt;
&lt;p&gt;In fact if you hit “Reconnect” and it can’t reconnect, the files will close giving you no further choice in the matter. Whereas, say you’re on a plane (with no internet), if you just leave FileMaker alone it will:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;display the wordy dialog&lt;/li&gt;
&lt;li&gt;try to connect and fail&lt;/li&gt;
&lt;li&gt;dismiss the dialog&lt;/li&gt;
&lt;li&gt;connect when you get the connection back&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;So the moral of the story is that you’re better just to wait and see what happens!&lt;/p&gt;
&lt;p&gt;Too bad FM had to bother the user with the dialog in the first place—to my mind that should only be necessary if the user tries to actually use the database before reconnection is sorted. And perhaps it should just say “This database can’t be used until you’re connected to the internet again.”&lt;/p&gt;
&lt;p&gt;Ideally the database should be “paused”, dimmed out or something, allowing you to use FileMaker for other things like working on any local databases.&lt;/p&gt;
&lt;p&gt;In fact the ultimate answer is that FileMaker should never throw out the cache (unless specifically ‘asked’ to) so that even if you do close the database, when you re-open the same database the cache should be able to be used again. With the cache encrypted and inaccessible there’s no harm in keeping it around. Go lobby for this feature if you agree... :-)&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/72ba8ddf-97fb-448c-8ea9-d774590ec5ee.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3&gt;   &lt;/h3&gt;
&lt;h3&gt;Another Catch&lt;/h3&gt;
&lt;p&gt;The reconnect works great with a single file solution, however there’s a problem when you have multiple files or interface / data separation (e.g. where the initial interface or main file is the one you log in to, then other files are opened using the same credentials in the background).&lt;/p&gt;
&lt;p&gt;The problem is that during reconnect those credentials are not passed on to the background files in &lt;em&gt;certain circumstances&lt;/em&gt; and the user will be bothered by an authentication dialog:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 541px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/ad435f89-b909-424f-a56b-172a948af3b7.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Have I mentioned that I despise dialog boxes? A dialog is a slap in the face for the user, so general tip: Don’t Do Modal Dialogs!&lt;/p&gt;
&lt;p&gt;Anyway there’s another great feature missing here which is the ability to store the credentials in the keychain. Compare the above dialog with the standard authentication dialog when opening a solution:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 488px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/e9958980-9537-412b-a5b1-42143676ed8f.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;See the difference – there’s an option to store their user name and password in the keychain so that provided the user is logged in on the device, the solution will open and authenticate completely automatically.&lt;/p&gt;
&lt;p&gt;I first noticed this with Go where the ability to store the user name and password creds in the keychain is a real boon (though it begs the question, what sort of security practices should we have around this?)&lt;/p&gt;
&lt;p&gt;     &lt;/p&gt;
&lt;h3&gt;Certain Circumstances&lt;/h3&gt;
&lt;p&gt;During the writing of this article I figured out that this authentication issue doesn’t always happen in multi file solutions - only in “certain circumstances”...&lt;/p&gt;
&lt;p&gt;In the end I nailed it down to the fmreauthenticate extended privilege, which exists for the purpose of dictating how long FileMaker Go can be switched out before requiring the user to re-authenticate.&lt;/p&gt;
&lt;p&gt;Turns out in 14 fmreauthenticate also affects FMPro but not quite as you’d expect: it doesn’t dictate how long before you have to re-authenticate, rather it will force re-authentication if it’s not the same in all files. In other words:&lt;/p&gt;
&lt;p&gt;All files in a multi-file solution must have the same fmreauthenticate privilege for any given privilege set.&lt;/p&gt;
&lt;p&gt;However it doesn’t matter what value it actually has, so it could be fmreauthenticate0 or fmreauthenticate10 or whatever.&lt;/p&gt;
&lt;p&gt;Go behaves a bit more as you’d expect—i.e. if you set a big fmreauthenticate number (which is the number of minutes since the app was used before requiring re-authentication, then users won’t need to re-authenticate provided they come back within that period.&lt;/p&gt;
&lt;p&gt;The maximum number for fmreauthenticate is 10080, i.e. fmreauthenticate10080 which is 7 days. So anyone returning to the app after more than 7 days would have to manually enter their user name and password again.&lt;/p&gt;
&lt;p&gt;      &lt;/p&gt;
&lt;h3&gt;Still Not Entirely Happy&lt;/h3&gt;
&lt;p&gt;So that’s the easy solution.&lt;/p&gt;
&lt;p&gt;However I’m still not entirely happy: given that FileMaker has given users the means to store their credentials in the keychain for automatic log in, any file that is thus opened (whether directly or indirectly) should never ask for the user name and password even if it is a week or a more later since it was last used, and indeed the main file won’t but any background files will.&lt;/p&gt;
&lt;p&gt;One option is to not allow the creds to be stored in the keychain for your solution. You can do that in the File Options settings:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 541px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/603d57ea-b383-4b52-9c99-2cd44ee4d5a6.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Still not happy though—there are legitimate cases for allowing this so why disable it? A better answer seems to be that we’d need to provide an easy means for the user to store the user name and password for the other files in their keychain. This is going to be a slightly annoying step to have to do but it’s one-off and workable as long as there aren’t many other files (e.g. separation model solutions typically have only 2 or 3 files).&lt;/p&gt;
&lt;p&gt;I haven’t worked out the best way to tackle that type of solution, but you basically you’d want to make automate the process so that users could elect to “Store Authentication Details”, and then be prompted for each of the files. To do that they have to be opened directly (as opposed to indirectly from a main file that has access to them).&lt;/p&gt;
&lt;p&gt;I can think of 2 possible solutions for having this function built into the front end or main file:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;At start up before any of the secondary files are referenced, use Open URL to directly open the secondary databases. You can’t use the standard Open File command because the file you’re on has the same credentials and an external reference to that file so passes on the credentials automatically.&lt;/li&gt;
&lt;li&gt;Create a standalone “Authenticator” file which has no credentials in it: you can then use the standard Open File command and will get the full authentication dialog with “Store in Keychain” option. There’re a number of ways of instigating the process but the key thing is that the actual solution files must be closed for the Authentication process to work.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;One More Thing&lt;/h3&gt;
&lt;p&gt;For all of this to work we need to encourage (or prevent even) users from closing the solution: there are a number of ways of doing that:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Tell them not to: e.g. “A kitten dies if you close this database.”&lt;/li&gt;
&lt;li&gt;Or you could just use the window controls to give the user a window with the close control disabled:&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 200px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/72a841c3-d5ad-4e0d-a541-8c418d665de3.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Daniel suggests a variant on this which provides for &quot;a per user approach&quot; by putting twink or tape on the individuals screen where the close control appears.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Either way this approach could be a confusing and frustrating—you’re taking away an expected behaviour so another alternative would be: &lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Intercept the script trigger for “Last Window Close” and do something like this which lets the user decide whether to actually close or just hide the solution&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/fe42d3f9-d6f2-4fa7-b531-5be63fa32281.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Mind you I did say that dialogs are evil, so you could just Hide the solution by default and give users a more explicit “Close Solution” button or control within the solution itself: if your users are the kind who hit the close box just get the solution out of the way then this is the probably the best answer.&lt;/p&gt;
&lt;p&gt;(I tried the dialog approach on one of our own databases and found that it works really well especially with Hibernate as the default in the dialog so 9 times out of 10 you just hit return to accept that action.)&lt;/p&gt;
&lt;p&gt;      &lt;/p&gt;
&lt;h3&gt;Official Information&lt;/h3&gt;
&lt;p&gt;Finally, here’s what FileMaker have to say about this feature:&lt;/p&gt;
&lt;blockquote&gt;&lt;a href=&quot;http://help.filemaker.com/app/answers/detail/a_id/14232&quot;&gt;http://help.filemaker.com/app/answers/detail/a_id/14232&lt;/a&gt;&lt;/blockquote&gt;
&lt;p&gt;(Note that although the automatic reconnect attempt gets longer, it will attempt to reconnect instantly if the user “opens” the database again or clicks onto it at all.)&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;All Good then?&lt;/h3&gt;
&lt;p&gt;I know this all sounds fiddly and is a distraction from your main focus of building features and functionality into your solutions, but if the solution is being used over the internet then get this process sorted your users will love it.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/286bda6a-b032-4c6b-95f1-26d186266cbd.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 15 Jul 2015 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/14-for-14-reconnect-with-your-databases/</guid>
		</item>
		
		<item>
			<title>14 for 14:  Developer Assistant v3.0 Review</title>
			<link>https://www.teamdf.com/blogs/14-for-14-developer-assistant-v3-0-review/</link>
			<description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;Developer Assistant is an application produced by Chris Dragon and his company &lt;a href=&quot;http://www.dracoventions.com&quot; target=&quot;_blank&quot;&gt;Dracoventions&lt;/a&gt;.  It has been around for a couple of years, and version 3.0 has recently been released. This is the version we will be reviewing.&lt;/p&gt;
&lt;p&gt;The Developer Assistant application is bundled with a nice easy to use installer and essentially is a plugin. You can choose to install it for just yourself or for all users, across all versions of the FileMaker platform (7v3 to 14).  &lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/5f02c9ae-2771-4813-803c-9f65e7017795.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;As of writing this review, it is not currently available for Windows platform given a recent change from win32 to .net - but a windows version is expected soon and you can download beta versions as they come out.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;So what is Developer Assistant?&lt;/h3&gt;
&lt;p&gt;The name is a good start!  This tool is for developers first and foremost. It is a tool for searching your schema: fields, scripts, functions, relationship graph and so on. In addition to this it also contains a couple of other very cool developer-centric features which we&#039;ll cover. In essence this that missing allen key in any developers toolbox.&lt;/p&gt;
&lt;p&gt;So why would you want to search these areas? Perhaps this is best illustrated with a demonstration.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Fixing Broken References&lt;/h3&gt;
&lt;p&gt;Imagine a solution with hundreds of scripts. In these scripts are numerous broken field references that need fixing. In FileMaker, a broken field reference generally contains the string &amp;lt;field missing&amp;gt; if any script step references a missing field.  &lt;/p&gt;
&lt;p&gt;So how can we find all of these?  There are a few ways to this point that developers have done:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Print all scripts to PDF and search the PDF&lt;/li&gt;
&lt;li&gt;Run your solution through &lt;a style=&quot;font-size: 1em; background-color: #fafafa;&quot; href=&quot;http://goya.com.au/baseelements&quot; target=&quot;_blank&quot;&gt;BaseElements&lt;/a&gt; and look for missing references&lt;/li&gt;
&lt;li&gt;Manually go through every script - only for the patient!&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Developer Assistant gives you a really quick way to not only find missing references, but to work your way through them fixing each.&lt;/p&gt;
&lt;p&gt;This is done by first opening the script workspace.  Developer Assistant searches in whatever your current context is - be it the script workspace, field definitions dialog, an individual calculation, or a specific script.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/61dee824-2b13-4b6e-9f1e-38f3cb6f1f82.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here in the Developer Assistant window we can type in our search string. We have a few options here. First we can choose to just find references to the search value, or replace (more on this later). We can choose to step through results one at a time using the next/prev buttons, or we can just choose to &#039;Find All&#039; to list every script step where this search string is found.  This is the option we are going to run now.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/72f83e47-55ad-4996-b452-cab5132241d8.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is what you get after finding all.  The search process can take a little time depending on how many scripts you have. This is because it will iterate through each script, opening it in the script workspace and searching, before moving onto the next (currently you cannot have it search a specific subset of scripts)&lt;/p&gt;
&lt;p&gt;Each result is a single script step found where its contents matches the search string. As you can see we have quite a lot!   The beauty of this now is that you can double-click on any result to take you directly to that script, and that script step so you can fix. You don&#039;t need to locate the scripts yourself, Developer Assistant does all this for you.&lt;/p&gt;
&lt;p&gt;In fact, when it comes to missing references, Developer Assistant has thought of it and given you an option to do this:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/05ff3bdf-bca8-4731-ac5d-12d3596ae525.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;By clicking the search icon you are given a number of useful options.  You have some powerful search options when it comes to how you conduct your search query. The most powerful of these being the ability to use regular expressions.  The &#039;Find Missing References&#039; is a shortcut way to achieve what we did in our example. You also have a history of previous searches.&lt;/p&gt;
&lt;p&gt;Consider the possibilities:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Finding missing fields&lt;/li&gt;
&lt;li&gt;Finding all instances of something such as the database name, if you wish to replace&lt;/li&gt;
&lt;li&gt;Find everywhere a global variable is used&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This is so great! Because it is happening right away, you can very quickly address issues in your solution without producing a DDR or PDF of your schema.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Not Just Scripts..&lt;/h3&gt;
&lt;p&gt;As we mentioned earlier, Developer Assistant can effectively search most schema dialog boxes for a given piece of text, examples include:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Scripts (all or selected)&lt;/li&gt;
&lt;li&gt;Fields (all in selected table or specific field)&lt;/li&gt;
&lt;li&gt;Calculations&lt;/li&gt;
&lt;li&gt;Value Lists (names and values)&lt;/li&gt;
&lt;li&gt;Custom Functions (names and parameters)&lt;/li&gt;
&lt;li&gt;The relationship graph (table occurrence names)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This last one gets us particularly excited!&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Relationship Graph Searching&lt;/h3&gt;
&lt;p&gt;Previous versions of the Developer Assistant have allowed you to search the graph but this was somewhat limited. It relied on you entering the entire TO name if you wanted to go direct to a table occurrence, otherwise it worked much like the normal search on the graph where you have to cycle through matches.&lt;/p&gt;
&lt;p&gt;With Developer Assistant 3.0 introducing a list of search results, we can essentially produce a list of all of our table occurrences for easy selection of any TO on the graph - perfect for large relationship graphs or legacy solutions where you are tasked with untangling a spiders web!&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/2ba14a6e-5903-49bf-97ce-264b6ddcfdbf.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Above is a search on one of our solutions relationship graphs. Because we use a naming convention where every table occurrence contains an underscore, by simply searching for an underscore we produce a list of every table occurrence on the graph.&lt;/p&gt;
&lt;p&gt;Double clicking on a result takes you directly to that occurrence on the graph with no visible cycling through results, it is brilliant!  You can then rename the TO or do whatever you want. When it comes to tidying up graphs  or managing large graphs this is an invaluable tool.  If you use an anchor-buoy structure then with consistently named anchors you can turn the results into a list of your anchors for easy access to table occurrence groups.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Replacing Text - Ultimate Power!&lt;/h3&gt;
&lt;p&gt;Version 3.0 of Developer Assistant has introduced a powerful replace function to complement the find function. This function is available in the Advanced version of Developer Assistant only, but is well worth the cost of the upgrade!&lt;/p&gt;
&lt;p&gt;Effectively you can update any piece of text in the schema area you are searching. Scripts is the obvious candidate. Imagine you are tidying a solution and wanting to rename some variables. You can use this to find all occurrences of a global variable and change its name to something else. &lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/a5da6435-344a-46f8-9da4-1023103f533c.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here in this example we are looking for &#039;Daniel Wood&#039; and replacing it with the text &#039;Weetbicks&#039;.  We are just searching one script and the name has been found as part of a comment line.  Just hit the replace button to update the text, it&#039;s that simple!&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;Evaluate - the hidden gem!&lt;/h3&gt;
&lt;p&gt;The core of Developer Assistant is searching your schema and having easy access to the results for editing or replacing. A hidden gem in Developer Assistant however is this little button in the lower left corner:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/5715820b-3129-4c67-a033-cf17c787fb3d.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Welcome to your in-line, evaluate-anywhere data viewer! This little beauty allows you to evaluate any selected calculation no matter where you are in your solution.  Imagine you are editing a complex calculation in a field definition. If you want to test it to make sure it is working you can always copy it, save changes, and paste it into the data viewer. Doing this generally means you have to adjust some field references so it works in the data viewer, not to mention you have to save all your schema changes before testing.&lt;/p&gt;
&lt;p&gt;Not anymore!&lt;/p&gt;
&lt;p&gt;Using the Evaluate button you can instantly evaluate your calculation without ever leaving your calculation dialog!&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/24a4c390-e462-439e-af1f-50018b71b426.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This little feature alone will save you enough time over a while to justify getting Developer Assistant!  You can use this in any calculation dialog, so custom functions, scripts, field definitions etc.  You&#039;ll quickly find that the data viewer plays second fiddle to this little tool.&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;Plus Much more!&lt;/h3&gt;
&lt;p&gt;Developer Assistant does more than what we&#039;ve covered in this review. Windows users get a few other nice features such as the ability to move multiple selected fields with a click of a single button.&lt;/p&gt;
&lt;p&gt;All features of Developer Assistant 3.0 are listed on the &lt;a href=&quot;http://www.dracoventions.com/products/2empowerFM/family/developer.php&quot;&gt;Dracoventions site here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;The bottom line, how much does it cost?&lt;/h3&gt;
&lt;p&gt;Developer Assistant 3.0 will cost you $195 USD for a single license ($395 USD for advanced). They also offer 5 and 10 license plans where you can save up to 60% per user if buying in bulk.  Finally they offer an unlimited license for $1,995 USD which would be perfect for large development companies.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;In Conclusion&lt;/h3&gt;
&lt;p&gt;We think the price is fully justified by the product and what it can offer. For developers time is money, and if you can save 30 minutes here and there by using Developer Assistant as opposed to alternate methods then the product will pay for itself in no time. The Evaluate function alone is worth the price of admission!  We highly recommend this product. We use it ourselves and has become a valuable tool here at Digital Fusion.&lt;/p&gt;
&lt;p&gt;You can download a free 30 day trial from the &lt;a href=&quot;https://www.dracoventions.com/products/2empowerFM/family/developer.php&quot; target=&quot;_blank&quot;&gt;Dracoventions website&lt;/a&gt; - try it out and you&#039;ll be hooked!&lt;/p&gt;</description>
			<pubDate>Mon, 06 Jul 2015 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/14-for-14-developer-assistant-v3-0-review/</guid>
		</item>
		
		<item>
			<title>14 for 14: Ditch those Cartesian Joins, Use Refresh Portal Instead (maybe!)</title>
			<link>https://www.teamdf.com/blogs/14-for-14-ditch-those-cartesian-joins-use-refresh-portal-instead-maybe/</link>
			<description>&lt;h3&gt;A bit of background&lt;/h3&gt;
&lt;p&gt;Back when we first started writing this blog one of our first articles was around portal refreshing and how sometimes complex relationships simply couldn&#039;t be refreshed without a forced flush cache as part of the refresh window script step.  Normally these complex relationships were based on unstored calculations, related data, or the relationship in question was more than one relationship away from the base table occurrence. &lt;/p&gt;
&lt;p&gt;We wrote an article on a technique you could employ to bypass the need to flush the cache and merely &quot;flush the relationship&quot; instead. The end result was refreshed relationships without the need to flush away all record data that had been sent from server to client during the session.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.teamdf.com/weetbicks/42/ditch-those-flush-caches-use-cartesian-join-instead&quot; target=&quot;_blank&quot;&gt;You can read the original article here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The technique is still solid and we have used it all these years for certain relationships that just won&#039;t refresh nicely.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/63c13092-19f3-4304-9e54-0edffd4de97b.png&quot; alt=&quot;&quot;&gt;    &lt;/p&gt;
&lt;h3&gt;How FileMaker 14 changes the game&lt;/h3&gt;
&lt;p&gt;FileMaker 14 has changed the game by introducing the &quot;Refresh Portal&quot; script step to address this issue.  The script step is very simple and looks as follows:&lt;/p&gt;
&lt;pre&gt;Refresh Portal [ Object Name: &quot;ObjectName&quot; ]
&lt;/pre&gt;
&lt;p&gt;It&#039;s very simple and just requires the object name of the portal to be refreshed.  This forces the update of displayed records in the named portal, effectively refreshing the relationship&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;*Disclaimer!  &lt;/h3&gt;
&lt;p&gt;We put a big fat &quot;maybe&quot; at the end of the article title because we don&#039;t necessarily recommend you switch (that was just trying to keep the same article name format as our earlier article on the subject!)  Whether you switch to this technique or not depends on a number of factors which we&#039;ll outline below.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Benefits of switching from Cartesian to Refresh Portal&lt;/h3&gt;
&lt;p&gt;So the question is why would you want to switch to this if your cartesian join relationships have been working fine?  Well, the answer is subjective. For some, there is no benefit, and for others there will.&lt;/p&gt;
&lt;p&gt;First benefit would be removing &quot;hacks&quot; from your solution. We still consider the cartesian join technique a hack and it may no longer be supported in future versions whereas Refresh Portal will.&lt;/p&gt;
&lt;p&gt;Secondly is that relationships that use a cartesian join cannot have records created via them. If you have a portal where you want to achieve this, then you may be better off using the Refresh Portal step if records don&#039;t correctly refresh.&lt;/p&gt;
&lt;p&gt;Lastly, you remove the need for a field in your database to act as the portal refresh (however you gain a script step!)&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Benefits of staying with Cartesian Join  &lt;/h3&gt;
&lt;p&gt;It&#039;s the old saying - if it ain&#039;t broke, don&#039;t fix it. If there is no visible benefit in removing cartesian joins to refresh a relationship then why bother.  Both methods appear to work exactly the same - the Refresh Portal script step doesn&#039;t do anything significantly different to a cartesian join refresh that we can see.&lt;/p&gt;
&lt;p&gt;Another big benefit of a cartesian join refresh is that it can be triggered without a script. Because the refresh occurs when the value of the field used in the cartesian join is changed, this can be triggered using an auto-enter calculation on the cartesian join field that refreshes when any referenced field changes - no need for a script trigger.  &lt;/p&gt;
&lt;p&gt;In a lot of cases this is quite elegant and better than relying on script triggers&lt;/p&gt;
&lt;p&gt;There is also another big benefit of keeping with Cartesian Joins. The Refresh Portal script step requires an actual portal on your layout to refresh!  Cartesian Join refresh operates at the relationship level, whereas the Refresh Portal step acts at the portal level (but still technically is refreshing the relationship).   If you are using cartesian join purely to update a relationship and not a visual portal, then you would need to add this portal to your layout. Fortunately it can be added on the right edge of your layout so is not visible to the user, but you still need it there for this to work.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;In Conclusion&lt;/h3&gt;
&lt;p&gt;If you are using cartesian joins to refresh your relationships and portals and it works fine, we don&#039;t think there is any reason to change. If you are concerned about it working in future, it may be best to switch now to the Refresh Portal step.  Either way you now have 2 great options!&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;We&#039;ve built a new example file that shows both the Cartesian Join refresh technique from our earlier demo, and now the Refresh Portal script step technique also. You can compare both for yourself and see what will work best for you.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.teamdf.com/assets/files/weetbicks/14for14/14for14_RefreshPortal.zip&quot; target=&quot;_blank&quot;&gt;Click here to download the example file.&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 29 Jun 2015 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/14-for-14-ditch-those-cartesian-joins-use-refresh-portal-instead-maybe/</guid>
		</item>
		
		<item>
			<title>14 for 14: Setting up cool  looking buttons just got easier</title>
			<link>https://www.teamdf.com/blogs/14-for-14-setting-up-cool-looking-buttons-just-got-easier/</link>
			<description>&lt;h3&gt;Buttons that just keep getting cooler&lt;/h3&gt;
&lt;p&gt;Buttons in FileMaker 14 are cool! So cool in fact that they got their own bar (more on that in a later article).  For now we&#039;ll focus on just the button object, what is new, what&#039;s the same, and what you can do to take them even further.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;The new button user interface&lt;/h3&gt;
&lt;p&gt;The first thing you may notice is the button setup has dramatically changed from FileMaker 13. Gone is the modal popup dialog and procedural setup. In its place is a more stylish looking non-modal popup where you can determine specifically what aspect of the button you want to setup.&lt;img style=&quot;display: block; margin: auto; width: 251px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/c7601ac5-2c70-4e56-afdd-f0620c46fca3.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The button setup comprises of four main sections...&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;Button type&lt;/h3&gt;
&lt;p&gt;You can define whether the button has just a label, icon, or both. You can also define the position of the icon relative to the label.  Icon options are only displayed if your button type includes an icon.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 205px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/b8f0d39a-6c86-4180-b2d1-7b68a3224288.png&quot; alt=&quot;&quot;&gt;FileMaker has 140 built in icons. These icons cannot be removed or modified. You can use the slider to scale the icons in size.  This is possible because button icons are scalable vector graphics (SVG) format.&lt;/p&gt;
&lt;p&gt;When you insert your own icons you can choose to insert either png or SVG format icons. PNG format icons can be scaled (though not as well as SVG, it&#039;s just a basic resize) whereas SVG icons can not only be nicely scaled, you can make use of styling and have full control over the icons colour in a range of different states, including conditional formatting.&lt;/p&gt;
&lt;p&gt;Also when inserting icons you can choose to insert as many icons as you want in a single operation. Icons are stored with the file.  Note also that icons cannot be added to a file while that file is hosted, it must be local for icons to be able to be saved with a file for future use.&lt;/p&gt;
&lt;p&gt;We recommend you check out &lt;a href=&quot;http://www.flaticon.com/&quot; target=&quot;_blank&quot;&gt;http://www.flaticon.com&lt;/a&gt; for a huge selection of great free SVG icons you can add to your solutions.&lt;/p&gt;
&lt;p&gt;Currently custom icons added appear in a darker grey colour which is not actually a bad thing as it allows you to distinguish between what is a custom icon and what is a native icon.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 286px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/02fc5490-f076-432b-9276-b56b9ce34ad4.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;There is also another quite cool way to automatically add custom icons to your solution. If you paste any button into your solution which itself contains a custom icon not already stored with your solution, then upon pasting that icon will be added to your icon list.  With this technique you can create your own icon sets by creating button bars with sets of icons associated. Simply paste them into any solution you wish to add the icons to (more on button bars later!)&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Button text. &lt;/h3&gt;
&lt;p&gt;While not definable by calculation (probably for backwards compatibility) it is now so much easier to change a buttons text when a script is attached. &lt;/p&gt;
&lt;p&gt;Prior to FileMaker 14 you would have to select the text tool before clicking a scripted button otherwise you would launch the button setup dialog. Now just double click the button and edit the text right away - no need for text tool selection. However you can still use the text tool to directly edit a buttons label if you wish to bypass the button setup popup.&lt;/p&gt;
&lt;p&gt;While calculations are not supported, merge field and merge variables are still supported.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Button Action&lt;/h3&gt;
&lt;p&gt;Action allows you to choose one of three options: Do nothing, single step, or script While these three options are the same as FileMaker 13, the method in which you use them is different.&lt;/p&gt;
&lt;p&gt;For a single step you use the script workspace engine to define the step, rather than selecting a single step from a list. This allows you to make use of auto-complete in scripts or show a list of steps. &lt;/p&gt;
&lt;p&gt;The real cool feature is being able to change your single step into a script. Often buttons are defined but you realise you need a second step, or need to flesh it out a bit into a script. You can now do this direct from button setup by clicking the &quot;Convert to Script&quot; button:&lt;img style=&quot;font-size: 1em;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/a4ec3c1e-2eec-4bd4-bdf2-9fad364d0804.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;When you do this you are prompted to enter the script name. Upon clicking OK the dialog will change to that of an actual script, and the new script is placed in a created folder called &quot;Scripts for Buttons&quot;&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/43ddd185-0e5a-4e0e-834c-0d07fed3555d.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 244px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/f5f5811f-935d-4068-b307-29ea84c07f44.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Button Options&lt;/h3&gt;
&lt;p&gt;At this stage the only button options are to show a hand cursor over a button. It seems a little odd for there to be only one option under options, and even more odd you have to expand this area by default in order to set the option - but maybe they are anticipating more options in future who knows!&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;To supplement this article we have provided a demo file in which you can see how buttons can be setup, and how custom SVG icons can be added and used in a solution. The demo file includes over 400 custom icons already added to button setup to demonstrate. All custom icons are from the freeicons.com website, and we have included a sample set with the file.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/14for14/14for14_CustomisingButtonIcons.zip&quot;&gt;Click here to download the demo file.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Further Resources&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.fmstartingpoint.com/svgdownload.php&quot; target=&quot;_blank&quot;&gt;SVG Helper Tool from Richard Carlton Consulting&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.indats.com/2015/06/15/indats-icon-manager/&quot; target=&quot;_blank&quot;&gt;Icon Manager FileMaker database from Indats (recommended!)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://fmhelp.filemaker.com/docs/14/en/svg/&quot; target=&quot;_blank&quot;&gt;FileMaker Pro 14 SVG Grammar Guidelines&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Thu, 18 Jun 2015 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/14-for-14-setting-up-cool-looking-buttons-just-got-easier/</guid>
		</item>
		
		<item>
			<title>14 for 14: What is a Navigation Part?</title>
			<link>https://www.teamdf.com/blogs/14-for-14-what-is-a-navigation-part/</link>
			<description>&lt;h3&gt;Why add a new part now... and for navigation?&lt;/h3&gt;
&lt;p&gt;Good question, to answer that we first need to understand the properties of the navigation layout part and once those are clear the reasons for having it become quite obvious.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 336px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/c3bb1c15-0275-4b6f-bb59-ac0a0e5da184.png&quot; alt=&quot;&quot;&gt;The setup of a layout part couldn&#039;t be easier, in fact there are no additional options for a part, it&#039;s either top or bottom navigation.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 153px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/9b00ba94-b8dc-4cf5-8e06-7958a856a223.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We have identified 4 key features of the navigation part that make it a really great UI enhancement for your solutions.&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;Navigation Parts remain fixed to the top/bottom of screen&lt;/h3&gt;
&lt;p&gt;This is the most important aspect of a navigation part, and what makes it truly feel like navigation (if used for that purpose).&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/3b181c11-2584-47ab-82de-4bf47312d426.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Take a look at the above picture of a layout. Notice anything? There is something about this layout that was never before possible. I&#039;ll give you a second......... got it? Yes? No?&lt;/p&gt;
&lt;p&gt;There are a few clues here:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The layout is in form view&lt;/li&gt;
&lt;li&gt;The layout is in browse mode&lt;/li&gt;
&lt;li&gt;The layout is scrolled&lt;/li&gt;
&lt;li&gt;yet the header and footer remain visible&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Well, the last point basically answered it.  When in form view (or any view for that matter) navigation parts remain fixed to the top and bottom of the screen.  Headers and Footers on the other hand do not remain fixed. They remain fixed in list and table views but scroll in form view.&lt;/p&gt;
&lt;p&gt;So why does this matter? Well, it opens the doors for us to build sweet layouts that are scrollable, whilst not losing our top/bottom navigation.  FileMaker developers have always been sticklers for putting everything on screen and avoiding scrolling anything that isn&#039;t a list layout.&lt;/p&gt;
&lt;p&gt;This is quite a paradigm shift, but it draws parallels with websites. Most websites are scrollable and retain their navigation at the top visible to the user. Data-entry forms online also benefit from scrolling by allowing you to build long single data entry forms instead of relying on tabs or multiple screens. This is all now really easy in FileMaker 14. With the rise of FileMaker WebDirect this will be more important than ever as users will be expecting an experience similar to their normal web experience.&lt;/p&gt;
&lt;p&gt;Last note on this - if you wish to use top/bottom navigation parts in table view, make sure you mark them as visible via the table view setup:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/3d466576-910e-4362-a1f5-7d79e20ed970.png&quot; alt=&quot;&quot;&gt;       &lt;/p&gt;
&lt;h3&gt;Navigation Parts do not zoom&lt;/h3&gt;
&lt;p&gt;Look at the below picture:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 399px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/8ae7be9f-3e83-4aec-9a83-c23540287c34.png&quot; alt=&quot;&quot;&gt;   &lt;/p&gt;
&lt;p&gt;That is 10pt text with the layout zoomed to 400%. The navigation part however remains unchanged. Indeed both the top and bottom navigation parts are will not zoom with the layout zoom.&lt;/p&gt;
&lt;p&gt;On some level we can understand why this is the case - it&#039;s for navigation not actual data so is there any real reason to zoom it? We think not but we can understand if people are a bit confused by this one. Hopefully FileMaker will give us an official reason ;)&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Navigation Parts do not print&lt;/h3&gt;
&lt;p&gt;Now this feature makes perfect sense! The part is to be used for navigation, not printing - nuff said! If you use it for its intended purpose, and place inside it navigation such as links or a button bar then why on earth would you want to print that? You should use a header and footer for printing!&lt;/p&gt;
&lt;p&gt;The beauty of this is it allows you to build a layout that might also print quite nicely such as a list view. You can easily print it without all the UI navigation stuff.&lt;/p&gt;
&lt;p&gt;(Perhaps) unfortunately you cannot have both a top navigation and a header on your layout and choose to use the header for preview mode, and navigation part for browse mode - you must choose one or the other so if you want a proper printed list with header and footer you will still need another layout.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Navigation Parts have nice animation effects and are stylable&lt;/h3&gt;
&lt;p&gt;This last one is not functionally necessary but so damn cool (and fun) we included it. Navigation parts have a nice animation effect associated with them when using a trackpad or iPad device and are scrolling a layout.  When you scroll to the top or bottom, the navigation part header/footer &quot;bounces&quot;.  It&#039;s a little difficult to illustrate but you will have seen this effect on iOS for a couple of years now. You can scroll past the top of the layout essentially.&lt;/p&gt;
&lt;p&gt;While we have not yet figured out how to alter the underlying fill colour you see (we&#039;d love to know how) it is a nice little animation that ties it in nicely with the feel of iOS.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 373px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/11faa74c-84e4-4230-b7b8-5b7fe01c92f3.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;Navigation parts can also be styled in the same way as headers and footers. You can define a background fill for the navigation part system-wide by turning it into a style of the theme you use.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;To go along with this article we&#039;ve done a sweet demo file you can download below. This shows you the setup of a navigation part and an example of a scrollable form-view layout that uses navigation parts so you can get a feel for the usage and benefit.  Note because this uses a FileMaker 14 feature it obviously will only work nicely in 14, but you can try opening in 13 at your own risk :)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/14for14/14for14_NavigationParts.zip&quot;&gt;Click here to download the demo file.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Update!&lt;/h3&gt;
&lt;p&gt;Reader LaRetta pointed out that the colour you see when doing the &quot;bounce&quot; effect for the navigation parts is actually the layout background, of course!  You can change this by clicking off the edge of the layout to set the inspector to layout background and then alter the colour from there, thanks LaRetta for the tip!   LaRetta also kindly attached a modified example file to illustrate this which you can download below.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/14for14/14for14_NavigationParts_newBounceColor.zip&quot;&gt;Click here to download the modified demo file.&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Fri, 12 Jun 2015 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/14-for-14-what-is-a-navigation-part/</guid>
		</item>
		
		<item>
			<title>Integrating FileMaker with Xero</title>
			<link>https://www.teamdf.com/blogs/integrating-filemaker-with-xero/</link>
			<description>&lt;p&gt;Xero remains the number one piece of software our clients want their FileMaker solution integrated with.&lt;/p&gt;
&lt;p&gt;This has been the case for nearly five years now, but what we are finding is that clients are keen to integrate FileMaker and Xero in different ways, and for different business reasons.&lt;/p&gt;
&lt;p&gt;Traditionally the request was to ‘push’ all invoicing (including invoice contact details) from a FileMaker solution through to Xero. &lt;/p&gt;
&lt;p&gt;Now clients are wanting more than just the invoice contact details pushed through, and they are keen for the information to flow both ways, from FileMaker to Xero and back again.&lt;/p&gt;
&lt;p&gt;To follow are some of the requests and work we have performed by using the Digital Fusion Xero plugin. We have also listed the business case as to why this is important:&lt;/p&gt;
&lt;h2&gt;Push of invoice and contact details from FileMaker to Xero&lt;/h2&gt;
&lt;p&gt;As mentioned above, this is the most requested form of integration. Depending on how well your FileMaker solution is developed we can get this working reasonably quickly, but sometimes it does take additional work to make sure FileMaker is setup correctly.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Business use:&lt;/span&gt; Integrating FileMaker with Xero in this way allows for a seamless experience for your staff. They are able to raise invoices in FileMaker and all this information then flows through to your accounting package, in this case Xero. The integration works behind the scenes so once an invoice is finalised there is nothing more that is needed to be done.&lt;/p&gt;
&lt;h2&gt;Information moving both ways&lt;/h2&gt;
&lt;p&gt;This is becoming a more sought after requirement for integrations we perform. As above, invoice and contact information is pushed from FileMaker to Xero but in this case account updates are pulled back from Xero into FileMaker. This one has a few more things to take into consideration, the main one being how often the information needs to come back from Xero into FileMaker. Xero has a limit on the number of daily ‘calls’ that can be made to and from their software, so we can’t have an endless pull of information back from Xero to FileMaker (although we have some cunning ways to get around this)&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Business use:&lt;/span&gt; The big gain with a two way flow is that this allows all your staff to see how a client account is looking without having to give them access to Xero itself. Now sales staff can see if a client has their account up to to date, or they can now be the ‘prompter’ when discussing outstanding accounts with clients. Although Xero now offer ‘limited access’ to the software, having all this information in FileMaker makes for a seamless experience, with all client information contained within one solution.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Push all contacts through to Xero&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Typically we have only pushed contact information through to Xero when an invoice is raised. Xero then looks to see if the client already exists and if not, it adds it as a new client. &lt;/p&gt;
&lt;p&gt;Recently we have been asked to integrate all contacts that are in FileMaker with Xero. This can include contacts such as supplier, staff etc, essentially any contact that you believe will need a reference in Xero.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Business use:&lt;/span&gt; The big gains here are around reducing double handing, you know longer need to key in details in both solutions, increasing the overall accuracy of data.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;As you can tell from the above, there are a number of options to consider when integrating FileMaker with Xero. Each come with varying degrees of complexity but all are possible and becoming more the norm.&lt;/p&gt;
&lt;p&gt;We like to think of ourselves as the experts in integration with Xero so if you requirements match the above or differ in any way, &lt;a href=&quot;https://www.teamdf.com/contact-us/&quot; target=&quot;_blank&quot;&gt;please get in touch&lt;/a&gt; we would love to discuss your requirements.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Wed, 10 Jun 2015 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/integrating-filemaker-with-xero/</guid>
		</item>
		
		<item>
			<title>14 for 14: New Layout Object Formatting and Styling Options</title>
			<link>https://www.teamdf.com/blogs/14-for-14-new-layout-object-formatting-and-styling-options/</link>
			<description>&lt;h3&gt;Better than ever!&lt;/h3&gt;
&lt;p&gt;FileMaker just keeps getting better!  With 14 we have more flexibility than ever before when it comes to creating gorgeous looking solutions. A number of a new layout styling options help make this possible. In this article we cover some of the new layout object styling options.&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;Placeholder Text&lt;/h3&gt;
&lt;p&gt;Not so much a new style property as it is a new feature that can also be styled. Placeholder text is fully styleable in the same way a text label is.  &lt;a href=&quot;http://www.teamdf.com/weetbicks/253/14-for-14-the-power-of-the-placeholder&quot; target=&quot;_blank&quot;&gt;Check out this article on placeholders&lt;/a&gt; for more information and other cool applications of placeholder text.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/aa0a34d2-64ca-4e9f-8d5b-ff22e219562e.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Touch Keyboard Control&lt;/h3&gt;
&lt;p&gt;With FileMaker 14 you now have total control over which keyboard to use for any layout object on iOS devices. You can specify a keyboard that is most relevant for the field type. This option is on the data tab of the inspector.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/fafdc4ea-764e-462e-b4a3-e75a23429d38.png&quot; alt=&quot;&quot;&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/7bd8be5d-0087-4ed6-add3-d37d4d42144a.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can also now disable the touch keyboard programatically using the new script step:&lt;/p&gt;
&lt;pre&gt;Enable Touch Keyboard [ Off/On ]
&lt;/pre&gt;
&lt;p&gt;This is useful in read-only solutions, or fields where you want the user to be able to enter it and scroll (think large text boxes) but not edit. A script trigger could be utilised to turn the keyboard off when entering (and on when exiting).&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;Better scrollbars for portals and fields&lt;/h3&gt;
&lt;p&gt;This is one of my favourite new features for creating beautiful solutions. Both portals and fields now have additional scrollbar options. These allow you to not show the scrollbar unless the portal/field is being scrolled. They look much more like native OS scrollbars and it means you need not show FileMaker&#039;s standard scrollbar all the time. The scrollbar only appears when scrolling, or when the mouse is placed over the scroll area. This option is on the data tab of inspector under control style.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/3a368672-9190-478e-b2ff-bfdcb726ac98.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/b77938b5-f5d2-4398-8806-76854261e659.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Easier Tab control styling.&lt;/h3&gt;
&lt;p&gt;Tabs have been improved when it comes to easier styling. You can now define style properties that are automatically applied to each individual tab.  Prior to 14, each tab of a tab control object was styled individually and you had to select every tab if you wanted to style them all at once. This inevitably led to tabs being setup with different styles.&lt;/p&gt;
&lt;p&gt;Now it is simply a case of ticking an option in the tab control setup to allow you to define one style for all tabs.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/c78d3dfd-6875-4564-8f69-e232f917b9bc.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Field control over button &amp;amp; Icon&lt;/h3&gt;
&lt;p&gt;Fields that use the control style of popup, drop-down or calendar now have more formatting control over the button area and the icon:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/7b7c059b-9048-4261-85a7-0f8cc4c79226.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The button area is the right hand side section that is clickable to initiate the drop-down or calendar.  This area has full styling options now in all of the states.&lt;/p&gt;
&lt;p&gt;The icon can have its colour changed in all of the states such as hover, in-focus and pressed.&lt;/p&gt;
&lt;p&gt;Using these new formatting options you can build some very nice looking fields.&lt;/p&gt;
&lt;p&gt;The icon is also styleable through conditional formatting, this means you can impelment some cool features such as having the icon appear grey/disabled if the field is not required. You could also utilise icon colour to indicate an error with the field.&lt;/p&gt;
&lt;p&gt;Consider a date field where you want to visually indicate whether the entered value has expired:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/84f47bad-9743-4c3f-8467-558af619674f.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The icon can be conditionally formatted as such:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/d6e6ac12-53b5-4730-a772-9660ed9b0826.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This creates a really nice visual cue for expiration as opposed to filling the entire field red, or any extra labels.&lt;/p&gt;
&lt;p&gt;Icons cannot currently be changed - you are restricted to the standard arrow/calendar icons, but hopefully this will change in future given the new icons we can setup for buttons.&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;Checkboxes and Radiobuttons&lt;/h3&gt;
&lt;p&gt;There have been some additional styling options added to both checkboxes and radiobuttons.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/47e03f4a-d58d-477d-a1d8-9fd3caf9dd96.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The first thing you may notice above is that the checkbox actually now shows a tick. This is a customisable option via the control options and is available for checkbox sets only:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/e8f878b3-06e7-454f-b9ea-fc9f77ce8d5f.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Check is the new option, and the default is &quot;X&quot;.&lt;/p&gt;
&lt;p&gt;Checkboxes and radiobuttons also now have full styling for the &quot;button&quot; and &quot;icon&quot;. In the case of these controls, button refers to the square checkbox, or the circular radiobutton. Icon refers to the contents of those - either the tick/X for a checkbox, or the inner circle for a radiobutton.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Buttons and Button Bars&lt;/h3&gt;
&lt;p&gt;Both of these are topics we&#039;ll cover in other 14 for 14 articles, but it is good to reiterate here that buttons now have more customisation options available with the introduction of icons. With a standard button you can control the icons colour (providing the icon is either a standard FileMaker icon, or an SVG inserted).&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/164f6661-3b74-464d-9467-35e59017869d.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;With button bars you can control all the style options that buttons have, with a couple of additions:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/bd34ebab-9888-4448-bc00-a8629449136f.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Segment and Icon areas are the main formatting options for the buttons on a button bar. Dividers are literally just the dividing lines between segments, and button bar has styling options common across all segments such as the border outline, outer shadow and rounded edges.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;We have included a demo file with this article so you can check out all of the new formatting options for yourself.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.teamdf.com/assets/files/weetbicks/14for14/14for14_NewFormatting.zip&quot;&gt;Click here to download the demo file&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 03 Jun 2015 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/14-for-14-new-layout-object-formatting-and-styling-options/</guid>
		</item>
		
		<item>
			<title>14 for 14: Building a Navigation Button Bar</title>
			<link>https://www.teamdf.com/blogs/14-for-14-building-a-navigation-button-bar/</link>
			<description>&lt;h3&gt;Previous Navigation Articles and our own Navigation&lt;/h3&gt;
&lt;p&gt;This is the third navigation article we have done and it has been quite some time between drinks. The first one - &lt;a href=&quot;http://www.teamdf.com/weetbicks/37/build-a-navigation-system-part-one-starting-out-simple&quot; target=&quot;_blank&quot;&gt;Starting out Simple&lt;/a&gt; - covers building a basic navigation bar using repeating fields.  In the second article - &lt;a href=&quot;http://www.teamdf.com/weetbicks/80/build-a-navigation-system-part-two-taking-it-further&quot; target=&quot;_blank&quot;&gt;Taking it Further&lt;/a&gt; - we extended upon the first by introducing selected screen highlights and a navigation script.&lt;/p&gt;
&lt;p&gt;It may surprise you to know that we here at Digital Fusion still use this method for our navigation bar with some small tweaks. Repeating fields are still utilised and have been abstracted to the point the navigation bar setup can be customised per-user and all of the formatting can be done via a combination of styles and editing the repeating field contents.  It is robust, works well and highly flexible.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;So why consider the button bar?&lt;/h3&gt;
&lt;p&gt;It&#039;s a great question. The button bar on its surface seems to be very similar to our navigation method in regards to how it can be styled to look, and how it functions. Each segment can run a script for navigation, and you have total control over how it looks - sounds like a perfect substitute!&lt;/p&gt;
&lt;p&gt;And for most applications it is, but there are some small limitations as we&#039;ll get into later.&lt;/p&gt;
&lt;p&gt;One of the biggest benefits of the button bar over other methods is that the button bar is simply a layout object without a fixed context. If properly setup, it can be built to be entirely generic and contextless, and therefore able to be copy/pasted across multiple layouts.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;The components of a button bar we need to setup&lt;/h3&gt;
&lt;p&gt;So you&#039;ve decided you want to use a button bar for your navigation - how do you now make it entirely generic and contextless? If we look at the button bar setup we can identify areas we&#039;ll need to abstract:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/62d2b4fb-1d19-4d8a-9a0c-3305cb185b41.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The first we will cover is the label.  Fortunately labels can be defined for a segment based on calculation so that is perfect, we can have a different calculation result for each segment.&lt;/p&gt;
&lt;p&gt;Next we need to be able to run a script to carry out the navigation. The script needs to know which segment was pressed by the user in order to carry out the correct navigation. Fortunately we can pass a script parameter that differs for each segment, so that takes care of that.&lt;/p&gt;
&lt;p&gt;What about if we wish to highlight the current screen segment the user is on? Fortunately once again we can specify what the active segment is via calculation so all good there.&lt;/p&gt;
&lt;p&gt;The last thing is icons. Ahh, now we have a little issue.  To this point everything could be abstracted into a calculation, and thus alterable outside of the button bar object, but can we change the icon? The answer at this point is no.  If your navigation bar is to use built in button icons, then once you define an icon for a segment that&#039;s it. You cannot programmatically alter this icon in the future, meaning if you wanted to change it you would have to copy/paste the button bar across all your layouts again.&lt;/p&gt;
&lt;p&gt;No icon? Perfect! The button bar is a great tool for a text based navigation bar.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;So how do we abstract?&lt;/h3&gt;
&lt;p&gt;There are a number of ways in which you can abstract the information needed by the button bar. In our example we are going to build a simple navigation table to store our information. We&#039;ll then build a custom function to obtain this information for the button bar to use.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/82b35df9-6b3c-4462-a715-0e580b3aace5.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Above we have our navigation table. It has three fields:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Segment - just a number. It will correlate to a segment of the button bar.&lt;/li&gt;
&lt;li&gt;Label - what we wish the label to be in the button bar&lt;/li&gt;
&lt;li&gt;Layout - what layout will the navigation take the user to when clicked.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;And here is our example navigation bar:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/fc40e271-f1cd-4b3e-ba72-90cb1bd97c5d.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can see we have 5 segments. Each label correlates to the segment defined in the navigation table. If we were to for example swap the segment numbers for Penguin and Phone in the navigation table we end up with:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/8bdf2efa-e27e-45ea-9b8b-5ab425cbfaaf.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The button bar automatically responds to this change and reorders the Phone and Penguin segments.&lt;/p&gt;
&lt;p&gt;Notice anything unusual though? The icons! We cannot have control over these so this type of dynamic reordering of a button bar is prone to problems if you use icons unfortunately :(&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;Getting the Navigation information to the button bar&lt;/h3&gt;
&lt;p&gt;It&#039;s all fine and well to setup this information in a table but we need to deliver it to the button bar in a way such that the button bar does not have to deal with context.&lt;/p&gt;
&lt;p&gt;To achieve this we have built a simple custom function which we call &lt;strong&gt;@NAV_GetProperty&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This custom function takes two parameters:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;_theNumber: This is a segment number for which you want information.&lt;/li&gt;
&lt;li&gt;_theProperty: This is a keyword that tells the function what information you need.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;And that&#039;s it.  As an example, what if we needed the label for the third segment:&lt;/p&gt;
&lt;pre&gt;@NAV_GetProperty ( 3 ; &quot;Label&quot; )&lt;/pre&gt;
&lt;p&gt;The result of this function will be &quot;Phone&quot;.&lt;/p&gt;
&lt;p&gt;The custom function is used in three situations:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;To define labels - @NAV_GetProperty ( 1 ; &quot;Label&quot; )&lt;/li&gt;
&lt;li&gt;Navigation script to obtain layout - @NAV_GetProperty ( 1 ; &quot;Layout&quot; )&lt;/li&gt;
&lt;li&gt;To determine active segment - @NAV_GetProperty ( &quot;&quot; ; &quot;Active&quot; )&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The last situation there is a slightly different case where we do not pass a segment number. In this case the custom function returns a segment number that corresponds to which one should be the active segment.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Using ExecuteSQL to abstract&lt;/h3&gt;
&lt;p&gt;The custom function is able to return this information, and determine active segment, through the use of the ExecuteSQL function.&lt;/p&gt;
&lt;p&gt;For obtaining the layout or label, it simply is carrying out a SELECT query based on the passed segment number, and property.  &lt;strong&gt;Note: &lt;/strong&gt;The property corresponds to the field name in the navigation table - so if you decide to change these field names you must also update the custom function accordingly.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Defining what an Active Segment is&lt;/h3&gt;
&lt;p&gt;In order for us to show an active segment, we must first understand how FileMaker defines what the active segment is for a button bar.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/4fa9d923-aac6-4288-8477-641440e1296d.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We can either define the active segment explicitly, or via calculation. If defined explicitly we have no control over dynamically altering this, so it is useless for our navigation bar.&lt;/p&gt;
&lt;p&gt;What needs to be returned by our calculation in order for the result to be treated as the active segment?  The answer is an object name.  Each segment can be assigned an object name via the Inspector, and FileMaker compares the calculation result to object names in order to determine active segment.&lt;/p&gt;
&lt;p&gt;What are the implications of this? Well first you need to ensure every segment in your button bar has an object name. In our example we have given each the following:&lt;/p&gt;
&lt;pre&gt;nav_X&lt;/pre&gt;
&lt;p&gt;where X is a number from 1 to 5, in order.&lt;/p&gt;
&lt;p&gt;Active segments are determined by first looking at what layout the user is on. The custom function will perform a SELECT query to obtain the Segment number for the navigation record whose layout matches the current layout. This tells us which segment number our layout is for. We can then simply prefix it with &quot;nav_&quot; to return an object name that corresponds to the button bar active segment.&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;Putting it all together&lt;/h3&gt;
&lt;p&gt;We have now a single custom function that we can use to define the active segment and segment labels and layouts.&lt;/p&gt;
&lt;p&gt;Our active segment calculation is thus: &lt;/p&gt;
&lt;pre&gt;@NAV_GetProperty ( &quot;&quot; ; &quot;Active&quot; ) &lt;/pre&gt;
&lt;p&gt;Our label calculation is:&lt;/p&gt;
&lt;pre&gt;@NAV_GetProperty ( 1 ; &quot;Label&quot; )&lt;/pre&gt;
&lt;p&gt;and our Navigation script is passed a segment number from which it can obtain the layout:&lt;/p&gt;
&lt;pre&gt;@NAV_GetProperty ( Get ( ScriptParameter ) ; &quot;Layout&quot; )&lt;/pre&gt;
&lt;p&gt;Very elegant, very simple, and very flexible!&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;Taking it further&lt;/h3&gt;
&lt;p&gt;Because ExecuteSQL is used to obtain navigation information, you can do some pretty cool things with your navigation bar setup.&lt;/p&gt;
&lt;p&gt;Perhaps you added a new table called &quot;UserNavigation&quot; which acts as a join table between Navigation, and your Users table. Each record has a user ID and a navigation ID. Basing your navigation bar on this table, you could have different navigation bars for users based on things such as their access privileges, or role.  Simply add a record for a user to give them screen access via the button bar.&lt;/p&gt;
&lt;p&gt;Another cool feature of the button bar is that text formatting functions will override the styles. You can therefore conditionally format labels to appear disabled if you wish to prevent user access to certain screens as opposed to hiding that screen from the button bar. Using the TextColor function you can achieve this.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Button Bar limitations&lt;/h3&gt;
&lt;p&gt;We have already covered some limitations around abstracting icons, but there is another property of button bars that may mean they are not suitable to your needs. Each segment of a button bar is the same width as all other segments - you cannot define an individual segments width. This means segments with a long label will wrap its text as opposed to extending the width of the segment:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/611888bb-e69a-4134-9ff8-e6e70c6fb4ee.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Sometimes this may not look that bad, but icons will be offset to accommodate.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;In conclusion&lt;/h3&gt;
&lt;p&gt;Button bars are a great FileMaker 14 tool and can be used for a number of applications, one of which may be a navigation bar. As far as making them totally abstracted goes, they work best without icons but if you can live with the icons being fixed to the object then they look great with icons.&lt;/p&gt;
&lt;p&gt;Compared to our older articles around navigation bars the button bar comprises of only a single object as opposed to multiple objects for the repeating field implementation. Button bars should also work great in WebDirect and FileMaker Go.&lt;/p&gt;
&lt;p&gt;We are strongly looking at whether it is worth making the switch from our repeating field based navigation to button bars. At this point the jury is still out and icon abstraction is a big limitation that will likely see us keep to repeating fields for now.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Example File.&lt;/h3&gt;
&lt;p&gt;All the screenshots and examples in this article are from our demo file that you can download below. Obviously being a FIleMaker 14 feature this works best in 14, but you can still open it in 13 if you need to.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.teamdf.com/assets/files/weetbicks/14for14/14for14_NavigationButtonBar.zip&quot;&gt;Click here to download the example file&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Thu, 28 May 2015 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/14-for-14-building-a-navigation-button-bar/</guid>
		</item>
		
		<item>
			<title>14 for 14:  Shortcuts for Quick Script Step Entry</title>
			<link>https://www.teamdf.com/blogs/14-for-14-shortcuts-for-quick-script-step-entry/</link>
			<description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;One of the coolest overhauls in FileMaker 14 is to the scripting area, now known as the Script Workspace. There are many cool new features here but the one we will focus on in this article is the ability to type script steps directly into a script. Further to this, we cover how FileMaker 14 attempts to auto-complete your entry to find the corresponding script step.&lt;/p&gt;
&lt;p&gt;With a little practice and habit, you can find the best shortcuts to use for every script step that will allow you to type either the shortest, or the most intuitive shortcut to find the specific script step you wish to add.&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;Please Download our Reference File Provided&lt;/h3&gt;
&lt;p&gt;There isn&#039;t really much to this article itself because the real benefit will come in downloading and viewing our associated reference file. In this file we have provided a number of shortcuts that can be used for &lt;strong&gt;every&lt;/strong&gt; script step.&lt;/p&gt;
&lt;p&gt;We provide what we believe to be the most intuitive shortcut you can use to auto-complete a script step. We also give you the shortest shortcut (in terms of characters required) to enter any script step.  Finally, we give any useful variations on these that can also be used.&lt;/p&gt;
&lt;p&gt;We hope this provides a useful resource for you starting out with FileMaker 14 and ease some of the burden of discovering these shortcuts yourself :)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/14for14/14for14_ScriptShortcuts.zip&quot;&gt;You can click here to download the Reference file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Please Note: &lt;/strong&gt;While this particular reference file will work in FileMaker 13, it works (and looks) best in FileMaker 14!&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/f5a60086-dc20-4555-a144-d9a3bf2cd546.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;How does the Auto-Complete work?&lt;/h3&gt;
&lt;p&gt;FileMakers auto-complete for script steps follows a couple of rules that help determine which script step(s) it finds as matching results to what you type.&lt;/p&gt;
&lt;p&gt;If you are typing a word, then it will match any script steps that contain any word that begins with what you type.  For example if we enter &quot;insert&quot; into the script workspace we get:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/7854b47e-c4d3-4add-9033-9a9bca949124.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Every single script step with a word that begins with  &quot;insert&quot; is found.  Now this is quite a lot, and so trying to isolate a specific script step just with &quot;insert&quot; is not very useful, as it will require you to mouse/keyboard through the results.&lt;/p&gt;
&lt;p&gt;Ideally what we want is a word that is used in a script step that better identifies that step.  Let&#039;s say we wanted to find the &quot;Insert from Device&quot; step.   Let&#039;s try the word &quot;from&quot;:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/5b502c52-1eda-4683-a605-3c08310541ce.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Better, but not perfect.  The next logical choice is to enter &quot;Device&quot;:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/623a6419-0b0a-448e-9da7-cf4639914cd5.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Bingo! That is exactly what we are after - a single result. We can now just press return to auto-complete.  You will find there are a large number of script steps that have an &quot;intuitive&quot; word in them that only exists in one script step, and can be used to isolate that step.&lt;/p&gt;
&lt;p&gt;What about script steps that are more common?  How about the classic &quot;set field&quot; ?&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/42f3492d-4d91-46ab-a4b0-b4bd7a4cf96e.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Ah, we have a problem here. There are a lot of script steps with the word &quot;set&quot; in it.  Now, we can just continue typing &quot;set field&quot; and that will find our result, but can we type something else even quicker?  How about just &quot;field&quot;?&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/b48ebe85-3497-4bc5-a017-104bd3c66e8a.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Ah, well that is actually worse!  What has happened here is all matches for the word &quot;field&quot; are shown, but the sort order here is interesting.&lt;/p&gt;
&lt;p&gt;FileMaker will sort the results alphabetically starting from the first word, moving onto the second word, and so on.  Export Field Contents is the first matching step that is first alphabetically, and so is the first result.&lt;/p&gt;
&lt;p&gt;You will find that this sort order is both helpful and a hinderance depending on what script step you are trying to auto-complete, which makes it even more important to know how to best find the step you are after.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Auto-Completing using the First letter&lt;/h3&gt;
&lt;p&gt;So far we have covered searching using keywords, and how FileMaker orders matching results. For most steps, simply entering an intuitive word, or typing enough of the step so that it is the only match is enough to find the right match.&lt;/p&gt;
&lt;p&gt;There are some however that are a little trickier given their use of common words, or their length.  There is another way we can find results using the &lt;strong&gt;first letter &lt;/strong&gt;of script step words.&lt;/p&gt;
&lt;p&gt;lets use the classic &quot;Go to Related Record&quot; as an example.  Using our methods so far, we could find this step using the word &quot;Related&quot; because this is the only step with this full word in it.  &lt;/p&gt;
&lt;p&gt;However quite often people know this step as its abbreviation &quot;GTRR&quot;. We can actually type this to find the step also as this follows the rule of using the first letter of script step words.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/ca4df580-d0fd-4c95-b233-9932d949bf5f.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Something interesting has happened here! It has found the right script step, but we are also seeing &quot;Go to Record/Request/Page&quot; also, why?  Well if we follow the rule, both script steps actually have words that begin with the letters &quot;GTRR&quot; in that order.  If we followed the rule even further we could use &quot;GTRRP&quot; to find just the first step.  Now, there are actually easier ways to find that step but the first letter rule can also be applied here (or to any script step).&lt;/p&gt;
&lt;p&gt;Sometimes this first letter rule works nicely, other times it does not.  There are a couple of things to note about using the first letters:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;It works in order of the step. So &quot;RRTG&quot; will not find the Go to Related Record step.&lt;/li&gt;
&lt;li&gt;If multiple matches are found for an abbreviation, the alphabetical rule applies&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Below is an example of the alphabetical rule being applied:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/f199c646-c25f-4be6-9dd7-9bf20178d146.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;All three steps have words that begin with G, T and R in that order. Note however that &quot;Go to Portal Row&quot; is the first match. This is because if we view them alphabetically the word &quot;Portal&quot; comes before &quot;Record&quot; and &quot;Related&quot;.  This seems odd that GTR would find this result, but based on the rules it is correct.  A better abbreviation to use to find this step would be &quot;GTP&quot;.  It matches all of our rules, and there is only one script step whose words begin with G, T and P in that order.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Reference File&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/14for14/14for14_ScriptShortcuts.zip&quot;&gt;You can download the reference file here&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Thu, 21 May 2015 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/14-for-14-shortcuts-for-quick-script-step-entry/</guid>
		</item>
		
		<item>
			<title>14 for 14: Working with the Script Workspace</title>
			<link>https://www.teamdf.com/blogs/14-for-14-working-with-the-script-workspace/</link>
			<description>&lt;h3&gt;What the Script Workspace looks like&lt;/h3&gt;
&lt;p&gt;Below is our reference image of the script workspace that we will use in the article, just click on it to enlarge.&lt;/p&gt;
&lt;p&gt;&lt;a style=&quot;font-size: 1em; background-color: #fafafa;&quot; href=&quot;http://www.teamdf.com/assets/blog/images/original/2f29bef2-1408-44ad-94ec-a29e87b410d7.png&quot; target=&quot;_blank&quot;&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/2f29bef2-1408-44ad-94ec-a29e87b410d7.png&quot; alt=&quot;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;1. Running a Script&lt;/h3&gt;
&lt;p&gt;These two buttons allow you to either run the selected script directly, or to run the selected script in the debugger. Being able to run direct in debugger is a great new feature and saves you having to open and close the debugger while working on a script.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/0cb390f7-e685-482d-a576-ab682d426d6c.png&quot; alt=&quot;&quot;&gt; &lt;/p&gt;
&lt;p&gt;The + button is for creating a new script. The new script is placed underneath the selected script (if any) otherwise it is placed at the bottom of the list of scripts.&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;2. Working with the Scripts Menu&lt;/h3&gt;
&lt;p&gt;The script workspace is divided into three main sections. The first we will deal with is called the Scripts Menu and this always appears as the left-most section.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/28e90fd3-bdea-4ee8-9cf8-330f21f6522c.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The first button is for showing/hiding the &quot;Show in Scripts Menu&quot; checkbox. When ticked, a script appears in the scripts menu. This button is not for setting this checkbox, merely to show or hide it.&lt;/p&gt;
&lt;p&gt;The next icon is for creating a script folder.&lt;/p&gt;
&lt;p&gt;The last icon is for adding a separator. In the Script workspace, separators are no longer blank scripts, they are actual separators.&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;3. Script Search&lt;/h3&gt;
&lt;p&gt;This is for locating a specific script or scripts in your list. The search works in the same way as previous versions - it will search from any point in the script name but only sequentially. In the screenshot above we have scripts named Script A through Script D.&lt;/p&gt;
&lt;p&gt;A search for &quot;Script&quot; will find all scripts. A search for &quot;Script A&quot; only finds that script.  A search for &quot;ript A&quot; will also find this script.&lt;/p&gt;
&lt;p&gt;It is important to note this search differs from the way the script workspace and data viewer now carries out auto-complete on your text, you can learn more about these in other 14 for 14 articles&lt;/p&gt;
&lt;p&gt;Folders are also shown in search results for the matching script.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;4. Script List&lt;/h3&gt;
&lt;p&gt;The list of scripts will show folders and script names. We have already covered the show in scripts menu checkbox.&lt;/p&gt;
&lt;p&gt;There are two other icons that can appear beside a script:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/16d91d39-0113-4797-831d-8890816f7a98.png&quot; alt=&quot;&quot;&gt; This icon indicates the script is run with full access privileges&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/a9c9421c-46a1-49a2-935d-32374fabae6b.png&quot; alt=&quot;&quot;&gt; This icon indicates the script is in an unsaved state.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;5. Open Scripts&lt;/h3&gt;
&lt;p&gt;There is more to this one than meets the eye. The script workspace now has tabbed scripting meaning no longer will you have separate windows for open scripts.&lt;/p&gt;
&lt;p&gt;Now, there are some interesting things to note about how the tabs work.  To demonstrate this lets start with no scripts selected:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/3f057426-a0e9-40e5-8c57-312423a519a5.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Without a script chosen we get a nice icon of a script, how lovely.&lt;/p&gt;
&lt;p&gt;Now lets &lt;strong&gt;single click &lt;/strong&gt;on a script. Note here single as opposed to double click.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;font-size: 1em; display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/f546d3de-3269-4385-9aa8-b3913d8e6fe8.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;When a single script is chosen using a single left-mouse click you&#039;ll notice the script name appears in blue text.  The blue indicates that this script is the &quot;active&quot; script, and the one that we shall call &quot;unlocked&quot;.&lt;/p&gt;
&lt;p&gt;If you now click through other scripts using a single click, this will change the active unlocked script to the one you choose. The end result is only one script tab open at any given time.&lt;/p&gt;
&lt;p&gt;Now lets go back to nothing selected and this time we will &lt;strong&gt;double click &lt;/strong&gt;the same script:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/0f4d84dd-3e4e-4ef0-bf71-70d903cb4683.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The script tab is now entirely filled blue as opposed to the text blue.  A blue tab indicates the active tab. In this case because we double-clicked Script C it is now locked into its own tab. If we now select another script, we will open that in a new tab, with Script C now locked into its own tab:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/3acdb917-504f-4149-aa0a-7443016b6dc2.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Script B is now the active tab, but because we single-clicked script B to open, it is not locked to its own tab, and choosing another script will replace Script B with the new script.&lt;/p&gt;
&lt;p&gt;This will be an important distinction to learn. In situations where you want to keep a script open in the workspace remember to double-click. If you do not need it locked single-click instead.&lt;/p&gt;
&lt;p&gt;You can also still open scripts in their own standalone windows if you need to. This is not a shortcut feature, nor is there a button for it. You can access this via the contextual menu or the View menu while in the script workspace:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/910da3a7-9c84-495d-acbf-a4e5a7605d00.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Note also the feature to select scripts in the scripts pane. This is useful if you have lost your context in the scripts list, for example if you have searched for another script in the mean time.&lt;/p&gt;
&lt;p&gt;You can directly edit a scripts name by double-clicking its open tab:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/9c5dff31-1ab0-4496-af7d-3d521b3f5b9e.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;6. Scripting Area&lt;/h3&gt;
&lt;p&gt;This is where the core of your scripting occurs. There are a number of great features here to help you write scripts fast.&lt;/p&gt;
&lt;p&gt;One of these is auto-completion of script steps you type. This is covered in a separate 14 for 14 article where we give you all the shortcuts you can enter to enter specific script steps.&lt;/p&gt;
&lt;p&gt;One thing you may notice first is there is some colour now to scripts. Colour can be defined for the following:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/d535ba99-e3e6-42b7-9ffb-ed3da35df9aa.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The above menu is accessible via the View -&amp;gt; Syntax Coloring... menu.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/aa3d2cbb-4920-4cfc-9217-997fce6550dc.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This script step has been disabled, but how do we disable steps? In FileMaker 13 there used to be a big disable button at the bottom of the script, but this is now gone.&lt;/p&gt;
&lt;p&gt;The answer is to use a shortcut key, this is by far the quickest way. On a mac the shortcut is cmd+/ ,  on windows this is ctrl+/ .  You can use this to toggle enabled/disabled.  The option is also available via the Edit menu.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/deeec392-6ee6-4d6a-87c8-1af326494392.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A blue line indicates that line is selected. How might we go about inserting a blank line into a script? In the example above lets say we want to put a blank line between these two steps.&lt;/p&gt;
&lt;p&gt;The answer is simply the return key.... with a couple of gotchas to look out for.  A script step may be selected such as above, but there is a difference between a selected line, and an active script step.  When no step is active, the return key will create a blank line.&lt;/p&gt;
&lt;p&gt;We can now also define whether to insert a blank line below or above the selected line. Hold the shift key with return to insert a line above the selected line.&lt;/p&gt;
&lt;p&gt;Back to active steps. How can we tell if a script step is active? The surefire giveaway for most steps is either the settings cog icon appears blue, or any part of the line appears in a blue outline:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/9eb0316f-5129-4a6b-948d-70974e616084.png&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/fe6c978e-539e-407e-bfe9-f7a902df3c4c.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Both of the above steps are considered active. For active script steps the return key does not create a blank line but has the action of activating the step. This normally means either toggling a setting, opening the script step setup, opening a popup menu, or directly entering the step for data entry as is the case with an IF script step.&lt;/p&gt;
&lt;p&gt;Initially this may cause the greatest source of frustration for you when trying to work with scripts. More often than not once you finish setting up a script step your next action is to insert a blank line, however your script step may still be active in which case you will go back into its settings.&lt;/p&gt;
&lt;p&gt;There are two ways to resolve this issue.  The first is to use  the command modifier key with return (ctrl on windows). By using cmd+return, this will always insert a blank line beneath your active script step.&lt;/p&gt;
&lt;p&gt;Another way we have uncovered during development is to simply save your script using cmd+S.  Saving a script will deactivate any active line.&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h4&gt;Working with Script Step Settings&lt;/h4&gt;
&lt;p&gt;Once you have an active script step, return generally will open its settings in whatever form that may take. For control steps such as IF and LOOP it will depend on what is visually the active element of the step:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/351c008a-4868-402a-8bed-0a4f1a802d54.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;These steps have two possible active elements - the direct data entry component, or the Fx button which will open the calculation engine. The great thing about this script step in 14 is you can directly enter the code for a basic IF statement without the need to enter the calculation engine.  The tab or arrow keys can be used to toggle between the active areas of the step, and the return or space bar will activate that area.&lt;/p&gt;
&lt;p&gt;We won&#039;t cover all variations on steps but suffice to say the vast majority of script steps will no longer require the user to reach for the mouse to setup which is great.  There are still some steps that are going to require you to reach for the mouse, such as Set Variable, or set field (if you need to specify via calculation) or the setup of a Custom Dialog. We think these will slowly become a thing of the past and in future everything will be mouse free.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h4&gt;Knowing when to use space bar versus return&lt;/h4&gt;
&lt;p&gt;Not all script steps work quite the same, and different steps have different amounts of settings. Sometimes you will find using the space bar to setup a step is much faster than return. We will use the common &quot;Set Field&quot; step as an example here.&lt;/p&gt;
&lt;p&gt;First thing we do is type &quot;set f&quot; followed by return to create the step:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/888c8aa8-43dc-41e5-8f22-343b54272910.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The step is selected, and the settings icon is activated. This means we can use the return or spacebar to open the settings:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/607f2b9d-c5e8-4883-a3dd-d5be62fc30c3.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;For all intents and purposes it looks like the &#039;specify target field&#039; option is selected. It is, but the return key will dismiss the settings popover we are looking at, which is not what we want.&lt;/p&gt;
&lt;p&gt;Instead, the spacebar more often than not will open the selected settings area, and from there we can setup the target field (albeit having to reach for the mouse most likely!)&lt;/p&gt;
&lt;h3&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/0fe525e9-abf4-44f7-9b22-be03d95b2a99.png&quot; alt=&quot;&quot;&gt;&lt;/h3&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Once we select the field, we are presented with the above. Now it looks like no setting is highlighted so what do we do?  Well, return key will dismiss the dialog so that&#039;s no good.  The spacebar does nothing because no setting is chosen.&lt;/p&gt;
&lt;p&gt;In this instance arrow keys become our most useful keys. A down arrow press will reselect the specify field option. Pressing down a second time selects the calculated result option, and then spacebar will open it.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/eadc8278-b1cf-40ca-ad84-e95a097c6a50.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;While it may seem odd, we guarantee you will get into the habit of using a combination of return, space and arrow keys to navigate these various steps with ease, it just takes a little practice!&lt;/p&gt;
&lt;p&gt;What about comments? Well in 14 a comment is still a script step, but it is very easy to add. simply enter a hash symbol to directly enter a comment. Alternatively a quick way is to use space+return in sequence. Space will initiate the drop-down of auto-complete steps. Comment is the first step in this list as shown below. Now just hit return to add that. Some may find this easier than reaching for the shift+3 shortcut.  (note that compatibility shows in auto-complete how nice!)&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/e5f0d125-9489-4594-a547-f040f5138730.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The final thing we&#039;ll mention about the script area are line numbers. &lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/93da731e-fde8-4a2f-b2b1-dd1d1c7fe145.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;While they serve no real scripting benefit, they are useful if you are referencing a specific point in a script to another developer or user.  Breakpoints can still be set by clicking on a line number as shown above.&lt;/p&gt;
&lt;p&gt;There is so much more to the scripting area but we will leave it up to you to explore!&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;7. Manage workspace and compatibility&lt;/h3&gt;
&lt;p&gt;The first of these three buttons is for nominating a specific compatibility platform:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/c4e41aa7-4ef0-419d-b876-f893557ac5c8.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Lets say we only want to show Server compatible steps:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/cf9dce85-3a5d-4a8e-92fa-e7a90e60107c.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Incompatible steps appear here in red in both the script itself, and the list of script steps. This colour is a customisable colour, but red is pretty clear !&lt;/p&gt;
&lt;p&gt;The other two icons are for expanding/collapsing both the scripts list, and the script step lists. We think that you&#039;ll actually end up never showing the list of script steps when you become more proficient at working with the new script workspace. Once you learn your favourite shortcuts for auto-completing script steps there really becomes no need to show a list of steps, and it can be hidden to free up more space for the script.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;8/9/10. Script Step List&lt;/h3&gt;
&lt;p&gt;If you do feel the need to list all of the script steps, there is a nice new feature that allows you to mark specific steps as your favourites. These appear in the top group of scripts so that they are readily available (Think Show custom Dialog!!)&lt;/p&gt;
&lt;p&gt;To add an item as a favorite, click the star icon with the step selected - and do the same to remove it from the favorite list.&lt;/p&gt;
&lt;p&gt;The a/z icon is for showing the script steps as a full list alphabetically as opposed to grouped by category.&lt;/p&gt;
&lt;p&gt;If not sorting alphabetically the grouped option is really much better now as you can collapse groups that aren&#039;t frequently used to keep your list of steps shorter.&lt;/p&gt;
&lt;p&gt;Script steps can also be right-clicked to reveal the following contextual menu:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/cf72fb31-65d3-4b1a-a095-89463192ac5f.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A useful option here is to look up the step in documentation, useful for beginners (or developers who have forgotten a thing or two!)&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;11. Selected Step Information&lt;/h3&gt;
&lt;p&gt;Another good feature for beginners. This panel displays some information about what the selected script step does. You can also click the little question mark icon to go to the documentation for that step.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/4ff076f6-67d9-4654-9808-338b84d5738e.png&quot; alt=&quot;&quot;&gt;    &lt;/p&gt;
&lt;h3&gt;Contextual Menus and Script Menus&lt;/h3&gt;
&lt;p&gt; It is worth also exploring contextual menus and the script menus for additional options and shortcuts. There are a number of contextual menus in the script workspace.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/a898a0d9-4be6-4f9f-8ff6-a8b11c1de016.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The folder contextual menu has options that are normally achieved through shortcuts, however we think the Print option is pretty cool. this will print all scripts within that folder. This has been a useful tool in the past if you need to locate a given item in a script. Print the scripts to PDF and then search the PDF for what you want.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/3ca111d5-c1f1-4296-add4-74401759ed4a.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Most of the items in the script contextual menu are again fairly straightforward but you&#039;ll notice here you can choose to open a script in a new window. This is not a shortcut feature so you will have to use the contextual menu on either the script, scripts open tab, or the View menu.  Note that a script in its own window does not have the scripts list:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/851b6e6e-2a31-4dca-be63-8f10ddce0c5d.png&quot; alt=&quot;&quot;&gt;The edit menu in the script workspace has all the usual suspects, but just take note that this is where the disable/enable script step option and shortcut lives:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/f0f1ff22-21ea-4953-b423-320f8acd457d.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The view menu contains the syntax coloring option which is not accessible from anywhere else, and has no shortcut attached.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/cf2737ce-b324-40d6-9d89-cf51861a6705.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Note the different shortcuts for closing items. We don&#039;t think closing all tabs will be used much as holding down the close tab shortcut for a second or two seems to do the same job.  It will be important though to distinguish between closing a tab and closing the workspace. In FileMaker 13 we only had the ability to close a script - there was no workspace.  Now you&#039;ll need to learn to hold shift to close the whole workspace.&lt;/p&gt;
&lt;p&gt;It is also interesting to note that if you close the workspace with scripts open, those scripts will remain open once you reopen the workspace, a really nice feature. Even cooler is that this persists even after the file is closed for files both local and hosted!&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/f65c1ba8-2709-44ee-aa87-fcacff92da52.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The scripts menu has all the usual suspects. Ones to note are the shortcut for opening a script directly into a new window when selected.  If you have a script open in a tab, then using the &quot;Open Script in New Tab&quot; has the effect of locking that script tab open.&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;In Conclusion...&lt;/h3&gt;
&lt;p&gt;The script workspace is awesome, embrace it and love it!!!!!&lt;/p&gt;</description>
			<pubDate>Tue, 19 May 2015 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/14-for-14-working-with-the-script-workspace/</guid>
		</item>
		
		<item>
			<title>14 for 14: The Power of the Placeholder</title>
			<link>https://www.teamdf.com/blogs/14-for-14-the-power-of-the-placeholder/</link>
			<description>&lt;h3&gt;What is a placeholder label?&lt;/h3&gt;
&lt;p&gt;Sometimes also called an in-line label, a placeholder is a field label that appears inside a field when that field has no value. For the rest of the article to make things less confusing we&#039;ll call it a placeholder label.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/311e1c53-f628-4ef7-9dba-aa882eb3bc24.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A placeholder label is a valuable UI tool. Firstly, it frees up space on your layout by having the label occupy the same space as the field. Secondly, there are some fields which don&#039;t constitute the need for a label to be visible at all times. Consider an e-mail address.  When a valid e-mail is entered into the field, it is obvious to almost everyone what that data represents, so to tell users that it is an e-mail address is somewhat redundant. Using a placeholder label for this field will free up space otherwise occupied by an unnecessary label.&lt;/p&gt;
&lt;p&gt;Sometimes placeholder text can help further describe a field in addition to a label that is always visible. Lets take a date field on a layout labelled &quot;last contact&quot; :&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/5b5c1f14-15ff-4aec-bf7e-d53ead0cdfbc.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This field is to have a date entered for the last time the customer in question was last contacted by the individual.  Simply taking &quot;last contact&quot; alone is not enough information to know what should go into the field. Is it the last contact who worked for the customer? Is it the name of the last person who someone spoke to? Or does (as in this case) contact refers to a date communication was made?  Sometimes a placeholder label can supplement the primary label to give additional information as to what should be entered in the field. Once the information is entered, the primary label is sufficient to describe the value.&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;FileMaker 14 Makes them so much easier&lt;/h3&gt;
&lt;p&gt;Prior to native placeholder text in FileMaker 14, placeholder labels were possible, but nowhere near as easy to implement, nor did they function in such a nice way.  The standard way to do a placeholder label was to overlay a text label on top of a field, and either conditionally format it (pre FileMaker 13) or hide it (in FileMaker 13) when the underlying field was not empty.  This method suffered from a couple of problems. First of all the label would disappear as soon as the user clicked into the field.  If you were able to resolve that issue through some transparency trickery, then the next issue was the label would not disappear as you began typing (again this could be resolved through script triggers), but what a hassle!&lt;/p&gt;
&lt;p&gt;In FileMaker 14 it is so simple. Placeholder text is defined as part of the layout object, and can be specified on the Data tab of inspector:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 249px;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/da5c0990-3034-4028-b94c-25a8473a9c34.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The text appears in browse mode (and find mode if you use the checkbox option) when the associated field is empty.&lt;/p&gt;
&lt;p&gt;You also have full styling control over the placeholder text via the appearance tab:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 369px;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/f07b82f8-cba2-4330-92ac-bebff09ec646.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can even reveal the placeholder text while working in layout mode by placing your mouse over the new placeholder badge on the layout object (note this actually now works in 14 for all types of layout/object badges, try it!):&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 288px;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/a16189f1-1f77-4e93-b3c9-715559ca831b.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;An awesome secondary usage - a layout calculation display engine!&lt;/h3&gt;
&lt;p&gt;You may have noticed above the little edit icon next to where you define the placeholder text. This will open the calculation dialog allowing you to specify the text to be whatever you want. &lt;/p&gt;
&lt;p&gt;Boiling all this down to its core - you can define text to display in a field via calculation. What if that text was not necessarily a label, but instead a summary value, a text display, a warning, an error check, and so on?  Why not use placeholder text as a means to display calculated values direct on a layout?&lt;/p&gt;
&lt;p&gt;Why not indeed!&lt;/p&gt;
&lt;p&gt;To do this all you need is a global field that is non-enterable and will never have a value. In this state, placeholder text will always display. Then simply define your text using the calculation, and format it how you want using the styling options, it&#039;s just that simple! Style the field itself to be visually hidden to replicate a calculated piece of text.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Why would you want to do this, what&#039;s wrong with calculation fields?&lt;/h3&gt;
&lt;p&gt;Nothing is really wrong with a calculated field to achieve this, and it will still work in FileMaker 14. There are however a number of benefits to your solution for using this method:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Fewer UI related calc fields in your schema, keep your tables for data only&lt;/li&gt;
&lt;li&gt;Keep display where it belongs, on layouts&lt;/li&gt;
&lt;li&gt;works great with executeSQL and portals, define placeholder within portal contexts&lt;/li&gt;
&lt;li&gt;Text formatting functions work great with it, alter colour of your display within the calculation&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Overall we see the biggest benefit is simplifying your tables and removing UI related fields and relationships.  Just be careful of overusing this when it comes to FileMaker WebDirect solutions!&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;To accompany this article we have produced a lovely demonstration file to give you some ideas as to how you can use placeholder text and how it can be setup. &lt;/p&gt;
&lt;p&gt;Please note that because this file is demonstrating a FileMaker 14 feature. While we have not restricted access to the file to FileMaker 14 only, if you try to open it in FileMaker 13 don&#039;t be surprised if you don&#039;t see much of any use :)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.teamdf.com/assets/files/weetbicks/14for14/14for14_PlaceholderEngine.zip&quot;&gt;Click here to download the demo file.&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Fri, 15 May 2015 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/14-for-14-the-power-of-the-placeholder/</guid>
		</item>
		
		<item>
			<title>Introducing the FileMaker Weetbicks 14 for 14 Series!</title>
			<link>https://www.teamdf.com/blogs/introducing-the-filemaker-weetbicks-14-for-14-series/</link>
			<description>&lt;h3&gt;We&#039;re all about 14!&lt;/h3&gt;
&lt;p&gt;FileMaker 14 is here! To celebrate, FileMaker Weetbicks has written 14 articles all about FileMaker 14. Over the next few weeks we will be releasing these articles to the community. We cover all the cool new features (and some hacks!) and take things further as we usually like to do :) Stay tuned!&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;A Sneak Peek at what we&#039;ll cover&lt;/h3&gt;
&lt;p&gt;14 articles means a lot of great content on a number of different topics, some examples of what you can expect:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Button bars and what you can do with them&lt;/li&gt;
&lt;li&gt;Script Workspace and making the most of it&lt;/li&gt;
&lt;li&gt;Calculations and schema&lt;/li&gt;
&lt;li&gt;All the little hidden features you may miss&lt;/li&gt;
&lt;li&gt;All the cool new layout stuff and examples of putting it to good use&lt;/li&gt;
&lt;li&gt;Features that can be used for more than their original intended use ;)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;and more!  Keep checking back for new articles, or sign up with your e-mail address to receive notifications when new articles are released.&lt;/p&gt;
&lt;p&gt;A number of the articles also have sweet 14-ized demo files to go along with them that look great and are a handy compliment to the articles.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/8d8fdb9f-7468-428b-874b-aa5799fd6777.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3&gt;   &lt;/h3&gt;
&lt;h3&gt;14 is as cool as it sounds&lt;/h3&gt;
&lt;p&gt;We have loved writing these articles and playing with FileMaker 14 - it really is an awesome release chock full of awesome new features to make development easier and more fun than ever before!&lt;/p&gt;
&lt;p&gt;.... I&#039;m just glad I decided on 14 for 14 instead of 30 for 30 years of FileMaker!&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/71b49507-3280-415b-bea1-0cae1a96b39b.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;(by the way this counts as #1, nya nya!)&lt;/p&gt;</description>
			<pubDate>Wed, 13 May 2015 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/introducing-the-filemaker-weetbicks-14-for-14-series/</guid>
		</item>
		
		<item>
			<title>FileMaker 14</title>
			<link>https://www.teamdf.com/blogs/filemaker-14/</link>
			<description>&lt;p&gt;We are pleased to announce that FileMaker have today released version 14 of their software for desktop and iOS.&lt;/p&gt;
&lt;p&gt;We are all incredibly excited by this release. It brings some new features that the developers have wanted/needed and we can see areas where we can further enhance your solutions. FileMaker WebDirect and FileMaker Go make some big leaps forward and both products are starting to ‘mature’ really nicely.&lt;/p&gt;
&lt;p&gt;For all the good stuff in it this is a major change so we recommend you &lt;span style=&quot;text-decoration: underline;&quot;&gt;don’t upgrade&lt;/span&gt; just yet.&lt;/p&gt;
&lt;p&gt;As there are a number of system requirements that surround the upgrade, we believe it is best to wait and we will give you some more details in the next week or so.&lt;/p&gt;
&lt;p&gt;In terms of showing off some of the new features, our own Daniel Wood has written 14 blog posts that will be released over the coming weeks. These get into the real specifics around FileMaker 14 features, so if you have a technical bent, it would pay to regularly check back on Daniels blog at &lt;a href=&quot;http://www.weetbicks.com&quot;&gt;http://www.weetbicks.com &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For those who want an idea of what to expect, here’s a bit on each of the different FileMaker 14 platforms:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FileMaker Pro&lt;/strong&gt;&lt;br&gt;The flagship desktop product has a raft of new design and user interface tools that makes it easier than ever to create even more beautiful solutions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FileMaker WebDirect&lt;/strong&gt;&lt;br&gt;FileMaker’s WebDirect technology for web based deployment has been vastly improved in terms of performance and support. It now supports mobile browsers on tablet devices such as the iPad and Samsung Galaxy, and other Android based tablets. FileMaker have invested a lot in this method of deployment so you should check it out and see whether it is right for you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FileMaker Go for iOS&lt;/strong&gt;&lt;br&gt;FileMaker Go has a number of great user interface and performance improvements. These new features such as improved touch controls and gestures will make databases feel even more like native iOS applications than ever before. Combine that with a number of user interface and usability improvements and the future looks bright for mobile deployments.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FileMaker Server&lt;/strong&gt;&lt;br&gt;FileMaker Server has had a security overhaul and it is now more secure than ever to host your solutions with FileMaker Server to keep your data safe and secure. If 100% uptime of your solutions is important to you then you’ll love FileMaker Servers new failover server feature that will allow you to switch to a backup standby server (with a little help from IT support!).&lt;/p&gt;
&lt;p&gt;As always we are here to support you with all things FileMaker so if you do have questions or need our assistance &lt;a href=&quot;http://www.teamdf.com/contact&quot;&gt;do get in touch&lt;/a&gt;.&lt;/p&gt;</description>
			<pubDate>Wed, 13 May 2015 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-14/</guid>
		</item>
		
		<item>
			<title>Change Containers from Files to Interactive Content in an Instant</title>
			<link>https://www.teamdf.com/blogs/change-containers-from-files-to-interactive-content-in-an-instant/</link>
			<description>&lt;h3&gt;File versus Interactive&lt;/h3&gt;
&lt;p&gt;If you are wondering what we are meaning when we talk about files and interactive content it is rather simple. There are two ways in which data can be stored in a container. The first is simply as a file. This is done using the &quot;Insert File&quot; option or script step (without interactive settings chosen).&lt;/p&gt;
&lt;p&gt;Items inserted into containers as files are unable to be used as interactive content, and they display as an icon and filename only.  In the past before FileMaker 12 this was the primary method of inserting items into containers, and when it comes to older solutions you will find most have files stored in this manner.&lt;/p&gt;
&lt;p&gt;FileMaker 12 introduced interactive containers - a means to make container data more &quot;interactive&quot; funnily enough. It gave the ability to scroll PDF documents, listen to and stream both audio and video direct from containers (and the server).  The problem with this new method of container display was that it did not play ball nicely with container data that was inserted as a file.  Interactive containers on layouts were unable to detect the type of file in a container whose contents was added as a file, and so contents could not be rendered interactively. Below is an example of what a container looks like with a file inserted.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/afb5581a-0599-4aec-b43a-76ef02557f63.png&quot; alt=&quot;What a container with a file in it looks like&quot;&gt;&lt;/p&gt;
&lt;h3&gt;How do we make use of Interactive Containers?&lt;/h3&gt;
&lt;p&gt;This dilemma arose primarily out of the fact interactive containers can nicely render PDF documents that can be scrolled, opened in preview, printed and saved.  We wanted to use this new feature, but all our existing client solutions prior to FileMaker 12 had their PDF documents inserted as files, and as such were not compatible with interactive containers.&lt;/p&gt;
&lt;p&gt;Our initial methods for making the fix were rather crude and involved writing scripts that would loop through records, exporting container contents to the temporary folder on disk, and then re-importing that back into the same container, albeit this time as a PDF, such that it could be displayed interactively.&lt;/p&gt;
&lt;p&gt;The process was tedious and time consuming, not to mention hard to setup for multiple containers on a large solution!&lt;/p&gt;
&lt;p&gt;    &lt;/p&gt;
&lt;h3&gt;Introduce Stephen the Bright Spark!&lt;/h3&gt;
&lt;p&gt;Recently our most experienced developer Stephen was musing over this very issue for one of his clients solutions that house literally thousands and thousands of PDF&#039;s, which by the way are all hosted on remote volumes.&lt;/p&gt;
&lt;p&gt;How could he display these PDF&#039;s as interactive content, without the hassle of exporting and re-importing? and then it hit him!&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/892a9dbb-553b-4ec5-b584-a526809ce1d3.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Actually, we&#039;re not quite sure how it hit him, but it&#039;s a little bit of luck, combined with a little stroke of genius, and he cracked it!&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Base64 Encoding and Decoding is the key!&lt;/h3&gt;
&lt;p&gt;Stephen tested and showed that if you use FileMaker 13&#039;s Base64Encode and Base64Decode functions, you can convert container data into interactive container data, here&#039;s how it works:&lt;/p&gt;
&lt;pre&gt;Base64Decode ( Base64Encode ( Container ) ; Filename )&lt;/pre&gt;
&lt;p&gt;That&#039;s it!  He realised that the encode function simply encodes data with no knowledge of its file type.  The decode function however requires you to specify a filename with extension. This is the key thing, decode function will turn the encoded text back into a file of the nominated stream depending on the extension you choose.  All you need to do is make sure the filename is the same as the original files name and you&#039;re all set!&lt;/p&gt;
&lt;p&gt;In fact if we look at the definition for Base64Decode we see:&lt;/p&gt;
&lt;pre&gt;Base64Decode ( text {; filenameWithExtension } )&lt;/pre&gt;
&lt;p&gt;It explicitly requires an extension for this very purpose.&lt;/p&gt;
&lt;h3&gt;   &lt;/h3&gt;
&lt;h3&gt;Putting it to use&lt;/h3&gt;
&lt;p&gt;There are a number of ways to make use of this. in Stephens case, he wanted to keep the files exactly as they were untouched so did not replace the container data. However he created an unstored calculation on the table with the container, and set it to the above function. He now had a calculation that can render the container as interactive content that he could use on layouts where needed.&lt;/p&gt;
&lt;p&gt;You can also write a very simple replace script that can update all container data in a single step.&lt;/p&gt;
&lt;p&gt;The example file attached below illustrates this. Here we have abstracted it all into a single custom function called &quot;Interactivate&quot; that is passed a container as a parameter. The output of this is the container data turned into interactive content.  Simply run this function over any container you want to update to interactive content.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;Please find attached an example file. This file is provided to help you fully understand what is going on in the rest of the article above. Note that FileMaker 13 is required to view this example file as it uses FileMaker 13 specific functions.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.teamdf.com/assets/files/weetbicks/interactivate/Interactivate.zip&quot; target=&quot;_blank&quot;&gt;Click here to Download the Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Tue, 21 Apr 2015 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/change-containers-from-files-to-interactive-content-in-an-instant/</guid>
		</item>
		
		<item>
			<title>Integrating FileMaker with Xero</title>
			<link>https://www.teamdf.com/blogs/integrating-filemaker-with-xero-2/</link>
			<description>&lt;p&gt;Xero remains the number one piece of software our clients want their FileMaker solution integrated with.&lt;/p&gt;
&lt;p&gt;This has been the case for nearly five years now, but what we are finding is that clients are keen to integrate FileMaker and Xero in different ways, and for different business reasons.&lt;/p&gt;
&lt;p&gt;Traditionally the request was to ‘push’ all invoicing (including invoice contact details) from a FileMaker solution through to Xero.&lt;/p&gt;
&lt;p&gt;Now clients are wanting more than just the invoice contact details pushed through, and they are keen for the information to flow both ways, from FileMaker to Xero and back again.&lt;/p&gt;
&lt;p&gt;To follow are some of the requests and work we have performed by using the Digital Fusion Xero plugin. We have also listed the business case as to why this is important:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Push of invoice and contact details from FileMaker to Xero&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As mentioned above, this is the most requested form of integration. Depending on how well your FileMaker solution is developed we can get this working reasonably quickly, but sometimes it does take additional work to make sure FileMaker is setup correctly.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Business use:&lt;/span&gt; Integrating FileMaker with Xero in this way allows for a seamless experience for your staff. They are able to raise invoices in FileMaker and all this information then flows through to your accounting package, in this case Xero. The integration works behind the scenes so once an invoice is finalised there is nothing more that is needed to be done.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Information moving both ways&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is becoming a more sought after requirement for integrations we perform. As above, invoice and contact information is pushed from FileMaker to Xero but in this case account updates are pulled back from Xero into FileMaker. This one has a few more things to take into consideration, the main one being how often the information needs to come back from Xero into FileMaker. Xero has a limit on the number of daily ‘calls’ that can be made to and from their software, so we can’t have an endless pull of information back from Xero to FileMaker (although we have some cunning ways to get around this)&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Business use:&lt;/span&gt; The big gain with a two way flow is that this allows all your staff to see how a client account is looking without having to give them access to Xero itself. Now sales staff can see if a client has their account up to to date, or they can now be the ‘prompter’ when discussing outstanding accounts with clients. Although Xero now offer ‘limited access’ to the software, having all this information in FileMaker makes for a seamless experience, with all client information contained within one solution.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Push all contacts through to Xero&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Typically we have only pushed contact information through to Xero when an invoice is raised. Xero then looks to see if the client already exists and if not, it adds it as a new client.&lt;/p&gt;
&lt;p&gt;Recently we have been asked to integrate all contacts that are in FileMaker with Xero. This can include contacts such as supplier, staff etc, essentially any contact that you believe will need a reference in Xero.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Business use:&lt;/span&gt; The big gains here are around reducing double handing, you know longer need to key in details in both solutions, increasing the overall accuracy of data.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;As you can tell from the above, there are a number of options to consider when integrating FileMaker with Xero. Each come with varying degrees of complexity but all are possible and becoming more the norm.&lt;/p&gt;
&lt;p&gt;We like to think of ourselves as the experts in integration with Xero so if you requirements match the above or differ in any way, &lt;a href=&quot;http://www.teamdf.com/contact&quot;&gt;please get in touch&lt;/a&gt; we would love to discuss your requirements.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/6ef5e9e3-f3c4-4acc-b14d-494e27d48eb1.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 18 Feb 2015 11:18:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/integrating-filemaker-with-xero-2/</guid>
		</item>
		
		<item>
			<title>What I&#039;ve learnt about FileMaker WebDirect</title>
			<link>https://www.teamdf.com/blogs/what-i-ve-learnt-about-filemaker-webdirect/</link>
			<description>&lt;p&gt;Okay I’m an account manager so please don’t hold your breathe for any technical wonderments in this article. What you will read is what we have experienced in terms of developing FileMaker WebDirect solutions.&lt;/p&gt;
&lt;p&gt;We have been lucky to work with two clients over the last few months where we have developed WebDirect solutions (we also have another three WD projects on the go).&lt;/p&gt;
&lt;p&gt;Both are very different, one we haven’t touched their main database, we have added a WebDirect element to the solution (in fact we have replaced the old Instant Web Publishing solution). The other is a new project, where we have developed a FileMaker Pro solution that can also be used via WebDirect.&lt;/p&gt;
&lt;p&gt;So what have we found:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;First up, get someone with WebDirect experience to develop you solution. The wealth of knowledge our team has built up over the past twelve months now makes us experts in how to tackle your development requirements. Along with this we have fantastic design skills, so it’s a seamless experience in terms of designing and developing for FileMaker WebDirect&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;If budget allows, use different design templates, and separate layouts (screens) for FileMaker Pro and WebDirect. Although you can ‘get by’ in using the same template for both, the user experience is not always ideal.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Be prepared to make refinements. WebDirect (particularly as we are only in version one) is not going to be perfect ‘out of the box’, there will need to be small tweaks made to get it to a tip top level of excellence.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Although WebDirect works in Firefox, it’s not a supported browser. We have discovered that it throws up the odd curly issue but on the whole the experience is not to bad, just not perfect&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;You need to install a custom SSL Certificate specific to your domain, otherwise your users will always have to authorise your browser to go to the domain name&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;WebDirect is not meant for the masses or the more intensive users of a solution, it’s a perfect solution for a discrete user group who don’t need the level of access that FileMaker Pro gives&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;There are some cool features we can now use, that were only previously available if you developed in native web. This includes being able to incorporate great design elements, plus the benefits of giving users a ‘web like’ user experience&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;It’s only going to get better. As we mention above, this is only version one (as part of FileMaker 13), with subsequent releases we have high hopes that FileMaker will continue to grow this product.&lt;/p&gt;
&lt;p&gt;So all up, we love WebDirect, it’s a great product and solution and something all of us at Digital Fusion are incredibly excited to develop in now.&lt;/p&gt;</description>
			<pubDate>Tue, 17 Feb 2015 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/what-i-ve-learnt-about-filemaker-webdirect/</guid>
		</item>
		
		<item>
			<title>FileMaker announces the end of support for FileMaker 11</title>
			<link>https://www.teamdf.com/blogs/filemaker-announces-the-end-of-support-for-filemaker-11/</link>
			<description>&lt;p&gt;At the end of last year FileMaker Inc announced the end of support for FileMaker 11 - that doesn&#039;t mean it will stop working, but it does mean they will no longer be doing updates such as bug fixes, compatibility and security patches.&lt;/p&gt;
&lt;p&gt;So maybe now is the time to make the leap?&lt;/p&gt;
&lt;p&gt;Moving up from FileMaker 11 is pretty simple despite the fact that under the hood the changes in FileMaker itself are huge. Databases convert very simply and quickly.&lt;/p&gt;
&lt;p&gt;The big change in FileMaker 12 was the layout &#039;engine&#039; - that is the underlying way that FileMaker draws screens and reports are changed - in fact it is now based on &lt;a href=&quot;http://en.wikipedia.org/wiki/Cascading_Style_Sheets&quot; target=&quot;_blank&quot;&gt;CSS&lt;/a&gt;, the same standardised technology that the web uses. As a result when you upgrade you might see one or two small rendering issues - some objects on layouts might appear slightly different in size or positioning - generally not a problem and easily fixed if need be.&lt;/p&gt;
&lt;p&gt;FileMaker 13 is the current version, and you can upgrade directly to it from 11 (or even earlier versions). FM13 builds upon the FileMaker 12 changes - it&#039;s faster and better again. It also adds some nice new user interface controls such as pop-overs and slides. They also added WebDirect in FM13 which provides a relatively quick way to make your database accessible in a web browser.&lt;/p&gt;
&lt;p&gt;The biggest downside to FileMaker 13 is the introduction of connection licenses - FileMaker Go and FileMaker WebDirect use these. You need to purchase concurrent licences for both, which essentially is how many people you think will be accessing the database at any given time i.e. you might have 100 users in total, but only 20 of these are expected to be accessing the database at one time, meaning you purchase 20 concurrent licences.&lt;/p&gt;
&lt;p&gt;On the plus side, FileMaker is getting faster over the internet and more web savvy with each version - this means FileMaker are staying current especially if you are using publishing to web or connecting over the internet i.e. cloud based hosting.&lt;/p&gt;
&lt;p&gt;As always, we at Digital Fusion always recommend using the annual licencing option given by FileMaker. The main reason behind this is the ability to upgrade free of charge to the latest version of FM.&lt;/p&gt;</description>
			<pubDate>Mon, 02 Feb 2015 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-announces-the-end-of-support-for-filemaker-11/</guid>
		</item>
		
		<item>
			<title>FileMaker to Xero Plugin</title>
			<link>https://www.teamdf.com/blogs/xero-plugin/</link>
			<description>&lt;p&gt;Bringing together our love of FileMaker and Xero (we are a &lt;a href=&quot;https://www.teamdf.com/about/xero-approved-developer&quot; target=&quot;_blank&quot;&gt;Xero approved developer&lt;/a&gt;) was always going to be a natural fit for Digital Fusion. We use Xero ourselves and when we come across clients using FileMaker and Xero we get excited—it&#039;s a brilliant combination for running a business.&lt;/p&gt;
&lt;p&gt;We are now at a point where we can say we are the experts in terms of custom integration for the two pieces of software, with a very robust plugin.&lt;/p&gt;
&lt;p&gt;We do need preface this by saying that no two client requirements are the same so although we do have a plugin, it’s not one that we can package up and sell as an ‘out of the box’ product. We do however offer this as a solution offering here at Digital Fusion so if you ever do want to discuss this please get in &lt;a href=&quot;https://www.teamdf.com/contact-us/&quot; target=&quot;_blank&quot;&gt;touch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This plugin fully automates processes so there&#039;s no importing or exporting. That means maximum efficiency and high integrity.&lt;/p&gt;
&lt;p&gt;What the plugin does offer is:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;It’s works on both Mac and Windows&lt;/li&gt;
&lt;li&gt;The ability to Push contacts, invoices and credit notes to Xero&lt;/li&gt;
&lt;li&gt;The ability to Pull contacts, invoices and credit notes from Xero&lt;/li&gt;
&lt;li&gt;Can be installed on either the FileMaker Pro client machine or your FileMaker Server, and is handled automatically.&lt;/li&gt;
&lt;li&gt;Supports Get and Post so we can develop features around any API endpoints that support these methods (Contacts, Products etc).&lt;/li&gt;
&lt;li&gt;It queues invoices for processing into Xero either instantly or at a later date/time.&lt;/li&gt;
&lt;li&gt;It works in both FileMaker 12 and 13. When using 13 you can leverage the Perform Script On Server command for instantaneous results.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;We have also had experience in pushing products, collecting payment information for invoices and pushing or pulling payments themselves. At the end of the day linking with Xero allows you to both synchonise transactions and pull out information for reporting.&lt;/p&gt;
&lt;p&gt;The plugin provides a simple framework that can be integrated with most FileMaker solutions and expanded to support any feature of Xero available through the API.&lt;/p&gt;
&lt;p&gt;As Xero release new features we will continue to explore opportunities for ways we can integrate these with FileMaker.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/97454f1f-63b4-4dd6-8a18-4c2aab1efef0.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Fri, 16 Jan 2015 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/xero-plugin/</guid>
		</item>
		
		<item>
			<title>Unlocking Hidden Error Messages in the ExecuteSQL Function</title>
			<link>https://www.teamdf.com/blogs/unlocking-hidden-error-messages-in-the-executesql-function/</link>
			<description>&lt;h3&gt;EDIT - Simpsons did it!&lt;/h3&gt;
&lt;p&gt;Well not quite the Simpsons, but maybe you get the cultural reference. Turns out this technique has been referred to previously on the custom function site &lt;a href=&quot;http://www.fmfunctions.com/fid/335&quot; target=&quot;_blank&quot;&gt;fmfunctions.com here&lt;/a&gt;. Thank you to readers for pointing it out, and Andries Heylen for submitting the function!  That is not to say the rest of the article is not interesting, so please carry on reading :)&lt;/p&gt;
&lt;h4&gt; &lt;/h4&gt;
&lt;h4&gt;A Simple ExecuteSQL Query as Illustration&lt;/h4&gt;
&lt;p&gt;Below we have a very simple query using ExecuteSQl. This query is asking for the field &lt;em&gt;Tasman_URL &lt;/em&gt;from a table occurrence named &lt;em&gt;zdev_Settings&lt;/em&gt;.  This table only has a single record, so we do not require a WHERE clause in the query. &lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/8ca30f08-1dc5-4e86-b6b7-9209af20c027.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can see, when we use the data viewer to evaluate the query, we are given the resulting field value as output, all pretty standard stuff.&lt;/p&gt;
&lt;p&gt;Next, lets break the query. To do this we are going to change the field name to &lt;em&gt;Tasman2_URL&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/e5b2a28f-ca73-439a-a222-cd901f295c8e.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Because this field does not exist, we have a syntax error in the query. Anytime there is an error in our query, FileMaker returns a solitary question mark as output. Oh how useful this is! The question mark tells us something is broken, but most of the time knowing what is broken is hard to track down, particularly in very large queries involving things like joins, where clauses, ordering, aliases etc.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Here&#039;s where things get interesting...&lt;/h3&gt;
&lt;p&gt;So recently I have been developing an internal solution and making more use of ExecuteSQL during development. While testing queries in the data viewer, I happened to enter a particular query in a &lt;em&gt;Let &lt;/em&gt;statement. The idea was that if &quot;?&quot; was returned, I wanted the result to be nothing instead of the question mark, eg:&lt;/p&gt;
&lt;pre&gt;IF ( Query = &quot;?&quot; ; &quot;&quot; ; Query )&lt;/pre&gt;
&lt;p&gt;When I put this into the data viewer and pressed &#039;Evaluate&#039; what I saw was quite interesting:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/110b9ae5-270e-4750-9dcc-9ca7b8d17b28.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Where did that come from!! The evaluated result of the calculation - which was meant to be nothing - instead was showing as a nice descriptive error message telling me exactly what was wrong in my query.&lt;/p&gt;
&lt;p&gt;When I went back into the data viewer calculation, the message was still showing. However as soon as I hit &quot;Evaluate&quot; it disappeared and the expected blank result was shown.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;So when does the message appear?&lt;/h3&gt;
&lt;p&gt;After (not so) extensive testing, I have been able to only reproduce showing the error message in the data viewer, after the &quot;Monitor&quot; button is pressed. Once you go back into the calculation the message remains, but using the &quot;Evaluate&quot; button will cause it to disappear.&lt;/p&gt;
&lt;p&gt;The error message does not appear to actually be a result of the calculation, as using the Let statement in scripts and other calculations never yields the message as a result, it appears confined just to the data viewer, which is actually quite a nice place for it to stay.&lt;/p&gt;
&lt;p&gt;You can actually get the messages to appear by simply returning blank:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/59622c2f-fb50-4760-9682-b939c3d48eab.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt; To make good use of it in practice I have created a simple custom function called &quot;SQL&quot; which simply takes the query as input, and outputs blank if the query yields a question mark (otherwise the query result is outputted).&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/d719ea4e-93e8-43b1-8366-03dc0d4155d8.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/0be62006-b211-442d-b732-3663923399e5.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;What types of error messages can it return?&lt;/h3&gt;
&lt;p&gt;Again I have not gone into huge testing here (hopefully the community reading this can do that ;) but I&#039;ve found a few messages it can return so far. After searching round the internet these may be standard SQL error messages, though not 100% sure on that.  Below are three examples of errors produced so far:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/58603fd5-1ed4-4cdf-b48e-873bc754810c.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/31fcd72a-a5d4-44f6-b7a5-9c500c97952f.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/74f7655a-836f-4aff-b3bf-8329a4d2cb70.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The first one results from an incorrectly named table occurrence. The second is an error in the query syntax - in this case I incorrectly spelt the keyword &#039;FROM&#039;.&lt;/p&gt;
&lt;p&gt;The last example is of a data type mismatch. In this example the field &#039;type&#039; is a text field, but we are comparing it to a number.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Further testing and discovery&lt;/h3&gt;
&lt;p&gt;I did some searching round the internet but was unable to find any references to this coming up in the community before. If anyone has come across this peculiarity before I&#039;d be keen to hear it. Also it would be good to know if there is an easier way to extract these messages, and whether they can be obtained by  means other than the data viewer. I look forward to hearing peoples results!&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;Sorry, I didn&#039;t think there was much worth in producing a demo file for this given it is so simply reproduced and FileMaker Pro Advanced is required for the data viewer.&lt;/p&gt;</description>
			<pubDate>Wed, 07 Jan 2015 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/unlocking-hidden-error-messages-in-the-executesql-function/</guid>
		</item>
		
		<item>
			<title>Designing and developing a &#039;Proof of Concept&#039; using FileMaker</title>
			<link>https://www.teamdf.com/blogs/designing-and-developing-a-proof-of-concept-using-filemaker/</link>
			<description>&lt;p&gt;Over the past twelve months we have been approached by a number of clients to develop a solution as a proof of concept. What a client deems a proof of concept can sometimes vary but in essence it’s to develop a solution as a ‘minimum viable product’&lt;/p&gt;
&lt;p&gt;Why would someone want to take this approach:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;For some it’s around reducing their risk, they invest at the lower end of the spectrum and then as the solution develops they can see whether it’s going to work out the way they expected.&lt;/li&gt;
&lt;li&gt;Another is to demonstrate different technology options. A number of clients approach us as they are not sure as to what platform will work out best in the long term. To develop a proof of concept in both allows then to assess things and then make the right decision.&lt;/li&gt;
&lt;li&gt;To demonstrate that a solution can be a viable resource. A prime example of this is a client that we have developed a FileMaker WebDirect solution for, they have now demonstrated to their peers that what they proposed is possible. Custom D will soon start developing them a web application that will replace the WebDirect solution, this can then be broadcasted to a far larger audience around the world.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;What we tell clients before they head down the POC path is that what we deliver won&#039;t be perfect and on the whole it will not be good enough for full client/public consumption. What they do get is a working model of their concept, enough for them to go away and decide whether it will be a viable option.&lt;/p&gt;
&lt;p&gt;A proof of concept frees the client up from feeling like they need to build out the whole system and therefore just focus on a implementing a key idea - it really helps people focus on true minimum viable product (MVP) unlike a ‘real’ project.&lt;/p&gt;
&lt;p&gt;To demonstrate what we mean, the donut below is your MVP. We could certainly add to it by sprinkling sugar on top, adding icing, but at it&#039;s core the donut is the proof of concept, once you have mastered that you are away.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 413px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/68b5b7aa-e8bc-4c66-b7cb-6b0d3d39ba5b.png&quot; alt=&quot;Proof of Concept&quot;&gt;&lt;/p&gt;
&lt;p&gt;On the whole we find clients that have gone down the proof of concept path come back for more. They generally see that what we have developed is something that will work in the business and they are keen to extend it further.&lt;/p&gt;
&lt;p&gt;So if you have an idea or thought around a solution you would like to see developed, do get in touch, we would love to discuss it with you.&lt;/p&gt;</description>
			<pubDate>Wed, 26 Nov 2014 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/designing-and-developing-a-proof-of-concept-using-filemaker/</guid>
		</item>
		
		<item>
			<title>Announcing Custom D - our new web company!</title>
			<link>https://www.teamdf.com/blogs/customd/</link>
			<description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I&#039;m absolutely thrilled to introduce &quot;Custom D&quot;, a new business that we&#039;re creating to focus on building more engaging web sites and applications.&lt;/p&gt;
&lt;p&gt;Custom D is a brand new business spun out from the web team at Digital Fusion - it&#039;s the logical way to get a clearer and more powerful message out there about extent of our capabilities and experience.&lt;/p&gt;
&lt;p&gt;Custom D inherits all the goodness of Digital Fusion and will focus on all things web. And the crew at Digital Fusion will now have a clearer mission — being one of the best FileMaker development teams on the planet.&lt;/p&gt;
&lt;p&gt;We’ll be sharing resources, knowledge and the coffee machine, working as closely together as ever. There will be plenty of combined projects that span FileMaker and web, and for the time being we&#039;ll keep things in one place for you through Tasman and our billing processes.&lt;/p&gt;
&lt;p&gt;Julie will be heading up the new company as Managing Director, with Sam as Technical Director, and Matthew taking charge of new business and looking after all our existing customers. The other members of the team are Tim, Robert, Phil, Josh, Glen and Cindy. While I won&#039;t personally be involved in the day to day running of Custom D, I&#039;ll still be a significant shareholder and a Director of the new company.&lt;/p&gt;
&lt;p&gt;It’s early days but the team are up and running in their mission to help you &#039;rock the boat&#039; in your industry or just do things better online. The new web site is online at &lt;a href=&quot;http://www.customd.com&quot; target=&quot;_blank&quot;&gt;www.customd.com&lt;/a&gt;, there are new contact numbers and you&#039;ll start to see communications from Custom D.&lt;/p&gt;
&lt;p&gt;Everyone here is excited about the change - Custom D has that &#039;start up air&#039; to it, but with the benefit of plenty of work on the books and a team that well and truly know what they&#039;re doing.&lt;/p&gt;
&lt;p&gt;For the most part it&#039;ll be business as usual, but drop us a line or give us a call if you&#039;ve got any questions...&lt;/p&gt;
&lt;p&gt;Cheers&lt;br&gt;Craig&lt;/p&gt;</description>
			<pubDate>Wed, 15 Oct 2014 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/customd/</guid>
		</item>
		
		<item>
			<title>Proper Printing in WebDirect [Updated]</title>
			<link>https://www.teamdf.com/blogs/proper-printing-in-webdirect-updated/</link>
			<description>&lt;h3&gt;[Update 26/9/14]&lt;/h3&gt;
&lt;p&gt;Thank you to some readers who pointed out a few bugs in the example file affecting windows users. The issue was in the &quot;RoboPrint - Process Print Jobs&quot; script. Interestingly, this script runs in the context of a popup window, and we were using a third off-screen window to carry out individual print jobs. When this off-screen window closed, the script focus was actually returned to the main window, not the popup which launched the off-screen window, a bug if ever I saw one! We have modified the example file to explicitly change context back to the RoboPrint popup once processing of print-jobs has been completed. You can download the revised example file at the bottom of this article.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;For those not familiar with WebDirect think of it as Instant Web Publishing enhanced. Whereas IWP was fairly static, the goal for WebDirect is to be more dynamic and responsive to user interaction. Most FileMaker Pro functionality is there in WebDirect and the overall experience can be made to feel very similar to FileMaker Pro. One of the key features it lacks though is the ability to print reports and this is quite an important feature if WebDirect is to be used as a substitute for FileMaker Pro as a deployment platform.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;The implications of no printing in WebDirect&lt;/h3&gt;
&lt;p&gt;Because the Print script step is unsupported in WebDirect, the only other way to print is through the browsers print function. This however is a very poor substitute as the browser will only print the &lt;em&gt;visible window contents. &lt;/em&gt;Any lists of records or any layout that cannot fit entirely in the visible window will not print. Without Preview mode we also have no ability for producing complex sub-summary reports or sliding of records. Basically, it just dun work!&lt;/p&gt;
&lt;p&gt;Side note: when we say printing in this article what we really mean is &lt;em&gt;preview mode&lt;/em&gt; and all that goes along with that (such as printing).&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Okay so it doesn&#039;t print, so what can it do?&lt;/h3&gt;
&lt;p&gt;One thing WebDirect does do quite well is displaying interactive container data. What has that got to do with anything you ask? Well, it means displaying a PDF within WebDirect is pretty nice, so if we could generate a report as a PDF and display that to the WebDirect user instead, then this should allow them to scroll through it, preview it, and subsequently print it via printing of the PDF.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; width: 95px; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/f952fc33-290e-4c57-8ed1-f2e24d46e492.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;How will we generate a PDF for the WebDirect user?&lt;/h3&gt;
&lt;p&gt;This is at the heart of the entire framework. Unfortunately FileMaker Server is unable to natively generate a PDF. The only two FileMaker platforms capable of generating a PDF is FileMaker Pro and FileMaker Go. Go is obviously not an option so lets use FileMaker Pro! What we need to do is have a copy of FileMaker Pro responsible for the PDF generation of WebDirect user initiated reports.&lt;/p&gt;
&lt;p&gt;This is not an uncommon technique and is something that sometimes is used when reports need to be e-mailed to users on a nightly basis. Because FileMaker Server cannot produce the PDF, we instead call on the help of a &lt;em&gt;&lt;strong&gt;Robot&lt;/strong&gt; &lt;/em&gt;copy of FileMaker Pro to do the effort of PDF generation. FileMaker Server can then attach and send the reports via a scheduled script or the copy of FileMaker Pro could just do this itself.&lt;/p&gt;
&lt;p&gt;We shall call this copy of FileMaker Pro from this point on &lt;strong&gt;RoboPrint&lt;/strong&gt; !&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; width: 118px; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/ec1684f3-d539-401f-84f2-a7f78191b046.png&quot; alt=&quot;RoboPrint&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;What is the basic framework outline?&lt;/h3&gt;
&lt;p&gt;In the framework we refer to the WebDirect user as &lt;strong&gt;RoboUser &lt;/strong&gt;and the robot copy of FileMaker Pro tasked with producing report PDFs as &lt;strong&gt;RoboPrint.&lt;/strong&gt; The basic process of events is as such:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;RoboUser&lt;/strong&gt; initiates a print job&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;strong&gt;RoboPrint&lt;/strong&gt; &lt;/strong&gt;is polling for new print jobs and detects the request from &lt;strong&gt;RoboUser&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;strong&gt;RoboPrint&lt;/strong&gt;&lt;/strong&gt; then runs the report on behalf of &lt;strong&gt;RoboUser&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The resulting report is saved as a PDF document onto the print job and marked as done.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RoboUser&lt;/strong&gt; now sees their report has been generated and is able to view the PDF.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;That is it in a nutshell. Now how this all actually works is a little more in-depth so we&#039;ll cover the process in a little more detail below and how this relates to the example framework file.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;... For those who just want to get stuck in and see how it works...&lt;/h3&gt;
&lt;p&gt;Technical jargon and explanations of how it all works are below, but if you want to just fire up the example file and see what it&#039;s all about then you will need to do a few things first:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Example file needs to be hosted on FileMaker Server (because WebDirect is FMS only).&lt;/li&gt;
&lt;li&gt;A copy of FileMaker Pro must be running the database logged in with username &lt;strong&gt;RoboPrint&lt;/strong&gt; (no password), and the RoboPrint procedure must be running by clicking the launch button.&lt;/li&gt;
&lt;li&gt;In WebDirect open the hosted database with username &lt;strong&gt;RoboUser&lt;/strong&gt;. You can then click on any of the 3 report buttons to test.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;If all goes well you should see the WebDirect RoboUser wait for the PDF to be generated. In FileMaker Pro you should see RoboPrint retrieve the print job, process it and mark it as done. Then back in WebDirect you&#039;ll see the resulting PDF displayed in an interactive container.&lt;/p&gt;
&lt;p&gt;You can also test as RoboUser in either FileMaker Pro or FileMaker Go - this does not require WebDirect to test with. If you do not have access to WebDirect then so long as you can access the database (shared) in 2 copies of FileMaker Pro you will be able to test the demo.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Still a work in progress&lt;/h3&gt;
&lt;p&gt;This framework at this stage is by no means perfect. It was built out of necessity for a large WebDirect deployment and has so far stood up to the test and been a reliable means of generating reports in WebDirect which is why we have turned it into an article :) &lt;/p&gt;
&lt;p&gt;There will always be improvements that can be made to the framework and the intention is that others in the community will take the general method and build upon it for others.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;Please find attached an example file. This file is provided to help you fully understand what is going on in the rest of the article below. Note that FileMaker 13 is required to view this example file.&lt;/p&gt;
&lt;p&gt;The example file is intended to be a demonstration of a framework. This is not a modular style implementation currently so to use in your own solution you would recreate the functionality found within the file.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.teamdf.com/assets/files/weetbicks/webprinting/WebPrinting.zip&quot;&gt;Click here to Download the Example File&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h1&gt;The geeky stuff on how it works&lt;/h1&gt;
&lt;h3&gt;   &lt;/h3&gt;
&lt;h3&gt;Still with us?&lt;/h3&gt;
&lt;p&gt;Good. You have made it through the first part of the article - congratulations! If you are still here then perhaps you have downloaded the example file and had a look and are curious as to the technicalities behind how it works. It&#039;s not that complicated really! Below we&#039;ll just cover the basics of the framework so you can feel confident if you need to implement into your own solutions or to make any adjustments or improvements. &lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;The idea of a print job&lt;/h3&gt;
&lt;p&gt;In the framework is the idea of a print job. Because RoboPrint runs in FileMaker Pro, and RoboUser can be on any platform, there needs to be a method of communication between them in order to convey the type of report RoboUser wants to run, and any criteria around running it. We do this by way of a table funnily enough also called RoboPrint (just to confuse you!).&lt;/p&gt;
&lt;p&gt;Each record in this table is an individual print job that is generated by a user for example lets say in WebDirect. The record contains a number of fields that will tell RoboPrint all the information it needs to generate the correct report. Most fields are self explanatory (you can check the comments on the fields for more info).&lt;/p&gt;
&lt;p&gt;When a WebDirect user runs a report the script that is run will generate one of these records, populate it with the required information, and sit back and wait until the record is marked as either complete or in the event something went wrong marked with an error.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;The request initiation script&lt;/h3&gt;
&lt;p&gt;When the WebDirect user wishes to run a report the generic script they run is called &lt;em&gt;&quot;Robouser - Initiate Print Job&quot;. &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/c0287de9-903d-4054-a2e1-a49da4792bbe.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We pass 3 key parameters:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Type is a keyword that will tell RoboPrint what type of report the user wishes to run&lt;/li&gt;
&lt;li&gt;Parameters is a text string of parameters that may be required to produce the correct report output.&lt;/li&gt;
&lt;li&gt;Timeout - this is a period - in seconds - which will be used for how long the WebDirect user will wait for the report output to be delivered. Default is 30 seconds.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The rest of the script will launch a new virtual web window and go to the RoboUser PDF layout. It creates a print job and then simply sits and waits until the process if finished, or expires.&lt;/p&gt;
&lt;p&gt;The nice thing about using a new window is that on WebDirect this acts as a &#039;virtual&#039; window which from the users perspective looks like they have gone to a different page entirely.  We can just use an onTimer at this point for the timeout.  The user can also click a &quot;Done&quot; button on this screen which will delete their print request and close the window - taking them back to their original layout.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Custom Functions for parameters&lt;/h3&gt;
&lt;p&gt;The framework makes use of 4 custom functions for managing multiple script parameters and results. It&#039;s not terribly important you know how they work, but it is important to know how to use them for script parameters.  &lt;/p&gt;
&lt;p&gt;To pass multiple parameters to a script we use the SetProperty function.  If you look at the initialisation script above it is taking three named parameters. We would pass these to the script in the following format:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/f5c49b8f-8e3b-4aaf-986e-fc403870a861.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The SetProperty function can be strung together with &amp;amp; to pass multiple named parameters.&lt;/p&gt;
&lt;p&gt;In the property called &quot;Parameters&quot; , we can nest further multiple parameters here if need be.&lt;/p&gt;
&lt;p&gt;The script uses the &lt;em&gt;GetScriptProperty &lt;/em&gt;function to parse out this data. This function is basically a helper function that calls the &lt;em&gt;GetProperty &lt;/em&gt;function, but will automatically pass through the Get(ScriptParameter) function, saving us having to do this bit.&lt;/p&gt;
&lt;p&gt;Finally, &lt;em&gt;GetResultProperty &lt;/em&gt;is exactly the same as &lt;em&gt;GetScriptProperty &lt;/em&gt;with the difference that it will automatically pass through Get(ScriptResult), so is useful for parsing multiple script results.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;RoboUser has sent a print request, what happens now?&lt;/h3&gt;
&lt;p&gt;RoboPrint should be initiated and running in a copy of FileMaker Pro. This is where print jobs are dealt with.  RoboPrint is launched using the script &lt;em&gt;RoboPrint - Initiate Process.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Again a fairly simple script. It takes one optional parameter called Duration. This tells RoboPrint how many seconds it should wait between checking for new print jobs. The default is 2 seconds.&lt;/p&gt;
&lt;p&gt;RoboPrint operates in a popup modal window which is completely locked down. We use a loop where processing occurs after the duration pause.  The loop carries on forever until the process is stopped.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/45bdf3da-598e-4cce-a5b7-b3f569f41200.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;At each check, the script &lt;em&gt;RoboPrint - Process Print Jobs &lt;/em&gt;is run.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Processing print jobs&lt;/h3&gt;
&lt;p&gt;This script is responsible for checking for new print jobs, and for any found making sure the correct report is run. It is also responsible for generation of the resulting PDF, and any tidyup after that.&lt;/p&gt;
&lt;p&gt;I won&#039;t go and post a big screenshot of the script here, you can check it out for yourself. The following are key points in the process flow of the script:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;It will immediately exit if it finds no new print jobs&lt;/li&gt;
&lt;li&gt;Two windows are utilised in processing of print jobs.  First is the main RoboPrint window which controls print job processing. The second is a helper window created off-screen. This special window is where the report itself is generated and the PDF is produced. The reason we use a second off-screen window is one of niceness. It ensures that the main RoboPrint window never changes context, and the dirty work of producing the report never gets seen.  The helper window is created and used for all print jobs being processed in this batch.&lt;/li&gt;
&lt;li&gt;RoboPrint must ensure it can get a record lock on a print job record before it will process it. The reason is that it ensures a user may not be in the act of creating or deleting their print job.&lt;/li&gt;
&lt;li&gt;The script will branch off and run a report-specific subscript whose responsibility is to correctly find the report records, set sort order, page setup etc.  At this point in the script the $Type variable passed as a parameter is utilised. &lt;strong&gt;This is the only part of this script that a developer will need to modify when new reports are added.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;At any point in the process if any errors occur, these are marked on the print job record and that job is then considered processed. The user will see that an error has occurred and the reason for the error.  Errors can be at the FileMaker level (eg could not produce PDF) or at the report level (user tried to run an invoice report but no invoices matched their criteria...)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Branching to run report specific subroutines&lt;/h3&gt;
&lt;p&gt;As mentioned above, there has to come a time in this process where a script is run for the specific reports, as each report is different.&lt;/p&gt;
&lt;p&gt;You can see this part of the script pictured below.  Each print job is tagged with a type keyword that is set into the local variable at the start of the script. Here is where you check the type and run your appropriate subroutine script, passing through the parameters that script will require.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/a6d544a8-7dd6-4df1-80a6-b76736f12c31.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Drinks Break!&lt;/h3&gt;
&lt;p&gt;&lt;img style=&quot;width: 277px; display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/735ba834-52d5-49b9-920a-c56bf5000761.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;How you should configure your report specific scripts&lt;/h3&gt;
&lt;p&gt;Okay back to it. There are a few rules that need to be followed when you setup your specific report scripts for use with RoboPrint.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Make sure there are no script steps that will pause the script, such as custom dialogs.&lt;/li&gt;
&lt;li&gt;Make sure error capture is on - we cannot have any FileMaker dialogs appearing here as RoboPrint ain&#039;t gonna dismiss them!&lt;/li&gt;
&lt;li&gt;In the event of an error, or a reason why the user can&#039;t run the report (e.g. no records, or no access) you should return a script result using the &lt;em&gt;Setproperty &lt;/em&gt;function with the property name &quot;Error&quot;. This will be set back onto the print job as an error that the user will be informed of.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Once done, your script just needs to exit without error. You needn&#039;t do anything regarding PDF generation, that is handled elsewhere, just finish!&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Production of the PDF&lt;/h3&gt;
&lt;p&gt;The Process Print Jobs script is responsible for calling another sub-script to produce the PDF once the users custom report script has been executed.  This script is called &quot;&lt;em&gt;RoboPrint - Produce PDF&lt;/em&gt;&quot;&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/a439a94a-2d76-4fb9-8007-b7dac85abc47.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The script again is pretty straightforward. We pass it the type of report simply for the purpose of the PDF filename.  By default the PDF filename is a combination of the current timestamp as a number, and the report type. This ensures a good chance of a unique PDF filename for the report.  You could change this here to whatever you wish the format to be for your solution.&lt;/p&gt;
&lt;p&gt;The script will either return an error if for some reason the PDF could not be saved or the path to that PDF on disk.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Finally...&lt;/h3&gt;
&lt;p&gt;The process print jobs scripts final task is to take that PDF path and insert the PDF into an interactive container on the print job.  Once it does this, the print job is marked as completed, and the script will go onto the next print job if there is one, otherwise it is done.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;The user has been waiting a while, what are they up to...&lt;/h3&gt;
&lt;p&gt;As soon as that PDF is inserted onto the print job, the user will see it magically appear in front of them&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/277c2f73-8954-4456-9fea-326306130ee5.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;They will be able to scroll through the PDF and depending upon the browser they are using they will se some PDF controls that will let them print, save, zoom etc..&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Print job statuses&lt;/h3&gt;
&lt;p&gt;We show the print jobs status both on the users screen, and in RoboPrint so that at all points of the process the user is kept notified of the status of their request. Statuses include &lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Waiting: Print job not yet picked up for processing by RoboPrint.&lt;/li&gt;
&lt;li&gt;In-Progress: RoboPrint has got the lock on the job and is now processing.&lt;/li&gt;
&lt;li&gt;Completed: RoboPrint has finished and put the PDF onto the print job.&lt;/li&gt;
&lt;li&gt;Error: Something went wrong. RoboPrint has put the error message onto the print job.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Some important information on SSL&lt;/h3&gt;
&lt;p&gt;Certain browsers such as Google Chrome and Firefox have security features that will mean you may notice some unusual behaviour when it comes to the PDF in the interactive content container. These browsers cannot display the content when secure connections to FileMaker Server (SSL) has been turned on within FileMaker Server. The reason is WebDirect will in this case use HTTPS protocol, however external container data will still use HTTP. In the event a secure site has insecure content within it, these browsers will flag it as such and prevent the content from displaying.&lt;/p&gt;
&lt;p&gt;What you will see instead is either the icon/filename for the file (which you can actually still right click and export to view) or you will see a link in some cases which you can click to view the PDF.&lt;/p&gt;
&lt;p&gt;While not ideal, there are possible ways around this but may involve accepting security dialogs when used first time.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://help.filemaker.com/app/answers/detail/a_id/12049/~/interactive-content-displays-as-link-in-filemaker-webdirect&quot; target=&quot;_blank&quot;&gt;This FileMaker knowledgebase article better documents the issue&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;Please find attached an example file. This file is provided to help you fully understand what is going on in the rest of the article above. Note that FileMaker 13 is required to view this example file.&lt;/p&gt;
&lt;p&gt;The example file is intended to be a demonstration of a framework. This is not a modular style implementation currently so to use in your own solution you would recreate the functionality found within the file.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.teamdf.com/assets/files/weetbicks/webprinting/WebPrinting.zip&quot;&gt;Click here to Download the Example File&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Fri, 15 Aug 2014 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/proper-printing-in-webdirect-updated/</guid>
		</item>
		
		<item>
			<title>Creating New Records in a Portal With a Twist</title>
			<link>https://www.teamdf.com/blogs/creating-new-records-in-a-portal-with-a-twist/</link>
			<description>&lt;h3&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;When it comes to creating child records records in FileMaker we have a couple of different options available. The first is to enable “Allow creation of records via this relationship” on the relationship graph. This displays an empty set of fields in the last portal row so that the user can enter data and create a record. The second method is to create a button located outside the portal that creates a new record ready for the user to enter their data.&lt;/p&gt;
&lt;p&gt;A new feature that we have been using extensively in FileMaker 13 is the ability to conditionally show and hide objects. In this article we will talk about combining the creation of records in a portal row and the conditionally showing and hiding of objects. This will allow us to create a nicer way for users to create records.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;How did this come about?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Recently we built an iPad solution for a local company; whose sales consultants do onsite visits measuring windows for new curtains and blinds. It’s not unusual for the consultants to measure a window that is much larger than the size of available tracks. The consultant can combine up to eight tracks to cover the required window.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 181px;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/dc9bf567-69a1-4bd4-bbd7-c9fbb3b2d5a6.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We had to come up with an elegant solution that would allow the consultants to specify the number of tracks to join and at what lengths. We also have limited real estate outside of the portal for an add button. What if we could have a button in the last row of the portal that allowed us to create records?&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;What was our solution to the problem?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Using a combination of showing / hiding objects and allowing creation of records through the relationship we can show an add button that appears only in the last row of the portal. Tapping on this will create a record for a length of track. Once we have reached our maximum of eight records the button no longer appears.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;How do we go about setting this up?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;First we setup the relationship that we will use for the portal, ensuring that “Allow creation of records in this table via this relationship” is ticked on the portals table occurrence. Next, we define the portal using the relationship that we just setup, adding the fields we want to display into the portal. At this stage the last row will show our fields and allow the user to enter into them to create records.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/5bec3357-9340-4455-b850-36a8a368aa31.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Hiding the contents of the last row&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;We can now specify a simple calculation to hide the contents of the last row. We select all the objects that we want to hide in the last row and specify the “Hide object when” calculation to be:&lt;/p&gt;
&lt;pre&gt;IsEmpty ( Tracks::Track ID )&lt;/pre&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;We could select any field that will have a value auto entered at record creation (eg a record ID). All objects in the last row of the portal with this hide condition defined will now be hidden.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Adding a button for creating a record&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;We can now add our button for creating records to the portal. We only have to make one small alteration to our calculation we used to hide the contents of the last row. Simply adding &lt;strong&gt;not&lt;/strong&gt; to the beginning of our calculation will have the desired effect. Our calculation now becomes:&lt;/p&gt;
&lt;pre&gt;not IsEmpty ( Tracks::Track ID )&lt;/pre&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/7e51ceec-c451-4258-9560-42968db6bc03.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Creating the record&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Creating the record is simply a case of attaching a script to our visible object. The script simply sets a value into the related field creating a record.&lt;/p&gt;
&lt;pre&gt;Set Field [Tracks::Interface ID; Interface::Interface ID]
Commit Records/Requests []&lt;/pre&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog/images/original/a1859d7c-221b-4fd8-823e-fd006658978c.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Limitations&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;This technique works nicely when you have a fixed number of child records. If you have a large number of child records your users will be continually scrolling to the bottom of the portal to create new records.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Taking this technique to the next level&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;You could use this technique to hide a delete button that would otherwise appear in the last row of the portal (a technique we have demonstrated in the example file). You could also show labels on the second to last row of the portal to aid users in entering the correct data into the fields.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;Please find attached an example file. This file is provided to help you fully understand what is going on in this article. Note that FileMaker 13 is required to view this example file.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/newrecordswithatwist/NewRecordsWithATwist.zip&quot; target=&quot;_blank&quot;&gt;Click here to download example file&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Thu, 24 Jul 2014 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/creating-new-records-in-a-portal-with-a-twist/</guid>
		</item>
		
		<item>
			<title>Popovers that Open and Close on Mouse-Over</title>
			<link>https://www.teamdf.com/blogs/popovers-that-open-and-close-on-mouse-over/</link>
			<description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.teamdf.com/weetbicks/228/a-sliding-drawer-that-opens-and-closes-on-mouse-over&quot; target=&quot;_blank&quot;&gt;In our last article&lt;/a&gt;, we introduced a generic technique that could be used to replicate a mouse-over effect. This used a combination of a custom function, script, plugin and tooltips to allow the user to expand and collapse a sliding drawer control without the need for a mouse-click.&lt;/p&gt;
&lt;p&gt;In this article we take the technique and modify it to be suited toward opening and closing the popover object upon mouse-over. Popovers are a new feature in FileMaker 13 and are like a balloon tooltip.  They are great for revealing additional information on a layout such as actions, information, checkboxes etc (just like a sliding drawer).&lt;/p&gt;
&lt;p&gt;If you have not read the the &lt;a href=&quot;http://www.teamdf.com/weetbicks/228/a-sliding-drawer-that-opens-and-closes-on-mouse-over&quot; target=&quot;_blank&quot;&gt;article on sliding drawers&lt;/a&gt;, it is recommended you check it out before reading this article, as we&#039;ll assume a knowledge of the technique for this article.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Differences between sliding drawers and popovers&lt;/h3&gt;
&lt;p&gt;In our sliding drawer article, we only dealt with a single sliding drawer on a single layout. The demo was not built for multi-window, multi-layout, or even multi-panel within the same layout. If a user wished to have two drawers on a given layout, then they would have had to replicate the required functionality for the second drawer, hardly efficient!&lt;/p&gt;
&lt;p&gt;Popovers fortunately are a little simpler.  FileMaker imposes a restriction on a layout that there can be only one open popover per layout per window.  The benefit for us is this makes tracking open/closed popovers much easier - we don&#039;t have to know which popovers are open or closed at any given time (because only one can be open) we just need to know which one is open on a given window.&lt;/p&gt;
&lt;p&gt;Now, in reality tracking open popovers for multiple windows is a bit overkill for popovers. It would be much more important for sliding drawers however. However we have introduced multi-window support in this articles demo file - the same technique could be back-applied to sliding drawers if need be.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;The layout setup is very similar to sliding drawers&lt;/h3&gt;
&lt;p&gt;Because we are borrowing the same technique from sliding drawers, the layout setup for popovers is very similar.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/3ced3988-a77c-462b-883c-aa509c893fdc.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;What you are looking at here is a screenshot of the demo file.  There are a few components here:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;A layout object with a tooltip to initiate the popover. In this case it is clippy!&lt;/li&gt;
&lt;li&gt;The actual popover object. We have placed this underneath clippy (more on this later).&lt;/li&gt;
&lt;li&gt;The popover panel which will have a nominated object name (in this case &quot;ClipOne&quot;).&lt;/li&gt;
&lt;li&gt;A large object placed over the layout to close the popover. This will contain a tooltip that calls the HoverPopover custom function, with no parameter passed.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/ba50a1ab-00eb-40e2-b1bf-c21a2f9336be.png&quot; alt=&quot;Tooltip for closing popovers&quot;&gt;&lt;/p&gt;
&lt;p&gt;So much like a sliding drawer, our tooltip on Clippy will be used to open the popover, and the layout overlay tooltip is used to close&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;A little note about the popover panel&lt;/h3&gt;
&lt;p&gt;There is a little gotcha to beware of here when it comes to the activated popover.  Take a look at the picture below:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/c29e760d-e68a-4520-9352-1acac83a1913.png&quot; alt=&quot;The dead zone&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we have highlighted in green an area that sits between the popover panel, and the popover button.  We shall call this the dead zone. Within this area you are not in the popover - it is just like regular layout space.&lt;/p&gt;
&lt;p&gt;This means that in normal circumstances if you were to place your mouse in this area, then the &quot;Close&quot; tooltip would be evaluated and the popover would close.&lt;/p&gt;
&lt;p&gt;This is not desirable because after you place your mouse to open the popover, your normal behaviour is to move the mouse toward the popover.  If your mouse crosses this zone the popover will immediately close before you get there!&lt;/p&gt;
&lt;p&gt;This is why we don&#039;t actually use the popover button as the object that contains the initiating tooltip. Instead, we use the clippy object.  The clippy image object is large enough that it occupies this green space, so as the user moves the mouse toward the popover, they remain on the clippy object, preventing the popover from closing.&lt;/p&gt;
&lt;p&gt;Unfortunately we have no control over the positioning of the popover panel, it is always in the same relative spot to the popover button, and we cannot close this gap.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Changes to the tooltip custom function&lt;/h3&gt;
&lt;p&gt;As mentioned earlier, we have modified the custom function that is run on tooltips to be more specific toward popovers.  The function now also has some multi-window support built in, so lets take a look.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/cad83000-033d-49e8-9394-69a668b03d0a.png&quot; alt=&quot;HoverPopover function&quot;&gt;&lt;/p&gt;
&lt;p&gt;Whereas in the &lt;a href=&quot;http://www.teamdf.com/weetbicks/228/a-sliding-drawer-that-opens-and-closes-on-mouse-over&quot; target=&quot;_blank&quot;&gt;sliding drawer&lt;/a&gt; example we used a single variable &lt;em&gt;$$CurrentState&lt;/em&gt; to determine the open or closed state of the drawer, here we are going to dynamically generate and clear variables to determine state.&lt;/p&gt;
&lt;p&gt;Each variable is defined on a per-window basis.  We are using the current windows name as part of the variable name.&lt;/p&gt;
&lt;pre&gt;VariableName = Lower ( &quot;$$&quot; &amp;amp; Substitute ( Get ( WindowName ) ; [ &quot; &quot; ; &quot;&quot; ] ; [ &quot;-&quot; ; &quot;&quot; ] ) &amp;amp; &quot;_popover&quot; ) ; 


&lt;/pre&gt;
&lt;p&gt;Here we establish the global variable name, removing some common illegal characters that may appear in a window name (more work could be done here).&lt;/p&gt;
&lt;p&gt;We next immediately evaluate this variable into a Let variable called &lt;em&gt;CurrentPopover &lt;/em&gt;which will tell us (if any) what the currently open popover is.&lt;/p&gt;
&lt;p&gt;The outcome to the function is one of three scenarios.&lt;/p&gt;
&lt;h5&gt;When we need to close popovers&lt;/h5&gt;
&lt;p&gt;This scenario occurs when we are passed a blank popover name to the function. Recall our layout overlay was calling the function with no parameter.  The script responsible for closing popovers only has to be run if there is actually an open popover - otherwise we would be running it many hundreds of times unnecessarily. This is why we also check the &lt;em&gt;CurrentPopover &lt;/em&gt;variable to determine if any popover is open right now.&lt;/p&gt;
&lt;pre&gt;BE_ExecuteScript ( &quot;Popover&quot; ) &amp;amp; Evaluate ( &quot;Let ( &quot; &amp;amp; VariableName &amp;amp; &quot;=\\&quot;\\&quot;;\\&quot;\\&quot;)&quot; ) ;

&lt;/pre&gt;
&lt;p&gt;The above code is what is run in this scenario. It comprises of two parts. The first is our plugin call to execute our script.&lt;/p&gt;
&lt;p&gt;The second part is how we are updating our global state variable dynamically. We use the &lt;em&gt;Evaluate &lt;/em&gt;function to clear our dynamically named variable.&lt;/p&gt;
&lt;h5&gt;When we need to open a popover&lt;/h5&gt;
&lt;p&gt;This second scenario occurs when we are passed a popover name, and it is determined this is &lt;strong&gt;not &lt;/strong&gt;the one that is currently open by way of checking the &lt;em&gt;CurrentPopover &lt;/em&gt;variable.&lt;/p&gt;
&lt;pre&gt;BE_ExecuteScript ( &quot;Popover&quot; ; Get ( FileName ) ; $name ) &amp;amp; Evaluate ( &quot;Let ( &quot; &amp;amp; VariableName &amp;amp; &quot;=$name; \\&quot;\\&quot;)&quot; ) ;

&lt;/pre&gt;
&lt;p&gt;In this case, we are again calling the Popover script, but this time we pass a parameter to the script. The parameter we pass is the popover name passed to the script - the one we wish to open.&lt;/p&gt;
&lt;p&gt;The second part is similar to what we do when we close popovers, but this time we dynamically set our variable to the newly opened popover name.&lt;/p&gt;
&lt;h5&gt;When we need to do nothing&lt;/h5&gt;
&lt;p&gt;If we need to do nothing, then we do nothing !  This occurs when either popovers are closed and the users tooltip is to close popovers, or when a specific popover is open, and the users tooltip is telling the function to open that same tooltip. In both situations there is absolutely no point in running our script - this would just be a hinderance to performance of the system.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;The popover script&lt;/h3&gt;
&lt;p&gt;This script is much simpler than that for the sliding drawer.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/88a86353-d445-464b-a619-7d573ceb8f0c.png&quot; alt=&quot;popover script&quot;&gt;&lt;/p&gt;
&lt;p&gt;The script is passed a parameter which can either be blank (in which case we close popovers), or it will be the object name of a popover that is to be opened.  Depending on the value of the variable, we run the appropriate steps - simple !&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Multi-Window&lt;/h3&gt;
&lt;p&gt;With the additional of dynamic generation of the global variables to manage popover states, we are able to extend this to work across multiple windows.  This is a little hard to test given moving the mouse anywhere off a popover area will close it, but for those users who have FileMaker Pro Advanced, fire up the data viewer and check out the Current tab as you move your mouse around the layout.  You&#039;ll notice state variables being created &amp;amp; cleared instantly.  If you open multiple windows then you&#039;ll see different variable names being created and cleared also.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/654173dd-6704-4085-ac56-16528049884a.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The benefit of multi-window support would be far better suited for sliding drawers than popovers, but hopefully this article gives some ideas as to how the drawer file could be extended to be more powerful.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Some limitations and unresolved issues&lt;/h3&gt;
&lt;p&gt;The file works pretty reliably but there are a few situations that could arise. They are nothing major and will likely go unnoticed, but they are worth mentioning.&lt;/p&gt;
&lt;p&gt;The first is the fact that while our script is responsible for closing popovers via tooltips, the user can still close the popover with a click of their mouse somewhere that isn&#039;t on the popover button.&lt;/p&gt;
&lt;p&gt;If the user does this, then it will not clear the state global variable, so the system thinks the popover is still open.  This isn&#039;t a huge deal because as soon as the mouse goes somewhere else on the layout, the variable is reset.  Other things such as on-timers may cause popovers to clear without clearing their variable, but again these are minor issues.&lt;/p&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;Please find attached an example file. This file is provided to help you fully understand what is going on in this article. Note that FileMaker 13 is required to view this example file. The file also contains both windows and mac versions of the &lt;a href=&quot;http://www.goya.com.au/baseelements/plugin&quot;&gt;BaseElements&lt;/a&gt; plugin from &lt;a href=&quot;http://www.goya.com.au/&quot;&gt;Goya&lt;/a&gt;, and has been set to install silently on startup if you do not already have this plugin installed.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.teamdf.com/assets/files/weetbicks/hoverpopover/HoverPopovers.zip&quot; target=&quot;_blank&quot;&gt;Click Here to Download the Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 07 Jul 2014 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/popovers-that-open-and-close-on-mouse-over/</guid>
		</item>
		
		<item>
			<title>A Proper Printing Framework for WebDirect</title>
			<link>https://www.teamdf.com/blogs/a-proper-printing-framework-for-webdirect/</link>
			<description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;For those not familiar with WebDirect, think of it as Instant Web Publishing enhanced. Whereas IWP was fairly static,  the goal for WebDirect is to be more dynamic and responsive to the user. Most FileMaker Pro functionality is there in WebDirect and the overall experience can be made to feel very similar to FileMaker Pro.  One of the key features it lacks though is printing, and this is quite an important feature if it is a larger solution to be widely deployed to a number of users.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;The implications of no printing in WebDirect&lt;/h3&gt;
&lt;p&gt;Because the Print script step is unsupported in WebDirect, the only other way to print is through the browsers print function. This however is a very poor substitute, as the browser will only print the &lt;em&gt;visible window contents. &lt;/em&gt;This means any lists of records, or any layout that cannot fit entirely in the window will not properly print.  Without Preview mode, we also have no ability for producing complex sub-summary reports or sliding of records. Basically, it just dun work!&lt;/p&gt;
&lt;p&gt;As a note, when we say printing in this article what we really mean is preview mode and all that goes along with that (such as printing).&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Okay so it doesn&#039;t print, so what can it do?&lt;/h3&gt;
&lt;p&gt;One thing WebDirect does do quite well is displaying interactive container data. What has that got to do with anything you ask? Well, it means displaying a PDF within WebDirect is pretty nice, so if we could generate a report as a PDF and display that to the WebDirect user instead, then this should allow them to scroll through it, preview it, and subsequently print it via printing of the PDF.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;width: 95px; display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/f952fc33-290e-4c57-8ed1-f2e24d46e492.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;So how will we generate a PDF?&lt;/h3&gt;
&lt;p&gt;This is at the heart of the entire framework.  Unfortunately FileMaker Server is unable to generate a PDF. The only two FileMaker platforms capable of generating a PDF is FileMaker Pro, and FileMaker Go. Go is obviously not an option so lets use FileMaker Pro! What we need to do is have a copy of FileMaker Pro responsible for the PDF generation of WebDirect user initiated reports. &lt;/p&gt;
&lt;p&gt;This is not an uncommon technique. This is something that sometimes is done when reports need to be e-mailed to users on a nightly basis. Because FileMaker Server cannot produce the PDF, we call on the help of a &lt;em&gt;&lt;strong&gt;Robot&lt;/strong&gt; &lt;/em&gt;copy of FileMaker Pro to do the effort of PDF generation. FileMaker Server could then attach and send the reports via a scheduled script, or the copy of FileMaker Pro could just do this itself.&lt;/p&gt;
&lt;p&gt;We shall call this copy of FileMaker Pro from this point on &lt;strong&gt;RoboPrint&lt;/strong&gt; !  &lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;width: 118px; display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/ec1684f3-d539-401f-84f2-a7f78191b046.png&quot; alt=&quot;RoboPrint&quot;&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;What is the basic framework outline?&lt;/h3&gt;
&lt;p&gt;In the framework we refer to the WebDirect user as &lt;strong&gt;RoboUser &lt;/strong&gt;and the robot copy of FileMaker Pro tasked with producing report PDFs as &lt;strong&gt;RoboPrint.&lt;/strong&gt; The basic process of events is as such:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;RoboUser&lt;/strong&gt; initiates a print request&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RoboPrint &lt;/strong&gt;is polling for new print requests and detects the request from &lt;strong&gt;RoboUser&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RoboPrint&lt;/strong&gt; then runs the report on behalf of &lt;strong&gt;RoboUser&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The resulting report is saved as a PDF document onto the print request and marked as done.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RoboUser&lt;/strong&gt; now sees their report has been generated and is able to view the PDF.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;That is it in a nutshell. Now how this all actually works is a little more in-depth so we&#039;ll cover the process in a little more detail below and how this relates to the example framework file.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;... For those who just want to get stuck in and see how it works...&lt;/h3&gt;
&lt;p&gt;Technical jargon and explanations are below, but if you want to just fire up the demo file and see what it&#039;s all about, you&#039;ll need to do a few things first:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Demo file hosted on FileMaker Server (because WebDirect is FMS only).&lt;/li&gt;
&lt;li&gt;A copy of FileMaker Pro must be running the database logged in with username &lt;strong&gt;RoboPrint &lt;/strong&gt;(no password), and the RoboPrint function must be running by clicking the launch button.&lt;/li&gt;
&lt;li&gt;Fire up WebDirect and open the database with username &lt;strong&gt;RoboUser&lt;/strong&gt;. You can then click on any of the 3 report buttons.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;You should see the RoboUser wait for the PDF to be generated. In FileMaker Pro you should see RoboPrint retrieve the print job, process it and mark it as done.  Then back in WebDirect you&#039;ll see the resulting PDF displayed to the user.&lt;/p&gt;
&lt;p&gt;You can also run as RoboUser in either FileMaker Pro or FileMaker Go - this does not necessarily require WebDirect to test with.  If you do not have access to WebDirect, then so long as you can access the database (shared) in 2 copies of FileMaker Pro you will be able to test the demo.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Still a work in progress&lt;/h3&gt;
&lt;p&gt;This framework at this stage is by no means perfect. It was built out of necessity for a WebDirect deployment, and has so far stood up to the test and been a reliable means of generating reports via WebDirect, which is why we have turned it into an article :)  There will always be improvements that can be made to the framework and the intention is that others in the community will take the general method and build upon it for others.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;The idea of a print request&lt;/h3&gt;
&lt;p&gt;In the framework is the idea of a print request. Because RoboPrint and RoboUser are run on different platforms, there needs to be a method of communication between them.  We do this by way of a table, funnily enough also called RoboPrint (just to confuse you!).&lt;/p&gt;
&lt;p&gt;Each record in this table is an individual print request that is generated by a WebDirect user. The record contains a number of fields that will tell RoboPrint all the information it needs to run the report. Most fields are self explanatory (you can check the comments on the fields for more info).&lt;/p&gt;
&lt;p&gt;When a user wishes to run a report, they will generate one of these records, populate it with the required information, and sit back and wait until the record is marked as either complete, or in the event something went wrong it will be marked with an error.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;The Initiation script&lt;/h3&gt;
&lt;p&gt;When a WebDirect user wishes to run a report, the generic script they run is called &lt;em&gt;&quot;Robouser - Initiate Print Job&quot;. &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/c0287de9-903d-4054-a2e1-a49da4792bbe.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We pass 3 key parameters:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Type is a keyword that will tell RoboPrint what type of report the user wishes to run&lt;/li&gt;
&lt;li&gt;Parameters is a text string of parameters that may be required to produce the correct report output.&lt;/li&gt;
&lt;li&gt;Timeout - this is a period - in seconds - which will be used for how long the WebDirect user will wait for the report output to be delivered. Default is 30 seconds.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;The rest of the script will launch a new virtual web window and go to the RoboUser PDF layout. It creates a print request and then simply sits and waits until the process if finished, or expires.&lt;/p&gt;</description>
			<pubDate>Fri, 04 Jul 2014 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/a-proper-printing-framework-for-webdirect/</guid>
		</item>
		
		<item>
			<title>A Sliding Drawer that Opens and Closes on Mouse-Over</title>
			<link>https://www.teamdf.com/blogs/a-sliding-drawer-that-opens-and-closes-on-mouse-over/</link>
			<description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;The slide control is an exciting new  layout tool introduced in FileMaker 13. Because of it&#039;s primary function of sliding via a swipe, it is built with FileMaker Go in mind. However it is quickly finding it&#039;s place in FileMaker Pro with a number of cool uses for it being introduced into the community.&lt;/p&gt;
&lt;p&gt;The slide control is one of the first UI tools that has animation built into it. The action of moving from one slide control panel to another can be animated (or not animated) by way of script. We can also script the navigation between slide panels. For these two reasons the slide control becomes a good candidate for a number of other UI patterns, one of which is a sliding drawer.&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;What is a Sliding Drawer&lt;/h3&gt;
&lt;p&gt;A sliding drawer (also known as a Navigation Drawer) is a control which expands to fill a larger portion of the screen when either pressed, hovered over with the mouse, or swiped with the finger on a touchscreen device. They generally appear on the left edge of a screen, but can be on any edge if desired.&lt;/p&gt;
&lt;p&gt;The drawer is most useful when the screen does not have enough room on it to contain further functionality and actions.  These can be placed in the drawer and the drawer can be opened when required to give access to the additional functionality.&lt;/p&gt;
&lt;p&gt;Here is an example of a website that contains a sliding drawer.  The first image shows the collapsed drawer. When the mouse is placed over the drawer, it expands with an animated effect, revealing the full contents.  Moving the mouse off the expanded drawer will collapse it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;img style=&quot;width: 279px;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/cc88228a-b906-49be-8475-4c33e7539a2a.png&quot; alt=&quot;&quot;&gt;&lt;img style=&quot;width: 277px; background-color: initial;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/7930f615-7b95-42de-9ea6-e350fd2449e0.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt; &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;  &lt;/h3&gt;
&lt;h3&gt;So what is this article all about?&lt;/h3&gt;
&lt;p&gt;In this article we are going to build a sliding drawer, but not just any sliding drawer. This is one that will also animated, but also be activated upon hovering the mouse over it. The drawer will also collapse upon moving the mouse off the drawer, just like in the website example above.&lt;/p&gt;
&lt;p&gt;The demo file for this article has been in progress for a while now and I had been tinkering with it from time to time but never ready to publish.  Recently, there have been a couple of great articles concerning sliding panels which prompted me to get my arse into gear and publish this one too.&lt;/p&gt;
&lt;p&gt;One of those was from John Sindelar from &lt;a href=&quot;http://www.seedcode.com&quot; target=&quot;_blank&quot;&gt;Seedcode&lt;/a&gt; who published this &lt;a href=&quot;http://www.seedcode.com/filemaker-13-animated-slide-panels/&quot;&gt;great article&lt;/a&gt; in which he presents an animated sliding panel example. In his demo, the user initiates the slide panel by clicking a button to reveal it, and another click to hide.&lt;/p&gt;
&lt;p&gt;This is a great demo for showcasing what can be done with slide panels in FileMaker Pro, how to structure a panel object for this sliding effect, and how can it can be implemented.&lt;/p&gt;
&lt;p&gt;I wanted to take this one step further however and remove the need for the user clicking a button to initiate the drawer expanding - wouldn&#039;t it be cool if you could just put your mouse over the draw to initiate it, similar to the web?&lt;/p&gt;
&lt;h3&gt;  &lt;/h3&gt;
&lt;h3&gt;Wait a minute, did you say mouse-over?&lt;/h3&gt;
&lt;p&gt;Yes that is correct. The mere act of placing your mouse cursor over the panel will expand it. So how is this possible? FileMaker has no native mouse-over functionality, and in order to expand and collapse the drawer we obviously have to run a script. So how can we initiate a script based on where the mouse is?&lt;/p&gt;
&lt;p&gt;The answer is tooltips.&lt;/p&gt;
&lt;p&gt;The method we are using to determine where a mouse cursor is on the layout is to place tooltips on the layout. The calculation within the tooltip will be evaluated whenever the mouse cursor falls over the tooltip.  This evaluation of the tooltip occurs almost instantly and repeatedly each time the mouse is moved (even though it may still take 1-2 seconds for the tooltip contents to normally appear).&lt;/p&gt;
&lt;p&gt;So now it boils down to what we put in our tooltip as to how we can control opening/closing the drawer. &lt;/p&gt;
&lt;p&gt;We are in fact also making use of a script-triggering plugin.  This plugin will run a script via our tooltip calculation upon detecting we need to either open or close the drawer. But we are getting ahead of ourselves, first things first, lets dive into how it all works.&lt;/p&gt;
&lt;p&gt;It may be a good idea at this point if you are following along to download the demo file so you can dissect it all as you read.&lt;/p&gt;
&lt;h3&gt;  &lt;/h3&gt;
&lt;h3&gt;Panel Setup&lt;/h3&gt;
&lt;p&gt;The first part of the puzzle comes with setting up a sliding control. Our control contains 3 panels. The first of which is blank, the second contains the expanded drawer view, and the third blank.&lt;/p&gt;
&lt;p&gt;You may be wondering why we have the first and third panels as blank. This is to do with achieving the correct animation effect when the drawer is opened. The correct animation is to show the drawer expanding from left to right. To actually achieve this, we must animate the navigation from panel 3 to panel 2. &lt;/p&gt;
&lt;p&gt;The reason our panel #1 is also blank is because unlike a tab control object, we cannot determine the &quot;default&quot; panel to show - it is always panel #1.&lt;/p&gt;
&lt;p&gt;In the picture below I have moved the drawer off to the side and shown the dots on the panel for reference. Also note that our collapsed view of the drawer sits outside of the slide control object altogether. The reason for this is a little hard to explain, but it comes down to the speed at which tooltips are evaluated, and the resulting triggered scripts are run. With the closed drawer inside the slide control, we ended up in testing with lots of unusual things happening!&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/f3af7e2c-563b-4b12-b990-c7537a0450cf.png&quot; alt=&quot;Panel Setup&quot;&gt;&lt;/p&gt;
&lt;h3&gt;  &lt;/h3&gt;
&lt;h3&gt;Tooltip that activates the drawer&lt;/h3&gt;
&lt;p&gt;Let&#039;s have a look at the tooltip calculation that is responsible for opening the drawer. This tooltip is set on the green rectangle panel that is the representation of the drawer in its closed state:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/15ccfbf5-c6dd-4425-8ebc-f25df1872e7e.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Wow how easy is that, only one line of code!!  Well, okay maybe not, but as you can see we have abstracted the code into a custom function. The reason for this is re-use. The same code is going to be used to both open and close the drawer.  Let&#039;s take a look at the custom function.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/12137ac6-8e33-4e9d-83e0-9bd4616e8041.png&quot; alt=&quot;SlidingDrawer Custom Function&quot;&gt;&lt;/p&gt;
&lt;p&gt;Still one line, jackpot! The function is passed a keyword - on or off - to determine what action the mouse-event is trying to perform. In this case hovering over the closed panel will attempt to open the panel, so we pass the parameter &quot;On&quot;.&lt;/p&gt;
&lt;p&gt;Inside our function, we are comparing the new requested state of the drawer, to a global variable we have called &lt;em&gt;$$CurrentState&lt;/em&gt;.  This variable will contain a keyword that tells us what current state the drawer is on, be it on or off.&lt;/p&gt;
&lt;p&gt;If the new state is different to the current (e.g. current state is off, and user wants to turn it on) then the &lt;em&gt;LET&lt;/em&gt; statement within the function is executed.&lt;/p&gt;
&lt;p&gt;This part will change the &lt;em&gt;$$CurrentState&lt;/em&gt; variable to our new state, and then carry out a script called &lt;em&gt;SlidingDrawer&lt;/em&gt; which is responsible to changing the drawer state.&lt;/p&gt;
&lt;p&gt;Note here we are using the very awesome and free &lt;a href=&quot;http://www.goya.com.au/baseelements/plugin&quot; target=&quot;_blank&quot;&gt;BaseElements&lt;/a&gt; plugin from &lt;a href=&quot;http://www.goya.com.au&quot;&gt;Goya&lt;/a&gt; to trigger the script, but you can use any script triggering plugin you want. The demo file comes bundled with the plugin and it should auto-install on startup if not already installed.&lt;/p&gt;
&lt;h4&gt;  &lt;/h4&gt;
&lt;h4&gt;A Note on plugin use&lt;/h4&gt;
&lt;p&gt;Plugins are always something people are naturally skeptical of, but these days plugins are so simple to install in FileMaker that their use should not be seen as an issue. This particular implementation of a sliding drawer is a desktop-only implementation, so a plugin should be fine to use (This method makes no sense on FileMaker Go as there is no mouse).&lt;/p&gt;
&lt;p&gt;For WebDirect users, at this point this method will not work as plugins work as long as they are server-side, but our process references a global variable that is client specific so won&#039;t work. If anyone wants to work on a WebDirect implementation it would be more than welcome :)&lt;/p&gt;
&lt;h3&gt;  &lt;/h3&gt;
&lt;h3&gt;The script to open/close the drawer&lt;/h3&gt;
&lt;p&gt;The &lt;em&gt;SlidingDrawer &lt;/em&gt;script is also pretty simple:&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin: auto; width: 530px;&quot; title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/ed9595d6-c116-4385-9917-714415594f3f.png&quot; alt=&quot;SlidingDrawer Script&quot;&gt;&lt;/p&gt;
&lt;p&gt;Essentially all it does is turn on the animation effect and go to the required state of the drawer via object name. We have named the on and off panel objects accordingly.&lt;/p&gt;
&lt;p&gt;The first script step is a non-animated panel change. This is only required once the first time the drawer is used on the layout. Recall earlier we mentioned panel #1 is always the default visible panel, but that to achieve the correct animation effect we must begin from panel 3.  This step ensures that before the animation takes place, we switch from panel #1 to panel #3 if need be. We have named panel #1 &quot;Default&quot; in this case.&lt;/p&gt;
&lt;p&gt;Thanks goes to John Sindelar again for this bit of code from &lt;a href=&quot;http://www.seedcode.com/?wpdmdl=25&quot; target=&quot;_blank&quot;&gt;his example file&lt;/a&gt;, as this was an issue I was struggling with before seeing how he achieved it!&lt;/p&gt;
&lt;h3&gt;  &lt;/h3&gt;
&lt;h3&gt;Okay so the drawer is open, how do we close it?&lt;/h3&gt;
&lt;p&gt;The drawer is closed in exactly the same way as it is opened, via a tooltip.  This one however is a bit more of a messy affair.  Opening the drawer is easy, we just put the open tooltip on the closed version of the drawer.  However closing the drawer will occur if the user puts the mouse anywhere on the layout that is not over the expanded drawer, so how do we do that?&lt;/p&gt;
&lt;p&gt;The easiest way - and the way the demo file does it - is to create a large blank text object, and overlay this across the layout with the required tooltip attached. &lt;/p&gt;
&lt;p&gt;We define the ordering of tooltip objects on the layout as such so that our closed drawer is at the front, followed by our panel object, and the closing tooltip underneath that. All the other layout objects lie underneath our close tooltip.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/assets/blog/images/original/6af21743-60cb-41b0-8c13-8790ee6dd8e4.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can see in the image above the tooltip object as it sits on the layout.&lt;/p&gt;
&lt;p&gt;If you make this overlaying tooltip transparent fill, then a very cool thing happens. If you have other objects on your layout with their own tooltips, then these will continue to work even though those objects are underneath your closing tooltip.  But the closing tooltip will still evaluate, as will those other underlying tooltips.&lt;/p&gt;
&lt;p&gt;The net result is that your sliding drawer will close, and then any tooltip on any object where your mouse ends up will show.&lt;/p&gt;
&lt;p&gt;The only downside to the implementation is you end up with this large object covering most of your layout contents which can make developing a pain. You&#039;ll just have to move this object off your layout while developing - but don&#039;t forget to move it back on when done or your drawer will not close!&lt;/p&gt;
&lt;h3&gt;  &lt;/h3&gt;
&lt;h3&gt;Ensuring the drawer sits in front of everything&lt;/h3&gt;
&lt;p&gt;One of the limitations of a slide control panel is that underlying objects can still be clicked into and pressed.  When our drawer is in its open state, we want to ensure that any layout objects under the drawer are disabled and that the drawer is the only object that can be interacted with within that space.&lt;/p&gt;
&lt;p&gt;The solution is quite simple - turn the drawer object into a button. In the example file we use a rectangle object for the open drawer. To set it up you can do the following:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Turn it into a button&lt;/li&gt;
&lt;li&gt;Set the script step to &quot;Exit Script&quot;&lt;/li&gt;
&lt;li&gt;Disable the option that uses the Hand Icon&lt;/li&gt;
&lt;li&gt;Switch to the &quot;Pressed&quot; state of the Rectangle&lt;/li&gt;
&lt;li&gt;Change the pressed fill colour to a colour very similar to the normal colour, but &lt;strong&gt;fractionally &lt;/strong&gt;different.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;   &lt;/p&gt;
&lt;p&gt;That last point is key. If you set the pressed colour to the same as the normal colour, FileMaker will still add its normal grey pressed colour to the button.  We want to give the appearance that this is in fact not a button at all. So to do this, make a minuscule change to the colour, so small a normal user could not perceive the colours being different. Now when the user clicks on the rectangle, nothing seems to happen. In fact the Exit Script step is run, but this has no real effect on anything. Because it is now a button, it will sit in front of all underlying objects, blocking them.&lt;/p&gt;
&lt;h3&gt;  &lt;/h3&gt;
&lt;h3&gt;Current Limitations&lt;/h3&gt;
&lt;p&gt;This specific demo layout has been tested extensively during development, but not much testing has been done at all for other scenarios, such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Multi-Windowed environments&lt;/li&gt;
&lt;li&gt;Multiple layouts&lt;/li&gt;
&lt;li&gt;WebDirect&lt;/li&gt;
&lt;li&gt;Multiple panels per page (though this is probably a bad design choice anyway).&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;The example actually will not currently work with multiple windows as both windows would rely on the same &lt;em&gt;$$CurrentState&lt;/em&gt; variable, even though drawers on both windows may have their own state.  I do think though this could be quite easily remedied through some tweaks to the custom function and script. Consider generating dynamically named variables for each window, perhaps named using the window &amp;amp; layout name, and then passing the required new state to the script. This would remove the need for the script to reference a global variable, and would mean each layout in each window would have its own variable to control its current state.  I would love to see an implementation that does this&lt;/p&gt;
&lt;h3&gt;  &lt;/h3&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;Please find attached an example file. This file is provided to help you fully understand what is going on in this article. Note that FileMaker 13 is required to view this example file. The file also contains both windows and mac versions of the &lt;a href=&quot;http://www.goya.com.au/baseelements/plugin&quot; target=&quot;_blank&quot;&gt;BaseElements&lt;/a&gt; plugin from &lt;a href=&quot;http://www.goya.com.au/&quot; target=&quot;_blank&quot;&gt;Goya&lt;/a&gt;, and has been set to install silently on startup if you do not already have this plugin installed.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;http://www.teamdf.com/assets/files/weetbicks/SlidingDrawer/SlidingDrawer.zip&quot;&gt;Click here to Download the Example File&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;h3&gt;Update - New Demo Files from Users&lt;/h3&gt;
&lt;p&gt;Denis Somar has kindly contributed an awesome modification to the demo file which makes use of popovers to produce the active panel. He noted that popovers have the highest z-level ordering of any object on the layout and thus can be used as the active panel to cover any underlying objects.  The demo file he produced works in table-mode and is a very cool take on the traditional drawer, I urge you to check it out!  (also check the comments for more information from Denis)&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https://dl.dropboxusercontent.com/u/2103138/SlidingDrawerOnTables.fmp12.zip&quot; target=&quot;_blank&quot;&gt;You can download the example file here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another reader, Joel Shapiro (who did a great article also about &lt;a href=&quot;http://blog.jsfmp.com/post/89937370141/filemaker-13-animated-slide-panels-with-web-viewers&quot; target=&quot;_blank&quot;&gt;sliding drawers using web viewers here&lt;/a&gt;) has also contributed a modification to the demo file. His suggestion can be found in the comments, but he noted that by offsetting the slide control 48px to the right (such that it sits to the right of the collapsed panel) the end result is a much smoother transition effect from collapsed to expanded panel. The one downside here is the area occupied by the collapsed panel is not usable when expanded, however I&#039;m sure someone out there will be able to offer up a fix!&lt;/p&gt;</description>
			<pubDate>Tue, 01 Jul 2014 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/a-sliding-drawer-that-opens-and-closes-on-mouse-over/</guid>
		</item>
		
		<item>
			<title>Sending Email from FileMaker Using Mandrill</title>
			<link>https://www.teamdf.com/blogs/sending-e-mail-from-filemaker-using-mandrill/</link>
			<description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;Sending Email from FileMaker is a common feature these days. With the &lt;em&gt;Send Mail&lt;/em&gt; script step this has made it even easier as you can either send via an SMTP server or your Mail Client. While good, these methods do have restrictions such as a one attachment limit and no HTML support if using via SMTP server. Also if sending via your Email client then it becomes difficult to capture sent mail in your system and not all mail clients work the same.&lt;/p&gt;
&lt;p&gt;Developers have aimed to circumvent these issues by using FileMaker Email plugins capable of HTML and multiple attachments among other things. Plugins are a good alternative but require some setup and configuration of SMTP details, authentication, and are at the mercy of firewalls and other restrictions that may prevent Email from being sent.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/mail.png&quot; alt=&quot;mail&quot; width=&quot;128&quot; height=&quot;128&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Mandrill - What is it and why do I care?&lt;/h3&gt;
&lt;h4&gt;What is Mandrill?&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://www.mandrill.com&quot;&gt;Mandrill&lt;/a&gt; is different. It is basically the E-Mail sending side of &lt;a href=&quot;http://www.mailchimp.com&quot;&gt;MailChimp&lt;/a&gt; that has been spawned off to become its own site. Because of this, Mandrill also offers a wide range of features that you would expect from an Email campaign management site such as tracking of Email opens and clicks, full statistics on mail sent, bounce management, as well as a raft of other customisable settings.&lt;/p&gt;
&lt;h4&gt;And why do I care?&lt;/h4&gt;
&lt;p&gt;You can use Mandrill to send Email via standard SMTP, or via their API. Even if you wish to use it just via SMTP alone it makes sense. The Mandrill SMTP credentials are reliable, secure, and work anywhere (subject to firewall restrictions of course). In addition, you get all the benefits of comprehensive email tracking and settings to help customise the experience.&lt;/p&gt;
&lt;p&gt;In this article we will be covering sending Email via Mandrill by using their API. The benefit of this method is the Emails are sent using an HTTP POST request on port 80 so unless you work for a totalitarian company which has blocked the internets then you should be guaranteed that your Emails will send every time.&lt;/p&gt;
&lt;h4&gt;There is always a catch, what is the catch?&lt;/h4&gt;
&lt;p&gt;No catch I promise! I may sound like I work for Mandrill but my enthusiasm is based solely on using Mandrill now on 4 separate projects and having great success on all of them. Best of all Mandrill is free (now I have your attention!). With a free account you are given a starting limit of &lt;em&gt;12,000&lt;/em&gt; Emails per month, with an hourly limit of &lt;em&gt;250&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Mandrill works using algorithms that fairly allocate Email send capacity based on the type and quantity of Email that you send. If you are sending legitimate Email and not spam then you will begin to notice your daily and hourly limits increase over time - though for most FileMaker solutions these starting limits are more than enough.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage187187-mandrill.png&quot; alt=&quot;mandrill&quot; width=&quot;187&quot; height=&quot;187&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Setting up a Mandrill Account&lt;/h3&gt;
&lt;h4&gt;How do I create an account?&lt;/h4&gt;
&lt;p&gt;Go to &lt;a href=&quot;http://www.mandrillapp.com&quot;&gt;http://www.mandrillapp.com&lt;/a&gt; and sign up for a new account. Account setup is really easy - all you need is a unique Email address and password. If you intend to use it for multiple solutions then it would be good practice to create a new account per solution - 12,000 emails per day sounds like a lot but you don&#039;t want to run out. Accounts are also free so there is no reason not to.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage266323-mandrill-1.png&quot; alt=&quot;mandrill 1&quot; width=&quot;266&quot; height=&quot;323&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Generating an API Key&lt;/h4&gt;
&lt;p&gt;All Email you intend to send via the API must be sent with an API Key. The key identifies which account is sending the Email. Once logged into your account select &lt;em&gt;SMTP and API Credentials&lt;/em&gt; from the settings menu. Here you can create as many API keys as you wish for various purposes. You will also find the SMTP credentials if you prefer to use those.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600131-mandrill-2.png&quot; alt=&quot;mandrill 2&quot; width=&quot;600&quot; height=&quot;131&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Configuring your account for use&lt;/h4&gt;
&lt;p&gt;Mandrill is packed with configuration settings and tools for managing sent mail. These include things such as click tracking, blacklists, whitelists, custom metadata and webhooks to name a few. We won&#039;t go into depth on these here, but we will cover a couple of useful settings found in the &lt;em&gt;Sending Options&lt;/em&gt; area.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Generate plain-text from HTML Emails (and vice versa).&lt;/strong&gt; This is a useful option for mail client compatibility. Mandrill will automatically generate either HTML or Plaintext from your Email.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expose the list of recipients when sending to multiple addresses.&lt;/strong&gt; You can send an Email to multiple recipients in a single request, however you may not wish for all recipients to know who else got the Email. Use this option to show/hide the full list of recipients from others.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Send a copy of every Email to this address.&lt;/strong&gt; A great feature for initial deployment. If you are concerned about Emails not being sent, then you can be CC&#039;d in on everything sent using this option, or use it as a secondary log of everything sent out.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Forward bounce notifications to this address.&lt;/strong&gt; If knowing whether an Email reached its destination is important, you can have Mandrill forward a special bounce response to a nominated Email address. We have used this in solutions where we use a plugin to receive these Emails back into FileMaker and process the bounce accordingly&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage131131-mailchimp.png&quot; alt=&quot;mailchimp&quot; width=&quot;131&quot; height=&quot;131&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Integration with FileMaker&lt;/h3&gt;
&lt;h4&gt;What do I need to add to FileMaker&lt;/h4&gt;
&lt;p&gt;From this point on we are going to refer to the Mandrill example file that is included with this article.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/mandrill/Mandrill.zip&quot;&gt;Download the example file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are 3 key pieces of Mandrill information that you need to put into your FileMaker solution:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The API Key, you can get this from your account.&lt;/li&gt;
&lt;li&gt;The URL to which you will send the API request. Mandrill uses a REST API where you send to various URL&#039;s your request depending upon what you are trying to do. For sending Email, the URL is &lt;strong&gt;https://mandrillapp.com/api/1.0/messages/send.json&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;The request code into which you will place your email information. Best practice is to define the template and substitute placeholders for actual data.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;All of the URLs and request formats for the API can be found in the &lt;a href=&quot;https://mandrillapp.com/api/docs/messages.JSON.html&quot;&gt;documentation here&lt;/a&gt;. We will be sending requests using JSON format, so we use the &lt;em&gt;.json&lt;/em&gt; endpoint to the URL - however other formats are available such as XML and PHP.&lt;/p&gt;
&lt;p&gt;You can hard-code the above directly into your send scripts, but a better way is to store them in global fields so they can be used system-wide and can be easily modified if required.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage348308-mandrill-3.png&quot; alt=&quot;mandrill 3&quot; width=&quot;348&quot; height=&quot;308&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Generating an Email send request&lt;/h4&gt;
&lt;p&gt;The next step is to transform your request template into an actual request that can be sent to the API. You will see in the screenshot above that our request template has some place-holder data in it at various points, eg. &lt;em&gt;SENDERNAME&lt;/em&gt;, &lt;em&gt;SUBJECT&lt;/em&gt;, and &lt;em&gt;MESSAGE&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;How you record that information in the database we will leave entirely up to you. For our example file we have an &lt;em&gt;Email&lt;/em&gt; table onto which we will capture this information. For attachments we have a related &lt;em&gt;Attachments&lt;/em&gt; table where each record stores an attachment in a container. It is then simply a case of substituting out our placeholders for actual data. To do this we have created a couple of helpful custom functions.&lt;/p&gt;
&lt;h4&gt;mandrill_createRequest&lt;/h4&gt;
&lt;p&gt;This custom function takes a number of parameters, each corresponding to something we will substitute into the request. We are also passing the request template as the first parameter, however if you wish it may be easier to include the template within the custom function, particularly if you only intend to use one template for the entire solution. The function is basically a glorified substitute command, but it does a couple of required things:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;It will escape all required characters within the parameters, this is so that the request does not break as a result of prematurely terminated strings caused by a non-escaped characters.&lt;/li&gt;
&lt;li&gt;It will call a helper custom function &lt;em&gt;mandrill_attachmentCode&lt;/em&gt; to generate the required request code for attachments.&lt;/li&gt;
&lt;li&gt;Because we are sending all Email as HTML, it will transform the message into HTML code using the &lt;em&gt;GetAsCSS&lt;/em&gt; function if it detects it was not passed HTML code already.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;EDIT:&lt;/strong&gt; Thank you to Tim Dietrich, Stephen Dolenski and Michael Gaslowitz who all pointed out we also need to escape other characters in the request so as not to break it!&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600196-mandrill-4.png&quot; alt=&quot;mandrill 4&quot; width=&quot;600&quot; height=&quot;196&quot;&gt;&lt;/p&gt;
&lt;h4&gt;mandrill_attachmentCode&lt;/h4&gt;
&lt;p&gt;You don&#039;t really need to concern yourself with how this function works, however it is such a cool function function it deserves some mention!&lt;/p&gt;
&lt;p&gt;Custom functions can accept a container field as a parameter. However you cannot pass them a list of containers as the List() function is for strings only. We could define 1 parameter per attachment but that is really bad as a) we don&#039;t know how many attachments we will have, and b) if we have none or one then we have to define blank for all the other attachment parameters. So how do we process multiple container attachments with a single parameter?&lt;/p&gt;
&lt;p&gt;The answer to this came from &lt;a href=&quot;http://www.soliantconsulting.com/blog/2013/11/custom-function-parameters-value-or-reference&quot;&gt;this Soliant Consulting article&lt;/a&gt; written by the very smart Wim Decorte. He noticed that a parameter to a custom function has a dual nature - you can either treat it as a normal value, OR you can treat it as a reference to a value. Basically, if we treat it as a reference then we can use it in conjunction with recursion and the &lt;em&gt;GetNthRecord&lt;/em&gt; function to recurse through multiple related attachment containers and process each one. We are making use of the dual nature of the parameter, using it as a both a value and a reference. I think this is one of the coolest untapped features of custom functions!&lt;/p&gt;
&lt;p&gt;Attachments are converted into Base64 and along with a file name and mime type are put into the correct request format.&lt;/p&gt;
&lt;p&gt;I won&#039;t go into any more detail than that, feel free to dig deeper into how it works, and definitely check out &lt;a href=&quot;http://www.soliantconsulting.com/blog/2013/11/custom-function-parameters-value-or-reference&quot;&gt;Wim&#039;s great article on the topic&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600340-mandrill-5.png&quot; alt=&quot;mandrill 5&quot; width=&quot;600&quot; height=&quot;340&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Enough with the stalling, send the damn Email already!&lt;/h4&gt;
&lt;p&gt;This is the easiest part. Now that we have our request generated from the custom function, all that is left to do is send it to the API to send the Email.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;Insert from URL&lt;/em&gt; script step may be able to be used to send the request. At the point of writing this, I am still working on determining whether this is possible, and seeking the help of fellow developers in getting this working with this script step. In FileMaker Pro 13, the step does support HTTP POST, but I&#039;m still working on getting the syntax correct for sending. For now, we are going to use the BaseElements plugin to send the request. Thank you to Michael Gaslowitz for pointing out that Insert from URL does support HTTP POST.&lt;/p&gt;
&lt;p&gt;The example file comes pre-packaged with the excellent and free BaseElements plugin from &lt;a href=&quot;http://www.goya.com.au&quot;&gt;Goya Pty Ltd&lt;/a&gt;. This should auto-install on startup and prior to sending Email if not already installed. We use this plugin because not only does it have a working mac and windows version but it also has a 64-bit windows version compatible with FileMaker Server 12 and 13 for server-side sending.&lt;/p&gt;
&lt;p&gt;Because plugins do not work on iOS you have a couple of options - one is to have FileMaker Server carry out the sending by using the &lt;em&gt;Perform on Server&lt;/em&gt; script step. If your solution is not hosted then you can use the native FileMaker &lt;em&gt;Send Mail&lt;/em&gt; script step and use the Mandrill SMTP credentials instead of the API. We are also working on getting the Insert from URL step working (see above).&lt;/p&gt;
&lt;p&gt;Sending the request is now really easy and is a single function call:&lt;/p&gt;
&lt;pre&gt;BE_HTTP_POST ( $URL ; $Request )&lt;/pre&gt;
&lt;p&gt;Where $URL is the API endpoint for sending an email, and $Request is your completed request. Sending of a standard Email without attachments should take less than a second, and a little longer for attachments.&lt;/p&gt;
&lt;h4&gt;The API Response&lt;/h4&gt;
&lt;p&gt;After sending the request, the API will send you a response that contains useful information. A typical response will look something like this:&lt;/p&gt;
&lt;pre&gt;[&amp;lt;br /&amp;gt;{&quot;email&quot;:&quot;daniel@weetbicks.com&quot;,&amp;lt;br /&amp;gt; &quot;status&quot;:&quot;sent&quot;,&quot;_id&quot;:&amp;lt;br /&amp;gt; &quot;d54bb019417c491eb01fc8578c4641a5&quot;,&amp;lt;br /&amp;gt; &quot;reject_reason&quot;:null}&amp;lt;br /&amp;gt;]&amp;lt;br /&amp;gt;&lt;/pre&gt;
&lt;p&gt;This is a JSON array of values of the following:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;email.&lt;/strong&gt; Where the e-mail was sent&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;status.&lt;/strong&gt;This tells you the outcome. If the status is &lt;em&gt;sent&lt;/em&gt; or &lt;em&gt;queued&lt;/em&gt; then it succeeded. Emails without an attachment will send right away, whereas ones with an attachment will be queued - however they are typically only queued for a couple of seconds so you won&#039;t even notice. A status of scheduled means you have told Mandrill to send the message at a nominated date and time (you can define this as part of the request). If the status is &lt;em&gt;rejected&lt;/em&gt; or &lt;em&gt;invalid&lt;/em&gt; then something went wrong, and you can check the reason for more details&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;reject_reason.&lt;/strong&gt; The reason the Email failed to send if the status is &lt;em&gt;rejected&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;id.&lt;/strong&gt; This is a unique identifier assigned to the sent Email from Mandrill. This is useful to track the message via the online Mandrill dashboard, and also if you intend to process Email bounces (the bounce message contains the unique ID).&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;mandrill_parseResponse&lt;/h4&gt;
&lt;p&gt;We have included this custom function to help you easily obtain a specified parameter from the response. Pass this function the response, along with either the parameter keyword (or associated number) to retrieve the value. This is useful if you wish to run a test condition as to whether the email sent or failed.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage414360-mandrill-6.png&quot; alt=&quot;mandrill 6&quot; width=&quot;414&quot; height=&quot;360&quot;&gt;&lt;/p&gt;
&lt;h3&gt;So in Conclusion...&lt;/h3&gt;
&lt;p&gt;We hope this article has given you a good overview of Mandrill, what it is and what its benefits are. Integrating Mandrill with FileMaker is dead simple. It avoids a lot of potential SMTP related issues such as firewall restrictions, Outlook Exchange problems, or simply increasing usage of your own SMTP server. It also contains a wealth of settings and tracking options for marketing/campaign related emails. We haven&#039;t even touched upon the comprehensive online dashboard for tracking sent email statistics, but it&#039;s all there for you to explore. Have fun!&lt;/p&gt;
&lt;h3&gt;Example File&lt;/h3&gt;
&lt;p&gt;Please find attached an example file. This file is provided to help you fully understand what is going on in this article. Note that FileMaker 13 is required to view this example file. The file also contains links to the Mandrill API documentation and website, as well as the custom functions mentioned in the article.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/mandrill/Mandrill.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt;The example file has been updated on 23rd March with the following changes:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;More escaping of request characters within the mandrill_createRequest function&lt;/li&gt;
&lt;li&gt;added a mandrill_escapeData helper custom function to escape merge data in the request&lt;/li&gt;
&lt;li&gt;I have replaced angle bracket for merge data with « and » respectively.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/mandrill-7.png&quot; alt=&quot;mandrill 7&quot; width=&quot;300&quot; height=&quot;173&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Fri, 21 Mar 2014 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/sending-e-mail-from-filemaker-using-mandrill/</guid>
		</item>
		
		<item>
			<title>Cutting out the middle man</title>
			<link>https://www.teamdf.com/blogs/cutting-out-the-middle-man/</link>
			<description>&lt;p&gt;As an account manager, my job is to look after new and existing clients, with the end goal of keeping them happy. My role is also to keep our developers busy with work, a busy development team makes for a happy workplace.&lt;/p&gt;
&lt;p&gt;What has changed between my previous job and now (at Digital Fusion) is we have cut out the middle man. Previously it was my role to sell websites, pass the client to a project manager who would then form a team and oversee the design and development phases. Once I had handed the client over, I pretty much dropped out of the equation, coming in at the end of the project to give the client some love and to check that everything went well (with fingers and toes crossed).&lt;/p&gt;
&lt;p&gt;This was described by my previous manager as a &#039;touch and pass&#039; method, the Account Manager would &#039;touch&#039; the client and then &#039;pass&#039; them onto the project manager. As Account Managers we called the &#039;touch and pass&#039; method more the &#039;dump and run&#039; because invariably we had to move onto our next sale so we could keep the cogs moving.&lt;/p&gt;
&lt;p&gt;After joining Digital Fusion in late 2012 it was interesting to see how our model works, and I have to say it is fantastic. Here my role is more of a Relationship Manager, I check in with clients and developers and make sure they are all good. As our designers and developers manage all our projects, they are intricately involved. Clients love the fact that they are working directly with the people who are working on their projects, there&#039;s no having to explain something to a project manager and hoping that the message gets passed on to the unknown designer or developer. I am always there to support the clients and developers with the comms side of the project, keeping things ticking along is important.&lt;/p&gt;
&lt;p&gt;I will add here that I think we are blessed with an outstanding team, people who are more than capable of running projects and being a part of our clients businesses. This is credit to Craig and Julie that they employ staff incredibly well, there&#039;s not a dud one in the bunch of now 16 staff (and yes I include myself in this figure, they picked well when they employed me).&lt;/p&gt;
&lt;p&gt;So what&#039;s the upshot of this blog post? There are really two take-aways, one being how you employ your staff: look for well-rounded people that are passionate about what they do ? and can speak human language, not just geek speak. The other is to not put barriers between yourself and clients, keeping the communication channels as open as possible will lead to happy clients.&lt;/p&gt;</description>
			<pubDate>Thu, 13 Mar 2014 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/cutting-out-the-middle-man/</guid>
		</item>
		
		<item>
			<title>So what is an API and why should you care?</title>
			<link>https://www.teamdf.com/blogs/what-is-an-api/</link>
			<description>&lt;p&gt;Quite simply, an API is a purpose built extension of an existing system to allow information to flow back and forth with other systems.&lt;/p&gt;
&lt;p&gt;Who cares? You should... because API&#039;s are a simple and cost effective way for your website or application to communicate with other pieces of software.&lt;/p&gt;
&lt;p&gt;The best way to get your head around what an API is, would be to use an analogy:&lt;/p&gt;
&lt;p&gt;Your television set has an HDMI socket (or many), this allows you to plug devices into the television so you can get information into and out of it (think Sky Decoder, Apple TV, DVD recorder etc). Think of the HDMI socket as an API, without it you would have what is best described as a &#039;dumb&#039; television, you can watch programs but you can neither watch DVD&#039;s or record programmes.&lt;/p&gt;
&lt;p&gt;Software is the same, you can have a closed solution which doesn&#039;t &#039;speak&#039; to other pieces of software, or you can have an &#039;open&#039; solution which can communicate via an API.&lt;/p&gt;
&lt;p&gt;To give you an example of how an API works in the wild, we will use our good mates at &lt;a href=&quot;http://www.teamdf.com/about/xero-approved-developer/&quot;&gt;xero&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One of the best features of Xero is the automated population of transactions from your bank. To allow Xero to do this, the banks have developed API&#039;s that give Xero the ability to pull information out and display it in their system. The other cool thing about Xero is they have then taken it a step further and built their own API, which means web developers like us can then build solutions that either push or pull information into or out of Xero.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Wed, 19 Feb 2014 00:30:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/what-is-an-api/</guid>
		</item>
		
		<item>
			<title>Big Tabs!</title>
			<link>https://www.teamdf.com/blogs/big-tabs/</link>
			<description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Building FileMaker solutions for iOS introduces a new set of challenges for developers and requires UI controls that make it easy for users to interact. This article gives a very quick and simple technique you can use to make selecting tab controls much easier for FileMaker Go users on iPad and iPhone.&lt;/p&gt;
&lt;h4&gt;Tab Controls before FileMaker 13&lt;/h4&gt;
&lt;p&gt;Prior to FileMaker 13, the labels you define for tab panels would be the only means of dictating the height of those selectable tab panel areas. Increasing the font size inevitably increases the height of the tab panels selectable area.&lt;/p&gt;
&lt;p&gt;The problem here is that with increased font size comes unreadability of the tab label. Various methods could be employed to inhibit this behaviour such as making the label white to hide it. Another method people have used is to set the tab label to a series of space characters and then overlaying the actual label as a standard piece of text. Neither method is that elegant or easy to maintain.&lt;/p&gt;
&lt;h4&gt;The solution in FileMaker 13&lt;/h4&gt;
&lt;p&gt;With FileMaker 13, we can now define the labels for tabs by way of calculation and as such we can make use of some of the text formatting functions within that calculation.&lt;/p&gt;
&lt;p&gt;To retain big tabs but allow for readable labels, we can use the &lt;em&gt;TextSize&lt;/em&gt; function to reduce the label size to a readable level, while making the font size associated with the tab control object large.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600246-bigtabs-1.png&quot; alt=&quot;bigtabs 1&quot; width=&quot;600&quot; height=&quot;246&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is a tab control where the tab font size is set to 72pt. By doing this, the selectable tab area height is increased.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600406-bigtabs-2.png&quot; alt=&quot;bigtabs 2&quot; width=&quot;600&quot; height=&quot;406&quot;&gt;&lt;/p&gt;
&lt;p&gt;If we look at the tab setup, you&#039;ll notice all the tabs are defined by calculation. I have also set tab width to a fixed width per tab (choosing the other options tends to not work nicely with this technique).&lt;/p&gt;
&lt;p&gt;The tab function is simply a custom function that will correctly format the label to a desired size - this is purely for readability.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600489-bigtabs-3.png&quot; alt=&quot;bigtabs 3&quot; width=&quot;600&quot; height=&quot;489&quot;&gt;&lt;/p&gt;
&lt;h4&gt;The End Result&lt;/h4&gt;
&lt;p&gt;When viewed in browse mode, we end up with some really nice tall tabs with a readable font size. On an iOS device this gives a much larger area to tap for selecting a tab.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600237-bigtabs-4.png&quot; alt=&quot;bigtabs 4&quot; width=&quot;600&quot; height=&quot;237&quot;&gt;&lt;/p&gt;
&lt;p&gt;Compare this to a tab control based on the standard font size of 12pt.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600253-bigtabs-5.png&quot; alt=&quot;bigtabs 5&quot; width=&quot;600&quot; height=&quot;253&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file is provided to help you fully understand what is going on in this article. Note that FileMaker 13 is required to view this example file.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/bigtabs/BigTabs.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;And Finally...&lt;/h4&gt;
&lt;p&gt;It has been just over a year since my last article. in January of last year I set off and spent 5 months cycling across the African continent. Upon returning to work the motivation for writing new articles wasn&#039;t quite there and it took a while to get back into the swing of things. Now it is a new year and I&#039;m looking forward to cracking out some new articles in 2014 and explore everything that FileMaker 13 has to offer!&lt;/p&gt;
&lt;p&gt;Thank you for your continued readership and support!&lt;/p&gt;
&lt;p&gt;Cheers,&lt;br&gt;Daniel&lt;a href=&quot;http://www.teamdf.com/gonewild&quot;&gt;&lt;br&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/SouthAfrica.jpg&quot; alt=&quot;SouthAfrica&quot; width=&quot;540&quot; height=&quot;720&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Thu, 13 Feb 2014 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/big-tabs/</guid>
		</item>
		
		<item>
			<title>Weetbicks Returns</title>
			<link>https://www.teamdf.com/blogs/weetbicks-is-back/</link>
			<description>&lt;p&gt;We&#039;re rapt to announce that Daniel has returned to the keyboard to share some of the expertise and methods gleaned from the real world development work we do here at Team DF.&lt;/p&gt;
&lt;p&gt;Daniel&#039;s new article looks at a solution particularly useful in iOS development where everything needs be nice and big and easy to target when a finger is the pointer ? check out &lt;a href=&quot;http://www.teamdf.com/weetbicks/big-tabs/220/&quot;&gt;Big Tabs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://teamdf.com/files/display/575/221_1.jpg&quot; alt=&quot;&quot; title=&quot;&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Thu, 13 Feb 2014 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/weetbicks-is-back/</guid>
		</item>
		
		<item>
			<title>FileMaker 13 Hits The Streets!</title>
			<link>https://www.teamdf.com/blogs/filemaker13/</link>
			<description>&lt;p&gt;Wahoo! A new release of the venerable database platform, FileMaker, is out today.&lt;/p&gt;
&lt;p&gt;For software developers a new release of one our main tools of the trade is like Christmas... and look at that it *is* December already.&lt;/p&gt;
&lt;p&gt;With a new version like this we get some all new superpowers to make our solutions more impressive, faster, and of course, better looking. There are some really important things too, like security, encryption, and new server admin tools with graphs showing how many bits are bobbing around between the clouds, the people, and all those &#039;mobile devices&#039;.&lt;/p&gt;
&lt;h4&gt;Lovely. So what&#039;s in it for me?&lt;/h4&gt;
&lt;p&gt;Well, if you&#039;re a business owner or manager or someone just trying to make life better with some decent &#039;systems&#039; then FileMaker 13 brings some major new possibilities for you, especially with WebDirect and a lot of enhancements to the mobile version, FileMaker Go.&lt;/p&gt;
&lt;p&gt;So here we go with a bit of a run down on the highlights:&lt;/p&gt;
&lt;h4&gt;WebDirect&lt;/h4&gt;
&lt;p&gt;This is the biggy: it&#039;s FileMaker to web without getting down and dirty with HTML, JavaScript or PHP... Not that we don&#039;t like that?in fact we love the power of the web as a platform too, but sometimes you need the job done quickly and don&#039;t need all that power.&lt;/p&gt;
&lt;p&gt;I reckon there are 2 ways to look at it:&lt;/p&gt;
&lt;p&gt;You can think of WebDirect as a way to access FileMaker solutions from a web browser. Yes, that means you don&#039;t have to license and install the FileMaker application on everyone&#039;s computer!&lt;/p&gt;
&lt;p&gt;WebDirect used this way is ideal for people who don&#039;t need to work within a FileMaker system all day, every day. The FileMaker Pro application is still more powerful and does some things a lot better, like printing and producing PDFs. But for occasional users or people who only need to do a few specific things in the database, then this is an easier way to get them onto it.&lt;/p&gt;
&lt;p&gt;Or&lt;/p&gt;
&lt;p&gt;You can think of WebDirect as a low cost way to provide a &#039;web app&#039; for people outside your organisation, say your clients or contractors, to interact with you.&lt;/p&gt;
&lt;p&gt;Whichever way you look at it, WebDirect is revolutionary and there&#039;s honestly very little, if anything, out there that&#039;s comparable.&lt;/p&gt;
&lt;h4&gt;Slick New Interface Widgets&lt;/h4&gt;
&lt;p&gt;FileMaker 13 brings quite a few new ways to make better looking and easier to use screens. Behind the scenes we&#039;ve got a lot more control over how things look and behave too, with styles, customisable themes, and visibility control (so we can hide the sh*t you don&#039;t need right now).&lt;/p&gt;
&lt;p&gt;More obviously though are the two new types of control: Pop-overs and Slides... these are very web like and add to that &#039;liveliness&#039; feeling when you&#039;re using a system.&lt;/p&gt;
&lt;p&gt;Pop-overs bring up more information or options without having to open a new window or dialog box. They help keep things uncluttered while having more detailed information or additional options easy to access without going to a different screen or new window.&lt;/p&gt;
&lt;p&gt;Slides come from the mobile world, and in FileMaker Go (the iPhone and iPad version of FileMaker), they work by swiping left and right to move between slide panels. Slides help you access more information or move to the next step, without having to leave the screen you&#039;re on.&lt;/p&gt;
&lt;h4&gt;Licensing&lt;/h4&gt;
&lt;p&gt;You might also be interested to know how FileMaker Inc intend to make money from this if you can use a FileMaker solution from a free web browser now?&lt;/p&gt;
&lt;p&gt;Sadly although owned by Apple, which has more money than God, FileMaker Inc. is required to keep its head above water all by itself, so there&#039;s a new licensing system:&lt;/p&gt;
&lt;p&gt;Basically, to connect the free clients (WebDirect and FileMaker Go) you&#039;ll need some concurrent connection licenses for your FileMaker Server. The more you have, the more WebDirect and FileMaker Go licenses you can have on the system at any one time.&lt;/p&gt;
&lt;h4&gt;What else do you need to know?&lt;/h4&gt;
&lt;p&gt;Well, we&#039;ll be going more in depth in our FileMaker blog to look into the new stuff, and how to use but I will also add that there&#039;s a lot you don&#039;t see like speed improvements in both Server and FileMaker Go, and ongoing development of things like the backup process, SQL engine and 64-bit capabilities.&lt;/p&gt;
&lt;p&gt;In fact one thing to note is that because of changes to the SQL in FileMaker we&#039;re releasing an update to our Reactor plugin (that does Calendars, Gantt charts etc) in the next few days?so keep an eye on that over at &lt;a href=&quot;http://www.fusionplugins.com/&quot;&gt;Fusion Plugins&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We&#039;re rapt to see the FileMaker platform embracing the web and mobile spaces even more, and as always maintaining its place as one of the fastest and most robust ways to build database solutions there is.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.teamdf.com/contact/&quot;&gt;Drop us a line&lt;/a&gt; or fire questions at us via this blog and we&#039;re more than happy to fill you in on the finer points.&lt;/p&gt;</description>
			<pubDate>Wed, 04 Dec 2013 00:23:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker13/</guid>
		</item>
		
		<item>
			<title>Xerocon - If only I could come up with a better blog title</title>
			<link>https://www.teamdf.com/blogs/xerocon-if-only-i-could-come-up-with-a-better-blog-title/</link>
			<description>&lt;p&gt;Next week three DF&#039;ers are heading to Xerocon in Sydney. As first timers we thought we better make a bit of a splash so have been putting our &#039;thinking caps&#039; on and have come up with a bit of a competition (of sorts)&lt;/p&gt;
&lt;p&gt;Our tag line for the conference is &#039;If only?.&#039; which forms that basis for our booth and speech. The idea behind the tag line stems from our custom software development heritage, we develop solutions that are tailor made to you or your clients needs. This might be along the lines of developing a shopping cart that integrates with Xero, a database that invoices via Xero or the big bertha, a database and website and Xero, all interlinked.&lt;/p&gt;
&lt;p&gt;So back to the competition, we want to hear what &#039;If only?..&#039; you can come up with. Some of the ones we have tossed around are &#039;If only?I had bought my Xero shares two years ago&#039; or &#039;If only?.there were more beans to count&#039;. We want you to put your &#039;thinking caps&#039; on and and come up with some equally fun sayings. The more topical to Xerocon the better.&lt;/p&gt;
&lt;p&gt;If we like your idea and contact you via &lt;a href=&quot;https://twitter.com/&quot;&gt;Twitter&lt;/a&gt;, come see us at the conference (Booth 33) and pick up a t-shirt.&lt;/p&gt;
&lt;p&gt;While you are there, you can enter the draw to win an iPad mini.&lt;/p&gt;
&lt;p&gt;Remember to hashtag your idea with &lt;a href=&quot;https://twitter.com/search?q=#xerocon&amp;amp;src=hash&quot;&gt;#xerocon&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Tue, 20 Aug 2013 04:55:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/xerocon-if-only-i-could-come-up-with-a-better-blog-title/</guid>
		</item>
		
		<item>
			<title>Xero Makes It Big In Australia</title>
			<link>https://www.teamdf.com/blogs/xero-makes-it-big-in-australia/</link>
			<description>&lt;p&gt;Earlier this month we saw the results of &lt;a href=&quot;http://www.teamdf.com/about/xero-approved-developer/&quot; target=&quot;_blank&quot;&gt;Xero&#039;s&lt;/a&gt; continued growth, particularly the increase in users in Australia. With a growth rate of 219% for the year, we are starting to see that businesses in Australia are really getting behind the products (32% of all users are Australian based). We are also starting to see some of the unique requirements that go with using the solution in Australia.&lt;/p&gt;
&lt;p&gt;By nature, Australian businesses are typically larger and have a focus not just on business in Australia but also into the Asian region. They are also a number of years ahead of New Zealand businesses in terms how they expect to integrate other parts of their IT solutions into Xero and finding solutions that will save them money and time. This might be via shopping carts, CRM&#039;s or payment gateways but each have their unique requirements, particularly taking into account the need to transact in foreign currencies.&lt;/p&gt;
&lt;p&gt;As &lt;a href=&quot;http://www.teamdf.com/contact/&quot;&gt;Digital Fusion&lt;/a&gt; have an office and staff in Australia and a large part of our business comes from there, we understand the needs better than most and are able to put our experience to good use when it comes to website or database integration.&lt;/p&gt;
&lt;p&gt;We have a number of projects on the go at the moment where we are integrating large scale development projects (both &lt;a href=&quot;http://www.teamdf.com/services/web-design-development/&quot;&gt;web&lt;/a&gt; and &lt;a href=&quot;http://www.teamdf.com/services/filemaker-development/&quot;&gt;FileMaker&lt;/a&gt;) into Xero, in multi currencies and multi sites. One of the good things about this is our level of experience grows with each project and we like to think we are at the forefront of Xero development and integration in Australia.&lt;/p&gt;
&lt;p&gt;We use Xero &lt;a href=&quot;http://blog.xero.com/2011/07/xero-meant-nothing-till-now/&quot;&gt;ourselves&lt;/a&gt; so we understand the need to make it work for you. As with all things, we are keen to discuss what solution you require and how we can help. Do send us an email or give us a &lt;a href=&quot;http://www.teamdf.com/contact/&quot;&gt;call&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/558/206_1.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Tue, 16 Apr 2013 10:41:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/xero-makes-it-big-in-australia/</guid>
		</item>
		
		<item>
			<title>On the Right Track</title>
			<link>https://www.teamdf.com/blogs/on-the-right-track/</link>
			<description>&lt;p&gt;We recently finished an &lt;a title=&quot;Canterbury Track Cycling iPad FileMaker Go Solution&quot; href=&quot;https://www.teamdf.com/work/canterbury-track-cycling-website/&quot;&gt;iPad solution for Canterbury Track Cycling&lt;/a&gt; using FileMaker Go. Known as RacePlace, it records the results of their club racing, championships and special events and integrates smoothly with the website we built for them at the end of last year.&lt;/p&gt;
&lt;p&gt;There are lots of nifty mobile apps out there, but there are a few things that make this one a bit different, mainly that we&#039;ve used the mobile version of FileMaker - &lt;em&gt;FileMakerGo&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Why use FileMaker Go?&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Using FMGo makes development fast... and fast in the world of custom software equals affordable&lt;/li&gt;
&lt;li&gt;The solution can also be used offline (no internet connection) or online making results uploadable to the website in real time as race meetings are in progress&lt;/li&gt;
&lt;li&gt;Anyone with an iPad can record the results which means the organisers are not dependent on any one person to ensure results are published in a timely fashion&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;br&gt;If we&#039;d a approached this project using web technologies (HTML5) the solution would have to be connected to the internet to be used fully, thus restricting the recording of the results to those with a 3G iPad.&lt;/p&gt;
&lt;p&gt;The iOS (native app) platform was also an option, but the cost would have been much greater and speed of deployment inhibited. Approval from the App Store would have been needed before release of the initial version and any subsequent iterations.&lt;/p&gt;
&lt;p&gt;All this means FMGo is a very viable alternative for SME&#039;s looking for a mobile solution to help run their business?something that may not have been an option in the past.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Thu, 07 Mar 2013 17:06:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/on-the-right-track/</guid>
		</item>
		
		<item>
			<title>Gone Wild</title>
			<link>https://www.teamdf.com/blogs/gone-wild/</link>
			<description>&lt;p&gt;&lt;a title=&quot;FileMaker Weetbicks&quot; href=&quot;http://www.teamdf.com/weetbicks/&quot;&gt;Weetbicks&lt;/a&gt;, our FileMaker development blog, is well known within the FileMaker community. Daniel&#039;s articles help other developers with ways to work around sticky problems. But in the last two months, the FileMaker Weetbicks blog has dried up a little ? Daniel has gone M.I.A.!&lt;/p&gt;
&lt;p&gt;Fret not friends, Daniel is safe and sound in Ethiopia. He&#039;s part way though an &lt;a title=&quot;Gone Wild&quot; href=&quot;http://www.teamdf.com/gonewild/tour&quot;&gt;epic cycling journey&lt;/a&gt; that started in Cairo and ends in Cape Town. That&#039;s a staggering 12,000kms through 10 of the world&#039;s hottest countries. We think he&#039;s CRAZY!&lt;/p&gt;
&lt;p&gt;His blog of adventures has given us an insight into the heart of Daniel and Africa. While you&#039;re sitting there drinking your coffee, reading and laughing at Daniel&#039;s situation, consider giving a little to the Heart Foundation. He&#039;s riding for them and has set a target of $12,000 ($1 per km). &lt;a title=&quot;Help Daniel by donating to the Heart Foundation&quot; href=&quot;http://www.teamdf.com/gonewild&quot;&gt;Skip tomorrow&#039;s coffee and donate that $5&lt;/a&gt;. Every little bit helps. One Man. One Bike. A Whole Lot Of Heart.&lt;/p&gt;</description>
			<pubDate>Tue, 01 Jan 2013 15:26:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/gone-wild/</guid>
		</item>
		
		<item>
			<title>Miami Nice</title>
			<link>https://www.teamdf.com/blogs/miami-nice/</link>
			<description>&lt;p&gt;In the cold of July Daniel, Julie and myself packed our skimpiest summer gears, sprayed on the tan and headed to body-beautiful Miami? OK it wasn&#039;t exactly like that, but it was hot hot hot and the hotel Fontainebleau was a classy venue, right on the beach.&lt;/p&gt;
&lt;p&gt;The real reason we headed to Miami was of course the annual FileMaker Developer Conference where over 1200 of the best developers from around the world gather to indulge in all things FileMaker.&lt;/p&gt;
&lt;p&gt;So what did we indulge in? The odd cocktail may have been consumed, but DevCon is most definitely a geek?fest so invariably the conversation is very technical. I won&#039;t bore you with the details but suffice to say there was plenty of knowledge to be shared and great ideas gleaned.&lt;/p&gt;
&lt;p&gt;The real value of attending a global event like this is the chance to get a sense of where things are going and to be inspired by seeing some of the amazing things others are doing? like a Japanese solution for dental surgeons where you draw on a patient&#039;s teeth using an iPad. You draw on the iPad I mean.&lt;/p&gt;
&lt;h4&gt;Out There&lt;/h4&gt;
&lt;p&gt;This year the overwhelming sense was that &quot;mobile&quot; is really taking off in business, and that means iPhones and iPads finally getting down to some serious work?&lt;/p&gt;
&lt;p&gt;This is a tectonic shift in how technology is used ? it&#039;s a whole new game. You can now empower anyone in a workplace with a computer, camera, GPS and mobile internet connection, and all disguised as nothing more than a flashy phone.&lt;/p&gt;
&lt;p&gt;Not surprisingly then DevCon 2012 featured a number of sessions on developing specifically for mobile devices, from user interface design to performance enhancing magic.&lt;/p&gt;
&lt;p&gt;Another hot topic is &quot;location awareness&quot; ? an iPhone or iPad can know which job you&#039;re on if your work is location based so why not automatically bring up information about that job? (Of course it also knows when you&#039;re at the pub and could potentially log that too?)&lt;/p&gt;
&lt;h4&gt;Faster, Pussycat&lt;/h4&gt;
&lt;p&gt;Behind the commercial needs are the technology challenges, and what we saw at DevCon was that speed is the big one which everyone is tackling head on.&lt;/p&gt;
&lt;p&gt;For a start if you&#039;re mobile, you can&#039;t count on being connected to the mothership so there was a lot of discussion about synchronizing data, whereby database records are copied onto the device so it doesn&#039;t matter if cell reception is crap. Things work much faster this way too, so it&#039;s a better experience all round.&lt;/p&gt;
&lt;p&gt;But you also need to get connected and store everything centrally, so there were sessions on optimizing databases for &quot;WAN&quot; (over the Internet) performance. Engineers and product mangers from FileMaker Inc made it clear that performance, particularly over the internet, is a huge priority for them going forward.&lt;/p&gt;
&lt;h4&gt;New Interfaces&lt;/h4&gt;
&lt;p&gt;And what would a geek conference be without some new technology? In FileMaker 12 it&#039;s the new &#039;CSS&#039; web technology that gives us the ability to make much better looking screens, that feel contemporary and dynamic, just like the web kids do.&lt;/p&gt;
&lt;p&gt;Alas it&#039;s also still very easy to mess it up, so to go with the new tools there were sessions on User Interface design and Usability, including a great lecture by Heather Winkler who is head of UI at FileMaker Inc. In fact there were a lot of sessions from FileMaker staff ? a lot more than before, and really good to see because they&#039;re often able to give us a whole new level of insight, after all they know what&#039;s going on &#039;cause they built the product!&lt;/p&gt;
&lt;p&gt;Aside from the sessions and discussions, cocktails and beers, awards (see Mad Dog Daniel Wood) and nice dinners, we got to spend time chewing the fat with the FileMaker engineers and product managers. We were rapt to hear the way they&#039;re talking about FileMaker as a platform now, for business innovation, embracing &#039;app&#039; development and looking well out into the future. FileMaker 12 is a foundation version and opens the way for some very cool stuff to come yet.&lt;/p&gt;
&lt;p&gt;Right, so get back to Silicon Valley people and get to it, please.&lt;/p&gt;</description>
			<pubDate>Tue, 11 Sep 2012 15:17:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/miami-nice/</guid>
		</item>
		
		<item>
			<title>Out of the Wild</title>
			<link>https://www.teamdf.com/blogs/out-of-the-wild/</link>
			<description>&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/522/188_1.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Apple released its new operating system, Mountain Lion, a couple of weeks ago. As it is always a good idea to test new software before deploying it to all computers in a business, we tested it on a few computers, just to make sure not to run into serious problems.&lt;/p&gt;
&lt;p&gt;However, Mountain Lion (OS X 10.8) held up to the excitement one could find in the Apple fan community prior to release: it is more stable, quicker, uses less resources and altogether makes a far better impression than its predecessor Lion (OS X 10.7).&lt;/p&gt;
&lt;p&gt;Although Apple mainly indicated that this upgrade is a minor one - like before with the step from Leopard to Snow Leopard - Apple addressed not only performance issues, but also made a significant amount of changes to the system. I will give you a quick tour through some of the more noticeable changes now.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/523/188_2.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;What is new for users who had Lion installed already:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;You will find a notification column on the right now, which might look familiar if you are using iOS 5 on your iPhone or iPad. In this column you can find info about new emails, incoming chats, calendar events and everything else your computer wants to tell you.&lt;/li&gt;
&lt;li&gt;Safari got an overhaul and is apparently much nicer and smoother to use now. There is only one address field, which also serves as google search bar - Chrome users might recognise this. Also there is a new &#039;Share&#039; button, which lets you share pages via mail, messenger / ichat, Twitter, Facebook?&lt;/li&gt;
&lt;li&gt;Apple made some minor improvements to the launchpad, mouse-gestures and some other stuff like notes and reminders.&lt;/li&gt;
&lt;li&gt;iChat is now Messenger! If you are used to iChat thhe new Messenger takes a bit of getting used to - but it is worth it! The history function that keeps past conversations accessible can be very helpful, although it is harder to check who is online. However, you can activate the &#039;old&#039; buddy list through the menu and enjoy the new functions without loss.&lt;/li&gt;
&lt;li&gt;Software update is now completely integrated in App Store. This can be a little bit of an issue when multiple users install software with different Apple-IDs, but important system updates will be unaffected and work fine.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Coming from (Snow) Leopard, there is MUCH more:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Additional to all the stuff above, you will notice that your mouse scrolling now works the other way round. It needs a bit getting used to it, but once you adjusted it is actually quite nice.&lt;/li&gt;
&lt;li&gt;Mail got an overhaul with grouping emails in a nice way and some smaller changes here and there. Altogether a plus in my opinion!&lt;/li&gt;
&lt;li&gt;The Application starter from the task bar is now called Launchpad and looks more like iOS. I don&#039;t like it that much, but it might be a question of taste?&lt;/li&gt;
&lt;li&gt;ExposÃÂ© (the multiple desktop system) is now called MissionControl and is combined with the &#039;show all programs&#039; (function key F3) button. This is quite an improvement, and if you have a magic mouse or a touchpad, you can easily swipe between screens with two fingers.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;There are quite a few more changes, I guess, but I can&#039;t remember all of them. So just do the upgrade and enjoy.&lt;/p&gt;
&lt;p&gt;Just a little warning at the end: the upgrade takes about an hour (not including the time to download the 4GB image from the App Store) and Spotlight will reindex your computer in the first hour or so after login, which makes your computer react a bit slower than normal. However, once this is completed it should be as fast as ever - at last!&lt;/p&gt;</description>
			<pubDate>Tue, 11 Sep 2012 15:17:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/out-of-the-wild/</guid>
		</item>
		
		<item>
			<title>Daniel &#039;Mad Dog&#039; Wood</title>
			<link>https://www.teamdf.com/blogs/daniel-mad-dog-wood/</link>
			<description>&lt;p&gt;Our very own Daniel Wood has just been awarded the coveted Mad Dog PR Award at FileMaker DevCon 2012. The award recognises developers who have made a significant contribution to advancing the awareness of FileMaker in the media and community.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/500/183_1.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 18 Jul 2012 15:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/daniel-mad-dog-wood/</guid>
		</item>
		
		<item>
			<title>Weetbicks Trivia 1.0</title>
			<link>https://www.teamdf.com/blogs/weetbicks-trivia-1-0/</link>
			<description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;A little while ago I received an e-mail asking for ideas on how to implement a multiple choice testing database. It just so happens that I had begun to build a database a few years ago which does just that. While it is not finished, I have decided to release a first version for people to download, dissect and use.&lt;/p&gt;
&lt;h4&gt;Weetbicks Trivia&lt;/h4&gt;
&lt;p&gt;This database was built around 2008 and the original purpose behind it was to create a trivia database that could be placed on a FileMaker Server and where the database users would be able to take quizzes to test their knowledge in a range of areas - mainly FileMaker related. It was to be built up to be a nice certification training tool, or just to brush up on FileMaker knowledge.&lt;/p&gt;
&lt;p&gt;However other things got in the way and it was never finished. The toughest part was simply coming up with numerous FileMaker related questions. As with a lot of projects, the motivation disappeared and it sat around on my hard drive for years unfinished.&lt;/p&gt;
&lt;h4&gt;Revival&lt;/h4&gt;
&lt;p&gt;With an e-mail received recently asking about this type of database structure, I decided to brush off the database, give it a spruce up for FileMaker 12, and release it here for anyone to download.&lt;/p&gt;
&lt;p&gt;Hopefully if there is enough interest in the database I will continue to finish it.&lt;/p&gt;
&lt;p&gt;Currently it only contains a practise mode where you can choose one/all categories of questions, and you are presented with question after question until you can take no more testing :)&lt;/p&gt;
&lt;h4&gt;Future Versions&lt;/h4&gt;
&lt;p&gt;The plan has always been to make the database quite comprehensive and have different gameplay modes such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Beat the Clock: X questions in Y minutes as a quick-fire mode, kind of like the certification exam.&lt;/li&gt;
&lt;li&gt;Challenge: Pit your knowledge against another user by challenging them to a test.&lt;/li&gt;
&lt;li&gt;Tournament: One or more database users enter into a longer format challenge which can span multiple tests over multiple days to find an overall victor.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Stay tuned for future releases. The plan is to release a new version once enough new functionality is added, perhaps one mode at a time.&lt;/p&gt;
&lt;h4&gt;Download&lt;/h4&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/weetbickstrivia1/WeetbicksTrivia1.zip&quot;&gt;Download Weetbicks Trivia 1.0 &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Any feedback, comments, bugs, suggestions etc are very much appreciated, thanks!&lt;/p&gt;</description>
			<pubDate>Tue, 03 Jul 2012 14:30:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/weetbicks-trivia-1-0/</guid>
		</item>
		
		<item>
			<title>Sweet Scrolling in FileMaker Go 12</title>
			<link>https://www.teamdf.com/blogs/sweet-scrolling-in-filemaker-go-12/</link>
			<description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Portal scrolling has always been a bit of a struggle in FileMaker Go up until the release of version 12. This article outlines some of the changes to portal scrolling in FileMaker Go 12 and we give a couple of examples how it can be set-up to give a very nice native-application look and feel. We also cover field scrolling.&lt;/p&gt;
&lt;h4&gt;Getting that Native-App look&lt;/h4&gt;
&lt;p&gt;If you look at any regular application on the iPhone or iPad you&#039;ll notice they all have very similar looking scrolling. This is typified by a thin grey bar to give a visual cue as to where the scroll position is - yet there is no actual scrollbar present.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/sweetscrolling-1.png&quot; alt=&quot;sweetscrolling 1&quot; width=&quot;427&quot; height=&quot;640&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/sweetscrolling-2.png&quot; alt=&quot;sweetscrolling 2&quot; width=&quot;427&quot; height=&quot;640&quot;&gt;&lt;/p&gt;
&lt;p&gt;In these applications the scroll indicator is close up to the right edge of the screen. You&#039;ll notice it can even slightly overlay some of the contents, as if the scroll is floating on top of everything else. This is what we are going to try and replicate for our FileMaker Go layout for iPhone.&lt;/p&gt;
&lt;h4&gt;Our iPhone layout design&lt;/h4&gt;
&lt;p&gt;So below we have a layout that we have designed to be used on an iPhone running FileMaker Go 12. This layout mostly contains a portal and as you can see in the image, we too have a little grey scroll indicator up to the right edge of screen.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/_resampled/ResizedImage425637-sweetscrolling-3.png&quot; alt=&quot;sweetscrolling 3&quot; width=&quot;425&quot; height=&quot;637&quot;&gt;&lt;/p&gt;
&lt;p&gt;You may be asking yourself why we didn&#039;t just use a list-view layout as opposed to a portal - surely that would have been easier. There are a couple of reasons why we chose not to:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;We do not wish for our context to be that of the portal (or a list-view layout).&lt;/li&gt;
&lt;li&gt;Portals have a tendency to render much faster than records in list-view. This means they feel much more like a faster native application, and we don&#039;t see so much blocky rendering happening.&lt;/li&gt;
&lt;li&gt;Portals in FileMaker Go 12 no longer require to be clicked into before you can begin scrolling which was the case in FileMaker Go 11. This means they are actually usable now!&lt;/li&gt;
&lt;li&gt;With a portal you get a nice left-edge of the screen without the list-view thin bar you get to indicate current record.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;If we look at the layout in layout mode, you can see how this effect has been achieved.&lt;/p&gt;
&lt;p&gt;&lt;a&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/sweetscrolling-4.png&quot; alt=&quot;sweetscrolling 4&quot; width=&quot;368&quot; height=&quot;496&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What we have done is to simply place the visible scroll-bar portion of the portal off the right edge of the layout. This means the visual scroll bar never appears on-screen but the grey scroll indicator does given that it is appearing to the left of the scroll bar - the area of which is still on screen.&lt;/p&gt;
&lt;p&gt;It is a very strange thing that portals in FileMaker Go 12 should even render with a scrollbar at all - they are completely useless and do not actually serve any functional purpose as we shall see later. Good thing we can now hide things off the edge of the screen!&lt;/p&gt;
&lt;h4&gt;What about scrolling within a layout?&lt;/h4&gt;
&lt;p&gt;Scrolling when the portal extends to the edge of the layout is fine because we can simply hide the scroll bar off the edge of the layout. But what if we have a portal we want to scroll that is contained within the layout too far from the edge to be hidden?&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/sweetscrolling-5.png&quot; alt=&quot;sweetscrolling 5&quot; width=&quot;427&quot; height=&quot;640&quot;&gt;&lt;/p&gt;
&lt;p&gt;Let&#039;s consider the screen above. In this case we have a portal that is not touching the edge of the layout. Never fear! We can still achieve the same desired effect with a little jiggery pokery.&lt;/p&gt;
&lt;h4&gt;But first...&lt;/h4&gt;
&lt;p&gt;Before we show how this effect can be achieved let&#039;s investigate why a regular portal is a bad idea to be used on-screen in FileMaker Go 12 for scrolling.&lt;/p&gt;
&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/sweetscrolling-6.png&quot; alt=&quot;sweetscrolling 6&quot; width=&quot;427&quot; height=&quot;640&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/_resampled/ResizedImage424398-sweetscrolling-7.png&quot; alt=&quot;sweetscrolling 7&quot; width=&quot;424&quot; height=&quot;398&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we have a typical portal displayed within the layout shown in both browse mode and layout mode. We have some rounded corners on the portal because the desired effect is to show a rounded white box on the screen with the records within. The scrollbar is clearly visible for all to see.&lt;/p&gt;
&lt;p&gt;Now, what do you suppose would happen if the user began to run their finger up the portal to scroll? Well, it&#039;s a scrollbar so you may expect it to look how it might in FileMaker Pro, surely.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/sweetscrolling-8.png&quot; alt=&quot;sweetscrolling 8&quot; width=&quot;427&quot; height=&quot;640&quot;&gt;&lt;/p&gt;
&lt;p&gt;As soon as the user begins to scroll, the scroll bar disappears entirely! This leaves no right edge to the portal which means it no longer has rounded right edges. The grey scroll indicator you can see is still present aligned to the left of where the scroll bar used to be.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/sweetscrolling-9.png&quot; alt=&quot;sweetscrolling 9&quot; width=&quot;427&quot; height=&quot;640&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this above picture, the user has stopped scrolling, but the scroll bar is still nowhere to be seen. In fact, the only time the scroll bar appears is when the user is not in the portal. It can be made to reappear when the user clicks elsewhere on the layout - but when it appears it is simply a scrollbar with no actual use. We should just get rid of it entirely!&lt;/p&gt;
&lt;h4&gt;Hide the scrollbar by covering it up&lt;/h4&gt;
&lt;p&gt;We&#039;ve all done this in FileMaker development at some point or another - cover up layout objects with other objects. Fortunately in FileMaker Go 12, if you cover just the scroll bar part of a portal with another object, the scroll bar will never appear, or jump in front of it&#039;s overlaying object, so it is quite simple to hide them.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/_resampled/ResizedImage429303-sweetscrolling-10.png&quot; alt=&quot;sweetscrolling 10&quot; width=&quot;429&quot; height=&quot;303&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we have placed a graphic over top of the scrollbar. It should be noted here that because the portal scrollbar constitutes the right-edge of the portal, then with it disappearing we no longer have a rounded right edge to display. To remedy this, we have made the portal transparent, and placed a rounded rectangle beneath the portal instead.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/sweetscrolling-11.png&quot; alt=&quot;sweetscrolling 11&quot; width=&quot;251&quot; height=&quot;135&quot;&gt;&lt;/p&gt;
&lt;p&gt;It does not matter where the portal scroll bar is positioned so long as it can be overlaid. In this case we wanted to get the scroll indicator positioned in such a place that means the scroll bar is part-on and part-off the layout. This is no problem however.&lt;/p&gt;
&lt;h4&gt;Scrolling of text fields&lt;/h4&gt;
&lt;p&gt;The next challenge we encountered with scrolling in FileMaker Go 12 came when we tried to scroll a text field on the layout. In FileMaker Pro 12 if you want to scroll a text field you put a scrollbar on it, click into the field, and then begin scrolling. Unfortunately it&#039;s not so easy in FileMaker Go 12.&lt;/p&gt;
&lt;p&gt;&lt;a&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/sweetscrolling-12.png&quot; alt=&quot;sweetscrolling 12&quot; width=&quot;333&quot; height=&quot;480&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here we have a field on the layout. Note we have no scrollbar. The reason is that once the user is clicked in the field, they can scroll whether there is a scrollbar or not, so it is again kind of a redundant artifact to be showing on a field.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/sweetscrolling-13.png&quot; alt=&quot;sweetscrolling 13&quot; width=&quot;427&quot; height=&quot;640&quot;&gt;&lt;/p&gt;
&lt;p&gt;So, here is the field in browse mode showing lots of text, too much to see on screen at once, so we really want to be able to scroll. Let&#039;s try clicking into the field ala FileMaker Pro 12.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/sweetscrolling-14.png&quot; alt=&quot;sweetscrolling 14&quot; width=&quot;427&quot; height=&quot;640&quot;&gt;&lt;/p&gt;
&lt;p&gt;Problem! in FileMaker Go 12 when you click into a field, it automatically reveals the keyboard in anticipation for input. It does not know that we merely want to view and scroll the information in the field, not edit it! We don&#039;t want to show the keyboard every time we want to scroll, nor do we want to have to click into the field to begin scrolling. It would be nice if it performs like portals do.&lt;/p&gt;
&lt;h4&gt;Web viewers to the rescue&lt;/h4&gt;
&lt;p&gt;One solution to this issue we found was to use web viewers instead. In FileMaker Go 12, the web viewers exhibit a nice scrolling experience much the same as portals. Also they do not reveal the keyboard because there is no field to click into.&lt;/p&gt;
&lt;p&gt;The one difference between web viewers and portals however is that a web viewer must be clicked into and given focus before it will scroll, it does not register scrolling automatically. We can overcome this however through using some script triggers, more on this below.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/sweetscrolling-15.png&quot; alt=&quot;sweetscrolling 15&quot; width=&quot;341&quot; height=&quot;477&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/_resampled/ResizedImage600648-sweetscrolling-16.png&quot; alt=&quot;sweetscrolling 16&quot; width=&quot;600&quot; height=&quot;648&quot;&gt;&lt;/p&gt;
&lt;p&gt;In order to display the fields contents we are using a &lt;a href=&quot;http://en.wikipedia.org/wiki/Data_URI_scheme&quot;&gt;Data URL&lt;/a&gt;. This allows us to render text in the field directly via the web viewer without the need for plugins - which are not compatible with FileMaker Go anyway.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/sweetscrolling-17.png&quot; alt=&quot;sweetscrolling 17&quot; width=&quot;427&quot; height=&quot;640&quot;&gt;&lt;/p&gt;
&lt;p&gt;The end result is quite nice. To overcome the fact the web viewer has to be in focus to be scrolled, we are ensuring that when we go to the above particular screen, we go directly to the web viewer through a Go to Object script step. By arriving at this screen directly in the web viewer, the user can begin scrolling right away.&lt;/p&gt;
&lt;p&gt;In the picture above we have used data:text/plain as our data URL scheme which gives the font in courier. This lets the text automatically wrap itself to the edge of the web viewer so we have no side-scrolling required to view all of the text. We are sure there are always to alter the font and retain this behavior but have not investigated this further.&lt;/p&gt;
&lt;p&gt;Because in this solution nothing is editable, the user has no reason to leave the web viewer unless they choose to via one of the navigation buttons. To keep the scroll alive, we put a simple little script trigger on the web viewer for the onObjectExit condition.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/_resampled/ResizedImage600462-sweetscrolling-18.png&quot; alt=&quot;sweetscrolling 18&quot; width=&quot;600&quot; height=&quot;462&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Sweet-Scrolling/sweetscrolling-19.png&quot; alt=&quot;sweetscrolling 19&quot; width=&quot;344&quot; height=&quot;140&quot;&gt;&lt;/p&gt;
&lt;p&gt;Whenever the user attempts to leave the web viewer, they will only succeed in doing so if the parameter to the script is non-empty. Because we are passing the current script name as a parameter - it means the user will only be able to exit the web viewer if navigating away from it via script. If they manually attempt to click outside of the web viewer - e.g. on the layout - then this will fail and they will be kept in the web viewer. Because all of our navigation is from scripts, this ensures that when a script tries to navigate the user away from this screen it will succeed in doing so.&lt;/p&gt;
&lt;h4&gt;Just a note about web viewers in FileMaker Go 12&lt;/h4&gt;
&lt;p&gt;In building the database on which this article is based we encountered a number of rendering issues with the web viewers in FileMaker Go 12. Often the web viewers simply fail to render anything, and are displayed as a black box. Other times they part-render insomuch as they display as a blank white box instead of black! It is only about 1/2 the time that they actually work properly and render the contents of the data URL.&lt;/p&gt;
&lt;p&gt;We have also noticed other issues with web viewers in FileMaker Pro 12 Advanced which are bugs, and we have been submitting these to FileMaker in the hopes they will be resolved in an upcoming patch. So fingers crossed the reliability of the web viewer improves in future releases so that this technique becomes 100% reliable :)&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file is provided to help you fully understand what is going on in this article, and to let you experiment with this solution in both FileMaker Pro and FileMaker Go.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/sweetscrolling/SweetScrolling.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 14 May 2012 18:06:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/sweet-scrolling-in-filemaker-go-12/</guid>
		</item>
		
		<item>
			<title>Being there is everything</title>
			<link>https://www.teamdf.com/blogs/being-there-is-everything/</link>
			<description>&lt;p&gt;Digital Fusion have been working out of Australia for a few years now, sharing an office in Sydney with one of our favourite clients - Streamtime. During this time we&#039;ve had good success but not good enough for our liking.&lt;/p&gt;
&lt;p&gt;And running an operation in this vibrant city is pricey and we didn&#039;t feel like we were doing the best we could for the dollars we were spending.&lt;/p&gt;
&lt;p&gt;Now I know what you&#039;re thinking... but we didn&#039;t decide to close the office - quite the opposite in fact. Working on the premise that being there is everything, we&#039;ve leased our own office that comes complete with a 2 bedroom upstairs apartment.&lt;/p&gt;
&lt;p&gt;We&#039;re making it super-easy for our Christchurch team to be in Sydney, by providing some very stylish digs - this way they?ll get there more often, increasing our presence in this fantastic market.&lt;/p&gt;
&lt;p&gt;Already we&#039;ve had a steady flow of developers working over the ditch, both onsite with clients and in the office itself. With the continuous and rapid evolution of tools like VOIP (Voice Over IP) phone systems and centrally hosted databases, the office in which we do our work is becoming less and less relevant.&lt;/p&gt;
&lt;p&gt;So next time you&#039;re talking to one of our team, you never know where in the world they might be... here in Christchurch or in our new office in Sydney.&lt;/p&gt;</description>
			<pubDate>Thu, 19 Apr 2012 11:09:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/being-there-is-everything/</guid>
		</item>
		
		<item>
			<title>Hook me up.... connecting FileMaker with your website </title>
			<link>https://www.teamdf.com/blogs/hook-me-up/</link>
			<description>&lt;p&gt;As our human race progresses through the ages, we&#039;re constantly after a bigger bang for our buck. We want more for less: more productivity for less effort i.e. efficiency.&lt;/p&gt;
&lt;p&gt;In business, the biggest productivity gains come from automating our processes and connecting all facets of our business. Each time one thing automatically links to another, one of your precious team members reclaims time that can be used to add better value to your business.&lt;/p&gt;
&lt;h4&gt;So how does this apply to the systems we use?&lt;/h4&gt;
&lt;p&gt;If our potential customers are able to find out about our company, the services we provide, and the products we sell without having to wait to speak to someone. That&#039;d be a good thing, right?&lt;/p&gt;
&lt;p&gt;And if our customers can then order the products they want, with real-time feedback on stock availability at a time that?s convenient to them. Surely they&#039;ll keep coming back for more, yes?&lt;/p&gt;
&lt;p&gt;And if our customers can pay their account, update their contact details and download a copy invoice, all from the comfort of their home, office or pool-side recliner. That has to be a win-win!&lt;/p&gt;
&lt;p&gt;Never far from our client&#039;s primary objectives are improvements to efficiency. And the best way to improve that is to automate and connect.&lt;br&gt;At Digital Fusion we like to think of ourselves as connection experts - in particular FileMaker to Web. There?s two ways to make this all-important love connection:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Take information from your FileMaker database and show it on your website (product info, stock levels etc)&lt;/li&gt;
&lt;li&gt;Grab information entered on your website by your customers and drop it into your database (orders, contact details etc)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;New Zealand cycle clothing manufacturer, Ground Effect is a good case study. Customers can browse the current product range and even see the availability of different colours (very important for us girls). Online orders take a fast-track to dispatch, and customers can instantly update their delivery details.&lt;/p&gt;
&lt;p&gt;Printing company IBS Design have taken it even further, customers can generate their own quotes, place an order and track it right through to courier dispatch and delivery. Purchase history is also available, facilitating re-orders at the click of a button.&lt;/p&gt;
&lt;p&gt;The University of Canterbury students can view Community Education courses, place availability and enrol online. All of which is driven directly from their FileMaker database.&lt;/p&gt;
&lt;p&gt;Making these connections smooth and seamless can sometimes be tricky, but the rewards are huge. More and more it&#039;s what your customers expect - it&#039;s also going to make your staff happier, more productive and delivering better value to you (the business owner) and your customers.&lt;/p&gt;</description>
			<pubDate>Thu, 19 Apr 2012 11:08:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/hook-me-up/</guid>
		</item>
		
		<item>
			<title>Cool things to do with Tab Controls in FileMaker 12</title>
			<link>https://www.teamdf.com/blogs/tab-controls-overlay-menus-revealing-filemaker12/</link>
			<description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;FileMaker 12 is here, and with it comes many new cool new features, a lot of which are a result of the new css-based layout engine. In this article we are focusing on one small change borne out of the new layout engine which has massive potential for building new interface controls.&lt;/p&gt;
&lt;h4&gt;FileMaker 12&lt;/h4&gt;
&lt;p&gt;So FileMaker 12 is here and by now I&#039;m sure you are getting stuck into it and learning about all the cool new features. We figure rather than re-hashing the same feature lists that you have already seen, we will skip that and cut straight to the cool stuff - namely how can you use the new cool stuff in 12 to do even cooler stuff :)&lt;/p&gt;
&lt;p&gt;If you need to learn about any of the new features in FileMaker 12, here are some great resources to get you started:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://www.filemaker.com/products/filemaker-pro/all-features.html&quot;&gt;FileMaker version comparisons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://help.filemaker.com/app/answers/detail/a_id/10002/session/L3RpbWUvMTMzNDIxMjcwNi9zaWQvZmx6cFZxVms%3D&quot;&gt;FileMaker Knowledgebase Article&lt;/a&gt; documenting all of the changes - a great resource!&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.dbservices.com/articles/filemaker-12-whats-new&quot;&gt;FileMaker 12 Whats New&lt;/a&gt; from &lt;a href=&quot;http://www.dbservices.com&quot;&gt;DB Services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.dbservices.com/articles/filemaker-12-managing-container-data&quot;&gt;FileMaker 12 Managing Container Data&lt;/a&gt; also from DB Services&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.filemakermagazine.com/videos/filemaker-12-new-features.html&quot;&gt;New Features Video&lt;/a&gt; from Matt Petrowsky of &lt;a href=&quot;http://www.filemakermagazine.com&quot;&gt;FileMakerMagazine.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.filemakeracademy.com/&quot;&gt;12 days of FileMaker 12&lt;/a&gt; series of webinars from &lt;a href=&quot;http://www.filemakeracademy.com&quot;&gt;FileMaker Academy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;Tab controls are no longer hungry object-grabbers&lt;/h4&gt;
&lt;p&gt;In FileMaker 11, tab controls are an all or nothing type object when it comes to objects that they enclose. An object is either enclosed in a tab control, or not enclosed in a tab control, it cannot be half-in or half-out.&lt;/p&gt;
&lt;p&gt;This behavior made placing tab control objects over the top of existing layout objects a troublesome affair, especially if you did not wish for the tab control to enclose those objects. In FileMaker 11, objects could become enclosed when the tab control itself was moved or resized.&lt;/p&gt;
&lt;p&gt;Here is an example of what we mean:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/12overlay-1.png&quot; alt=&quot;12overlay 1&quot; width=&quot;311&quot; height=&quot;277&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is a tab control and inside it a field. The field is completely enclosed in the tab control - that is to say no edge of the field lies outside of the tab boundary.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/12overlay-2.png&quot; alt=&quot;12overlay 2&quot; width=&quot;327&quot; height=&quot;280&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can see, we can move the tab control to another location on the layout and the field moves with it. Everything enclosed in the tab moves with the tab.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/12overlay-3.png&quot; alt=&quot;12overlay 3&quot; width=&quot;189&quot; height=&quot;178&quot;&gt;&lt;/p&gt;
&lt;p&gt;Even putting the field outside of the tab boundary above is still considered enclosed in the tab.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/12overlay-4.png&quot; alt=&quot;12overlay 4&quot; width=&quot;464&quot; height=&quot;192&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we have a typical portal. One of the things you are bound to have done during development is attempt to enclose a portal in a tab or try to resize a tab control over a portal only to find some odd things happening if you don&#039;t quite get it right:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600218-12overlay-5.png&quot; alt=&quot;12overlay 5&quot; width=&quot;600&quot; height=&quot;218&quot;&gt;&lt;/p&gt;
&lt;p&gt;Uh-oh! It looks as if one of the fields that was in the portal is now gone. Where did it go? Well the answer is it went nowhere. Remember that everything not fully enclosed in the tab control is considered outside of it.&lt;/p&gt;
&lt;p&gt;Another key rule is that anything which falls partly in and partly out of a tab control will by default be placed &lt;strong&gt;in front of&lt;/strong&gt; the tab control.&lt;/p&gt;
&lt;p&gt;In the above example, the portal is in front of the tab and everything inside. One field managed to become fully enclosed inside the tab and that field now appears behind the portal.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600244-12overlay-6.png&quot; alt=&quot;12overlay 6&quot; width=&quot;600&quot; height=&quot;244&quot;&gt;&lt;/p&gt;
&lt;p&gt;If we now reposition the tab control you can see the portal field revealed behind the portal.&lt;/p&gt;
&lt;h4&gt;So what does this all mean?&lt;/h4&gt;
&lt;p&gt;FileMaker 12 is completely different in the way that it handles tab controls and enclosed objects. An object is still either enclosed in a tab control or not, but this is distinction is now visually blurred somewhat. Objects can appear to be enclosed in a tab control when in actuality they are not - they are simply behind or in front of the tab control.&lt;/p&gt;
&lt;p&gt;Whereas before a tab control would enclose any objects within its boundaries, in FileMaker 12 the user has to literally drag, copy and paste, or move an object within a tab control for it to be considered enclosed in that tab. We can best illustrate this with an example.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/12overlay-7.png&quot; alt=&quot;12overlay 7&quot; width=&quot;495&quot; height=&quot;307&quot;&gt;&lt;/p&gt;
&lt;p&gt;Again here we have a portal, this time in FileMaker 12&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600372-12overlay-8.png&quot; alt=&quot;12overlay 8&quot; width=&quot;600&quot; height=&quot;372&quot;&gt;&lt;/p&gt;
&lt;p&gt;When we drag the portal part-way into a tab control, you&#039;ll notice nothing disappears from view. The reason for this is that we dragged the entire portal plus fields into the tab control. FileMaker 12 treats this as a single moved object and because it does not entirely fall inside the tab, nothing is considered enclosed in the tab - not even the field that appears to be fully enclosed.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600374-12overlay-9.png&quot; alt=&quot;12overlay 9&quot; width=&quot;600&quot; height=&quot;374&quot;&gt;&lt;/p&gt;
&lt;p&gt;Because nothing is actually enclosed in the tab, we can now move the tab control around the layout. Moving the tab control in FileMaker 12 has &lt;strong&gt;no effect&lt;/strong&gt; on any of the objects on the layout in terms of them becoming enclosed in the tab control.&lt;/p&gt;
&lt;p&gt;Remember - layout objects cannot be placed inside a tab control by means of adjusting the tab control itself - only through moving an object into the tab control.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/12overlay-10.png&quot; alt=&quot;12overlay 10&quot; width=&quot;329&quot; height=&quot;133&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now look what happens when we move the field slightly. This time we are moving the field and not the tab control and we have moved it within the tab boundaries. The field is now considered to be enclosed in the tab.&lt;/p&gt;
&lt;p&gt;As a result, it now appears behind the portal that is still outside of the tab - just like it did in FileMaker 11. If we now move the tab, you&#039;ll notice the field moves with the tab.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/12overlay-11.png&quot; alt=&quot;12overlay 11&quot; width=&quot;396&quot; height=&quot;190&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Okay I get all that, so what is the benefit?&lt;/h4&gt;
&lt;p&gt;Well, the benefit is that you can create tab controls full of objects, then drag them somewhere on your layout and have them have no effect on existing layout objects. This may seem a pointless thing to do - why would you put objects in a tab control and them move them in front of other layout objects?&lt;/p&gt;
&lt;p&gt;One reason you might wish to do this is in creating overlay menus - hence the name of this article :) An overlay menu is one which we will activate via a button and the menu itself will become visible in front of any other objects on the layout. This functionality can be achieved through the use of a hidden tab control.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/12overlay-12.png&quot; alt=&quot;12overlay 12&quot; width=&quot;520&quot; height=&quot;405&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we have a tab control with 2 tabs. We have placed it on the layout and it happens to be covering part of a portal - no worry! Because we moved the tab control here, it has not enclosed any contents of the portal causing issues.&lt;/p&gt;
&lt;p&gt;The button on the first tab is hooked up to the &quot;Go to Object&quot; script step to take the user to the second tab - both tabs have object names.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/12overlay-13.png&quot; alt=&quot;12overlay 13&quot; width=&quot;309&quot; height=&quot;411&quot;&gt;&lt;/p&gt;
&lt;p&gt;And here is the second tab with the menu itself present. We have used some opacity on the menu so the user can see what the menu is overlaying. When the user wishes to hide the menu they just click the button which takes them back to the first tab. The overall effect is really quite nice.&lt;/p&gt;
&lt;h4&gt;The power of tab controls&lt;/h4&gt;
&lt;p&gt;Using this technique you could in fact end up building some rather cool menu and navigation systems. In FileMaker 12 layouts now have a right edge, so you can use the area outside of the layout for construction of your menu tab controls. When satisfied with them, simply drag them onto the layout wherever you want them to go. You could even group multiple tab controls into a single object to make it even easier. If you need to make changes to a menu, you can do so direct on the layout - just as long as you don&#039;t accidentally move any existing layout objects into one of the tab controls you&#039;ll be fine.&lt;/p&gt;
&lt;h4&gt;The case of the disappearing tab control&lt;/h4&gt;
&lt;p&gt;Another very awesome feature of tab controls in FileMaker 12 is the fact that once a layout object is classified as enclosed in a tab, it is in it until you move it out - no questions asked! This means even if you are to resize the tab control object, shrinking it down to a smaller size - those objects that it enclose are technically still in the tab control, just not visible and not accessible, here is an example:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/12overlay-14.png&quot; alt=&quot;12overlay 14&quot; width=&quot;332&quot; height=&quot;241&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we have reduced the height of the tab control, and as a result half of our menu is now gone. It is still in the tab but because the tab is smaller, it is inaccessible.&lt;/p&gt;
&lt;p&gt;Why would this be useful you ask? Well, you can very easily resize a tab control in this fashion to access underlying layout objects you wish to edit.&lt;/p&gt;
&lt;p&gt;What else could you do with this functionality? hmm. Let&#039;s say you create a tab-control object with a whole heap of stuff in it - a really tall tab control for example. Place it at the bottom of your layout and set it to anchor to top &amp;amp; bottom of the layout. Initially on the layout a user will not see anything, but as they begin to drag the layout height to make it taller, the tab control will reveal its secrets!&lt;/p&gt;
&lt;p&gt;Note that in testing this technique we discovered that placing the tab control too close to the bottom of the body part means when the layout is resized the tab control contents are not revealed. There seems to be a threshold point about 30-40 pts above the bottom of the layout part after which the contents don&#039;t reveal themselves - odd !&lt;/p&gt;
&lt;p&gt;You can find an example of this technique in the demo file supplied below.&lt;/p&gt;
&lt;h4&gt;A couple of &quot;bugs&quot; as of writing&lt;/h4&gt;
&lt;p&gt;With all new features in a new version of FileMaker Pro, there are bound to be some issues. In the example file you may notice that the overlay menu itself is actually constructed from a web viewer object rather than a straightforward rectangle object. The reason for this is that if the tab control is placed over an object such as a portal, then clicking in the tab control is actually going to click on the underlying object in some cases - in this case the portal. This means if you miss-click an item on the menu you may in fact click on a portal row instead.&lt;/p&gt;
&lt;p&gt;To fix this we use a web viewer because the web viewer object is always in front of portals no matter what, so you can freely click on the menu without it selecting underlying portal rows.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;when tested in FileMaker Go 12, this didn&#039;t work properly - the web viewer does not appear to render its transparency or colour in Go and instead is just a white void obscuring the menu items. Perhaps it would work better in that scenario with a rectangle for the menu instead of a web viewer.&lt;/p&gt;
&lt;p&gt;The technique for revealing layout contents on layout resizing doesn&#039;t exactly work great on the iPad where the only way to resize a layout is to change orientation - though it could be used for that purpose to reveal something when you enter portrait mode, and hide it when in landscape for example.&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This is a brand new example file for FileMaker 12.&lt;/p&gt;
&lt;p&gt;This file was used for &quot;most&quot; of the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/12overlays/FileMaker12TabControls.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In addition to this, Patrick Kenlock has also kindly submitted his example file of a cool thing you can do with tabs in FileMaker 12. His example allows you to toggle individual tab controls on or off, conditionally formatting them differently depending on whether they are toggled or not. He has also included an updated version of the example produced by David Jondreau, cheers guys!&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/12overlays/WhichTab.zip&quot;&gt;Download Patricks Example File&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/12overlays/WhichTabNew.zip&quot;&gt;Download Davids Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Fri, 13 Apr 2012 15:17:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/tab-controls-overlay-menus-revealing-filemaker12/</guid>
		</item>
		
		<item>
			<title>FileMaker 12: What&#039;s New?</title>
			<link>https://www.teamdf.com/blogs/filemaker-12-whats-new/</link>
			<description>&lt;p&gt;We&#039;re all buzzing about the new version of FileMaker that has just been released. There are all sorts of goodies for you as users and us as developers (and there are a few gotchas you should be aware of too).&lt;/p&gt;
&lt;p&gt;Let&#039;s start with the cool stuff for you:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Containers&lt;/strong&gt;, those fields that house photos and graphical data, are now easier to manage when they&#039;re stored externally. FileMaker Pro and FileMaker Server can keep all of your documents in a single location on the Server (or locally) and can encrypt them. The end result is that database files are smaller and so faster to back up, and all your files are stored in one place, rather than all over the place. Containers have also been optimized in 12 to be much faster to load, and are now capable of streaming audio and video, as well as displaying PDF&#039;s directly in the container. And you can drag &#039;n drop into containers now.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Progressive Backups&lt;/strong&gt; are now possible, meaning that only what has changed since the last backup needs to be backed up. If you have a large database, you&#039;ll see major speed improvements in the time it takes for you to do a backup.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Graphs&lt;/strong&gt; have been given expanded capability and a new user interface, so you may find that a graph that we couldn&#039;t do before is now possible.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FileMaker Go&lt;/strong&gt;, the FileMaker application for iPads and iPhones, has been brought into feature parity with FileMaker, meaning fewer limitations on that side of the fence.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Web Publishing:&lt;/strong&gt; there&#039;s been a complete rewrite of the FileMaker Web Publishing engine, to get better performance for Custom Web Publishing. The speed improvement is touted to be up to 100 times faster.&lt;/p&gt;
&lt;p&gt;For us as developers and for those of you who like to get your hands dirty, here are a few of of our favourite new features:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layouts based on Web Technology&lt;/strong&gt;: The Layout engine has been rebuilt based on CSS. This makes possible the styles and alignments described in the next two paragraphs. It also raises the hope that in the future, CSS-savvy developers might be able to make changes of their own, including designing customised database themes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Object Styles:&lt;/strong&gt; A bit like conditional formatting taken to new heights: you can specify different styles/colours for a button (or other object) when it is in focus, hovered over, pressed, or just sitting there. And colour gradients and transparency are available for the first time too.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Aligning Objects:&lt;/strong&gt; Guides that are local to a layout or global to all layouts in the database are now possible. It&#039;s much easier to keep the look and feel more uniform across a database. And FileMaker makes a real effort to help you keep fields aligned and buttons or fields of uniform size with its dynamic guidelines and same-size recognition.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Execute SQL function:&lt;/strong&gt; FileMaker is signalling greater support for SQL by expanding the existing Execute SQL from a script step that can only be used on external ODBC data to a function that can be used to query FileMaker databases. This means that records from unrelated tables can be queried without having to set up a relationship.&lt;/p&gt;
&lt;p&gt;Now the things to be aware of:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Mac OSX 10.5 (Leopard) and earlier, and Power PCs are no longer supported, so you won&#039;t be able to run FileMaker 12 on a Mac unless it&#039;s OS 10.6 (Snow Leopard) or later. Macs bought in 2009 or later should be fine (i.e. have 10.6) and older ones bought from 2006 onwards (Intel-based) can be upgraded.&lt;/li&gt;
&lt;li&gt;FM12 involves a file format change from earlier versions, which means it&#039;s not reversible: once you&#039;ve converted a database, it will be openable in FM12 only.&lt;/li&gt;
&lt;li&gt;If you have your own FileMaker Server, and you upgrade to 12, you&#039;ll need to upgrade your Server too.&lt;/li&gt;
&lt;li&gt;Conversions go pretty smoothly, but you can expect the odd problem and sometimes these can take a bit of time to resolve.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;</description>
			<pubDate>Thu, 12 Apr 2012 10:03:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-12-whats-new/</guid>
		</item>
		
		<item>
			<title>Changes to FileMaker Go 12</title>
			<link>https://www.teamdf.com/blogs/changes-to-filemaker-go-12/</link>
			<description>&lt;p&gt;FileMaker Go has been &quot;brought into feature parity with FileMaker Pro&quot;. In this article we&#039;ll look at what that means more specifically.&lt;/p&gt;
&lt;p&gt;Firstly, &quot;features&quot; don&#039;t extend to things like Layout mode, Manage Database or Edit Script: you still need to do development on a Desktop machine. And we&#039;ll include a list of some specific things that are not supported at the end of this article.&lt;/p&gt;
&lt;p&gt;But there&#039;s plenty of new stuff to get excited about:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Speed&lt;/strong&gt; - it&#039;s faster overall.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Preview Mode&lt;/strong&gt; is now supported where it was not previously. And air printing has been available since version 1.2 (no expansion of printing capabilities in the new version).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thumbnails&lt;/strong&gt; of images can now be generated and displayed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Importing&lt;/strong&gt; is hugely enhanced to take advantage of the things that iPhones and iPads do:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;import a photo or video capture from inbuilt camera&lt;/li&gt;
&lt;li&gt;import audio from inbuilt audio recorder&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Exporting&lt;/strong&gt; is expanded from just exporting a single record to exporting multiple records in a variety of formats, including pdf, csv, jpeg, mp3 and lots more, and offering email, save and view options.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Snapshot Link&lt;/strong&gt; is enabled, in both opening and creation modes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New Chart Types&lt;/strong&gt; have been added, as in FM12.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conditional Formatting&lt;/strong&gt; - As in standard FM12, you can specify different styles/colours for a button (or other object) when it is in focus, touched, or just sitting there. Colour gradients and transparency are available for the first time. And conditional formatting in tab panels has been implemented too.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Email/Save Photo&lt;/strong&gt; lets you choose a File Size option.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Location&lt;/strong&gt; - a new function, Location(), allows you to retrieve your location from GPS, Cell or Wifi.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Behaviour when in the Background&lt;/strong&gt; has been tweaked. The extended privilege fmrestorelogin has been replaced by fmreauthenticate, which has optional entry of a number of minutes of grace before re-authentication is required. The re-authentication dialog is used not only when restoring from hibernate, but also when switching from background to foreground and from sleep to wake. The setting &quot;Try to restore Login?&quot; is no longer used because it will always try to restore, subject to security settings.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Not Supported:&lt;/strong&gt;&lt;br&gt;Tooltips&lt;br&gt;Plug-ins&lt;br&gt;Script debugger&lt;/p&gt;</description>
			<pubDate>Thu, 12 Apr 2012 10:03:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/changes-to-filemaker-go-12/</guid>
		</item>
		
		<item>
			<title>FileMaker 12: Better, Faster, Stronger...</title>
			<link>https://www.teamdf.com/blogs/filemaker-12-released/</link>
			<description>&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/452/150_1.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We&#039;re rapt to see the new version of FileMaker released, a major release covering all 3 aspects of the FileMaker suite (FileMaker Pro, Server and Go) in one hit, and bringing a raft of new features along with speed and robustness improvements... all very good stuff, so here&#039;s a few highlights and what they&#039;ll mean for you.&lt;/p&gt;
&lt;p&gt;The biggest change is the &quot;layout engine&quot; which is the technical way of saying that it&#039;s now a lot easier to have modern style screen layouts. FileMaker have used the same technology used in web pages so we can do a lot of the same effects, like changing what shows when you mouse over something, gradients and transparency... all of which means your FileMaker solutions can look and feel a lot more like a modern program or web site. In turn that helps keep screens clean and clear, make better user of space, and ultimately makes for happy productive staff using the systems.&lt;/p&gt;
&lt;p&gt;Behind the scenes the server product has very important improvements that basically mean more speed, continuous backups, and a huge improvement in stability - it&#039;s now much harder for plugins and scripts running on the server to crash. You won&#039;t notice this day to day so much, but we know that FileMaker systems are the backbone of many businesses and these changes greatly reduce the chance of interruption and disgruntled staff... keep em happy!&lt;/p&gt;
&lt;p&gt;Other changes include the way documents, images and files are handled which means FileMaker can be used as a document management system with much greater aplomb; and connecting your database up to the web will see you dish out web pages much faster, all as a result of some serious rejigging under the hood in that area of FileMaker Server.&lt;/p&gt;
&lt;p&gt;Finally FileMaker Go, which is FileMaker for the iPad has been updated too. It&#039;s very slick ? much faster than the previous version and of course it inherits all the new layout capabilities from the desktop application. Perhaps the biggest thing is that it&#039;s free which is a very nice surprise and we&#039;re sure that&#039;ll mean it spreads like wild fire... it&#039;s by far the best and only real option for quickly building quality business solutions for iOS devices ? iPad, iPhone and iPod Touch. And no, it doesn&#039;t run on Android.&lt;/p&gt;
&lt;p&gt;The only real drawback with the new FileMaker stable is that it&#039;s not compatible with the old version, so files have to be converted and you can&#039;t mix and match. We think the price of that is worth it for all the good stuff this new version brings, but before you upgrade please talk to us and we&#039;ll help make sure everything will go smoothly and advise on when we think it&#039;s time to make the jump.&lt;/p&gt;
&lt;p&gt;For more details &lt;a href=&quot;http://www.teamdf.com/news/filemaker-12-whats-new/153/&quot;&gt;read our blog article on some of the technical changes&lt;/a&gt;&lt;a&gt;&lt;/a&gt;.&lt;/p&gt;</description>
			<pubDate>Thu, 05 Apr 2012 15:57:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-12-released/</guid>
		</item>
		
		<item>
			<title>Tips &amp; Hints - Scripting</title>
			<link>https://www.teamdf.com/blogs/tips-hints-scripting/</link>
			<description>&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-weetbicks1.png&quot; alt=&quot;tipshints1 weetbicks1&quot; width=&quot;337&quot; height=&quot;184&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;This is the third article in our series of tips and hints for FileMaker. This time we are focusing on scripts - from their creation, to editing and debugging. Take it as it is - this is just an assortment of our favorite time-savers, shortcuts, tips, hints, tricks, tools of the trade and more.&lt;/p&gt;
&lt;h4&gt;Getting to a Script for Editing&lt;/h4&gt;
&lt;p&gt;There are a number of different ways to access individual scripts or the Manage Scripts dialog.&lt;/p&gt;
&lt;p&gt;Obviously the most common of these is via the Scripts menu, or using the shortcut cmd+shift+S (ctrl+shift+S on windows).&lt;/p&gt;
&lt;p&gt;When in layout mode, one of the most common things done is creating buttons and attaching scripts to them:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600513-tipshints1-39.png&quot; alt=&quot;tipshints1 39&quot; width=&quot;600&quot; height=&quot;513&quot;&gt;&lt;/p&gt;
&lt;p&gt;From this dialog you can select the script via a modified - and modal - version of the Manage Scripts dialog.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-40.png&quot; alt=&quot;tipshints1 40&quot; width=&quot;536&quot; height=&quot;697&quot;&gt;&lt;/p&gt;
&lt;p&gt;While not initially obvious, you can in fact create and edit scripts from this dialog. In the normal Manage Scripts dialog a double click on a script will open it for editing. Here however the double click action is used to assign the script to the button.&lt;/p&gt;
&lt;p&gt;To edit a script from this dialog, first select it and then choose Edit from the menu shown below.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-41.png&quot; alt=&quot;tipshints1 41&quot; width=&quot;446&quot; height=&quot;433&quot;&gt;&lt;/p&gt;
&lt;p&gt;When editing a script from this modal Manage Scripts dialog the script itself is also modal. You&#039;ll notice an OK and Cancel button provided on the script just like in versions of FileMaker prior to 10 (cmd+S to save and cmd+W to close are not available here).&lt;/p&gt;
&lt;p&gt;Creating and editing scripts from this modal manage scripts dialog is a huge time saver when setting up a button as it saves you having to work your way back out of the chain of dialogs to get to the regular manage scripts dialog. If the script is simple enough then you may as well create it when you define the button :)&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600437-tipshints1-42.png&quot; alt=&quot;tipshints1 42&quot; width=&quot;600&quot; height=&quot;437&quot;&gt;&lt;/p&gt;
&lt;p&gt;The script debugger in FileMaker Pro Advanced is another location where you may need to quickly access the script being debugged.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-43.png&quot; alt=&quot;tipshints1 43&quot; width=&quot;100&quot; height=&quot;36&quot;&gt;&lt;/p&gt;
&lt;p&gt;The middle button will open the script currently being debugged. This makes the debugger a useful tool for quickly opening a script attached to a button while in browse mode. Of course, the script you open cannot be saved while the script is still running in debugger, so be sure to halt the debugger in this situation.&lt;/p&gt;
&lt;p&gt;Don&#039;t forget also that if editing scripts via the Manage Scripts dialog you can open more than one at a time. This is useful if you are dealing with a script that uses sub-scripts, or if you need to modify a large number of scripts at once. To do so, highlight the scripts you want to edit and then double-click - all chosen scripts will open.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-44.png&quot; alt=&quot;tipshints1 44&quot; width=&quot;338&quot; height=&quot;167&quot;&gt;&lt;/p&gt;
&lt;p&gt;Script folders are a great way to organize your scripts. If you are anything like me then you like to keep things tidy. Sometimes you&#039;ll have folders collapsed and others expanded, which can make locating a particular folder a real chore.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-45.png&quot; alt=&quot;tipshints1 45&quot; width=&quot;147&quot; height=&quot;128&quot;&gt;&lt;/p&gt;
&lt;p&gt;There is however a way to locate any folder whether it is expanded or collapsed by using the folder filter at the top of the Manage Scripts dialog.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-46.png&quot; alt=&quot;tipshints1 46&quot; width=&quot;186&quot; height=&quot;396&quot;&gt;&lt;/p&gt;
&lt;p&gt;Problem! While this filter does keep folders in the correct order, it does not nicely display the sub-levels of folders, and as a result all folders appear one beneath the other - you have no idea which is a sub-folder of another folder!&lt;/p&gt;
&lt;p&gt;This can be remedied by adding spaces to the beginning of your folder names for each level. I&#039;ll admit it&#039;s not the nicest solution - this is something FileMaker should just do natively - but it can provide a nice effect for quick folder selection.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-47.png&quot; alt=&quot;tipshints1 47&quot; width=&quot;189&quot; height=&quot;343&quot;&gt;&lt;/p&gt;
&lt;h4&gt;A Note on the Import Records script step&lt;/h4&gt;
&lt;p&gt;When it comes to creating copies of scripts, FileMaker gives you a few options. You can start with a blank script and copy script steps into it. You could duplicate the script or use the copy/paste script functionality. Finally, you can import scripts from other files.&lt;/p&gt;
&lt;p&gt;All of these methods are fine methods but pay particular attention to the difference between the duplicate and copy/paste functionalities. Aside from the resulting copy&#039;s name change (a 2 on the end for copy/paste vs &quot;copy&quot; for duplicate) there is an interesting change that occurs in the Import Records script step.&lt;/p&gt;
&lt;p&gt;In the picture below we have a straightforward import records script step that is importing contacts from another file into the current file.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-48.png&quot; alt=&quot;tipshints1 48&quot; width=&quot;361&quot; height=&quot;88&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600521-tipshints1-49.png&quot; alt=&quot;tipshints1 49&quot; width=&quot;600&quot; height=&quot;521&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we are using the matching names option as a means of providing the field mapping.&lt;/p&gt;
&lt;p&gt;Now if we were to make a copy of this script using the copy/paste functionality we end up with:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-50.png&quot; alt=&quot;tipshints1 50&quot; width=&quot;315&quot; height=&quot;32&quot;&gt;&lt;/p&gt;
&lt;p&gt;as the mapping method on the import records step as opposed to using the duplicate command and having the step retain its mapping method:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-51.png&quot; alt=&quot;tipshints1 51&quot; width=&quot;306&quot; height=&quot;29&quot;&gt;&lt;/p&gt;
&lt;p&gt;In a situation where the import records script step is used in a script, the duplicate command is preferable to a straightforward copy/paste if you need to copy the script.&lt;/p&gt;
&lt;p&gt;In fact, even copy/pasting that single script step to another script will revert the mapping to &quot;last order&quot;. If the script is imported from another file, then the mapping is also changed.&lt;/p&gt;
&lt;h4&gt;Making writing a script easier&lt;/h4&gt;
&lt;p&gt;Here&#039;s a quick tip: when writing a script it is always a good idea to put yourself on a layout which is the main context the script will spend the majority of its time on. By doing so it means anytime you need to reference a field in a script step you can be sure that it will be in the initial list of fields to appear.&lt;/p&gt;
&lt;h4&gt;Chatty Scripts (mac only)&lt;/h4&gt;
&lt;p&gt;Sometimes we create scripts that can take quite a long time to execute. Examples of such might be doing a mass mail-out, or generating millions of test records. Other times we are debugging complex scripts that can take a long time to step through in the debugger to find out what&#039;s happening.&lt;/p&gt;
&lt;p&gt;What do both of these scenarios have in common? Well, they both take a long time to do - time that busy developers do not have. What if there was a way to start a script running so you can basically forget about it, yet still debug it or be notified of its progress at the same time? There is a way on the mac.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-63.png&quot; alt=&quot;tipshints1 63&quot; width=&quot;494&quot; height=&quot;372&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Speak [] script allows for a calculation to be presented to you in an auditory manner :) Better yet, it has an option to have the speech not impact on the scripts execution by pausing while talking.&lt;/p&gt;
&lt;p&gt;There is some good potential for this script step to be used in debugging or progress notifications. Consider the script shown below:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600392-tipshints1-64.png&quot; alt=&quot;tipshints1 64&quot; width=&quot;600&quot; height=&quot;392&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we have a script that we will use to generate 100 million dummy records. We want to be kept abreast of how it is progressing, yet we don&#039;t wish to do this via custom dialogs that we have to manually dismiss, nor do we want to waste time defining variables to view in the data viewer (which suffers from update issues during script execution).&lt;/p&gt;
&lt;p&gt;The Speak [] step is a great solution. We simply have the script tell us its progress. This is done every time a new 1 million records are created. The script step tells us how many records have been created. We could very easily tweak this to have it tell us what percentage of completion it is up to. Very cool! We can now fire up another copy of FileMaker Pro on the mac and do other work while leaving this to run in the background.&lt;/p&gt;
&lt;p&gt;We first learn&#039;t of this cool technique from &lt;a href=&quot;http://www.dwaynewright.com/scripting/2008/8/28/filemaker-the-speak-script-step-macintosh-only.html&quot;&gt;this article&lt;/a&gt; by the very talented Dwayne Wright at his &lt;a href=&quot;http://dwaynewright.squarespace.com/filemaker-thoughts/&quot;&gt;FileMaker Thoughts&lt;/a&gt; blog - well worth checking out!&lt;/p&gt;
&lt;h4&gt;Secondary Action Modifiers&lt;/h4&gt;
&lt;p&gt;There are a number of script steps which require require two or more pieces of information for the step to be fully specified. In some cases it is possible to use a modifier key to open the secondary options.&lt;/p&gt;
&lt;p&gt;As an example let&#039;s look at the Set Field script step.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-58.png&quot; alt=&quot;tipshints1 58&quot; width=&quot;557&quot; height=&quot;106&quot;&gt;&lt;/p&gt;
&lt;p&gt;The primary option is to specify the field as noted by the fact the button has focus. Double-clicking on the script step is going to run this first option. The secondary option of specifying the calculated result can be opened by using the option modifier key (alt on windows) and double-clicking on the script step. This is a huge time saver when writing scripts that use this step often.&lt;/p&gt;
&lt;p&gt;Other script steps where a modifier key can be used to open the secondary options are:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Install OnTimer Script []&lt;/li&gt;
&lt;li&gt;Set Selection []&lt;/li&gt;
&lt;li&gt;Set Field []&lt;/li&gt;
&lt;li&gt;Set Field By Name []&lt;/li&gt;
&lt;li&gt;Set Next Serial Value []&lt;/li&gt;
&lt;li&gt;Insert Text []&lt;/li&gt;
&lt;li&gt;Insert Calculated Result []&lt;/li&gt;
&lt;li&gt;Insert File []&lt;/li&gt;
&lt;li&gt;Replace Field Contents []&lt;/li&gt;
&lt;li&gt;Export Field Contents []&lt;/li&gt;
&lt;li&gt;Save Records as Excel []&lt;/li&gt;
&lt;li&gt;Save Records as PDF []&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The import records script step cannot have its secondary option opened via modifier key, but it can be opened using the return/enter key which is still faster than using the specify button provided.&lt;/p&gt;
&lt;h4&gt;Adding Multiple Script Steps&lt;/h4&gt;
&lt;p&gt;Just in the same way we demonstrated how you can open multiple scripts at the same time, you can do the same with individual script steps. Quite often when writing a script you have a good idea of the steps you will require, so why not just add them all at the same time. You can go shopping for script steps, adding each step to your cart by selecting them from the list of steps. When you have chosen all of your steps, use the move button to checkout your steps to the script, or double click any of the selected steps.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-59.png&quot; alt=&quot;tipshints1 59&quot; width=&quot;212&quot; height=&quot;354&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Steps every script should have&lt;/h4&gt;
&lt;p&gt;There are some important script steps that it would be a good idea to add to most of your scripts prevent issues for your users.&lt;/p&gt;
&lt;p&gt;The first is adding a script step to the very start of your script that determines the initial mode the script should be in. Typically this is going to be the Enter Browse Mode [] script step. Why you ask? Well consider a user who has gone into find mode to do a search, but in doing so they happen to click on a button that runs one of your scripts. That script is going to begin its execution in find mode - a new record command will be adding a new request, set field will be defining a find request, and so on.&lt;/p&gt;
&lt;p&gt;You should always be explicit in defining context at the beginning of a script.&lt;/p&gt;
&lt;p&gt;Lastly, putting an Exit Script[] step as the last step of your script is a very handy thing to do for debugging purposes. Without it you are unable to fully debug the very last script step.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-60.png&quot; alt=&quot;tipshints1 60&quot; width=&quot;380&quot; height=&quot;198&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is a very simple script to illustrate that last point. The script has a single set variable script step. Let&#039;s now debug this script to try and determine the value of $variable during execution:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600435-tipshints1-61.png&quot; alt=&quot;tipshints1 61&quot; width=&quot;600&quot; height=&quot;435&quot;&gt;&lt;/p&gt;
&lt;p&gt;Uh-oh! We are on the last script step, but our data viewer is still not showing the value of $variable. This is because $variable has not been defined yet. Because this is the last script step, once we move to the next step the script will end and $variable will be lost - we will never know what it could have been set to&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600367-tipshints1-62.png&quot; alt=&quot;tipshints1 62&quot; width=&quot;600&quot; height=&quot;367&quot;&gt;&lt;/p&gt;
&lt;p&gt;What if we put an Exit Script [] step as the very last step? Now the Set Variable step is not the last in the script, and we have an opportunity to view its value. The script is going to exit anyway at the last step so the Exit Script [] step merely helps to serve as an extra debugging step for the &quot;real&quot; last step that precedes it.&lt;/p&gt;</description>
			<pubDate>Mon, 05 Mar 2012 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/tips-hints-scripting/</guid>
		</item>
		
		<item>
			<title>A &#039;Local&#039; Way to Suppress Script Triggers</title>
			<link>https://www.teamdf.com/blogs/a-local-way-to-suppress-script-triggers/</link>
			<description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Script triggers are a great feature in FileMaker that allow you to initiate a script when certain actions occur such as committing a record or leaving a layout. Not only do they run when user initiated, they can also be script initiated by script steps. This can sometimes produce unexpected results and so you may wish for triggers to be disabled. This article presents a very simple and elegant method of suppressing script triggers from firing when initiated by other scripts.&lt;/p&gt;
&lt;h4&gt;EDIT: You always think of new things once the article is written, d&#039;oh!&lt;/h4&gt;
&lt;p&gt;So after writing the entire article and then sitting down afterwards and having a little thing, it became apparent there is in fact a far more elegant solution that follows the same technique as in the article - but without the need for any variables of any type. It will make more sense as you read the article, but for the time being just note that you could simply pass &lt;strong&gt;Get ( ScriptName )&lt;/strong&gt; as the parameter to the script trigger and check for whether it is empty or non-empty as your test. Anyways onto the article...&lt;/p&gt;
&lt;h4&gt;Some conventions before we begin:&lt;/h4&gt;
&lt;p&gt;Because we are dealing with two types of scripts in this article, we will refer to triggered scripts as &lt;strong&gt;T&lt;/strong&gt;. The main script that is executing will be called &lt;strong&gt;A&lt;/strong&gt;.&lt;/p&gt;
&lt;h4&gt;The method we have used to this point&lt;/h4&gt;
&lt;p&gt;Suppressing script triggers is a common issue and one that has had solutions devised in the past which we have used. The conventional method involves setting a global variable at the beginning of script &lt;strong&gt;A&lt;/strong&gt; as a means to tell other triggered scripts &lt;strong&gt;T&lt;/strong&gt; that script &lt;strong&gt;A&lt;/strong&gt; is executing and that they should halt their own execution immediately.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/stsuppress-1.png&quot; alt=&quot;stsuppress 1&quot; width=&quot;428&quot; height=&quot;313&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/stsuppress-2.png&quot; alt=&quot;stsuppress 2&quot; width=&quot;321&quot; height=&quot;189&quot;&gt;&lt;/p&gt;
&lt;p&gt;While this method works, it does require a fair amount of maintenance. Not only does the global script variable have to be set in &lt;strong&gt;A&lt;/strong&gt;, but if there are any exit conditions later on in the script, it must be cleared otherwise the global variable will persist with its value when future scripts are run.&lt;/p&gt;
&lt;h4&gt;The thing about local variables&lt;/h4&gt;
&lt;p&gt;You&#039;ve all seen local variables and almost certainly used them in scripts to store information required during execution. So what does &quot;local&quot; mean? Well, the local variable only exists within the context in which it is defined. In the case of scripts, when you define a local variable then that variable will only exist while that script is running. Once the script ends, the local variable is trashed. The &quot;script&quot; is the context in this case. We tend to think of these as script variables, but they really aren&#039;t.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/stsuppress-3.png&quot; alt=&quot;stsuppress 3&quot; width=&quot;381&quot; height=&quot;51&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Set Variable script step does not actually mention at any point that these are script variables, they are local variables.&lt;/p&gt;
&lt;p&gt;Are there any other contexts in a FileMaker solution where we might be able to define a local variable? The answer is yes!&lt;/p&gt;
&lt;h4&gt;Defining a local variable outside of a script&lt;/h4&gt;
&lt;p&gt;Just like the title says, local variables can be defined outside the context of a script. When this is done, the local variable exists and is available to be referenced anywhere in the current file &lt;strong&gt;EXCEPT&lt;/strong&gt; when a script is running. Once a script begins to execute, the context has changed and the local variable is not available until the script ends.&lt;/p&gt;
&lt;h4&gt;How this translates into a method for script trigger suppression&lt;/h4&gt;
&lt;p&gt;So what do we know so far? We know that if we can set a local variable outside of a script, then this variable will exist only outside of scripts. Conversely we know that when a script is executing, the local variable is unavailable, and so if we try to obtain its value it will return a blank.&lt;/p&gt;
&lt;p&gt;Ah ha!&lt;/p&gt;
&lt;p&gt;What if we define a local variable outside of a script and then pass it to the script &lt;strong&gt;T&lt;/strong&gt; as a parameter. If &lt;strong&gt;T&lt;/strong&gt; is user initiated then the parameter passed will be the value in the local variable.&lt;/p&gt;
&lt;p&gt;However if another script &lt;strong&gt;A&lt;/strong&gt; is executing and triggers script &lt;strong&gt;T&lt;/strong&gt; it is going to pass the local variable. Because the context is a script, the local variable is going to be blank and so script T will receive a blank parameter.&lt;/p&gt;
&lt;p&gt;Confused? Ok lets break it down....&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Part 1: Defining the Local Variable&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The first step involves setting a local variable outside of the confines of a script. This is not quite as easy as it sounds. In order to do this we require a calculation to define the local variable, and we require that calculation to evaluate outside of the script.&lt;/p&gt;
&lt;p&gt;In this article we are using 2 different examples of where we can place this calculation and have it evaluate outside of a script.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600480-stsuppress-4.png&quot; alt=&quot;stsuppress 4&quot; width=&quot;600&quot; height=&quot;480&quot;&gt;&lt;/p&gt;
&lt;p&gt;The first place we could define the local variable is within conditional formatting. These calculations are evaluated when a layout renders for the first time and when the layout refreshes thereafter. In this case we have defined conditional formatting but applied no formatting for the calculation - it is merely to define the local variable.&lt;/p&gt;
&lt;p&gt;You could place an object on your startup layout (or a number of layouts) that contain this conditional formatting calculation. You need to make sure it is visible on the layout for it to evaluate.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600406-stsuppress-5.png&quot; alt=&quot;stsuppress 5&quot; width=&quot;600&quot; height=&quot;406&quot;&gt;&lt;/p&gt;
&lt;p&gt;The second possible location is within a custom menu name. If you have a menu item that is used in your custom menus then you can hide the definition of the local variable within the menu name as shown. Custom Menu names are evaluated when layouts load, refresh and when the menu is accessed.&lt;/p&gt;
&lt;p&gt;Other possibilities might be to create a calculation field placed on a layout that defines the variable, or modify an existing calculation field on a layout to define the variable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; If you use a startup script, be careful because conditional formatting and custom menus are going to evaluate while the startup script is executing, and as such the variables defined will actually become script variables!&lt;/p&gt;
&lt;h4&gt;Part 2: Setting up your Script Triggers&lt;/h4&gt;
&lt;p&gt;The next step involves setting up script triggers. In this example we are using 3 layout-level script triggers.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/stsuppress-6.png&quot; alt=&quot;stsuppress 6&quot; width=&quot;573&quot; height=&quot;669&quot;&gt;&lt;/p&gt;
&lt;p&gt;Each of the &lt;strong&gt;T&lt;/strong&gt; scripts are being passed the local variable defined in Part 1 which we have called $ScriptTrigger.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/stsuppress-7.png&quot; alt=&quot;stsuppress 7&quot; width=&quot;496&quot; height=&quot;497&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the scripts we place a few lines of code to check the script parameter.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/stsuppress-8.png&quot; alt=&quot;stsuppress 8&quot; width=&quot;381&quot; height=&quot;148&quot;&gt;&lt;/p&gt;
&lt;p&gt;If the triggered script &lt;strong&gt;T&lt;/strong&gt; is user initiated then it is being initiated from outside the context of a script. This means $ScriptTrigger exists with a value and as such the script is passed a non-empty parameter. The triggered script &lt;strong&gt;T&lt;/strong&gt; can then execute because it knows a user has caused it to trigger.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/stsuppress-9.png&quot; alt=&quot;stsuppress 9&quot; width=&quot;467&quot; height=&quot;50&quot;&gt;&lt;/p&gt;
&lt;p&gt;If however script &lt;strong&gt;A&lt;/strong&gt; is executing and does something that causes &lt;strong&gt;T&lt;/strong&gt; to trigger then when it tries to pass $ScriptTrigger it is going to pass a blank variable. Remember, $ScriptTrigger only exists outside of a scriptural context! The variable does not exist in script &lt;strong&gt;A&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/stsuppress-10.png&quot; alt=&quot;stsuppress 10&quot; width=&quot;415&quot; height=&quot;92&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Script Debugger&lt;/h4&gt;
&lt;p&gt;If you are using the script debugger to try this out you may end up with differing results. With debugger enabled, the conditional formatting and custom menu calculations will actually evaluate at some point during the process so that $ScriptTrigger gets defined within the context of script A. This does not occur when the script debugger is disabled.&lt;/p&gt;
&lt;h4&gt;Some things to note, and other stuff..&lt;/h4&gt;
&lt;p&gt;This technique can very easily be reversed so that you can use script triggers in a way that they are initiated only from other scripts and not when they are user initiated - simply change the check at the beginning of the triggered scripts.&lt;/p&gt;
&lt;p&gt;This technique should probably be accompanied by some documentation as to where you are defining your local variable outside of the script context and what the name of that variable is. You should probably also document the technique in the triggered scripts or parameters passed to them. If other developers come along in future and see a local variable being passed to a script, they may wonder what is going on, and could think it is an error and remove the variable!&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/stsuppress/ScriptTriggerSuppress.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Sat, 11 Feb 2012 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/a-local-way-to-suppress-script-triggers/</guid>
		</item>
		
		<item>
			<title>Tips &amp; Hints - The Relationship Graph</title>
			<link>https://www.teamdf.com/blogs/tips-hints-the-relationship-graph/</link>
			<description>&lt;h4&gt;Share your own tips and hints:&lt;/h4&gt;
&lt;p&gt;We had a &lt;a href=&quot;http://www.teamdf.com/weetbicks/tips-hints-layout-mode/137/&quot;&gt;great response to our first article&lt;/a&gt; with readers submitting their own favorite layout mode tips - a huge thank you to everyone who contributed. If you have any cool tips for the relationship graph we&#039;d love to hear and share them, be sure to leave a comment with your favorite tips and hints.&lt;/p&gt;
&lt;h4&gt;Accessing the Relationship Graph&lt;/h4&gt;
&lt;p&gt;How do you get to the relationship graph? Well the obvious way is via the Manage Database dialog (File -&amp;gt; Manage -&amp;gt; Databases). Incidentally, if you are not using the cmd+shift+D (ctrl+shift+D on windows) shortcut to get here then shame on you - this should be the first FileMaker shortcut you should learn!&lt;/p&gt;
&lt;p&gt;There are actually many other areas in FileMaker from which you can enter the relationship graph, and these areas are actually far more powerful a means of accessing the graph than Manage Database. It took me (Daniel) a couple of years of neglecting these access points to eventually realise that I should be using them all the time, and now I do!&lt;/p&gt;
&lt;p&gt;Ever seen the option below when setting up a value list?&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600335-tipshints1-27.png&quot; alt=&quot;tipshints1 27&quot; width=&quot;600&quot; height=&quot;335&quot;&gt;&lt;/p&gt;
&lt;p&gt;Or this when specifying a field on a layout?&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-28.png&quot; alt=&quot;tipshints1 28&quot; width=&quot;357&quot; height=&quot;501&quot;&gt;&lt;/p&gt;
&lt;p&gt;Or even this when choosing a field in a calculation?&lt;/p&gt;
&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-29.png&quot; alt=&quot;tipshints1 29&quot; width=&quot;504&quot; height=&quot;310&quot;&gt;&lt;/p&gt;
&lt;p&gt;These are all links to the Manage Database dialog. Depending on the context from which you follow this link, you will either be taken to the last tab you were on when you last visited the Manage Database dialog, or directly to the relationships tab.&lt;/p&gt;
&lt;p&gt;In all of the examples above the key context is the need to select a field, be it for the value list, the field on the layout, or in the calculation.&lt;/p&gt;
&lt;p&gt;However FileMaker is very smart, and it knows that we entered the Manage Database dialog from this specific point. It knows that if we create a table occurrence when in the dialog, then there is a good chance we have created it because we need it in the original context.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;FileMaker will automatically select the last created table occurrence for you when you leave the dialog, if entered from one of these special &quot;Manage Database&quot; links.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As a classic example, let&#039;s say we are creating a value list. The value list is to be based on a related field value from a given context. We have the initial context, but we have forgotten to establish a relationship to the related context. Rather than cancel out of all the dialogs to this point (and thus losing our work), we can instead go direct to the Manage Database dialog via the value list.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-30.png&quot; alt=&quot;tipshints1 30&quot; width=&quot;584&quot; height=&quot;483&quot;&gt;&lt;/p&gt;
&lt;p&gt;From here, we can add the relationship required for the value list&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60053-tipshints1-31.png&quot; alt=&quot;tipshints1 31&quot; width=&quot;600&quot; height=&quot;53&quot;&gt;&lt;/p&gt;
&lt;p&gt;When we press OK, FileMaker knows we added the table occurrence, and so we likely wish to use it in the value list. It automatically selects the table occurrence for us so we can continue to build the value list.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600514-tipshints1-32.png&quot; alt=&quot;tipshints1 32&quot; width=&quot;600&quot; height=&quot;514&quot;&gt;&lt;/p&gt;
&lt;p&gt;If we are already in the Manage Database dialog, perhaps editing a field calculation, we can still use the &quot;Manage&quot; shortcut, however in this situation it is a link to &quot;Manage Relationships&quot; instead of &quot;Manage Database&quot;.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-33.png&quot; alt=&quot;tipshints1 33&quot; width=&quot;464&quot; height=&quot;83&quot;&gt;&lt;/p&gt;
&lt;p&gt;FileMaker prevents us from accessing more than 1 Manage Database dialog at a time, but it does let us access the relationship part of the dialog via a separate window.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600409-tipshints1-34.png&quot; alt=&quot;tipshints1 34&quot; width=&quot;600&quot; height=&quot;409&quot;&gt;&lt;/p&gt;
&lt;p&gt;You&#039;ll notice this window is purely for the relationship graph - there is no tab for tables or fields at the top. There is also no cancel or OK button, simply a close. This dialog works the same as the other access points. Upon pressing close, FileMaker will use the last created table occurrence back on the preceding dialog.&lt;/p&gt;
&lt;h4&gt;Relationship Graph Shortcuts&lt;/h4&gt;
&lt;p&gt;While not really obvious from looking in the relationship graph, there are in fact a number of really cool and useful shortcuts available. Refer to &lt;a href=&quot;http://www.filemaker.com/11help/html/keys_mac.28.18.html&quot;&gt;this link&lt;/a&gt; for a full list of shortcuts available. Below are some cool uses for these shortcuts.&lt;/p&gt;
&lt;h4&gt;Quick Selection of Table Occurrence Groups&lt;/h4&gt;
&lt;p&gt;If you use the anchor-buoy method of designing your graph then there may be times you need to select an entire table occurrence group. The simplest way is to start by selecting the anchor, and using the cmd+Y (ctrl+Y on windows) shortcut to progressively select table occurrences more and more levels away from the anchor. Just repeatedly tap the cmd+Y key a few times to quickly select the entire TOG. You could now use cmd+T to expand the entire TOG if you wish.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60096-tipshints1-19.png&quot; alt=&quot;tipshints1 19&quot; width=&quot;600&quot; height=&quot;96&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Got a Big or Messy Graph?&lt;/h4&gt;
&lt;p&gt;Sometimes a common problem on large or messy graph is the inability to locate a particular table occurrence you want.&lt;/p&gt;
&lt;p&gt;You can start by trying to type the name of the table occurrence if you know it and this can be all you need in some cases. If your table occurrence has a long name or contains spaces then it can be difficult to type the name fast enough to find it. If you found at least 1 result then you can use Cmd (ctrl) + G shortcut to cycle through the full list of found matches until you find the one you were after.&lt;/p&gt;
&lt;p&gt;If that doesn&#039;t work, try using the cmd (ctrl) + U shortcut. Start by selecting a table occurrence whose underlying table is the same as the one you want to find. Can&#039;t find a table occurrence? Then just add one temporarily for this purpose. Select it and use cmd+U. Now zoom out of the graph and focus just on the highlighted table occurrences.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60080-tipshints1-20.png&quot; alt=&quot;tipshints1 20&quot; width=&quot;600&quot; height=&quot;80&quot;&gt;&lt;/p&gt;
&lt;p&gt;An application we often use here is &lt;a href=&quot;http://www.dracoventions.com/products/2empowerFM/family/developer.php&quot;&gt;2empowerFM Developer Assistant&lt;/a&gt; which among other things is great for locating Table Occurrences on the graph.&lt;/p&gt;
&lt;p&gt;Finally you can just print the graph. The Print button is located in the lower left corner of the relationship graph. When printing, you have the option to print the graph on a single page or multiple pages - either option is good.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-55.png&quot; alt=&quot;tipshints1 55&quot; width=&quot;453&quot; height=&quot;251&quot;&gt;&lt;/p&gt;
&lt;p&gt;Instead of printing it, generate a PDF instead using the Preview/Save as PDF option from the print dialog (and the windows equivalent).&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-56.png&quot; alt=&quot;tipshints1 56&quot; width=&quot;233&quot; height=&quot;369&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now you can search the graph using your PDF reader instead of FileMaker. This is actually not a bad idea for large graphs as FileMakers search tends to get significantly slower with an increased number of table occurrences, whereas the PDF readers tested perform fine.&lt;/p&gt;
&lt;p&gt;The other benefit of using a PDF reader like Preview, is that it can be easier to quickly see and scroll through all found results.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600183-tipshints1-57.png&quot; alt=&quot;tipshints1 57&quot; width=&quot;600&quot; height=&quot;183&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Quickly Creating Relationships&lt;/h4&gt;
&lt;p&gt;When forming a relationship between two table occurrences, don&#039;t waste time dragging the relationship line directly onto the field you want in the source and destination table occurrences - you&#039;ll be there all day waiting for the fields to scroll!&lt;/p&gt;
&lt;p&gt;The quickest way to add a relationship is to drag the relationship line from any field on the source side to any field on the destination side. Then use the edit Relationship dialog to correctly choose the fields required. Be sure to use the type-ahead functionality provided to quickly locate the fields. If you need to expand table occurrences in order to drag the relationship line, use the shortcut cmd (ctrl) + T to expand both table occurrences at the same time. You can then use it again afterwards to collapse them at the same time - every second counts !&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-21.png&quot; alt=&quot;tipshints1 21&quot; width=&quot;582&quot; height=&quot;190&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Keep your Graph Tidy!&lt;/h4&gt;
&lt;p&gt;This is the number one thing you can do for your graph to boost productivity and decrease development time. A tidy graph is a happy graph. Try to avoid overlapping relationship lines and keep some kind of logical layout to your table occurrences.&lt;/p&gt;
&lt;p&gt;Remember, the alignment tools are your friend, just as they are when working in layout mode. They work very much the same way - with the exception of there being no shortcut keys (Shame on you FileMaker!).&lt;/p&gt;
&lt;h4&gt;Alignment Tools and Custom Menus&lt;/h4&gt;
&lt;p&gt;A bug that presented itself in FileMaker 10 and has persisted until this day concerns the alignment tools in the relationship graph. If you entered the graph from a layout that is in browse mode, and are using a custom menu, then the alignment tools are going to be greyed out and unavailable. You should ensure that you are in layout mode first, or switch your custom menu. Here&#039;s hoping FileMaker will fix this in future!&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-22.png&quot; alt=&quot;tipshints1 22&quot; width=&quot;204&quot; height=&quot;128&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Comment Boxes&lt;/h4&gt;
&lt;p&gt;Comment boxes need not just be used for comments. We also use them as dividers that separate table occurrence groups, or logical sections of the graph. Particularly useful in anchor-buoy systems is adding a large comment above the TOG to indicate its purpose, or the screen it pertains to. This makes locating TOGs on the graph much easier. For large graphs, make the text size big so you can still find TOGs when zoomed out.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-22.png&quot; alt=&quot;tipshints1 22&quot; width=&quot;204&quot; height=&quot;128&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you prefix your TOG labels with something standard - such as &quot;zzz&quot; - then searching for a particular TOG becomes a cinch. Use the graphs search functionality - it looks for comments as well as table occurrences!&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-24.png&quot; alt=&quot;tipshints1 24&quot; width=&quot;473&quot; height=&quot;464&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Creating Table Occurrences&lt;/h4&gt;
&lt;p&gt;Much like creating objects in layout mode, there are a few ways to create table occurrences on the graph. Firstly, you could use the provided button to add a table occurrence from scratch. A duplicate button is also provided - select a table occurrence and then use the button to duplicate.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-25.png&quot; alt=&quot;tipshints1 25&quot; width=&quot;140&quot; height=&quot;42&quot;&gt;&lt;/p&gt;
&lt;p&gt;Our favorite method however is option (ctrl) + Drag to create table occurrences. When using the option+drag method, the edit table occurrences dialog does not appear automatically after the duplicate is created. This is really handy, because often you want to position the table occurrence first.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-26.png&quot; alt=&quot;tipshints1 26&quot; width=&quot;307&quot; height=&quot;67&quot;&gt;&lt;/p&gt;
&lt;h4&gt;And Finally, Table Occurrence Names&lt;/h4&gt;
&lt;p&gt;Using a naming convention is a great way to assign names to your table occurrences to keep everything in order, and make it easy to identify a table occurrences purpose, and its associations. There are many different conventions out there and everyone has their favorite.&lt;/p&gt;
&lt;p&gt;Often naming conventions are such that in order to add a new table occurrence it is easiest to create a duplicate of the table occurrence it will be related to. You can then change its underlying table and rename it by changing a few parts of the table occurrence name.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60017-tipshints1-52.png&quot; alt=&quot;tipshints1 52&quot; width=&quot;600&quot; height=&quot;17&quot;&gt;&lt;/p&gt;
&lt;p&gt;Above I have created a duplicate of a table occurrence that I wish to establish a new relationship from.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-53.png&quot; alt=&quot;tipshints1 53&quot; width=&quot;535&quot; height=&quot;556&quot;&gt;&lt;/p&gt;
&lt;p&gt;If I go directly into the table occurrence setup and change the underlying table, you&#039;ll notice that the table occurrence name has reverted back to the table name. This happens upon entering the dialog and making no changes to the occurrence name. Once you make any change to the table occurrence name, it will remain as-is when you change the table.&lt;/p&gt;
&lt;p&gt;So the tip here is, change your table occurrence name first before changing the table. Another good habit of getting into is copying the occurrence name to clipboard when entering this dialog. Tab followed by cmd (ctrl) + C will put it on the clipboard. Then if you change the table it doesn&#039;t matter if it gets overwritten as you can paste it back in.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-54.png&quot; alt=&quot;tipshints1 54&quot; width=&quot;535&quot; height=&quot;556&quot;&gt;&lt;/p&gt;
&lt;p&gt;Every second counts so if you can reuse any existing table occurrence name then it is worth doing.&lt;/p&gt;</description>
			<pubDate>Tue, 31 Jan 2012 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/tips-hints-the-relationship-graph/</guid>
		</item>
		
		<item>
			<title>Tips &amp; Hints - Layout Mode</title>
			<link>https://www.teamdf.com/blogs/tips-hints-layout-mode/</link>
			<description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;This is the first in a series of articles that will present some useful and time saving tidbits for various areas of FileMaker. In this first article we focus on layout mode. There is no rhyme or reason, no common theme - just an assortment of our favorite time-savers, shortcuts, tips, hints, tricks, tools of the trade and more:&lt;/p&gt;
&lt;h4&gt;Drawing Lines and Shapes&lt;/h4&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-2.png&quot; alt=&quot;tipshints1 2&quot; width=&quot;122&quot; height=&quot;35&quot;&gt;&lt;/p&gt;
&lt;p&gt;We all know the shape tools. You know - those tools to draw lovely lines, circles and squares? There are a couple of cool shortcuts that can be used in conjunction with these tools.&lt;/p&gt;
&lt;p&gt;Holding the shift key while using the line tool will snap the line to a vertical or horizontal alignment - perfect for drawing straight lines!&lt;/p&gt;
&lt;p&gt;Did you know that holding the option key (ctrl on windows) while using the line tool will snap the line to a 45, 135, 225 or 315 degree angle? This can be useful for drawing triangles or any other shape where an angled line is required.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-1.png&quot; alt=&quot;tipshints1 1&quot; width=&quot;102&quot; height=&quot;81&quot;&gt;&lt;/p&gt;
&lt;p&gt;Sometimes you want to draw a perfect square or circle quickly. Rather than drawing something akin to humpty-dumpty and then using the inspector to fix the dimensions, you can instead hold the option key (ctrl on windows) to fix the width and height to the same dimensions. Now you too can make perfect circles every time.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-4.png&quot; alt=&quot;tipshints1 4&quot; width=&quot;79&quot; height=&quot;61&quot;&gt;&lt;/p&gt;
&lt;p&gt;The option (ctrl) modifier key even works with all of the other layout drawing tools and object tools as well.&lt;/p&gt;
&lt;p&gt;Remember to never draw a line with an initial width of 0pt and then change it to 1pt or higher. This is going to result in a blurry line due to a FileMaker rendering bug that has been around for a while. This is an issue on both mac and windows. One of the lines below is not like the other...&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-3.png&quot; alt=&quot;tipshints1 3&quot; width=&quot;89&quot; height=&quot;37&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Creating Copies of Objects&lt;/h4&gt;
&lt;p&gt;There are a number of ways to create copies of objects on a layout. The first is simply selecting an object and using the copy/paste commands (cmd/ctrl c/v). When using this option the pasted object will be moved to the location of where the mouse was last clicked on the layout. In fact, the last clicked location will be dead centre of the pasted object, so if you want to quickly paste an object in a location of the layout, click there before pasting.&lt;/p&gt;
&lt;p&gt;The option key (ctrl on windows) can be used to drag a copy of an object. Select an object, then while holding the option key, drag the object to a new location. Release the mouse while still holding the option key. Use this in conjunction with the shift key (for locking to horizontal/vertical alignment) to copy an object and keep it in-line with the original.&lt;/p&gt;
&lt;p&gt;Finally there is the duplicate command. You may be wondering why you would bother using duplicate when you could just as easily use copy/paste or option-drag. Well, the duplicate has a nifty feature built into it.&lt;/p&gt;
&lt;p&gt;Select an object - let&#039;s call it A - and duplicate it (cmd+D). Now move the new object - B - to some location, such as beneath the original object A using either the keyboard arrow keys or the mouse.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-5.png&quot; alt=&quot;tipshints1 5&quot; width=&quot;117&quot; height=&quot;105&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you now duplicate B, you&#039;ll notice that the resulting duplicate C is positioned relative to B, in exactly the same way B is positioned relative to A.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-6.png&quot; alt=&quot;tipshints1 6&quot; width=&quot;145&quot; height=&quot;119&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now duplicate C to get D, and D will be relative to C the way it is relative to B and so on....&lt;/p&gt;
&lt;p&gt;You can use this technique to quickly create a series of objects all evenly spaced.&lt;/p&gt;
&lt;h4&gt;Don&#039;t Reinvent The Wheel&lt;/h4&gt;
&lt;p&gt;Here&#039;s a quick tip - don&#039;t waste time designing layout controls or formatting objects if they have already been designed elsewhere. You can really speed up your development by reusing existing objects from other layouts and re-purposing them for your requirements. In fact in most cases once a database reaches a particular point, there is very little need to create any object from scratch because it should already reside somewhere in the system waiting for you to copy it :-)&lt;/p&gt;
&lt;h4&gt;Quick formatting of objects&lt;/h4&gt;
&lt;p&gt;The format painter is a great tool for quickly applying formatting styles to objects on a layout. It exists in the status area as a paint icon.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-7.png&quot; alt=&quot;tipshints1 7&quot; width=&quot;431&quot; height=&quot;56&quot;&gt;&lt;/p&gt;
&lt;p&gt;To use, select a layout object. Then click the format painter icon. Now select another object on the layout to apply the formatting from the originally selected object.&lt;/p&gt;
&lt;p&gt;The format painter tool can also be locked in the ON position by double-clicking the icon. This lets you select an object and then apply its formatting to multiple objects. When finished, click on the selection tool icon, or press the escape key.&lt;/p&gt;
&lt;p&gt;In fact it&#039;s not just the format painter that can be left in the locked position - every tool in the picture shown above can be locked in the ON position - this is great for creating lots of lines, circles, squares, portals, you name it.&lt;/p&gt;
&lt;h4&gt;Make Formatting Faster&lt;/h4&gt;
&lt;p&gt;Format painter is great, but what if you need to apply a style across a large number of objects? Lets say for example you have a layout with 100 text labels on it, and you wish to apply formatting from another label to all labels on this layout.&lt;/p&gt;
&lt;p&gt;You could use the format painter in its locked mode and click on all 100 labels to change them, but there is a better way.&lt;/p&gt;
&lt;p&gt;When the format painter tool is used on a series of grouped objects, the formatting is applied individually to all objects in that group. So, to format the 100 labels we simply need to group them. This could be a case of dragging a text selection box over the labels and grouping them. If the labels are sporadically placed on the layout, you can use a nifty shortcut to select all layout objects of a particular type.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-8.png&quot; alt=&quot;tipshints1 8&quot; width=&quot;178&quot; height=&quot;109&quot;&gt;&lt;/p&gt;
&lt;p&gt;Cmd+Option+A (ctrl+shift+A on windows) will select all like objects on a layout, such as text labels. Once selected, just group them into a single object and apply the formatting to that grouped object. When done, ungroup them.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-9.png&quot; alt=&quot;tipshints1 9&quot; width=&quot;164&quot; height=&quot;104&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-10.png&quot; alt=&quot;tipshints1 10&quot; width=&quot;158&quot; height=&quot;103&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Duplicating Tab Control Objects&lt;/h4&gt;
&lt;p&gt;Tab controls can contain many tabs and many objects on those tabs, so what happens if you want to make a new tab control with the same formatting but none of the contents? The first step is to make a copy of the existing tab control object.&lt;/p&gt;
&lt;p&gt;Here is a pretty complex tab control object that contains many internal objects and other layouts of tabs.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600342-tipshints1-11.png&quot; alt=&quot;tipshints1 11&quot; width=&quot;600&quot; height=&quot;342&quot;&gt;&lt;/p&gt;
&lt;p&gt;For the first method, go into the tab control setup and remove all tabs apart from the first one (at least one tab is required to retain formatting).&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;This leaves you with just one tab to clear of contents rather than all tabs. When done, just go back into tab control setup and add your new tabs. Remember that when in tab setup don&#039;t remove all tabs and begin re-adding tabs, otherwise all formatting is lost. Make sure you leave 1 tab and click OK before going back in and adding your tabs.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600393-tipshints1-12.png&quot; alt=&quot;tipshints1 12&quot; width=&quot;600&quot; height=&quot;393&quot;&gt;&lt;/p&gt;
&lt;p&gt;The second method involves resizing the tab control object in a way that all contents that were in the tabs are no longer inside the object. To do this, drag the lower left corner of the tab control up to the upper right corner and keep going until the tab control object is completely outside the realm of the contents, as shown below.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600334-tipshints1-13.png&quot; alt=&quot;tipshints1 13&quot; width=&quot;600&quot; height=&quot;334&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can see above, the tab control is now a tiny object in the upper right corner. Because everything is no longer in the tab, it is all combined into a large mess of objects overlapping one another. This is fine though because it makes it really easy to drag a selection box over it all and hit the delete button.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600325-tipshints1-14.png&quot; alt=&quot;tipshints1 14&quot; width=&quot;600&quot; height=&quot;325&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now just resize the tab back to whatever you want. The cool thing about this method is all the original tabs and their names are retained. You can restore it to its original dimensions using the &quot;resize to largest width and height&quot; command.&lt;/p&gt;
&lt;h4&gt;Learn to Love the Arrange Menu&lt;/h4&gt;
&lt;p&gt;The arrange menu contains so many great and powerful tools (and shortcut keys) that if learned will greatly improve your productivity, especially if you can use the shortcuts available without having to resort to the inspector or the menu. When arrange tools are used in conjunction they can make seemingly tedious tasks much faster.&lt;/p&gt;
&lt;p&gt;As an example, let&#039;s say we have a series of labels we want to align to be horizontally spaced and left aligned.&lt;/p&gt;
&lt;p&gt;First, begin by positioning Object 1 and Object 6 to the top and bottom coordinates you want the objects to be spaced in. Don&#039;t worry about everything else just yet.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600324-tipshints1-15.png&quot; alt=&quot;tipshints1 15&quot; width=&quot;600&quot; height=&quot;324&quot;&gt;&lt;/p&gt;
&lt;p&gt;Next, for all the other objects, put them in the order you want them to appear. Again, don&#039;t worry about any spacing or alignment just yet: as long as one is beneath the other it&#039;s all good.&lt;/p&gt;
&lt;p&gt;Once done, you are ready to do the final steps. Select all of the objects and left-align using cmd+option+left (ctrl+alt+left on windows). Now simply use the align vertically command and you are done.&lt;/p&gt;
&lt;p&gt;The key here is that once you have your top and bottom objects positioned, and everything in between, the rest is really simple.&lt;/p&gt;
&lt;h4&gt;More about Selecting Objects&lt;/h4&gt;
&lt;p&gt;Selecting objects on a layout can be done in the following ways.&lt;/p&gt;
&lt;p&gt;First is simply clicking the mouse on an object to select it. Holding the shift key will let you individually select multiple objects.&lt;/p&gt;
&lt;p&gt;Drag the mouse button to select multiple objects. All objects that fall entirely within the selection box will be selected.&lt;/p&gt;
&lt;p&gt;Holding the option key (ctrl on windows) while dragging will draw a special selection box that will select any object that partially falls within the selection area.&lt;/p&gt;
&lt;p&gt;Cmd+A (ctrl+A on windows) will select all objects on the layout, locked or otherwise.&lt;/p&gt;
&lt;p&gt;With an object selected on the layout, use Cmd+Option+A (ctrl+shift+A on windows) to select all other objects of the same type on the layout. This is a really awesome feature that can really assist with development, as discussed below.&lt;/p&gt;
&lt;h4&gt;Working with Hidden Tab Controls&lt;/h4&gt;
&lt;p&gt;We have already touched on a few uses of the &quot;Select Same&quot; command above, but have you ever thought of using it as a means for finding objects on a layout?&lt;/p&gt;
&lt;p&gt;Hidden tab controls are becoming ever more popular as a means for showing and hiding layout content. The problem however is that they can be a real pain to develop - they&#039;re hidden! One quick way to find hidden tab controls is to use the &quot;Select Same&quot; function. Select an existing visible tab control on the layout (or add one if there is none). Then with it selected, use the &quot;Select Same&quot; function - this is going to select all tabs, including hidden ones. From there you can locate the edge of the hidden tab for selection.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600127-tipshints1-17.png&quot; alt=&quot;tipshints1 17&quot; width=&quot;600&quot; height=&quot;127&quot;&gt;&lt;/p&gt;
&lt;p&gt;Another way of locating hidden tabs is to apply a blank tooltip to its tab controls, and then turn on &quot;show tooltips&quot;. hidden tabs will appear as tooltip badges where you would not expect a tooltip to be :-)&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600134-tipshints1-18.png&quot; alt=&quot;tipshints1 18&quot; width=&quot;600&quot; height=&quot;134&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Resizing Text Labels&lt;/h4&gt;
&lt;p&gt;Finally we have a tip for resizing text labels. How often do you copy and paste an existing label only to change its text and realize the dimensions of the label are now way too big?&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-35.png&quot; alt=&quot;tipshints1 35&quot; width=&quot;150&quot; height=&quot;122&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is a really common problem when the text in a label changes. The easiest way to snap the dimensions of the label to their smallest dimensions is to change a style of the label and then undo that change. Making the label bold/underline/italic is a really easy way to do this. Underline for example would be cmd+shift+U twice.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-36.png&quot; alt=&quot;tipshints1 36&quot; width=&quot;140&quot; height=&quot;93&quot;&gt;&lt;/p&gt;
&lt;p&gt;Sometimes you may notice that your label does not snap to the smallest dimensions with this technique. There are a few reasons why this may happen, but they all are concerning paragraph settings of the label as shown below.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/tipshints1-38.png&quot; alt=&quot;tipshints1 38&quot; width=&quot;227&quot; height=&quot;199&quot;&gt;&lt;/p&gt;
&lt;p&gt;For a label to snap to smallest dimensions, vertical alignment must be top and horizontal alignment must be left. There can be no indents or lines above/below. Line spacing must be 1pt.&lt;/p&gt;
&lt;p&gt;If your text has justified alignment, then the label will snap to the smallest height, but not width.&lt;/p&gt;</description>
			<pubDate>Thu, 26 Jan 2012 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/tips-hints-layout-mode/</guid>
		</item>
		
		<item>
			<title>Tour de DF</title>
			<link>https://www.teamdf.com/blogs/tour-de-df/</link>
			<description>&lt;p&gt;We were supposed to be competing (hmm... let me think about that word?) in the Lakes Loop Challenge, originally set for early this month. But fate stepped in at the last minute and the event was postponed.&lt;/p&gt;
&lt;p&gt;Disappointed barely covers it. We had a house booked for the weekend in Nelson, the post-event beverages were all but ordered and we had new designer cycle jerseys (thanks to our resident designer Mat) made specially.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/324/109_2.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;What do you do when your dreams go up in smoke? Well I&#039;ll tell you... you pick yourself up, brush yourself off and make a whole new dream! Catherine suggested we make our own custom-made cycle ride. Non-competitive (sort-of) and stops along the way. We all said &quot;hooray for Cath&quot;.&lt;/p&gt;
&lt;p&gt;So Catherine, Daniel, Phil, me and my daughter Sarah decided to ride out to Lincoln on the old, but now tar-sealed Rail Trail. It was a struggle to find another weekend that suited us all but eventually the stars were aligned and a date was set.&lt;/p&gt;
&lt;p&gt;Barely 5 minutes into the ride and Daniel needed a break and he said it was a flatty, but was it really?&lt;/p&gt;
&lt;p&gt;We biked to Lincoln, had a lovely lunch at Hillyer&#039;s then headed for home. But after a long ride of another 5kms (ish) Cath suggested we stop at the Prebbleton Pub for some well earned refreshment. I know what you&#039;rere thinking and it&#039;s ok, Sarah just had a lemonade.&lt;/p&gt;
&lt;p&gt;It was a great little outing and we were quite a sight in our matching jerseys.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/325/109_1.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Tue, 29 Nov 2011 11:15:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/tour-de-df/</guid>
		</item>
		
		<item>
			<title>I Have A Dream... Practice Management Without Fuss</title>
			<link>https://www.teamdf.com/blogs/i-have-a-dream-practice-management-without-fuss/</link>
			<description>&lt;p&gt;Every business dreams of a paperless office right? Where administration takes a back seat to customer care and excellence in your field. Dr Alex Buller and his team at &lt;a href=&quot;http://www.eyesurgeonshawkesbay.co.nz/&quot;&gt;Eye Surgeons Hawkes Bay (ESHB)&lt;/a&gt; have put the blinkers on, buckled their seat belts and embraced this challenge with absolute determination.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;This Practice Management solution needed to be able to email, print, scan in documents, track and monitor patients, calendar appointments, set reminders, and invoice all pretty standard stuff. They also needed the ability to receipt payments against multiple bank accounts and operate smoothly across Macs and PC&#039;s this is a bit more complicated, but still not too unusual.&lt;/p&gt;
&lt;h3&gt;So why not look for an &#039;off-the-shelf&#039; solution?&lt;/h3&gt;
&lt;p&gt;Alex wanted control! From the outset he knew they wanted a custom solution which isn&#039;t for everyone, at times it can be more stressful than a houseful of pre-schoolers. But they were committed and didn&#039;t want to be constrained or confused by features that were designed to suit the masses. Ongoing improvements, additions and modifications needed to be driven by them and reflect the changing needs of their practice.&lt;/p&gt;
&lt;p&gt;Dr. Alex Buller&lt;/p&gt;
&lt;p&gt;Talking to Alex there were some other twists to the requirements:&lt;/p&gt;
&lt;blockquote&gt;&quot;Clinical notes include examination drawings and diagrams, and the variations to these are multiple. A system including freehand sketches was a must, so we wanted a system that could receive them from a tablet allowing us to draw right onto the computer screen. It&#039;s true that a picture can say a thousand words.&quot;&lt;/blockquote&gt;
&lt;p&gt;They came to Digital Fusion for some expert assistance with their partially developed FileMaker system, fondly named &#039;Orbit&#039;. They&#039;d built it themselves and the objective was to create a unique solution tailored to their specific workflow. We understood a couple of the key outcomes were to reduce the physical storage requirements and increase visibility of patient information in real time.&lt;/p&gt;
&lt;p&gt;But there was more...&lt;/p&gt;
&lt;blockquote&gt;&quot;Ophthalmology uses some specific information: although we&#039;re doctors we are usually more interested in how well a person can read the vision chart than their latest blood pressure reading. Working on our own system means we can have the specialised information we want, right where we want it. Most doctor-oriented software won&#039;t allow us to do that.&quot;&lt;/blockquote&gt;
&lt;p&gt;Each patient is moved through the various stages of a consultation: appointment scheduling, nurse assessment, completion of tests then consultation with a specialist, all of which is viewable by any of the practice staff ensuring continuity of care for the patient. By the time the patient reaches the reception desk to leave, all the information necessary for writing a clinical letter, billing, and recalling the patient at a later date is at the fingertips of Rosemary and Gwen who run the office.&lt;/p&gt;
&lt;h3&gt;So how has their life changed- has it all been worth it?&lt;/h3&gt;
&lt;p&gt;Alex&#039;s business partner Dr John Beaumont summed up their feelings on Orbit so far:&lt;/p&gt;
&lt;blockquote&gt;&quot;Excellent.&quot;&lt;/blockquote&gt;
&lt;p&gt;Alex was new to FileMaker and had no computer training, but was able to follow the tutorials easily.&lt;/p&gt;
&lt;blockquote&gt;&quot;I know what the practice wants, and how FileMaker works, so can interpret between the 2 professions quite confidently communication with Digital Fusion became very straightforward.&quot;&lt;/blockquote&gt;
&lt;p&gt;ESHB are the masters of their own destiny, they wanted to do things a bit differently so took a risk. And now they&#039;re reaping the rewards.&lt;/p&gt;
&lt;blockquote&gt;&quot;With Alex as both project leader and on site support to myself and our team of two nurses and three admin staff, we have been able to make major changes rapidly. Sure, there have been some stresses and also still developments ahead. Having a system built to our needs and under our future direction can only be good. &lt;cite&gt;Dr John Beaumont&lt;/cite&gt;&lt;/blockquote&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 29 Nov 2011 09:58:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/i-have-a-dream-practice-management-without-fuss/</guid>
		</item>
		
		<item>
			<title>Head in the Clouds</title>
			<link>https://www.teamdf.com/blogs/head-in-the-clouds/</link>
			<description>&lt;p&gt;Imagine being able to access your business systems from anywhere, at any time, not having to run your own server, worry about backup, or have a plan for when the server dies.&lt;/p&gt;
&lt;p&gt;That&#039;s the promise of one of the biggest trends in IT right now, a buzz word called &quot;Cloud Computing&quot;. Cloud computing promises to save companies a lot of money and hassle, but it seems that nobody can agree on exactly what it means.&lt;/p&gt;
&lt;p&gt;While Cloud Computing has some specific technical meanings, we reckon that from your point of view as a business manager it pretty much means &quot;having your stuff accessible over the internet&quot;, right?&lt;/p&gt;
&lt;p&gt;And taking it one step further, it means not having to run your own server. When it&#039;s done right those 2 points alone make for some pretty compelling advantages.&lt;/p&gt;
&lt;p&gt;Probably the biggest concerns are that because you don&#039;t physically store your own data it feels like you&#039;re giving up control what happens if the internet is down? What happens if the hosting service closes or disaster strikes?&lt;/p&gt;
&lt;p&gt;These are valid concerns and can easily be addressed make sure you have access to frequent backups and can extract your data at any time. Make sure the service is robust and well setup.&lt;/p&gt;
&lt;p&gt;But at the end of the day most hosting services are probably safer than your own in-house server. As Xero CEO Rod Drury put it &quot;How safe is that data on your laptop right now?&quot;&lt;/p&gt;
&lt;p&gt;Cloud Computing is not just for web applications we&#039;re building more and more FileMaker solutions that are being hosted in our data centre, and we&#039;re working on bringing the advantages of cloud computing to the FileMaker platform as well.&lt;/p&gt;
&lt;p&gt;My bet is that within a few years most businesses won&#039;t have their own servers, and one more barrier to your global domination will fall.&lt;/p&gt;</description>
			<pubDate>Thu, 24 Nov 2011 17:04:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/head-in-the-clouds/</guid>
		</item>
		
		<item>
			<title>Printing Records With Different Output Designs</title>
			<link>https://www.teamdf.com/blogs/printing-records-with-different-output-designs/</link>
			<description>&lt;p&gt;Most of the time when we print records in FileMaker, the output of every record appears pretty much the same, with similar formatting and design. But what if we want records to print with a completely different output design depending on the type of record? In this article we detail some of the various ways in which this can be achieved, and the pros and cons of each method.&lt;/p&gt;
&lt;h4&gt;Why would we want to do this?&lt;/h4&gt;
&lt;p&gt;It all depends on the situation. If you are printing a simple list of customers for example, then you would expect the appearance of information on each line of the output to be the same. By that we mean the same fields in the same columns with consistent formatting.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600151-printdesigns-1.png&quot; alt=&quot;printdesigns 1&quot; width=&quot;600&quot; height=&quot;151&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/printdesigns-3.png&quot; alt=&quot;printdesigns 3&quot; width=&quot;378&quot; height=&quot;92&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/printdesigns-4.png&quot; alt=&quot;printdesigns 4&quot; width=&quot;363&quot; height=&quot;161&quot;&gt;&lt;/p&gt;
&lt;p&gt;Above is an example of a standard report output. Fields appear in their respective columns, and all look pretty similar, nothing fancy going on here.&lt;/p&gt;
&lt;p&gt;Consider now a different printing scenario. What if we were printing a test, where questions could be one of 3 different types? Some questions may be multiple choice, others a short answer, and others may be longer paragraph answers - with each record being a question. In this situation it makes no sense to have every record appear exactly the same, because that would make the test useless to the person looking at it. Ideally what we would want to do is have each type of question output in its own correct format, completely independent of the format of other question types.&lt;/p&gt;
&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/printdesigns-2.png&quot; alt=&quot;printdesigns 2&quot; width=&quot;349&quot; height=&quot;143&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Something like the above would be desirable, so how do we go about doing this output? Well, it so happens there are a few ways in which you can do this. We will discuss 5 potential methods, and the pros and cons that each method presents.&lt;/p&gt;
&lt;p&gt;It should be pointed out at this stage that the article is only concerned with changing the display of records for the purpose of printing. Actually having different record displays from a data-entry perspective is a different topic (and a more complicated one for that matter!)&lt;/p&gt;
&lt;h4&gt;Method One: Conditional Formatting&lt;/h4&gt;
&lt;p&gt;Ever since the introduction of conditional formatting in FileMaker Pro 9, people have been searching for ways to manipulate its intended use, and this is no different :) Here we are going to make use of the ability of conditional formatting to alter a fields text size, font color and style.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/printdesigns-5.png&quot; alt=&quot;printdesigns 5&quot; width=&quot;588&quot; height=&quot;430&quot;&gt;&lt;/p&gt;
&lt;p&gt;What we are looking at here is our printing layout. On it is 3 different sections for the 3 different types of questions (colored so you can see them).&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Yellow: Multiple Choice&lt;/li&gt;
&lt;li&gt;Green: Short Answer&lt;/li&gt;
&lt;li&gt;Blue: Long Answer&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Each has been formatted as we wish for the question type to appear. Now it is simply a case of trying to hide the two designs that do not apply to the type of question for any given record.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600480-printdesigns-6.png&quot; alt=&quot;printdesigns 6&quot; width=&quot;600&quot; height=&quot;480&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is the conditional formatting calculation for the multiple choice section. In this situation we are telling the multiple choice related labels to change their formatting if the question type is NOT multiple choice.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600397-printdesigns-7.png&quot; alt=&quot;printdesigns 7&quot; width=&quot;600&quot; height=&quot;397&quot;&gt;&lt;/p&gt;
&lt;p&gt;We are setting the text color to white (same as background) in an attempt to hide any display of these fields. We also set the font point size to 1 in an attempt to make it so small it cannot be viewed. Finally we superscript that sucker in a further attempt to make it even smaller. The other question type fields have similar conditional formatting on them.&lt;/p&gt;
&lt;p&gt;Sliding is set on all of these fields so that they slide up where possible. Because we make the multiple choice section so tiny in this case, the other sections will slide up.&lt;/p&gt;
&lt;p&gt;Pros:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Easy to setup for simple output designs&lt;/li&gt;
&lt;li&gt;Questions will slide up, though not perfectly (but close enough!)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Cons:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Limited to only textual objects that can have font size changed&lt;/li&gt;
&lt;li&gt;Layout design can get messy depending on number of output types&lt;/li&gt;
&lt;li&gt;Sliding issues get worse with the more output types&lt;/li&gt;
&lt;li&gt;Formatting/alignment issues if wanting to make complex outputs&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;Method Two: Calculations&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;This method uses a single calculation field in which all of the output design is done. Whatever you can accomplish in FileMakers calculation engine is at your disposal, but that is all.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/printdesigns-9.png&quot; alt=&quot;printdesigns 9&quot; width=&quot;521&quot; height=&quot;493&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is our calculation to display each of the three different question outputs. As you can see it is fairly basic and we are pretty limited to what we can do here.&lt;/p&gt;
&lt;p&gt;Pros:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Sliding works great&lt;/li&gt;
&lt;li&gt;Perfect for simple text-based designs&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Cons:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Can&#039;t use layout objects in design&lt;/li&gt;
&lt;li&gt;Design is in the schema in a calculation, not on layout&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;Method Three: Web Viewers&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;Now we are beginning to get into some of the more &quot;unconventional&quot; methods. In this method we are going to be rendering each question type through a web viewer. The code that is used in the web viewer to render the question will change depending on the question type. We are using a Data/URL to render each question, substituting in information from the record into the html.&lt;/p&gt;
&lt;p&gt;To look at the HTML code used, check out the example file. The html is rendered by the web viewer through the data/url syntax:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/printdesigns-18.png&quot; alt=&quot;printdesigns 18&quot; width=&quot;269&quot; height=&quot;114&quot;&gt;&lt;/p&gt;
&lt;p&gt;Pros:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Full power of the web at your disposal for rendering&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Cons:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Sliding of web viewers is nonexistent so every question has same fixed height&lt;/li&gt;
&lt;li&gt;More difficult to make adjustments to the design&lt;/li&gt;
&lt;li&gt;Will potential render differently on mac and windows&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Method Four: Hiding Portals&lt;/strong&gt;&lt;br&gt;This method makes use of a number of different features such as relationships, portal filtering and preview mode niceties.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/printdesigns-10.png&quot; alt=&quot;printdesigns 10&quot; width=&quot;583&quot; height=&quot;270&quot;&gt;&lt;/p&gt;
&lt;p&gt;Bit of a mess isn&#039;t it! Well that is how it looks in layout mode when it is all built, but lets deconstruct what is going on here.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60096-printdesigns-11.png&quot; alt=&quot;printdesigns 11&quot; width=&quot;600&quot; height=&quot;96&quot;&gt;&lt;/p&gt;
&lt;p&gt;That&#039;s better. What we have here is 3 separate 1-row portals. Each portal corresponds to a particular question type, and in each portal is the design you wish each question type to have. Originally all the portals were stacked on top of each other but have now been placed side by side.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600576-printdesigns-12.png&quot; alt=&quot;printdesigns 12&quot; width=&quot;600&quot; height=&quot;576&quot;&gt;&lt;/p&gt;
&lt;p&gt;Every portal is using a simple self-join relationship to relate to itself and display its own record.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/printdesigns-13.png&quot; alt=&quot;printdesigns 13&quot; width=&quot;534&quot; height=&quot;63&quot;&gt;&lt;/p&gt;
&lt;p&gt;Each portal also has a filtering calculation on it to determine whether the contents should be displayed or not. Each portal is setup in a similar way as shown above depending on question type.&lt;/p&gt;
&lt;p&gt;The end result is that only one of the three portals will show its output depending on the question type:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600204-printdesigns-14.png&quot; alt=&quot;printdesigns 14&quot; width=&quot;600&quot; height=&quot;204&quot;&gt;&lt;/p&gt;
&lt;p&gt;When all of the portals are stacked on top of each other, a cool thing happens. The two portals that do not show a record will not only show nothing, but they completely disappear from the output, its as if they aren&#039;t on the layout. This leaves the one remaining portal that is showing contents to be the only portal visible on that record. Note that data entry and browse mode is another story... but for printing it works great!&lt;/p&gt;
&lt;p&gt;Pros:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;You &lt;strong&gt;CAN&lt;/strong&gt; use FileMaker layout objects in your design&lt;/li&gt;
&lt;li&gt;Easy to design each different output type in its own portal box&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Cons:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;No sliding up of portals unfortunately, so every question has same height&lt;/li&gt;
&lt;li&gt;Unstacking portals to make changes can get tedious&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;Method Five: Containers&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;This is perhaps the most extreme and convoluted method, but can deliver good results if the effort is put in.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/printdesigns-15.png&quot; alt=&quot;printdesigns 15&quot; width=&quot;324&quot; height=&quot;66&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we have created new layouts for each question type. Each layout contains the design we want to use for that type of question. For example, here is the Multi Choice layout:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/printdesigns-16.png&quot; alt=&quot;printdesigns 16&quot; width=&quot;474&quot; height=&quot;192&quot;&gt;&lt;/p&gt;
&lt;p&gt;A container field has been added to the table. The idea is that we populate this container field with an image that looks like the question design we want to output.&lt;/p&gt;
&lt;p&gt;To do this, we basically go to one of the three layouts, take a picture of the layout, then go back to the container and paste in the results. We do this for each record until every record has an image of itself, then we output the images, simple huh!&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/printdesigns-17.png&quot; alt=&quot;printdesigns 17&quot; width=&quot;514&quot; height=&quot;197&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is a simple script to populate the containers. As you can see, it loops through each record. For each record it then goes to that record on the corresponding design layout. We must enter preview mode to take the picture. The picture is taken simply by using a copy script step - if done in browse mode we get just the text from the record. We then return to the original layout and paste the image - now on clipboard - into the container.&lt;/p&gt;
&lt;p&gt;A couple of things about this method:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Freeze window should be used to increase speed&lt;/li&gt;
&lt;li&gt;Consider using a separate table (i.e. virtual list table) for the container field, as this method could increase the size of your database considerably if care is not taken!&lt;/li&gt;
&lt;li&gt;Changes in rendering of images from version to version of FileMaker may mean this method is prone to breaking over time. This technique worked great in FileMaker 6, but has since been prone to giving blurry printed outputs in subsequent versions&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Pros:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Can use FM layout objects in design&lt;/li&gt;
&lt;li&gt;Will slide to a degree if done correctly (see below)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Cons:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Because images being used, can increase size of database if not maintained&lt;/li&gt;
&lt;li&gt;Potential for blurry printing&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;A further note about sliding with container method&lt;/h4&gt;
&lt;p&gt;In order to get sliding to work properly using the container method, the page setup for each different layout being copied has to be set so that the height of the page is basically the same as the height of your body part on the layout. If this is not the case, then when you enter preview mode the resulting preview is your layout body part plus the rest of the full page. Upon copying this you end up with a large image which is the entire page. So ideally what you need to do is reduce the height of your page so that when you go into preview mode, you are only copying the question component and that only.&lt;/p&gt;
&lt;p&gt;Custom page setups can be setup and will remain attached to a Page Setup script step on the mac, which means it can be used across any other mac computer without issue. I believe on a PC it should still run fine with the page setups scripted (at least it appears to in testing).&lt;/p&gt;
&lt;p&gt;The container field on your layout should be set to have top vertical alignment and to slide up and reduce height of enclosing part. If done properly you can have some good results with sliding - with the added bonus that you have full control over designing your outputs using FileMaker layout objects - something none of the other methods offer.&lt;/p&gt;
&lt;p&gt;If sliding is not a requirement then custom page setups for each layout is not required. You could copy the entire page. On your output layout, set the containers alignment to top, but set it to crop image to frame. This will leave just the top of the image visible (the top part should contain your question design anyway).&lt;/p&gt;
&lt;h4&gt;Conclusion of the methods&lt;/h4&gt;
&lt;p&gt;Which method is chosen really depends on the complexity of output you require and whether sliding is an issue for you. Each have their benefits but come with baggage. Ideally what we are striving for is a method that gives you full control over design by using FileMakers layout objects in your design, but can nicely slide up on printing. The container method has both these features, but unfortunately it comes with a LOT of baggage! We tend to prefer the calculation method for most things, though it does struggle with multi-columnar formatting so best to avoid that if possible.&lt;/p&gt;
&lt;h4&gt;A sixth method - Append to PDF?&lt;/h4&gt;
&lt;p&gt;While not covered in this article, there is the potential for another method that would result in a PDF document as the output as opposed to a printed form. This would be done in a similar fashion to the container method through record looping, but instead of creating the image and pasting into a container, the record on its own special layout would be saved and appended to a PDF document. The end result would be a PDF of all records in their own format, and this method would support sliding quite nicely.&lt;/p&gt;
&lt;h4&gt;Any other methods out there? Let us know!&lt;/h4&gt;
&lt;p&gt;If you have any other ideas or methods that you use to output different designs for records, we&#039;d love to hear them, feel free to leave a comment outlining your method.&lt;/p&gt;
&lt;p&gt;UPDATE: We have had 2 further examples submitted by Stephen Dolenski and Mikhail Edoshin. Please refer to the example files section below for more information and download links.&lt;/p&gt;
&lt;h4&gt;Example Files x3&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/printdesigns/PrintDesigns.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This additional example file was kindly supplied by Stephen Dolenski from &lt;a href=&quot;http://www.fmforums.com&quot;&gt;Fmforums.com&lt;/a&gt; in which he demonstrates another method using Bruce Robertson&#039;s virtual list technique.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/printdesigns/PrintDesignsVL.zip&quot;&gt;Download Virtual List Example File&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;.. and finally we have another reader submitted example file from Mikhail Edoshin in which he demonstrates a variation of the portal hiding technique. Mikhail points out that the portals need not in fact be stacked on top of each other, yet can be placed on the layout one beneath the other, and they will slide up. The portal contents within do not slide but because the portals themselves will slide, this is a nicer approach as it lets you see all of the different portals without the need to move them out from under one another.&lt;/p&gt;
&lt;p&gt;Also in his example file he shows how it can be combined with other methods such as calculation fields or regular field sliding to achieve the desired result.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/printdesigns/DifferentLayouts.zip&quot;&gt;Download Mikhail&#039;s Example File&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Appendix: Virtual List Information from Stephen&lt;/h4&gt;
&lt;p&gt;Here is information supplied by Stephen in regards to how he built his virtual list implementation, very cool stuff!&lt;/p&gt;
&lt;p&gt;The first step is in the Questions Table need to create a field&lt;/p&gt;
&lt;p&gt;zVirtualList this is a calc that will generate the return, pipe and %% separated text&lt;/p&gt;
&lt;p&gt;Let ( &lt;br&gt;[&lt;br&gt;q = Substitute ( Question ; &quot;ÃÂ¶&quot; ; &quot;%%&quot; ) ; &lt;br&gt;a = Substitute ( Answer A ; &quot;ÃÂ¶&quot; ; &quot;%%&quot; ) ; &lt;br&gt;b = Substitute ( Answer B ; &quot;ÃÂ¶&quot; ; &quot;%%&quot; ) ; &lt;br&gt;c = Substitute ( Answer C ; &quot;ÃÂ¶&quot; ; &quot;%%&quot; ) ; &lt;br&gt;d = Substitute ( Answer D ; &quot;ÃÂ¶&quot; ; &quot;%%&quot; )&lt;/p&gt;
&lt;p&gt;];&lt;/p&gt;
&lt;p&gt;ID &amp;amp;&quot;|&quot; &amp;amp;Type &amp;amp;&quot;|Q|&quot; &amp;amp; q &amp;amp; ÃÂ¶ &amp;amp;&lt;/p&gt;
&lt;p&gt;Case ( Type â  &quot;Short Answer&quot; ; &lt;br&gt;ID &amp;amp;&quot;|&quot; &amp;amp;Type &amp;amp;&quot;|A|&quot; &amp;amp; a &amp;amp; ÃÂ¶ &amp;amp;&lt;br&gt;ID &amp;amp;&quot;|&quot; &amp;amp;Type &amp;amp;&quot;|B|&quot; &amp;amp; b &amp;amp; ÃÂ¶ &amp;amp;&lt;br&gt;ID &amp;amp;&quot;|&quot; &amp;amp;Type &amp;amp;&quot;|C|&quot; &amp;amp; c &amp;amp; ÃÂ¶ &amp;amp;&lt;br&gt;ID &amp;amp;&quot;|&quot; &amp;amp;Type &amp;amp;&quot;|D|&quot; &amp;amp; d &lt;br&gt;)&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;The script basically goes to the Questions Table sorts and loops thru each record adding that calc field to a global variable&lt;br&gt;then it goes to the VirtualList layout where the global variable is the rendered into rows and columns as needed.&lt;/p&gt;
&lt;p&gt;the calculation in that table determines the output calculations needed for generating the reports.. including formatting indents etc.&lt;/p&gt;
&lt;p&gt;The benefit of this you don&#039;t need to add calcs for visual output display needs in the schema of your data tables.&lt;/p&gt;
&lt;p&gt;I haven&#039;t employed it in the demo but you could even reduce some of the data needed and really only take the ID of the questions in the global variable&lt;br&gt;and then thru the relationship pull the question and answer text as needed.&lt;/p&gt;
&lt;p&gt;The virtual list will auto generate the necessary records as you have need for the question &amp;amp; response via the script, if your schema for your survey were more &lt;br&gt;normalized ( Question - Responses ) you could simply go to the response table and grab the records building the rows as needed, and printed reports&lt;br&gt;could be dynamic where you could have different versions of tests or questions and different responses or where the responses are in different orders.&lt;/p&gt;
&lt;p&gt;The virtual list technique will allow you to better allow for page breaks.&lt;/p&gt;
&lt;p&gt;You could add more complexity and have more question types or options in the question to create a Likert scale &lt;br&gt;http://en.wikipedia.org/wiki/Likert_scale&lt;/p&gt;
&lt;p&gt;The %% conversion on the original question/response - is to preserve any returns in them in the final output.&lt;/p&gt;</description>
			<pubDate>Thu, 03 Nov 2011 10:37:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/printing-records-with-different-output-designs/</guid>
		</item>
		
		<item>
			<title>FileMaker Go</title>
			<link>https://www.teamdf.com/blogs/filemaker-go/</link>
			<description>&lt;p&gt;If you are already using iPads or iPhones in your business or you can see just how handy they might be, then read on. If you&#039;re one of our many customers that uses FileMaker, then this is for you too.&lt;/p&gt;
&lt;p&gt;A little over a year ago FileMaker released a purpose built mobile version of their database application: FileMaker Go.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/304/103_1.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;With FileMaker Go, you can access your existing database system on your mobile device from wherever you are - be it in the office, on site, or on the road. All you need is an internet connection and you are ready to rock and roll.&lt;/p&gt;
&lt;h3&gt;FileMaker Go is packed with exciting features, such as:&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;Multi-touch gestures native to iPhone and iPad.&lt;/li&gt;
&lt;li&gt;Capture and add signatures to your database right from the iPhone and iPad.&lt;/li&gt;
&lt;li&gt;Add photos from your device to your database directly.&lt;/li&gt;
&lt;li&gt;Has the same functionality as FileMaker Pro (i.e. add, modify, delete, sort records).&lt;/li&gt;
&lt;li&gt;Convert data to a PDF and email it directly from your device.&lt;/li&gt;
&lt;li&gt;Print your reports and forms using AirPrint in the latest iOS.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Most databases will run fine on FileMaker Go without any modifications. However, given the differences between the iPhone, iPad and a regular desktop computer, it is sometimes a good idea to provide different interfaces to your database specific to the mobile device you&#039;re using.&lt;/p&gt;
&lt;p&gt;Digital Fusion has done a number of projects with FileMaker Go, and know what it takes to produce appealing and easy to use interfaces for the iPhone and iPad. If you think FileMaker Go sounds like the way forward for you, then lets talk!&lt;/p&gt;</description>
			<pubDate>Mon, 17 Oct 2011 17:01:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-go/</guid>
		</item>
		
		<item>
			<title>Integrating Kiosk Mode into your Solution</title>
			<link>https://www.teamdf.com/blogs/integrating-kiosk-mode-into-your-solution/</link>
			<description>&lt;p&gt;Kiosk mode is a cool way to run a FileMaker database in a full screen environment where users are prevented from accessing the other functionality of the operating system. But what if you have a normal FileMaker solution and wish to use kiosk functionality in certain areas only?&lt;/p&gt;
&lt;p&gt;In this article we illustrate how a typical FileMaker solution can be enhanced with a kiosk component for carrying out certain actions. We use the article example file to help illustrate this. We also give some information on what kiosk mode is, and things to watch out for when developing for it.&lt;/p&gt;
&lt;h4&gt;So what is Kiosk Mode?&lt;/h4&gt;
&lt;p&gt;The majority of FileMaker solutions run in what could be called a normal windowed environment. Upon opening a database, it appears in its own window on a mac - or within the FileMaker application on windows. Users are free to use the rest of their operating system whenever they wish.&lt;/p&gt;
&lt;p&gt;Kiosk mode is a little different in that it prevents users from interacting with the operating system, and keeps FileMaker open as the central and only application they can interact with. The term &quot;Kiosk&quot; is used because the functionality resembles that seen on kiosk machines in places such as restaurants, museums and so on.&lt;/p&gt;
&lt;h4&gt;How do you create a Kiosk file?&lt;/h4&gt;
&lt;p&gt;A FileMaker file by default has Kiosk mode disabled. Enabling is done by using the Developer Utilities dialog that is build into FileMaker Pro Advanced.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600501-kioskmode-1.png&quot; alt=&quot;kioskmode 1&quot; width=&quot;600&quot; height=&quot;501&quot;&gt;&lt;/p&gt;
&lt;p&gt;Select the file(s) you wish to enable Kiosk mode in by using the Add button, select the output folder also. You then want to click on &quot;Specify&quot; under Solution Options.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/kioskmode-2.png&quot; alt=&quot;kioskmode 2&quot; width=&quot;600&quot; height=&quot;614&quot;&gt;&lt;/p&gt;
&lt;p&gt;In here you want to tick the Kiosk mode option. Upon hitting the &quot;Create&quot; button on the main dialog, a kiosk mode version of the file will be generated.&lt;/p&gt;
&lt;h4&gt;Developing or Using a Kiosk File&lt;/h4&gt;
&lt;p&gt;Now that the file has had kiosk mode enabled, it is important to know how to access your file for either the purpose of using, or developing.&lt;/p&gt;
&lt;p&gt;FileMaker help has this to say:&lt;/p&gt;
&lt;p&gt;Kiosk mode is ignored if the solution is opened by accounts with the Full Access privilege set, a privilege set that allows management of extended privileges, or a privilege set that allows modification of layouts, value lists, and scripts.&lt;/p&gt;
&lt;p&gt;This factor is key. If you want to develop your file, always remember to log in as a [FULL ACCESS] user. If not, you will inadvertently end up with the file open in Kiosk mode if your login account meets any of the criteria above.&lt;/p&gt;
&lt;p&gt;If your file does open in Kiosk mode, then you have to provide a means for yourself, or your users to close the file. There is no native close option, so without a button or some other means to close the file, you will be stuck in the file and have to resort to other means to get out of the file - such as force closing the file on Server, terminating the FileMaker Pro application via remote login, or restarting your machine. Neither option is really nice so be sure to provide a way to close the file!&lt;/p&gt;
&lt;h4&gt;Now with that all out of the way, time to get into the guts of this article:&lt;/h4&gt;
&lt;p&gt;The whole point of this article is integrating kiosk functionality into a regular non-kiosk database. We know that a kiosk-enabled file will open in kiosk mode under certain conditions, so having a single file is not going to cut it because we cannot guarantee all users will have the required account level to open in kiosk mode always.&lt;/p&gt;
&lt;p&gt;The solution is to build a secondary kiosk file that links to your main database. The kiosk file is called into action whenever that functionality is required. The overall process is not too difficult, but there are a number of things to take into consideration.&lt;/p&gt;
&lt;h4&gt;A basic example: Kiosk file for taking tests&lt;/h4&gt;
&lt;p&gt;One great use of the kiosk functionality is for users of the database who are required to take tests. If someone is taking a test then you would not wish for them to have access to things such as their web browser! Kiosk mode would be great for this given it restricts the users access to these things. For anyone who has ever taken the FileMaker certification exam, we are aiming for a similar feel here.&lt;/p&gt;
&lt;p&gt;We will use the attached example file as the basis for the example in this article, so it might be a good idea to download it if you haven&#039;t already.&lt;/p&gt;
&lt;h4&gt;Step One: Link your main file to your kiosk file&lt;/h4&gt;
&lt;p&gt;This part is achieved by setting up external data sources in both your main file and kiosk file. Each file should have a reference to the other file. One way to think of the kiosk file is merely an extension of the main file. It doesn&#039;t need to contain its own tables or data, it is purely for kiosk functionality for the main database.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600429-kioskmode-3.png&quot; alt=&quot;kioskmode 3&quot; width=&quot;600&quot; height=&quot;429&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Step Two: Setup a Full Access, and non Full Access user&lt;/h4&gt;
&lt;p&gt;This is done in the kiosk file. This file requires a [FULL ACCESS] account so you can modify the file if need be. However to make use of kiosk mode, it will require an account that is not full access.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600421-kioskmode-4.png&quot; alt=&quot;kioskmode 4&quot; width=&quot;600&quot; height=&quot;421&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we have a full access account, and another setup as data entry only. The &quot;Test User&quot; account is the one that will be used by everyone who accesses the file for taking tests.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/kioskmode-5.png&quot; alt=&quot;kioskmode 5&quot; width=&quot;554&quot; height=&quot;525&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here, we have set the Kiosk file to automatically login as this Test User.&lt;/p&gt;
&lt;p&gt;A very important thing to take note of here is how FileMaker will attempt to log a user into a file that opens from another file. Lets say a user is opening File B from File A. Upon launching File B, FileMaker is going to try and find a matching user account in that file, and if one is found, log the user into File B with that account. In this situation we don&#039;t wish for this to happen. The reason is that if a user is logged into File A with [FULL ACCESS], and there is a matching account in the Kiosk file, then they would log into kiosk with [FULL ACCESS] and as such, the kiosk functionality would not work - they would log into it as if it were a regular file.&lt;/p&gt;
&lt;p&gt;For this reason, it may be good convention to make the [FULL ACCESS] username and password in the kiosk file something entirely different from any [FULL ACCESS] account in your main file, that way this scenario will not occur, and everyone will open the kiosk file with the Test User account.&lt;/p&gt;
&lt;h4&gt;Step Three: Enable Kiosk mode&lt;/h4&gt;
&lt;p&gt;At this point it would be a good idea to enable Kiosk mode on your kiosk file if not already. Refer to the start of the article on how this is done, and some of the things you need to be careful of once the file becomes kiosk enabled.&lt;/p&gt;
&lt;h4&gt;Lets take a breather, where are we up to..&lt;/h4&gt;
&lt;p&gt;At this point we have the following:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;A main database file&lt;/li&gt;
&lt;li&gt;A kiosk enabled file with [FULL ACCESS] and non [FULL ACCESS] users.&lt;/li&gt;
&lt;li&gt;Kiosk file is set to login with non [FULL ACCESS]&lt;/li&gt;
&lt;li&gt;Both files are linked to each other via external data source.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The next steps will involve initialising the kiosk file from the main file, some issues that can arise from this process, and how we can resolve them.&lt;/p&gt;
&lt;h4&gt;Setting the scene for what we want to achieve&lt;/h4&gt;
&lt;p&gt;In the main file we have a portal of 10 test records as shown below:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/kioskmode-6.png&quot; alt=&quot;kioskmode 6&quot; width=&quot;436&quot; height=&quot;269&quot;&gt;&lt;/p&gt;
&lt;p&gt;When a user clicks on a test record, we want that test to open in kiosk mode. The user would then fill out the test, and when they are done, they would close the test and be back where they started. Sounds simple right?&lt;/p&gt;
&lt;h4&gt;Step Four: Initiating the Kiosk File&lt;/h4&gt;
&lt;p&gt;The kiosk file is closed at all times, other than when it is being used. We don&#039;t wish for it to appear in the FileMaker Windows menu, so we open and close it explicitly when we begin using it, and when we are done.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600392-kioskmode-7.png&quot; alt=&quot;kioskmode 7&quot; width=&quot;600&quot; height=&quot;392&quot;&gt;&lt;/p&gt;
&lt;p&gt;The above script is run when the user clicks on a test in the portal. At this stage we are still in the main file. The script is passed the ID of a test record, which will eventually be passed to the kiosk file.&lt;/p&gt;
&lt;p&gt;The last script step here calls a script over in the kiosk file and passes it a test ID. This is how the kiosk file is initiated.&lt;/p&gt;
&lt;h4&gt;Step Five: Correct setup of Kiosk File&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;A script has now been called in the kiosk file which is going to open the file and initiate it. There are some very important housekeeping things that this script must do first in order to ensure that kiosk mode is watertight and prevents the user from getting out of it.&lt;/p&gt;
&lt;p&gt;When a kiosk mode file is opened, and there happens to be other databases and windows also open, then these other database windows are also visible whilst in kiosk mode. In fact, if you click on one of the other databases it will switch to it and take you out of kiosk mode temporarily.&lt;/p&gt;
&lt;p&gt;From a testing perspective this is bad news, if a user can get to another database open, then they can reveal their dock and get into their browser and so on.&lt;/p&gt;
&lt;p&gt;The solution here is to ensure that when you open up the kiosk file, that its window dimensions are set exactly to that of the screens dimensions, so that the layout takes up the entire screen real estate, thus hiding any other open window underneath.&lt;/p&gt;
&lt;p&gt;(Note that prior to this, we had used scripts to hide and restore all other windows upon opening and closing the kiosk file, these work fine, but simply making the layout size full screen is much easier and less scripting!).&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600371-kioskmode-8.png&quot; alt=&quot;kioskmode 8&quot; width=&quot;600&quot; height=&quot;371&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is the start of the initiation script in the kiosk file. The freeze window helps the startup go smoother visually.&lt;/p&gt;
&lt;p&gt;You&#039;ll notice we do a very brief pause of 0.1 seconds. The reason for this is that when the kiosk file opens, it very briefly opens in a normal windowed mode, before entering kiosk mode. Without the pause, our next script step that sets the window position and size actually happens while it is still in a windowed mode, and this makes it near on impossible to correctly set the window to full screen size (due to issues arising with docks and such).&lt;/p&gt;
&lt;p&gt;The pause gives us just enough time to enter kiosk mode, so that when we set the window dimensions to Get(ScreenWidth) and Get(ScreenHeight) We are getting the full dimensions of the screen.&lt;/p&gt;
&lt;h4&gt;Step Six: Closing Kiosk File&lt;/h4&gt;
&lt;p&gt;When you are finished with the file and wish to return to the main database, you need to close the file by issuing a Close File script step command. Because kiosk mode has no exit or close command, you need to provide a means of closing the file by way of button.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/kioskmode-9.png&quot; alt=&quot;kioskmode 9&quot; width=&quot;300&quot; height=&quot;95&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this case our big finish test button simply closes the file.&lt;/p&gt;
&lt;h4&gt;Some things to watch out for&lt;/h4&gt;
&lt;p&gt;While kiosk mode is a great way to present a full screen layout to a user (for purposes such as taking a test) - it is not 100% secure in keeping the user locked out of their operating system. While developing this technique for a client solution I realised there are some applications out there that are able to dump you out of kiosk mode temporarily. The one application I noticed that did this was Tweetdeck. Whenever this application sent a notification of updates, the resulting popup caused kiosk mode to exit.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/kioskmode-10.png&quot; alt=&quot;kioskmode 10&quot; width=&quot;355&quot; height=&quot;430&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can see above, we have kiosk mode running the file, yet the dock became visible.&lt;/p&gt;
&lt;p&gt;So you need to be careful if using this for things such as testing, the computer should be setup with no other applications running that might interfere.&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/kioskmode/KioskMode.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Test_Kiosk.fp7 file has been set to login automatically as a non-admin user for the purpose of demonstrating kiosk mode. If you wish to access the file to have a look inside, hold down the option (shift in windows) key while opening the file:&lt;/p&gt;
&lt;p&gt;Username: Administrator&lt;br&gt;Password: (no password)&lt;/p&gt;</description>
			<pubDate>Wed, 05 Oct 2011 15:27:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/integrating-kiosk-mode-into-your-solution/</guid>
		</item>
		
		<item>
			<title>Simple Truncated Displaying of Long Lists (+more)</title>
			<link>https://www.teamdf.com/blogs/simple-truncated-displaying-of-long-lists-more/</link>
			<description>&lt;p&gt;Displaying a long list of items on a layout generally means that the majority of the list is hidden from the user until they click into the field, with no feedback as to the size of the list. This article details a nice technique you can use to present the same list in a truncated style that gives live feedback on the number of items.&lt;/p&gt;
&lt;h4&gt;The Issue&lt;/h4&gt;
&lt;p&gt;Consider the field shown below containing a return-delimited list of values:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/truncatedlist-1.png&quot; alt=&quot;truncatedlist 1&quot; width=&quot;273&quot; height=&quot;240&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we have a list but the size of that list is unknown. For all we know it could contain just the twelve names shown, or it may contain far more. The only way at this stage to get an idea of the size of the list is to click into it and then scroll through the names. Doing this however will still not give you a very good indication of the number of items in the list.&lt;/p&gt;
&lt;p&gt;One way to overcome this issue would be to give the user some kind of visual cue as to the size of the list. This would not only alert them to the fact that there are more items in the field than currently shown, but it also also tells them how many items there are.&lt;/p&gt;
&lt;p&gt;This could be achieved in various ways, one of which serves as the basis of this article and which we think is rather cool.&lt;/p&gt;
&lt;h4&gt;The (+More) Display&lt;/h4&gt;
&lt;p&gt;For lack of a better name, this technique has been denoted +More due to the display it gives. Below is a picture of what we are ultimately going to end up with.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/truncatedlist-2.png&quot; alt=&quot;truncatedlist 2&quot; width=&quot;266&quot; height=&quot;230&quot;&gt;&lt;/p&gt;
&lt;p&gt;The last displayed line in the field now tells us how many more items there are in the list. In this case the size of the list is the 11 displayed items plus 66 more, giving a total list size of 77 items.&lt;/p&gt;
&lt;p&gt;The effect is achieved by overlaying another object on top of the entry field. When the user clicks onto it, they are in fact clicking into the field underneath, and so can begin to edit the field contents.&lt;/p&gt;
&lt;h4&gt;Unstored Calculation Field&lt;/h4&gt;
&lt;p&gt;We have in fact placed a calculation field over the regular field, as shown below.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/truncatedlist-3.png&quot; alt=&quot;truncatedlist 3&quot; width=&quot;316&quot; height=&quot;232&quot;&gt;&lt;/p&gt;
&lt;p&gt;The calc field has been filled with white colour so as to completely obscure the underlying field.&lt;/p&gt;
&lt;h4&gt;The Issue of Anchoring and Field Resizing&lt;/h4&gt;
&lt;p&gt;One thing a user may end up doing on the layout is anchoring the field so that when the window is resized, the height of the field changes. Generally for lists this means more or less items are displayed when resized. The implications for our technique are that we need the display to dynamically update when the window is resized, so that the number of values shown, and the number of other items displayed is always accurate. All of this is taken care of using a special custom function we created to produce the display.&lt;/p&gt;
&lt;h4&gt;How Do We Define The Calculation?&lt;/h4&gt;
&lt;p&gt;The following single line of code is specified in the calculation:&lt;/p&gt;
&lt;pre&gt;truncateList ( Home::Values ; 18 ; &quot;MainList&quot; )&lt;/pre&gt;
&lt;p&gt;The custom function accepts three parameters:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;&lt;li&gt;theList: The actual list to display&lt;/li&gt;
&lt;li&gt;lineHeight: The height in pixels of a single line of text in the underlying field being displayed&lt;/li&gt;
&lt;li&gt;objectName: The layout object name of the underlying field being displayed&lt;/li&gt;
&lt;/ul&gt;&lt;pre&gt;Let ( [&lt;br&gt;	totalValues = ValueCount ( theList ) ;&lt;br&gt;	objectHeight = GetLayoutObjectAttribute ( objectName ; &quot;Height&quot; ) ;&lt;br&gt;	numLines = Floor ( objectHeight / lineHeight) ;&lt;br&gt;	visibleLines = numLines - 1&lt;br&gt;];&lt;br&gt;	If ( &lt;br&gt;		totalValues â¤ numLines ; &lt;br&gt;		theList ; &lt;br&gt;		LeftValues ( theList ; visibleLines ) &amp;amp; &lt;br&gt;		TextStyleAdd ( TextColor ( &quot;(+ &quot; &amp;amp; totalValues - visibleLines &amp;amp; &quot; more)&quot; ; RGB ( 62 ; 108 ; 176 ) ) ; Bold )&lt;br&gt;	)&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;So what is the function doing? Well, the first thing it does is determine the total number of items in the list so we know how many to display and how many remaining we need to show.&lt;/p&gt;
&lt;p&gt;Next, it uses the GetLayoutObjectAttribute function to determine the current height of the displayed field on the layout. The reason for this is that anchoring and layout resizing can affect the size of the field at any given point in time, which will in turn affect what we display.&lt;/p&gt;
&lt;p&gt;With that information known, we can now determine the number of lines of text that the field is capable of fully displaying currently. This is a simple calculation of dividing the fields height by the height of a single line.&lt;/p&gt;
&lt;p&gt;We also determine how many actual values the field can display if our +More line is used. This is always one less than the total number of lines the field can display.&lt;/p&gt;
&lt;p&gt;We now have everything we need to formulate the display. If the field is capable of showing the entire contents of the list then we simply show the list. If however it cannot, then we are going to show part of the list with our +more line as the last line. This part of the function also adds some colour and style formatting to the last line.&lt;/p&gt;
&lt;p&gt;So that&#039;s it, pretty simple really, nothing too over the top.&lt;/p&gt;
&lt;h4&gt;Putting it all Together...&lt;/h4&gt;
&lt;p&gt;The end result of the custom function and display calculation is a nice and simple to implement way to display a list of values to the users.&lt;/p&gt;
&lt;p&gt;As the layout is resized, the calculation is re-evaluated and the display updated. The changes to the display are instant when the window is manually resized which is nice, as illustrated in this crude animation below:&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/291/truncatedlist_4.gif&quot; alt=&quot;What happens to the display as the window is scaled.&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Implications of using a Calculation Field&lt;/h4&gt;
&lt;p&gt;The technique we have shown makes use of an additional calculation field for the purposes of the display. What this means is that a new calculation field is required in conjunction with the actual list field. A bit of a hassle really, but there are some reasons why we ended up taking this approach.&lt;/p&gt;
&lt;p&gt;The following part of the article details our initial thinking of implementing this technique, and why it failed causing us to revert to a calculation field. Hopefully this proves useful and you may get some cool ideas out of it - for this particular technique however it was not good enough (you can stop reading now if you just wanted the above technique!)&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;hr&gt;&lt;h4&gt;EXTRA: Looking for a Solution with no Additional Fields&lt;/h4&gt;
&lt;p&gt;When first tackling it, we looked for a technique that didn&#039;t require any additional fields in the schema. What we came up with was using merge variables to achieve this.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/truncatedlist-4.gif&quot; alt=&quot;truncatedlist 4&quot; width=&quot;300&quot; height=&quot;120&quot;&gt;&lt;/p&gt;
&lt;p&gt;So we defined a merge variable called $$ListDisplay and overlaid it on the field. The next trick was to have the variable define itself. We wanted the display to change whenever the user resizes the window, so we decided to make use of the layout objects conditional formatting as a means to define the variable. Conditional formatting re-evaluates during a screen redraw, so we thought this was perfect!&lt;/p&gt;
&lt;p&gt;On the merge variables conditional formatting we defined the following:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/truncatedlist-5.png&quot; alt=&quot;truncatedlist 5&quot; width=&quot;397&quot; height=&quot;232&quot;&gt;&lt;/p&gt;
&lt;p&gt;Basically it is the calculation definition but instead we are setting the global variable to it instead by using a Let statement within the conditional formatting.&lt;/p&gt;
&lt;p&gt;When we jumped into browse mode and began resizing the layout window by dragging it larger, we noticed that it appeared to work perfect! The merge variable was refreshing live as we resized the window and everything was good with the world.&lt;/p&gt;
&lt;p&gt;Fast forward a few seconds however and the world began to crumble before our eyes.&lt;/p&gt;
&lt;p&gt;It turns out merge variables don&#039;t like to play ball when it comes to screen redraws, and their behavior in that department is quite erratic. Certain actions did not force the merge variable to refresh:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Changing window size using + control in top left corner of window&lt;/li&gt;
&lt;li&gt;Actually editing the field contents (quite a critical one)&lt;/li&gt;
&lt;li&gt;Upon layout first loading after file opened&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The first two were killers, as to get it to work properly meant workarounds such as script triggers to force a refresh. In fact, it is worse than that as a simple refresh window step wasn&#039;t even enough, we had to introduce a brief 0.1 second pause prior to any screen refresh, no thank you!&lt;/p&gt;
&lt;p&gt;The last one was peculiar too. Turns out the merge variable evaluated &lt;strong&gt;before&lt;/strong&gt; the conditional formatting did, thus the initial view was an empty global variable and so no display. Only after the first screen redraw did the variable get initialized. This could have been remedied by setting it in the startup script but that still isn&#039;t very nice.&lt;/p&gt;
&lt;p&gt;The moral is what might look great at first has to be tested to the point where it no longer looks so good :) It was a good thought but too many issues.&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/truncatedlist/TruncatedListDisplay.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 22 Aug 2011 16:15:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/simple-truncated-displaying-of-long-lists-more/</guid>
		</item>
		
		<item>
			<title>The Search for Fast Aggregates - Trial &amp; Error</title>
			<link>https://www.teamdf.com/blogs/the-search-for-fast-aggregates-trial-error/</link>
			<description>&lt;p&gt;In the first of a two part series, we begin the search for a faster way to perform aggregates in FileMaker. We cover why aggregates can be quite a costly operation - especially on wide area networks - and use that as a jumping off point for finding a faster method.&lt;/p&gt;
&lt;h4&gt;What are Aggregates&lt;/h4&gt;
&lt;p&gt;An aggregate is a collection of items gathered together to form a total quantity. In FileMaker terms, the collection of items are records, and functions can be applied to the quantity to obtain useful information such as the sum, count, average, minimum and maximum to name a few.&lt;/p&gt;
&lt;p&gt;Aggregates generally come in two varieties. First are summary fields. These are commonly used on sub-summary reports and are placed in the various layout parts to summarize records in parts of the report. Summary fields can also be used to summarize record values through a relationship/portal.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600380-fastaggregates1-1.png&quot; alt=&quot;fastaggregates1 1&quot; width=&quot;600&quot; height=&quot;380&quot;&gt;&lt;/p&gt;
&lt;p&gt;The second type are in the form of functions that perform the aggregate operation on its passed parameters. You can pass them a specified set of values as parameters, but a more common usage is to pass them a related field using a relationship. This performs the aggregate on the field value from all related records, returning you the summarized result. Examples of these functions are list, sum, average, min, max, and a couple of other less commonly used ones.&lt;/p&gt;
&lt;pre&gt;Sum ( Home to Contacts for All Contacts::Weight )&lt;/pre&gt;
&lt;p&gt;If you do enough development in FileMaker you will undoubtedly have come across both summary fields and aggregate functions and so are familiar with how they work.&lt;/p&gt;
&lt;h4&gt;So what&#039;s the problem with them?&lt;/h4&gt;
&lt;p&gt;Both summary fields, and aggregate functions are hugely useful and beneficial features of FileMaker, and run great on local databases. However if you have ever tried to perform an evaluation of a summary field or aggregate function over a local or wide area network, you may have seen the following dialog from time to time:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/fastaggregates1-2.png&quot; alt=&quot;fastaggregates1 2&quot; width=&quot;448&quot; height=&quot;236&quot;&gt;&lt;/p&gt;
&lt;p&gt;A real favorite among developers and clients. Why do we see this dialog more often than not on a remotely hosted solution, and why does it sometimes take longer to process than other times? The answer lies in what is actually happening when a summary field or aggregate function is evaluated.&lt;/p&gt;
&lt;p&gt;The caveat here is that &lt;strong&gt;the entire set of records being aggregated is being sent from host to client&lt;/strong&gt; (with the exception of container fields, summary fields and unstored calculations).&lt;/p&gt;
&lt;p&gt;To put it in other terms, if you want to find an aggregate of a single field in any given table, then every single record you aggregate is downloaded from the host. You want to obtain the total of a field from 10,000 records, then hope you got some hard disk space handy cos they&#039;re all heading your way! The second you reference anything on any record, that entire record is sent to you.&lt;/p&gt;
&lt;p&gt;It can be summarized (ha) in single sentence that &lt;a href=&quot;http://www.skeletonkey.com&quot;&gt;Mark Richman&lt;/a&gt; gave in his Devcon session this year about improving WAN performance:&lt;/p&gt;
&lt;p&gt;If you touch it, you own it&lt;/p&gt;
&lt;p&gt;I can only assume that the reason for this is due to the fact all of the processing in determining the result happens on the client-side of things, and FileMaker doesn&#039;t exactly do partial transfer of records, it&#039;s all or nothing.&lt;/p&gt;
&lt;h4&gt;The implication this has on Aggregate Speed&lt;/h4&gt;
&lt;p&gt;So, now that we have established aggregate operations require the transfer of entire record sets from host to client, we can begin to identify some key factors in their performance:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Bandwidth speed, notably download speed&lt;/li&gt;
&lt;li&gt;Latency between host and client&lt;/li&gt;
&lt;li&gt;The number of records being aggregated&lt;/li&gt;
&lt;li&gt;The size of the records being aggregated&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;All of these things serve to impede performance of aggregate functions. This article in particular will focus on the issue around entire records having to be sent from host to client. The performance hit is generally much worse the first time an aggregate is evaluated as it is at this point the records are sent. After that, aggregate functions are able to make use of the cached records on the client, so generally perform much better after that. However once you close the database and reopen, all of that cached data is lost, and you must re-download the records all over again to obtain aggregates.&lt;/p&gt;
&lt;h4&gt;Where oh where to begin??&lt;/h4&gt;
&lt;p&gt;This challenge has been somewhat of an obsession of mine for the past month. There have been numerous failed attempts to crack this issue and find a technique that would allow faster aggregate speed. While the technique proposed is by no means perfect, think of it more as an exercise in &quot;can it be done&quot;, as we walk through the trial an error process of trying to find a faster method of doing aggregates.&lt;/p&gt;
&lt;p&gt;I should point out that the technique found, and explained in this article is by no means perfect, in fact it does have some limitations which make it not a good candidate for replacing aggregate functions in some situations. However there are other situations where it would be well suited, and greatly outperform its summary field or aggregate function counterparts. Hopefully the remainder of this article not only gives you a possible technique you could apply, but also gives you some ideas of your own which you could develop, and explain some of the trial and error process behind looking for a technique :-)&lt;/p&gt;
&lt;h4&gt;So if everything we do in FileMaker sends us records, is there anything that doesn&#039;t?&lt;/h4&gt;
&lt;p&gt;This was the single most important question to answer to begin looking for a solution. The main bottleneck in aggregates is the downloading of records being aggregated. If we could somehow eliminate this aspect, it would give us a good chance of greatly improving aggregate speed.&lt;/p&gt;
&lt;p&gt;There aren&#039;t a whole lot of things in FileMaker that only send us partial information about records, a couple of those identified were:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Certain functions, ie Get(RecordID), or Get(FoundCount)&lt;/li&gt;
&lt;li&gt;Certain value lists&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Get(FoundCount) was used in &lt;a href=&quot;http://preview.teamdf.com/&quot;&gt;this article&lt;/a&gt; to carry out very fast count aggregate operations, but unfortunately it doesn&#039;t have any use for the other aggregate types. Get(RecordID) is handy to know about insomuch as obtaining it for a record will not send you the entire record. Perhaps not useful for aggregates, but there is potential there, and we are currently working with it to look for useful applications in the areas of fast record sorting.&lt;/p&gt;
&lt;p&gt;The last item is value lists.&lt;/p&gt;
&lt;h4&gt;A Value List you say?&lt;/h4&gt;
&lt;p&gt;Value lists can be setup in a few various ways, such as custom values, using a list from another file, obtaining a field value either from all records in a table, or a subset via a relationship.&lt;/p&gt;
&lt;p&gt;In testing all of these possible value list combinations, we found that there is one specific setup of a value list that outperforms the rest in terms of traffic sent between host and client, and that is a field-based value list using &lt;strong&gt;all values&lt;/strong&gt;, in other words all records in the table.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600514-fastaggregates1-3.png&quot; alt=&quot;fastaggregates1 3&quot; width=&quot;600&quot; height=&quot;514&quot;&gt;&lt;/p&gt;
&lt;p&gt;When the above configuration of a value list is used, record data from all records is &lt;strong&gt;not&lt;/strong&gt; sent from host to client, instead, it appears that a form of the fields index is sent instead, or perhaps just the field values for that specific field.&lt;/p&gt;
&lt;p&gt;We are not entirely sure why, but hypothesize that the reason for this is no query is required from the client to obtain the value list from the host. FileMaker simply sees that the value list is for every record in the table, and decides it might just be faster to send the index for that field to the user rather than every single record (hopefully someone could explain exactly what is happening here).&lt;/p&gt;
&lt;p&gt;In any event, the host is not sent entire record data, which is VERY interesting for us.&lt;/p&gt;
&lt;h4&gt;Okay, so now what?&lt;/h4&gt;
&lt;p&gt;Let&#039;s assume for now that our end goal is to obtain the sum of a field called &lt;strong&gt;Weight&lt;/strong&gt; across every record in the table. If we take what we know now, the next logical step may be to build a value list of all values from the Weight field. We could then obtain the value list contents using the &lt;strong&gt;ValueListItems&lt;/strong&gt; function. With a list of the weights from every record obtained, we could then figure out a nice way to sum each value in that list to obtain the overall sum, sounds simple enough :-)&lt;/p&gt;
&lt;h4&gt;Another road block, value lists don&#039;t play nice&lt;/h4&gt;
&lt;p&gt;The primary purpose of a value list is a means to assist in selecting data for data entry, perhaps via a drop-down menu or popup, or checkboxes. Because of this, there is no real need to duplicate values in a value list. If two records contain the same value in a field, then both values are not shown in the list. The value list simply combines them into a single entry.&lt;/p&gt;
&lt;p&gt;This had major implications for us in devising this technique. If we have 10,000 records in our table, then we want our value list to contain values for every single record with a non-empty value in the field - duplicates included. It is no use to us if 100 records with the same weight value end up as a single value in the value list, because when we go to add up all items in the value list, we are not going to get the correct result.&lt;/p&gt;
&lt;p&gt;The challenge now was to somehow modify the value list, so that we would obtain all values from the records, rather than just unique values.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600514-fastaggregates1-4.png&quot; alt=&quot;fastaggregates1 4&quot; width=&quot;600&quot; height=&quot;514&quot;&gt;&lt;/p&gt;
&lt;p&gt;Hey what about the above setup of a value list? We keep the first field as the field we want to aggregate, but we make use of the &quot;show second field&quot; and set it to our primary key field that we know to be unique. Surely this will now force the value list to keep same values in the Weight field as separate entries in the value list because we know each value in Contact ID is unique, right?&lt;/p&gt;
&lt;p&gt;WRONG!&lt;/p&gt;
&lt;p&gt;As we discovered, as soon as you introduce a second display field into any value list, be it &quot;All Values&quot; setup, or related field setup, this will trigger FileMakers knee-jerk reaction of sending you every single record in its entirety.&lt;/p&gt;
&lt;h4&gt;Back to a single field in the Value list, how to make it unique?&lt;/h4&gt;
&lt;p&gt;So with that option dashed, we were left with the question of how to build this value list using only a single field value. We know that the field must contain the weight field as this is what we are going to use to aggregate. However records with the same value have to be kept unique from one another.&lt;/p&gt;
&lt;p&gt;The solution here was to build a new stored calculation field. This would comprise of both the weight and the contact ID. If we could make this field unique, and use it in the value list, then maybe there is a way at the other end to parse the contact ID out and leave us with just the weight values, which is what we are after.&lt;/p&gt;
&lt;h4&gt;Building the Value List calculation field&lt;/h4&gt;
&lt;p&gt;Ahh, another problem! The weight field is a number, but in our database our primary key field is also a number - a serial number. If we combine these two fields, how will we know what is what when it comes time to parse out the contact ID later on?&lt;/p&gt;
&lt;p&gt;We looked at a number of ways in which we could possibly do this. Some involved building recursive custom functions. We could insert the Contact ID into the calculation wrapped in special identifying characters, which we could then identify later on and use to rip out the Contact ID. The problem with this is that recursion is itself a costly process and the overhead in recursing through a huge list may in fact negate any performance benefit from the technique overall. A better way would be to find a native FileMaker function to use which was non-recursive and fast.&lt;/p&gt;
&lt;p&gt;For this particular situation we realised that the weight field will never contain any non-numerical digits, and the same applied for the Contact ID. Perhaps we could simply turn the contact ID into an alphabetical string rather than numerical.&lt;/p&gt;
&lt;p&gt;For example, if we had a Weight of 100.5, and our contact ID was 1234, our calculation might begin looking something like:&lt;/p&gt;
&lt;pre&gt;Weight &amp;amp; Contact ID&lt;/pre&gt;
&lt;p&gt;which would give us:&lt;/p&gt;
&lt;pre&gt;100.51234&lt;/pre&gt;
&lt;p&gt;Not very nice, but if we did a simple number to character translation, what if we made it:&lt;/p&gt;
&lt;pre&gt;100.5BCDE&lt;/pre&gt;
&lt;p&gt;and then after we obtain the value list items, we could strip out the Contact ID section simply by using the Filter function:&lt;/p&gt;
&lt;pre&gt;Filter ( value ; &quot;0123456789.-ÃÂ¶&quot; )&lt;/pre&gt;
&lt;p&gt;This would leave us with just the numerical component, minus our contact ID whose only purpose was to make the entry in the value list unique. This is exactly what we did.&lt;/p&gt;
&lt;p&gt;The first step was to build a straightforward custom function to carry out the translation of the Contact ID into an alphabetical string:&lt;/p&gt;
&lt;pre&gt;function: numToText&lt;/pre&gt;
&lt;p&gt;Substitute (&lt;br&gt; Value ;&lt;br&gt; [ &quot;0&quot; ; &quot;A&quot; ] ;&lt;br&gt; [ &quot;1&quot; ; &quot;B&quot; ] ;&lt;br&gt; [ &quot;2&quot; ; &quot;C&quot; ] ;&lt;br&gt; [ &quot;3&quot; ; &quot;D&quot; ] ;&lt;br&gt; [ &quot;4&quot; ; &quot;E&quot; ] ;&lt;br&gt; [ &quot;5&quot; ; &quot;F&quot; ] ;&lt;br&gt; [ &quot;6&quot; ; &quot;G&quot; ] ;&lt;br&gt; [ &quot;7&quot; ; &quot;H&quot; ] ;&lt;br&gt; [ &quot;8&quot; ; &quot;I&quot; ] ;&lt;br&gt; [ &quot;9&quot; ; &quot;J&quot; ]&lt;br&gt; )&lt;/p&gt;
&lt;p&gt;Then, our value list calculation field looks something like:&lt;/p&gt;
&lt;pre&gt;Weight &amp;amp; numToText ( Contact ID )&lt;/pre&gt;
&lt;p&gt;We can now be sure that every record, given it has a unique Contact ID, will now also have a unique result to the above calculation too. This field provided the basis of our single-field &quot;all values&quot; value list!&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600492-fastaggregates1-5.png&quot; alt=&quot;fastaggregates1 5&quot; width=&quot;600&quot; height=&quot;492&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600514-fastaggregates1-6.png&quot; alt=&quot;fastaggregates1 6&quot; width=&quot;600&quot; height=&quot;514&quot;&gt;&lt;/p&gt;
&lt;p&gt;Note that if your primary key is a combination of numeric and alpha characters you will need to pay more attention to converting the primary key into something non-numeric. You may need to translate your numeric components of the primary key into characters you know do not currently exist anywhere in your primary keys, that way you can be sure that any conversion from the numbers to characters will not end up in records having the same converted primary key value for this calculation.&lt;/p&gt;
&lt;h4&gt;A good time to summarize what we have done so far&lt;/h4&gt;
&lt;p&gt;This basically concludes the first part of this two-part series. In this article so far we have identified that the reason why aggregates are slow in FileMaker comes down to a number of factors, the main one being that any aggregate operation on a set of records requires all records to be sent from host to client. Number of records, size of records, bandwidth and latency all tie into this to impede performance.&lt;/p&gt;
&lt;p&gt;In the article we sought to identify something in FileMaker which will let us obtain values from records we wish to aggregate, but without sending us the entire record contents. We found that value lists were a key candidate for this.&lt;/p&gt;
&lt;p&gt;The value lists we tested yielded one particular configuration in which a much smaller amount of data was transmitted between host and client when the value list was evaluated. This was value lists that use a field value from a table, and are set to use &quot;All Values&quot; from that table.&lt;/p&gt;
&lt;p&gt;We identified an issue with this particular value list configuration in that all common values across records are combined into a single value in the value list. Because our goal is to aggregate from all records, we needed each record in the table to be represented in the value list with its weight value, respecting duplicates in the list.&lt;/p&gt;
&lt;p&gt;We then tried to achieve this using a value lists &quot;show value from second field&quot; option, but found that enabling this meant FileMaker transmitted entire record data, something we are trying to avoid.&lt;/p&gt;
&lt;p&gt;The only option left to us was to build a calculation that was unique for every record, but contained the weight value we required. We needed to construct the calculation not only to be unique, but to be fast and easy for us to obtain just the weight value after the value list was evaluated.&lt;/p&gt;
&lt;p&gt;To do this we built the calculation to be a combination of the weight value, and the records primary key field. To prevent mixup of the two fields, we first converted the primary key from a numerical value into a strictly alphabetical text string. This then allowed us later on to use the Filter function to easily strip out any non-numeric characters - such as the primary key - leaving us with the original weight values.&lt;/p&gt;
&lt;h4&gt;In part two:&lt;/h4&gt;
&lt;p&gt;This article turned out to be a bit too large to cram into a single article, so we have split it into two. This first part was identifying the issue, and constructing a path toward a solution.&lt;/p&gt;
&lt;p&gt;In part two, we are going to illustrate the technique in action, introduce and solve a couple more issues, and give some performance results across both a locally hosted solution and a wide area network.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-view&quot; href=&quot;http://www.digitalfusion.co.nz/weetbicks/the-search-for-fast-aggregates--implementation--results/100/&quot;&gt;Link to Part Two - Implementation &amp;amp; Results&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/fastaggregates/FastAggregates_10000.zip&quot;&gt;Download Example File With 10,000 Records (3.5mb)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/fastaggregates/FastAggregates_100000.zip&quot;&gt;Download Example File With 100,000 Records (36.4mb)&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Sat, 13 Aug 2011 16:20:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/the-search-for-fast-aggregates-trial-error/</guid>
		</item>
		
		<item>
			<title>The Search for Fast Aggregates - Implementation &amp; Results</title>
			<link>https://www.teamdf.com/blogs/the-search-for-fast-aggregates-implementation-results/</link>
			<description>&lt;p&gt;In the final part of this two part series, we go into a little more detail about the aggregate technique we developed in the first article. We also carry out a number of comparison aggregate tests and present the results. We also try to address some of the limitations of this technique and ways in which you could try to work around these:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/blogs/the-search-for-fast-aggregates-trial-error/&quot;&gt;Link to Part One - Trial &amp;amp; Error&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;A very quick overview of where we are at&lt;/h4&gt;
&lt;ul&gt;&lt;li&gt;Summary fields &amp;amp; aggregate calcs require all record data to be sent from host to client&lt;/li&gt;
&lt;li&gt;This makes aggregates on large datasets or large records slow&lt;/li&gt;
&lt;li&gt;We found an &quot;All Values&quot; value list based on a single field, does not send all record data from host to client. Instead, it sends just that field value from all records (perhaps using the fields index).&lt;/li&gt;
&lt;li&gt;Using this idea, we build a value list of values we want to aggregate, the idea being we evaluate the value list and apply an aggregate to the values, bypassing the need to download all the records.&lt;/li&gt;
&lt;li&gt;These value lists like to combine unique values from records into a single entry. For this reason our value list had to be based on a special calculation whose contents was unique for every record, that contained the value we wanted to aggregate, and be easy for us to retrieve the original value when needed.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;If you haven&#039;t yet read &lt;a href=&quot;https://www.teamdf.com/blogs/the-search-for-fast-aggregates-trial-error/&quot;&gt;part one of the article&lt;/a&gt; then it is probably a really good idea to give it a look before reading this one, it will make this article make a lot more sense to you!&lt;/p&gt;
&lt;h4&gt;Retrieving the Value List contents&lt;/h4&gt;
&lt;p&gt;So at this stage we have built our special calculation, and built a value list based on that. The end result is we obtain a value list with 1 entry per record for every record in the table. Here is a snippet of what the value list looks like:&lt;/p&gt;
&lt;pre&gt;107.6JDBD&lt;br&gt;107.7BFHA&lt;br&gt;107.7DDGB&lt;br&gt;107.7FGIC&lt;br&gt;107.7HCFB&lt;br&gt;107.7HEFE&lt;br&gt;107.7HHEI&lt;br&gt;107.7IFCD&lt;br&gt;107.8BAGB&lt;br&gt;107.8BICE&lt;br&gt;107.8CJAF&lt;/pre&gt;
&lt;p&gt;You can see the numeric component is the &lt;strong&gt;weight&lt;/strong&gt; field value we wish to aggregate eventually. The alpha part is a conversion of the primary key value from a number into an alphabetical string.&lt;/p&gt;
&lt;p&gt;The value list contents is obtained using the ValueListItems function:&lt;/p&gt;
&lt;pre&gt;ValueListItems ( Get ( FileName ) ; &quot;Aggregate_Weight All&quot; )&lt;/pre&gt;
&lt;p&gt;With the contents of the value list obtained, we can use the Filter function to strip out the alpha-representation of the primary key:&lt;/p&gt;
&lt;pre&gt;Filter ( theValueList ; &quot;0123456789-.&amp;amp;#195;&amp;amp;#130;&amp;amp;#194;&amp;amp;#182;&quot;)&lt;/pre&gt;
&lt;p&gt;You will note we have also kept some other possible characters that occur in a number, the negative sign and a decimal point. We also retain the return delimiters to keep the values as a list. The end result is:&lt;/p&gt;
&lt;pre&gt;107.6&lt;br&gt;107.7&lt;br&gt;107.7&lt;br&gt;107.7&lt;br&gt;107.7&lt;br&gt;107.7&lt;br&gt;107.7&lt;br&gt;107.7&lt;br&gt;107.8&lt;br&gt;107.8&lt;br&gt;107.8&lt;/pre&gt;
&lt;p&gt;Hey, this is looking promising! We now have a list of every Weight value in a list, and we obtained it by getting just the value, not the entire record, we are on the right track.&lt;/p&gt;
&lt;h4&gt;So how do we perform an aggregate?&lt;/h4&gt;
&lt;p&gt;We looked at a couple of ways to turn this list into an aggregate result, and decided that a custom function would be a great way to achieve this.&lt;/p&gt;
&lt;p&gt;Our initial attempt focused simply on a &lt;strong&gt;sum&lt;/strong&gt; aggregate. We began by running a substitute on the list, replacing all return characters with plus signs:&lt;/p&gt;
&lt;pre&gt;Substitute ( theList ; &quot;&amp;amp;#195;&amp;amp;#130;&amp;amp;#194;&amp;amp;#182;&quot; ; &quot;+&quot; )&lt;/pre&gt;
&lt;p&gt;Taking the snippet of the value list above, this gave us:&lt;/p&gt;
&lt;pre&gt;107.6+107.7+107.7+107.7+107.7+107.7+107.7+107.7+107.8+107.8+107.8&lt;/pre&gt;
&lt;p&gt;Which is now a simple FileMaker expression. We then ran this result through the Evaluate function. This function takes a text string as a parameter, and evaluates it as if it were a FileMaker expression:&lt;/p&gt;
&lt;pre&gt;Let ( [&lt;br&gt;  theList = ValueListItems ( Get ( FileName ) ; &quot;Aggregate_Weight All&quot; ) ;&lt;br&gt;  theList = Substitute ( theList ; &quot;&amp;amp;#195;&amp;amp;#130;&amp;amp;#194;&amp;amp;#182;&quot; ; &quot;+&quot; )&lt;br&gt;];&lt;br&gt;  Evaluate ( theList )&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;End result - well it &quot;kind&quot; of worked. With small lists it worked great, but we found the larger the number of items we aggregated, we were presented with a &quot;?&quot; result.&lt;/p&gt;
&lt;p&gt;The reason for this is that FileMaker has a limit on the number of characters permitted in any calculation expression. According to the &lt;a href=&quot;http://help.filemaker.com/app/answers/detail/a_id/7541/~/technical-specifications-of-filemaker-pro-11-and-filemaker-pro-11-advanced&quot;&gt;FileMaker websites technical specifications&lt;/a&gt;, this limit is 30,000 characters.&lt;/p&gt;
&lt;p&gt;To get around this issue, we built a recursive custom function that performed the above operation on the list, but in blocks of 500 values at a time. So the first 500 values were summed, and the result of that was added to the sum of the second 500, the third 500, and so on until each block of values had been summed. This worked great, and was pretty quick too. For example if you were summing 10,000 values, the custom function would perform 20 recursions, each summing 500 values.&lt;/p&gt;
&lt;h4&gt;That&#039;s great for sum, but what about min/max/average?&lt;/h4&gt;
&lt;p&gt;Because we were using the Evaluate function, we realised that we could adapt our custom function to take a second parameter, that being the name of the aggregate function we wished to apply&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600526-fastaggregates2-1.png&quot; alt=&quot;fastaggregates2 1&quot; width=&quot;600&quot; height=&quot;526&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is the original version of the custom function. The overall list is broken into chunks of 1000 values aggregated at any given recursion of the function.&lt;/p&gt;
&lt;p&gt;The first few variable declarations in the function grab the 1000 values, chop off the trailing return character, and replace all return delimiters with semi-colons (the character that is used as the separator for aggregate functions). At this point we end up with something like:&lt;/p&gt;
&lt;pre&gt;107.6;107.7;107.7;107.7;107.7;107.7;107.7;107.7;107.8;107.8;107.8&lt;/pre&gt;
&lt;p&gt;The &lt;strong&gt;AggregateFunction&lt;/strong&gt; parameter is the name of an aggregate function, which is then placed before the above string. For example if the parameter was &lt;strong&gt;sum&lt;/strong&gt;, we build the following string:&lt;/p&gt;
&lt;pre&gt;&lt;strong&gt;Sum&lt;/strong&gt; ( ... the above string... )&lt;/pre&gt;
&lt;p&gt;Run that sucker through the Evaluate function, and you have your aggregate! The handling of blocks of values using recursion keeps the evaluation expression under the necessary character limit.&lt;/p&gt;
&lt;h4&gt;The &quot;Average&quot; aggregate function, a curly one!&lt;/h4&gt;
&lt;p&gt;Sum, Min and Max work great with this custom function. The reason is that if you add values, you get one total result. Similarly there is only ever 1 minimum and 1 maximum value in an overall list. It doesn&#039;t matter if you add the list up in smaller blocks, or compare blocks of values with other blocks to obtain a min or max value, the outcome is always the same.&lt;/p&gt;
&lt;p&gt;Average is different however. To determine average aggregate, the total number of values has to be known, and the Average function determines this based on the number of parameters it is passed.&lt;/p&gt;
&lt;p&gt;Consider this example, a list of the following values:&lt;/p&gt;
&lt;pre&gt;1&lt;br&gt;2&lt;br&gt;3&lt;br&gt;4&lt;br&gt;5&lt;/pre&gt;
&lt;pre&gt;Average ( 1 ; 2 ; 3 ; 4 ; 5 )&lt;/pre&gt;
&lt;p&gt;The result of this calculation is 3. The average function first sums the values, and then divides it by the number of passed values to obtain the average. In this case, that is 15/3 = 5.&lt;/p&gt;
&lt;p&gt;Now consider out implementation of the above custom function using blocks of values from the overall list. What happens if we split the list into two:&lt;/p&gt;
&lt;pre&gt;1&lt;br&gt;2&lt;br&gt;3&lt;/pre&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;pre&gt;4&lt;br&gt;5&lt;/pre&gt;
&lt;p&gt;Using the custom function, we end up with the average of the first list being 6/3 = 2. The average of the second list is 9/2 = 4.5. The function would then combine the results into another aggregate calculation:&lt;/p&gt;
&lt;pre&gt;Average ( 2 ; 4.5 )&lt;/pre&gt;
&lt;p&gt;Which is deemed to be 6.5 / 2 = 3.25 , this is certainly NOT the expected result of 5 we were after.&lt;/p&gt;
&lt;p&gt;The simple fact is the average function has to be aggregated in a different way. We first need to sum the contents of the list, and then divide it by the number of values in the original list.&lt;/p&gt;
&lt;p&gt;Rather than try to make the current custom function any more complicated, we simply created a new custom function called &lt;strong&gt;ValueList_Average&lt;/strong&gt; that simply runs the other Aggregate custom function as a Sum aggregate, then divides the result by the number of values in the list:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600484-fastaggregates2-2.png&quot; alt=&quot;fastaggregates2 2&quot; width=&quot;600&quot; height=&quot;484&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Enough technical mumbo jumbo, time for some results&lt;/h4&gt;
&lt;p&gt;For testing, we built an example file (see bottom of this article). The test file carries out three types of aggregate tests:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Summary fields&lt;/li&gt;
&lt;li&gt;Aggregate Functions&lt;/li&gt;
&lt;li&gt;Value List technique with our Custom Aggregate Function&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;For each type of aggregate, we test the sum, average, min and max aggregates. The testing is done on a Contacts table with 10,000 records. There are a total of 32 stored fields on the table, and each record averages about 0.6kb in size for a total table size of 5.9 megabytes.&lt;/p&gt;
&lt;h4&gt;Test One: File opened locally client machine&lt;/h4&gt;
&lt;p&gt;For the first test, we are eliminating network as a factor in testing. This will hopefully give us insight into the performance of the functions used, and the performance of the value list retrieval and processing.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/fastaggregates2-3.png&quot; alt=&quot;fastaggregates2 3&quot; width=&quot;277&quot; height=&quot;182&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/fastaggregates2-4.png&quot; alt=&quot;fastaggregates2 4&quot; width=&quot;291&quot; height=&quot;180&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/fastaggregates2-5.png&quot; alt=&quot;fastaggregates2 5&quot; width=&quot;287&quot; height=&quot;179&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the results of the 3 tests are very similar. Multiple run-throughs of the test yield various aggregates reach the 1 second mark, but on following tests are under a second, and it is fairly random. This suggests the summary fields and aggregate functions are basically identical in speed. The higher frequency of more 1 second results for the value list implementation means it&#039;s basically the same speed, but maybe fractionally slower.&lt;/p&gt;
&lt;p&gt;Speeds for all 3 tests are very fast with 10,000 records when the database is local because no records have to be sent over the network, so any overhead is a result of the aggregate methods themselves - of which there is very little overhead at all.&lt;/p&gt;
&lt;h4&gt;Test Two: File opened remotely over wide area network - 10k records&lt;/h4&gt;
&lt;p&gt;Here is the real acid test. The file has been hosted on a remote server and is being accessed over a fairly average New Zealand internet connection. In order to give a fair test for each method, the file was closed and reopened after each test. The reason for this is to clear the clients cache of downloaded records from the host.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/fastaggregates2-6.png&quot; alt=&quot;fastaggregates2 6&quot; width=&quot;277&quot; height=&quot;181&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/fastaggregates2-7.png&quot; alt=&quot;fastaggregates2 7&quot; width=&quot;291&quot; height=&quot;183&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/fastaggregates2-8.png&quot; alt=&quot;fastaggregates2 8&quot; width=&quot;287&quot; height=&quot;181&quot;&gt;&lt;/p&gt;
&lt;p&gt;So, what can we tell from these results? Well first thing to note is that these tests above were carried out in order of the aggregates shown. This gives us clear indication that the very first time an aggregate is evaluated, the high performance hit is taken first time, as all of the records are downloaded from host to client. As you can see, the summary and aggregate function tests yield pretty much the same time taken to download all 10,000 records.&lt;/p&gt;
&lt;p&gt;The value list implementation on the other hand, was &lt;strong&gt;over 11 times faster&lt;/strong&gt; than the other two aggregate methods. The performance gain in just aggregating using a value list is huge. The main reason is far less traffic is sent between host and client. We showed in the local file test that overhead of the actual processing of the values is negligible, so by reducing the major bottleneck of traffic sent between host and client, we have greatly improved the speed of the aggregate calculations!&lt;/p&gt;
&lt;p&gt;Note that if the tests were run a second or third time directly after opening the file and running the first test, they were almost instant to calculate, the reason is the file had downloaded and cached all the records in the first 2 cases, and in the third the value list had been cached, so future tests were essentially working with local data.&lt;/p&gt;
&lt;p&gt;Changes to weight values on the records prior to running a new test resulted in the summary field and aggregate function tests taking relatively the same amount of time. The value list option took slightly longer in this case because since the value list had changed contents, the whole value list is resent from host to client - however given it is pretty damn quick the performance impact is minimal.&lt;/p&gt;
&lt;h4&gt;Test Three: File opened remotely over wide area network - 100k records&lt;/h4&gt;
&lt;p&gt;For the last test we are going all out and bumping up the record count to 100,000. The file is opened under the same conditions as test number two.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/fastaggregates2-10.png&quot; alt=&quot;fastaggregates2 10&quot; width=&quot;276&quot; height=&quot;178&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/fastaggregates2-11.png&quot; alt=&quot;fastaggregates2 11&quot; width=&quot;289&quot; height=&quot;180&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/fastaggregates2-12.png&quot; alt=&quot;fastaggregates2 12&quot; width=&quot;287&quot; height=&quot;178&quot;&gt;&lt;/p&gt;
&lt;p&gt;Again, tests 1 and 2 take relatively the same amount of time, this time over 10 minutes, subsequent aggregates are much faster as they are working on the now cached records.&lt;/p&gt;
&lt;p&gt;But once again we see the value list test has shone through, being over &lt;strong&gt;10 times faster&lt;/strong&gt; than the regular aggregate methods.&lt;/p&gt;
&lt;p&gt;Another thing we did when running this 100k test was to fire up an application called &lt;a href=&quot;http://www.wireshark.org&quot;&gt;Wireshark&lt;/a&gt;. This is a utility which lets you capture network traffic and keep track of packets transmitted and data flowing over the network.&lt;/p&gt;
&lt;p&gt;We setup Wireshark to only capture data sent between the client and the host server, on FileMaker port 5003. Here is what we found:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600469-fastaggregates2-13.png&quot; alt=&quot;fastaggregates2 13&quot; width=&quot;600&quot; height=&quot;469&quot;&gt;&lt;/p&gt;
&lt;p&gt;For the aggregate function test we found that total packet traffic between host and client was &lt;strong&gt;84,608&lt;/strong&gt; packets of data over the 10+ minutes. There was a total of 72,588,262 total bytes transmitted, which equates to a whopping &lt;strong&gt;69.2 megabytes!&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600470-fastaggregates2-14.png&quot; alt=&quot;fastaggregates2 14&quot; width=&quot;600&quot; height=&quot;470&quot;&gt;&lt;/p&gt;
&lt;p&gt;And here are the results for the value list technique. Note the total packets transmitted was &lt;strong&gt;5,372&lt;/strong&gt;. That is close to &lt;strong&gt;16 times less&lt;/strong&gt; packets transmitted - and less packets means less overall latency and data transmitted. The total data transmitted was 4,430,483 bytes which equates to only &lt;strong&gt;4.2 megabytes&lt;/strong&gt; - 16.5x less data transmitted!&lt;/p&gt;
&lt;h4&gt;Wow, so it&#039;s faster that&#039;s awesome... and here&#039;s the bad news...&lt;/h4&gt;
&lt;p&gt;To this point we&#039;ve been demonstrating a pretty ideal example. We have aggregated every record in the table. But seriously how often would you really want to do that? Perhaps there are some situations where you might want to do that, for example if you are using a special reporting table where you are generating records for reporting purposes.&lt;/p&gt;
&lt;p&gt;More often than not however you want to aggregate a subset of a tables overall records. Consider aggregate functions, they work best when aggregating related records through a relationship, which generally are filtered to be a subset of the tables overall records. Summary fields also excel in sub-summary reports where they are tallying subsets of the records in groupings.&lt;/p&gt;
&lt;p&gt;Unfortunately this value list technique does have limitations on how far you can take it.&lt;/p&gt;
&lt;h4&gt;The value list has to be stored.&lt;/h4&gt;
&lt;p&gt;This is perhaps the biggest limiting factor. Because the field used in the value list has to be stored, you cannot introduce complex filtering into your calculation based on globals, or fields from other tables.&lt;/p&gt;
&lt;p&gt;Lets consider an example where you have a couple of global fields where you enter a date range. You want to sum all records whose date field falls within your chosen range. How would you achieve this?&lt;/p&gt;
&lt;p&gt;Well first instinct would be to change your value list calculation to reflect this filtering. One cool and useful property of the value list, is if a record contains an empty value for the field used in the value list, that record is essentially omitted from the value list. this has no performance impact when it comes to our method which is great - if anything it makes the method faster as the a smaller set of values in the value list means faster processing times.&lt;/p&gt;
&lt;p&gt;Back to the problem though. Our date range is specified in global fields, so we cannot use those in the calculation, which means we can&#039;t set the calculation result to blank if the record calls outside of the chosen date range, bummer!&lt;/p&gt;
&lt;h4&gt;Having said that, some filtering is possible...&lt;/h4&gt;
&lt;p&gt;Hard-coded filtering is possible though and works quite well. Consider a contacts table with 10,000 records. There is a status field that contains either &quot;Active&quot; or &quot;Deleted&quot;. Further to that is a Country field.&lt;/p&gt;
&lt;p&gt;Lets say we want to find the average weight of all contacts living in america whose status is active. To do this we would simply modify our value list calculation as such:&lt;/p&gt;
&lt;pre&gt;if ( Status = &quot;Active&quot; and Country = &quot;USA&quot; ; &lt;br&gt;     Weight &amp;amp; numToText ( Contact ID ) ; &quot;&quot;&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;Here we have hard-coded a check in. If the contact is active and in the USA, we put a result in the calculation, if not the result is blank, and this record will not appear in the value list. Then we just run through the usual process of obtaining the aggregate from the value list.&lt;/p&gt;
&lt;p&gt;This is nice, but very restrictive. For each subset of records you wanted to aggregate in this way, you would require a separate calculation field and value list to do so. Perhaps this might be fine depending on your situation, but it is quite limited.&lt;/p&gt;
&lt;h4&gt;Found sets and summaries&lt;/h4&gt;
&lt;p&gt;The other thing this technique is not, is a replacement for summary fields in sub-summary reports. This technique simply cannot be used to replace summary fields in this manner. Calculations just can&#039;t know about sub-summary parts in this way and if they could, in all likelihood the calculation would end up being unstored anyway, thus breaking at the value list stage.&lt;/p&gt;
&lt;h4&gt;So in conclusion....&lt;/h4&gt;
&lt;p&gt;We&#039;ve talked about a lot in this article and the previous one. We&#039;ve shown various aggregate methods, and why some perform slow over wide are networks. We&#039;ve walked through the process of coming up with an alternative solution to the performance issue, and as a result came up with a technique combining a number of FileMaker areas including Value Lists, custom functions, and calculations.&lt;/p&gt;
&lt;p&gt;We have also gone into detail about building an aggregate custom function to turn a list of values into the desired result. We then showed results of testing of each of the three presented aggregate methods, and showed that the value list method has huge potential for significant performance gains &lt;em&gt;under very specific conditions&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Finally, we showed that this technique is most certainly not a perfect replacement for good old fashioned summary fields and aggregate functions. It can only be used under certain conditions, but if those match your situation, then you could be in for a good performance gain!&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution. In the file you will also find a couple of additional tests briefly touched upon in the article but not fully tested. These are in the area of aggregating a subset of the overall records in a table.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/fastaggregates/FastAggregates_10000.zip&quot;&gt;Download Example File With 10,000 Records (3.5mb)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download href=&quot;https://www.teamdf.com/&gt;Download Example File With 100,000 Records (36.4mb)&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Readers Note:&lt;/h4&gt;
&lt;p&gt;Christoph Teschers pointed out in the comments that in the example files the tests do not yield correct results if negative values are used in the field being aggregated. He points out that this can be resolved by adding a - symbol into the Filter function, ie:&lt;/p&gt;
&lt;pre&gt; Filter ( ValueListItems ( Get ( FileName ) ; &quot;Aggregate_Weight All&quot; ) ; &quot;-0123456789.&amp;amp;#195;&amp;amp;#130;&amp;amp;#194;&amp;amp;#182;&quot; )&lt;/pre&gt;
&lt;p&gt;Thank&#039;s for spotting that one Christoph!&lt;/p&gt;</description>
			<pubDate>Sat, 13 Aug 2011 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/the-search-for-fast-aggregates-implementation-results/</guid>
		</item>
		
		<item>
			<title>Dissecting DevCon</title>
			<link>https://www.teamdf.com/blogs/dissecting-devcon/</link>
			<description>&lt;p&gt;I can&#039;t think of a better escape than a trip San Diego in middle of the New Zealand winter, which is exactly what Daniel and I did a couple of weeks ago as we headed off to the annual FileMaker Developer Conference (DevCon) - an annual geek fest in a nice warm place.&lt;/p&gt;
&lt;p&gt;Actually Daniel went over a couple of weeks earlier and did a lap around Colorado on his bike first; to help me acclimatise I hired a convertible and drove down to San Diego it didn&#039;t take long to adjust.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;Of course DevCon is all business and in the past we&#039;ve always shown off our totally awesome Reactor plugin (interactive calendars and charts) and sold that to the other developers to cover our costs. This year was different, for the first time we didn&#039;t exhibit: what a stress relief that is - we could focus on building relationships and going to sessions, &quot;networking&quot; is extremely important of course, even if that means you miss the first session or two the next day, eh? We also managed to take in a ball game, a Spanish nightclub, and some serious outlet store shopping.&lt;/p&gt;
&lt;p&gt;There was the usual ton of good technical stuff, but we also picked up a few other interesting nuggets, like:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;In San Diego, &quot;relationship building&quot; finishes at 2AM.&lt;/li&gt;
&lt;li&gt;FileMaker Inc thinks the future is mobile and cloudy. We do too.&lt;/li&gt;
&lt;li&gt;There are QR codes* everywhere: from business cards to tee-shirts to buildings.&lt;/li&gt;
&lt;li&gt;Daniel is World Famous...&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Wherever we went during the conference people would automatically introduce themselves as soon as they saw Daniel&#039;s name tag. Could this be anything to do with his industry leading blog &lt;a href=&quot;http://www.filemakerweetbicks.com&quot;&gt;FileMakerWeetbicks.com&lt;/a&gt; which has thousands of readers every month? Just more world leading stuff from our crew.&lt;/p&gt;
&lt;p&gt;FileMaker themselves had a big contingent at the conference, from top brass to engineers to sales people, so it was great to talk to them and get a feeling for how business is going and where it&#039;s going. They&#039;ve done very well through the recent economic challenges, remaining profitable and continuing to grow. It&#039;s also quite clear that they understand what businesses want and where the technology needs to go - it&#039;s still the best platform for building business solutions that can evolve quickly.&lt;/p&gt;
&lt;p&gt;FileMaker have really embraced the iPad and iPhone with &quot;FileMaker Go&quot; and that was a major topic of the conference, as was how to make it perform well when you host it in the &quot;cloud&quot; as they say, i.e. on the internet. Big highlights from the sessions included: some very clever techniques for making huge performance gains; user interface designs and techniques for iPad and iPhone; and a lot of more advanced techniques like the use of SQL in FileMaker than we&#039;ve ever seen before.&lt;/p&gt;
&lt;p&gt;All-in-all a totally enjoyable experience, full-on, but low on stress and I can highly recommend San Diego as a very agreeable place to be in the NZ winter. Next year it&#039;ll be in Miami: any takers to join us?&lt;/p&gt;
&lt;p&gt;* In case you&#039;re wondering what QR codes are, they&#039;re those square black and white patterns you see on some things - you can &quot;scan&quot; them with an iPhone or similar, and the information held within could be anything from a web link to an entire vCard containing your contact details. Of course, you also generate these from within FileMaker and encode whatever you like. In the US we saw them everywhere including on the front of shops in the mall: so you can just point your phone at the shop and Twitter or Facebook a link right there.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 09 Aug 2011 15:27:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/dissecting-devcon/</guid>
		</item>
		
		<item>
			<title>Quake Updates Go Mobile</title>
			<link>https://www.teamdf.com/blogs/quake-updates-go-mobile/</link>
			<description>&lt;p&gt;Anyone that knows our Stephen Baker knows at least two things:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;He&#039;s Digital Fusion&#039;s first ever employee and after 13 years, he&#039;s still going strong.&lt;/li&gt;
&lt;li&gt;He&#039;s a very, very smart cookie.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;By day, he&#039;s a database developer, quietly dealing to some of our most tricky database intergrations, but by night, under the cover of darkness he&#039;s banging out some very sexy iPhone/iPad apps. His latest creation is &quot;Canterbury Earthquakes&quot;.&lt;/p&gt;
&lt;p&gt;This little beauty combines data from Geonet with the GPS on your iPhone or iPad. The basic features include a full list of all the &quot;events&quot; in Canterbury: size, date, time, location relative to where you&#039;re standing right now. This list can be filtered by date or aftershock size - a lot of us Cantabrians only want to know about the big boys!&lt;/p&gt;
&lt;p&gt;There&#039;s the quake drum (although personally that&#039;s a little beyond my comprehension) and a map that at first glance looks like your kids have thrown their spaghetti sauce all over it. However, on closer inspection it is in fact the Quake Map indicating the size and location of all the events since September 4th.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/270/92_1.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;But the best feature by far is the little arrow on the Aftershocks tab that takes you to a map of Canterbury with a pin to show where you are and another to show where the aftershock was located. Such a great feature for those that want to get a good sense of where the action is.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/271/92_2.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Canterbury Earthquakes is so simple, all the information you really want to know is presented in an easy to use format... thanks Steve!&lt;/p&gt;</description>
			<pubDate>Thu, 28 Jul 2011 10:32:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/quake-updates-go-mobile/</guid>
		</item>
		
		<item>
			<title>Xero Meant Nothing Until Now</title>
			<link>https://www.teamdf.com/blogs/xero-meant-nothing-until-now/</link>
			<description>&lt;p&gt;For a long time I was a bit of a doubting Thomas when it came to the online accounting package cleverly named &lt;a href=&quot;http://xero.com&quot; target=&quot;_blank&quot;&gt;Xero&lt;/a&gt;. I thought it was a good idea and was pretty impressed by what the NZ company based in Wellington were undertaking. But I guess I thought the product was still too immature to cover the full gamut of functionality required to replace our incumbent system and be a useful business tool.&lt;/p&gt;
&lt;p&gt;Well, I&#039;m here to say am a convert. We love &lt;a href=&quot;http://xero.com&quot; target=&quot;_blank&quot;&gt;Xero&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;I started easy, convincing my partner Ben to switch his business over just before Christmas - I thought we could see how that went and decide whether it would be a good fit for Digital Fusion. I didn&#039;t tell Ben he was my guinea pig, I thought that might influence his perspective... Even so, I was expecting lots of the usual change-related frustrations - you know swearing, cursing, slamming of laptop lids etc. Ben does all that quite well usually.&lt;/p&gt;
&lt;p&gt;Our accountants &lt;a href=&quot;http://woodwalton.co.nz&quot; target=&quot;_blank&quot;&gt;Wood Walton&lt;/a&gt; set things up and brought all the historic information across. I showed Ben how to log in and we worked out how to add his company logo and create a debtor invoice then I left him to it. I braced myself for impact and hoped for the best.&lt;/p&gt;
&lt;p&gt;But there was nothing, not a peep. Next thing I know, he&#039;s loading in creditor invoices, creating new customers, receipting invoices, checking his aged debtors and bank balances. I almost felt... surplus to requirements.&lt;/p&gt;
&lt;p&gt;The benefits of changing from a desktop-based solution to the web were obvious from the outset; it&#039;s always backed up, we can both view the information all of the time (which is a biggie given the amount of travel Ben does), and we can log in from any computer that has an internet connection. But there are extras, it as fast - really fast. I would estimate we have reduced our financial administrative time by about 75%. The automatic bank feeds means that your cash position is always up to date and bank reconciliations are a joy.&lt;/p&gt;
&lt;p&gt;Given the success of Ben&#039;s transition, the plan was to switch Digital Fusion over at the start of the new financial year, however the events of February 22nd brought our plans forward somewhat and we have now been using xero for several months.&lt;/p&gt;
&lt;p&gt;Digital Fusion may appear a simple business to the untrained eye, but there are some real hooks when you scratch beneath the surface. We operate in both Australia and New Zealand, use 4 different banks and need Xero to integrate with &lt;a href=&quot;http://nutshellcrm.com&quot; target=&quot;_blank&quot;&gt;Nutshell&lt;/a&gt; our CRM.&lt;/p&gt;
&lt;p&gt;For the most part Xero has stepped up, much like in Bens business we are seeing big reductions in admin time (now that Elaine and Xero have bonded), and the sharing of information between admin and management is easy - we all just log in and look. We have had a few difficulties with inter-bank transfers, the extraction of specific information is not always simple, and I am not sure we have come to terms all of the reporting as yet.&lt;/p&gt;
&lt;p&gt;These are pretty minor in the big picture though and overall the gains are huge... bigger than Texas. So if you have been considering Xero and you are on the fence, get off it. This has been a really big win for us for relatively little effort.&lt;/p&gt;</description>
			<pubDate>Fri, 08 Jul 2011 19:51:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/xero-meant-nothing-until-now/</guid>
		</item>
		
		<item>
			<title>Aussie, Aussie, Aussie</title>
			<link>https://www.teamdf.com/blogs/aussie-aussie-aussie/</link>
			<description>&lt;p&gt;We think those Aussies are kind of the same as us.... don&#039;t be fooled they are most definitely not!&lt;/p&gt;
&lt;p&gt;Craig and I are just back from a few invigorating days in Sydney courtesy of NZTE as the culmination of the Path to Market program timed to coincide with CeBIT. There were about 20 in our Kiwi delegation and the 4 days played out like a mini conference.&lt;/p&gt;
&lt;p&gt;We heard from both business and government, ex-pat Kiwis and die-hard Aussies. We were both impressed and surprised by the parochial attitude of each of the speakers when advocating for their respective state or city... the competitiveness is intense!&lt;/p&gt;
&lt;p&gt;Inspiring speakers such as Rebekah Campbell, former manager of Evermore and founder of posse.com, Paddy O&#039;Brien, general manager of SmartPay Australia and Ian Clarke CEO of Fronde were some of the highlights.&lt;/p&gt;
&lt;p&gt;We made some new friends including Matt Steele, Business Leader for Apple in Sydney (like). Apple are really keen to build relationships with companies who create productivity tools that are winners on the Mac platform. We have plans afoot to do presentations at some of the Apple stores in Sydney. Companies like us are the enablers, through our custom software we can demonstrate how business can operate on the Mac platform efficiently and effectively.&lt;/p&gt;
&lt;p&gt;We ate lunch at the top of the KPMG building in one of their swanky boardrooms... after a brisk 3 hour hike across the city in heels (me, not Craig) in the rain.&lt;/p&gt;
&lt;p&gt;We went to the opening of CeBIT at the Opera House, The Cure were playing on the same night next door... wish we went to that instead. I shouldn&#039;t complain really, we did get to listen first hand to Australian and German politicians in a mutual love fest.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/249/81_1.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This article wouldn&#039;t be complete without a mention of Lee Sinclair and Carole Wright from CDC and NZTE respectively - what a couple of super-cool chicks. They have been helping us and other affected Christchurch based businesses through some challenging times - it was great to spend some time and get to know them better over the past few days.&lt;/p&gt;
&lt;p&gt;So overall what did we learn about doing business in Australia?&lt;/p&gt;
&lt;ul class=&quot;bigpoints&quot;&gt;&lt;li&gt;If you wanna be taken seriously in Australia, you have to be there... this was the message from EVERY speaker. Rebekah Campbell described how she repatriated Evermore to Australia, going as far as making them *Australian citizens. She evolved them through the touring and pub scene, and it meant they were accepted by Australians as one of their own right from the start. Clever girl.&lt;/li&gt;
&lt;li&gt;Australian bankers are just as boring as bankers in New Zealand&lt;/li&gt;
&lt;li&gt;Each State in Australia should be treated as a separate market, based on their uniquely different personalities and cultures. In Sydney business is old school and done through contracts and networks where as Queenslanders are more entrepreneurial, straight talking and consider your word as your bond.&lt;/li&gt;
&lt;li&gt;They know how to work the stats, every state in Australia has the largest, fastest, biggest or best of something in the ICT sector.&lt;/li&gt;
&lt;li&gt;The opportunities in Australia are huge, maybe as big as Texas, maybe even bigger than Texas. Johnny Cates from Aveva was one of many to tell that wireless business is exploding.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The best part about Australia is - they want us. Almost every speaker was encouraging us to set up shop in their city, state or technology park. Offering introductions, free office space and a beer on Fridays.&lt;/p&gt;
&lt;p&gt;So Craig and I are not quite changing our All Black for the green and gold just yet, but we are incredibly enthusiastic about the possibilities in this market that&#039;s right on our doorstep.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 07 Jun 2011 10:42:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/aussie-aussie-aussie/</guid>
		</item>
		
		<item>
			<title>Build a Navigation System Part Two - Taking it Further</title>
			<link>https://www.teamdf.com/blogs/build-a-navigation-system-part-two-taking-it-further/</link>
			<description>&lt;p&gt;In &lt;a href=&quot;http://digitalfusion.co.nz/weetbicks/build-a-navigation-system-part-one--starting-out-simple/37/&quot;&gt;part one&lt;/a&gt;, we built a basic navigation bar made from repeating fields. In this followup article we take the formatting of the navigation bar further by introducing highlights. We also adjust the construction of the navigation, and introduce a custom menu implementation that can be used in conjunction with, or in place of the navigation bar.&lt;/p&gt;
&lt;h4&gt;Some changes to the construction&lt;/h4&gt;
&lt;p&gt;In order to make some of the new features of this upgraded navigation bar easier to manage, we are going to make a few minor tweaks to how the navigation bar is constructed. These changes may slightly affect how the navigation bar looks from earlier versions, but these can easily be overcome with field formatting options.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60049-navigationbartwo-1.png&quot; alt=&quot;navigationbartwo 1&quot; width=&quot;600&quot; height=&quot;49&quot;&gt;&lt;/p&gt;
&lt;p&gt;On first glance it may look very similar to the navigation bar in &lt;a href=&quot;http://digitalfusion.co.nz/weetbicks/build-a-navigation-system-part-one--starting-out-simple/37/&quot;&gt;part one&lt;/a&gt;, but there are a couple of changes that are shown better in layout mode.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60061-navigationbartwo-2.png&quot; alt=&quot;navigationbartwo 2&quot; width=&quot;600&quot; height=&quot;61&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here, the icon repeating fields have been increased in height so that their bottom border touches the top border of the label repeating fields, creating a single block with no gaps in between the icon &amp;amp; the labels.&lt;/p&gt;
&lt;p&gt;Another change less noticeable, is that each icon/label combination has been created as a separate series of objects to the other repetitions, better illustrated in the following picture:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/navigationbartwo-3.png&quot; alt=&quot;navigationbartwo 3&quot; width=&quot;437&quot; height=&quot;97&quot;&gt;&lt;/p&gt;
&lt;p&gt;Recall in &lt;a href=&quot;http://digitalfusion.co.nz/weetbicks/build-a-navigation-system-part-one--starting-out-simple/37/&quot;&gt;part one&lt;/a&gt; that we specified the icons and labels as single fields that were set to show all repetitions. There are a few reasons for this change which will become clear later.&lt;/p&gt;
&lt;p&gt;One final change is that each repetition combination of icon &amp;amp; label are grouped into a single object.&lt;/p&gt;
&lt;h4&gt;Highlighting the Selected Screen&lt;/h4&gt;
&lt;p&gt;The navigation bar in &lt;a href=&quot;http://digitalfusion.co.nz/weetbicks/build-a-navigation-system-part-one--starting-out-simple/37/&quot;&gt;part one&lt;/a&gt; gave no visual indication of which screen the user was currently viewing. It would be nice to highlight the screen being viewed so the user is not left guessing where they ended up, it also provides some solid feedback that the users click on the navigation bar was successful.&lt;/p&gt;
&lt;p&gt;What we are going to do then is to implement some highlight formatting as shown below:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600151-navigationbartwo-4.png&quot; alt=&quot;navigationbartwo 4&quot; width=&quot;600&quot; height=&quot;151&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the picture above you can see two things happening:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Background filled white&lt;/li&gt;
&lt;li&gt;Text label changed to black &amp;amp; bold&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Both of these formatting changes have been done by using conditional formatting.&lt;/p&gt;
&lt;p&gt;The decision to use conditional formatting over calculation fields that make use of text formatting functions is a conscious decision. The downside to the conditional formatting is that if you ever want to change the fill color or label changes, then the change has to be applied to all navigation bars (or a single navigation bar that is then replaced on all layouts). This could become a nuisance but we are going on the assumption that once set it won&#039;t change. The fact the entire navigation system is based on globals means changes aren&#039;t that difficult to make as it is a case of copy/pasting a new navigation bar on all layouts that use it.&lt;/p&gt;
&lt;p&gt;The reason why calculation fields that use text formatting functions were not used for the formatting, is because the goal here is to keep the navigation system entirely global. By having it all global based, there is only the need for a single Navigation table occurrence on the graph, and navigation bars can easily be applied to new layouts without additional setup. Global calculation fields are not suitable in this situation as they do not refresh as desired.&lt;/p&gt;
&lt;h4&gt;The conditional formatting calculation&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This section is somewhat irrelevant now after a discovery by Peter Bouma after the article was written. Please see the extra section at the bottom of this article before reading this section as it may save you some time, cheers :-)&lt;/p&gt;
&lt;p&gt;In order to highlight any particular screen in the navigation bar, we require a calculation that can be evaluated that is generic, but at the same time evaluated differently for each repetition. How can a specific repetition evaluate differently from another repetition you ask? Well the answer lies in using a FileMaker function that will give a different result depending on which repetition evaluated from, and there are two prime candidates:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Get ( ActiveRepetitionNumber )&lt;/li&gt;
&lt;li&gt;Get ( CalculationRepetitionNumber )&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Both of these are concerning repeating fields so have potential. Get ( ActiveRepetitionNumber ) however is of no real use because that only evaluates when the user has placed the mouse cursor inside of a repeating field. Because we have disabled browse mode access into our navigation bar, this function will never evaluate.&lt;/p&gt;
&lt;p&gt;The other possibility is Get ( CalculationRepetitionNumber ). This function will return a repetitions number when evaluated from a calculation context of that repetition. There is just one problem here, our navigation bar is composed of non-calculation repeating fields. The solution then is to make it based on calculation repeating fields :)&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/navigationbartwo-5.png&quot; alt=&quot;navigationbartwo 5&quot; width=&quot;431&quot; height=&quot;153&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the picture above you can see two new fields added to the Navigation table - &lt;em&gt;Labels Display&lt;/em&gt; and &lt;em&gt;Icons Display&lt;/em&gt;. Both are global calculation fields set to their equivalent non-calculation field.&lt;/p&gt;
&lt;h4&gt;&#039;Scuse me Egon, you said using global calc&#039;s was bad&lt;/h4&gt;
&lt;p&gt;Now, we mentioned earlier that we chose not to use global calculations to do the formatting, yet here we are using global calculations, what gives? Well in this situation they are fine because they will be used only for the navigation bar, and not formatting. Global calculation fields will re-evaluate when fields they reference are changed, but they will not change however when non-field references in them change, such as the current layout name.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60059-navigationbartwo-6.png&quot; alt=&quot;navigationbartwo 6&quot; width=&quot;600&quot; height=&quot;59&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is the new navigation bar above, based on the global calculation fields. Note the label definition is not visible because the label text is white by default.&lt;/p&gt;
&lt;p&gt;Now that the navigation bar is based upon global calculations, the Get ( CalculationRepetitionNumber ) field can be used in the conditional formatting. Here is the conditional formatting calculation we can apply across all repetitions:&lt;/p&gt;
&lt;pre&gt;Get ( LayoutName ) = Navigation::Layout Names[Get ( CalculationRepetitionNumber ) ]&lt;/pre&gt;
&lt;p&gt;It is simply comparing the current layout name, to the layout name contained in the Layout Names field repetition that corresponds to the current repetition being evaluated. For example, the 5th repetition in the nav bar will compare the current layout name, to that in the 5th repetition of the Layout Names field. If it is a match, the conditional formatting will evaluate to true.&lt;/p&gt;
&lt;h4&gt;Changes to make applying conditional formatting easier&lt;/h4&gt;
&lt;p&gt;Recall earlier the changes made to the navigation bar construction. These were done for various reasons, but one is to make the conditional formatting of the nav bar simpler.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/navigationbartwo-7.png&quot; alt=&quot;navigationbartwo 7&quot; width=&quot;109&quot; height=&quot;92&quot;&gt;&lt;/p&gt;
&lt;p&gt;The grouping of the label and icon repetition means that we can apply a single conditional formatting property across the single object that takes care of both the highlight and the text formatting, no need for a separate condition for the label and the highlight.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600368-navigationbartwo-8.png&quot; alt=&quot;navigationbartwo 8&quot; width=&quot;600&quot; height=&quot;368&quot;&gt;&lt;/p&gt;
&lt;p&gt;This single conditional formatting condition can be applied across the &lt;strong&gt;entire&lt;/strong&gt; navigation bar in a single hit, because it is generic across all repetitions. The text formatting of bold &amp;amp; text color will have no affect on the icon, and the fill color will be applied to both icon and label which is what we want.&lt;/p&gt;
&lt;p&gt;Note that in order for the highlight fill to work correctly, your icons should be transparent png&#039;s or gifs.&lt;/p&gt;
&lt;h4&gt;A custom function for conditional formatting&lt;/h4&gt;
&lt;p&gt;While not strictly necessary, we have used a custom function in the example file to contain the conditional formatting calculation. This is a nice illustration of how custom functions can actually reference fields - so long as those fields are able to be evaluated from the context of where the custom function is evaluated from.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600429-navigationbartwo-9.png&quot; alt=&quot;navigationbartwo 9&quot; width=&quot;600&quot; height=&quot;429&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600480-navigationbartwo-10.png&quot; alt=&quot;navigationbartwo 10&quot; width=&quot;600&quot; height=&quot;480&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Clickable area in the Navigation Bar&lt;/h4&gt;
&lt;p&gt;Now that the text label and icon are touching borders, and they are grouped, we can just make the clickable button the grouped object. This removes the need for a separate button overlay which was used in &lt;a href=&quot;http://digitalfusion.co.nz/weetbicks/build-a-navigation-system-part-one--starting-out-simple/37/&quot;&gt;part one&lt;/a&gt;. The reason it was used there was because our icon and label were not aligned and the same size as the clickable area. Because of this change, we can remove the button overlays, reducing the complexity of the navigation bar.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/navigationbartwo-11.png&quot; alt=&quot;navigationbartwo 11&quot; width=&quot;400&quot; height=&quot;67&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Building Navigation into a Custom Menu&lt;/h4&gt;
&lt;p&gt;With the navigation system completely global and already built, building it as a custom menu is a piece of cake.&lt;/p&gt;
&lt;p&gt;To do this, we use a technique demonstrated in a previous article called &lt;a href=&quot;http://www.digitalfusion.co.nz/weetbicks/hide-custom-menu-elements-dynamically/43/&quot;&gt;Hide Custom Menu Elements Dynamically&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The technique consists of creating menu items in a new menu. The name of each item is set using a calculation to a specific repetition of the labels repeating field. Because this is global based, it should work across all layouts where the menu item is used.&lt;/p&gt;
&lt;p&gt;When building a custom menu, there is no ability to soft-code item names making use of the menu items position in the menu. For this reason, each menu item&#039;s name is set from an explicit repetition of the Labels field. Because we may not know exactly how many repetitions of the navigation bar a solution may use, we accommodate for this by adding as many menu items as possible. Menu items will not display if their name evaluates to blank. This is the technique outlined in the article above, and for this reason we can be sure that the menu will only display items for just those that are in the navigation bar.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600438-navigationbartwo-12.png&quot; alt=&quot;navigationbartwo 12&quot; width=&quot;600&quot; height=&quot;438&quot;&gt;&lt;/p&gt;
&lt;p&gt;The picture above illustrates how the custom menu is built, and the fact that unused repetitions contain no name, and so will not be displayed in FileMaker 11 (in FileMaker 10 they display as blank, but have no action).&lt;/p&gt;
&lt;p&gt;The menu item name is set via the Labels repetition, and the action attached is a script that is passed a corresponding repetition number.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600392-navigationbartwo-13.png&quot; alt=&quot;navigationbartwo 13&quot; width=&quot;600&quot; height=&quot;392&quot;&gt;&lt;/p&gt;
&lt;p&gt;We have gone from using a single script step for the navigation, to putting that inside a script. The reason for this is one of future-proofing. If we ever wish to do post-navigation stuff, this lets us add that in later without having to redo the navigation bar or custom menu.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600164-navigationbartwo-14.png&quot; alt=&quot;navigationbartwo 14&quot; width=&quot;600&quot; height=&quot;164&quot;&gt;&lt;/p&gt;
&lt;p&gt;The above shows the custom menu in action.&lt;/p&gt;
&lt;p&gt;If you had a solution with lots of screens, you could choose to do away with the visual navigation bar entirely, and simply use the custom menu aspect for navigation.&lt;/p&gt;
&lt;h4&gt;Final Thoughts&lt;/h4&gt;
&lt;p&gt;With a few tweaks and additions, we have made the navigation bar more responsive visually, by having it give feedback on which screen is selected. We also extended it&#039;s use by building a custom menu to supplement it. All the while the navigation system has been kept global and generic so that it can easily be applied to layouts with zero modifications required.&lt;/p&gt;
&lt;h4&gt;Extra: Global Calcs not required via Peter Bouma&lt;/h4&gt;
&lt;p&gt;As always the readers of these articles come up with some great suggestions and contributions after the article is written and this case, &lt;strong&gt;Peter Bouma&lt;/strong&gt; from Amsterdam, has discovered that in fact the need for global calculations that contain the icons and the labels is not necessary for using the Get ( CalculationRepetitionNumber ) function as I had assumed.&lt;/p&gt;
&lt;p&gt;He has found that this function still evaluates correctly even from the context of a layout-based calculation such as the conditional formatting calculation. Even though the original labels and icons repeating fields were not calculations, the function still is able to obtain the relevant repetition via the conditional formatting calculation set on each repetition.&lt;/p&gt;
&lt;p&gt;End result is the solution can be made simpler than I originally presented, you can do away with the Icons Display and Labels display calc fields entirely and just keep the Icons and Labels global fields for your nav bar, awesome!&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/navigationbartwo/NavigationBarPartTwo.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Example File Extra from Stephen Dolenski&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://www.linkedin.com/in/oceanwest&quot;&gt;Stephen Dolenski&lt;/a&gt; of &lt;a href=&quot;http://www.oceanwest.net&quot;&gt;Ocean West Consulting, Inc.&lt;/a&gt; has provided an awesome adaptation of the original example file for this article. In Stephen&#039;s adaptation, he has added functionality to allow the navigation bar to toggle between each screens various list &amp;amp; form views, as well as a dashboard view, very cool, and I encourage you to check it out also.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/navigationbartwo/NavigationBarPartTwoAdaptation.zip&quot;&gt;Download Stephen&#039;s Modified Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 06 Jun 2011 00:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/build-a-navigation-system-part-two-taking-it-further/</guid>
		</item>
		
		<item>
			<title>Super Fast Record Display in Descending Creation Order</title>
			<link>https://www.teamdf.com/blogs/super-fast-record-display-in-descending-creation-order/</link>
			<description>&lt;p&gt;When FileMaker sorts records it happens on the client machine. Consequently, sorting can be a very painful process for users over a slow connection to a database.&lt;/p&gt;
&lt;p&gt;This article is all about a technique for presenting records to the user in their descending order of creation. The main focus is showing the records in a portal, but with the extension of the application to other areas such as list and table view. It is not concerned with any other type of sort on records.&lt;/p&gt;
&lt;h4&gt;Some Background Context on Sorting&lt;/h4&gt;
&lt;p&gt;Sorting records in FileMaker can be a painful and trying process. Record sorting occurs on the clients machine, which means that FileMaker has to send all records that are asking to be sorted over to the clients machine. Now, if the client is using a database locally, then this is not really an issue unless dealing with massive data sets.&lt;/p&gt;
&lt;p&gt;The problem with sorting is in the accessing of a database over a connection, be it local or wide area. Records have to be transferred from database to the client over this connection in order for the sort to occur, via FileMaker server or otherwise. Thus, the speed at which records will sort depends upon factors such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Client Download speed&lt;/li&gt;
&lt;li&gt;Server Upload speed&lt;/li&gt;
&lt;li&gt;Number of records being sorted&lt;/li&gt;
&lt;li&gt;Size of records being sorted&lt;/li&gt;
&lt;li&gt;Additional things, ie SSL encryption&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;All of these factors ultimately combine into a nasty experience for a user who just so happens to unwittingly sort their thousand record found set over a dodgy connection :)&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/fastportalsort-1.png&quot; alt=&quot;fastportalsort 1&quot; width=&quot;432&quot; height=&quot;202&quot;&gt;&lt;/p&gt;
&lt;h4&gt;What About Unsorted Records?&lt;/h4&gt;
&lt;p&gt;Unsorted records on the other hand do not require this en-masse transfer from server to client. FileMaker is smart enough to only send the client the records that they are accessing or viewing at any given time.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/fastportalsort-2.png&quot; alt=&quot;fastportalsort 2&quot; width=&quot;447&quot; height=&quot;303&quot;&gt;&lt;/p&gt;
&lt;p&gt;As an example of this, consider viewing a portal that is showing 100,000 related records. When unsorted, the database sends the client those records visible on-screen in the portal at that time. (I have a suspicion that a few more records beneath the visible ones are also sent, as a kind of buffer in anticipation of the user scrolling, can someone confirm this?)&lt;/p&gt;
&lt;p&gt;When the user begins to scroll down the portal, additional records are requested by the client, and the database sends these records back to the client so that they can be displayed. If a user grabs the scroll bar and navigates halfway down the list of records, then when they release the scrollbar, only the records now visible are sent to the client.&lt;/p&gt;
&lt;p&gt;Basically, records are sent from the database to the client on a need-to-access basis such as needing to view, manipulate or use them in some manner.&lt;/p&gt;
&lt;h4&gt;Here&#039;s the Situation...&lt;/h4&gt;
&lt;p&gt;We want to be able to present records in their descending creation order. We know that actually performing a sort on the records is going to mean the transfer of those records from database to client, and that this can potentially be very slow. We also know that displaying unsorted records is very fast because only a fraction of records are sent from database to user, those being the ones the user needs to see or use.&lt;/p&gt;
&lt;p&gt;Thinking...thinking....thinking.... aha !&lt;/p&gt;
&lt;p&gt;If viewing unsorted records is so fast, lets just leave them unsorted.&lt;/p&gt;
&lt;p&gt;But hang on a second....if they are unsorted then how the heck can they be presented sorted?&lt;/p&gt;
&lt;h4&gt;Think Opposite&lt;/h4&gt;
&lt;p&gt;The solution we came up with was to keep records unsorted, but have a calculation on each record that is capable of determining their &lt;strong&gt;opposite&lt;/strong&gt; records primary key value. When we say opposite, we mean the record that is at the same position as the current record, but at the other spectrum of the found set. Here is a visual interpretation of what we mean for a found set of 100 records:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table cellspacing=&quot;0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Record #&lt;/th&gt;&lt;th&gt;Opposite Record #&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;99&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;98&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;99&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;The first record in the found said is paired with the last record, the second with the second-last, and so on.&lt;/p&gt;
&lt;p&gt;This is why the method works only for creation order of records - because it is easy to know exactly what the opposite record is. If we wanted to sort based on a field value with this method, then the opposite record could potentially be anywhere in the found set, and a physical sort would be required.&lt;/p&gt;
&lt;p&gt;This technique makes use of the fact that even unsorted records have a default sort order, that being creation order. We are simply making use of the one &quot;sort&quot; that is fast in FileMaker, and reversing it :)&lt;/p&gt;
&lt;h4&gt;How it Works&lt;/h4&gt;
&lt;p&gt;This technique makes use of a few interesting properties of some Get functions in FileMaker, namely the Get ( FoundCount ) and Get ( RecordNumber ) functions.&lt;/p&gt;
&lt;p&gt;Both of these functions operate in context. The value they return depends on where they are evaluated from, and on which record they are on. Their value also depends upon the number of records in the found set.&lt;/p&gt;
&lt;p&gt;Take list view with a found set of 1,000 records. Get ( FoundCount ) is going to give you a value of 1,000, and Get ( RecordNumber ) will change depending on the record you are on, starting from 1 for the first record in the found set and incrementing.&lt;/p&gt;
&lt;p&gt;Even cooler is these functions can operate from the context of a relationship (and thus portal) when added as an unstored calculation to the table being displayed.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/fastportalsort-3.png&quot; alt=&quot;fastportalsort 3&quot; width=&quot;166&quot; height=&quot;298&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this portal above, there is an unstored calculation field which is on the related table, set to Get ( RecordNumber ). The calculation is being evaluated from the context of the portal, and so each portal row is returning the record number through the relationship. The found count shown is also being shown by displaying an unstored calculation field that contains Get ( FoundCount ) through the relationship.&lt;/p&gt;
&lt;p&gt;We have written articles in the past making use of these properties which you can refer to for more detailed information about how this works:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://digitalfusion.co.nz/weetbicks/a-very-nice-way-to-format-a-sorted-portal-using-conditional-formatting/34/&quot;&gt;Portal Formatting&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;http://digitalfusion.co.nz/weetbicks/a-lightning-fast-alternative-to-the-count-function/17/&quot;&gt;Alternative to Count() Function&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;The Point is This:&lt;/h4&gt;
&lt;p&gt;If we have an unstored calculation field on the related table, and that calculation is able to determine its record number, and the total number of records in the found set, then it should be a case of applying a simple calculation to determine its opposite records number.&lt;/p&gt;
&lt;p&gt;Refer to the table example shown earlier. We require a calculation that can take a records number, and determine its opposite records number. Here is what we came up with:&lt;/p&gt;
&lt;pre&gt;Let ([&lt;br&gt;  RecordNum = Get ( RecordNumber ) ;&lt;br&gt;  Total = Get ( FoundCount )&lt;br&gt;];&lt;br&gt;  Mod ( Total - RecordNum ; Total ) + 1&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;When this calculation is put in an unstored field on a table, the result is the opposite records number in the found set. Try it! Put it on a table view layout or a portal, sort records, modify the found set... the calculation changes live to reflect the opposite records number, and because it is using native FileMaker functions that require no data from the records, it is very very fast.&lt;/p&gt;
&lt;h4&gt;Next Step: Grabbing the Primary Key Value from the Opposite Record&lt;/h4&gt;
&lt;p&gt;Knowing the record number of any given records opposite is fine, but it is pointless if we cannot then obtain data from that opposite record for displaying and editing purposes. Fortunately FileMaker gives us another amazing function to do exactly this - GetNthRecord&lt;/p&gt;
&lt;pre&gt;GetNthRecord ( fieldName ; recordNumber )&lt;/pre&gt;
&lt;p&gt;The function takes two parameters. The first is the field name from which we wish to obtain the value. The second is the record number. Hey cool! We know exactly what the record number is that we want to obtain! GetNthRecord works both through a relationship, and on a layouts found set, so can be used in both situations.&lt;/p&gt;
&lt;h4&gt;And Here is the Beauty of it...&lt;/h4&gt;
&lt;p&gt;The greatest thing about GetNthRecord is that when requesting a field value from a specified record, the database will only send the client that specific record only.&lt;/p&gt;
&lt;p&gt;So lets return now right back to the beginning and go full circle. An unsorted portal will only send the client the records being viewed. Similarly GetNthRecord will only send the client the records being requested.&lt;/p&gt;
&lt;p&gt;Lets say that we create a calculation that obtains the primary key field value from that records opposite record. If we then use that calculated &quot;opposite&quot; primary key in a relationship to the opposite record, we can then place fields from that relationship either in a portal or on a layout for display and editing. In doing so, some very cool things happen. Firstly values are displayed in an apparently descending creation order from most recently created to first created. Secondly and even more cooler, is that the database is only sending the user two records for each portal row being displayed:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;&lt;li&gt;One for the actual record for each portal row, and&lt;/li&gt;
&lt;li&gt;One for the opposite record being displayed via calculated relationship&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This dramatically cuts down on the number of records that would otherwise need to be sent from database to user. In a portal showing 1,000,000,000,000 records if 20 portal rows are being displayed, then 40 records are sent to the user, not 1,000,000,000,000 ! Now I realize showing that many related records in a portal is highly unlikely, but it illustrates the point nicely :-)&lt;/p&gt;
&lt;p&gt;Think about most portals that show records. A user is highly unlikely to want to scroll through them all, generally they might be interested in the first bunch of records. Perhaps they know the &quot;general&quot; area of the record they want, so make use of the scroll bar to jump to that area, or perhaps they want to jump right to the end. The point is, having the client download every single record is pointless if the client has no intention of looking at or using every single record. This method sends the user &quot;almost&quot; exactly what they want - that being what they are looking at.&lt;/p&gt;
&lt;p&gt;At this point we would recommend you check out the example file at the bottom of this article for a working example of the technique, where you can get stuck in and find out how it is all put together.&lt;/p&gt;
&lt;h4&gt;What this Technique Isn&#039;t...&lt;/h4&gt;
&lt;p&gt;This technique is not actual sorting, and while that fact serves it well in terms of its speed and efficiency, it is also a source of limitation if you are intending on taking this idea and jumping right in to implement it. There are a number of things you need to beware of.&lt;/p&gt;
&lt;p&gt;First, the records are not sorted, and what you are seeing visually in a portal, or in a list view, is &lt;strong&gt;not&lt;/strong&gt; the actual record you are on. The technique basically gives the illusion of sorted records, but you must beware they are not. If you allow users to delete records, you need to script for the deletion of the &lt;strong&gt;real&lt;/strong&gt; record the user thinks they are deleting. While we haven&#039;t detailed how this works in this article, it isn&#039;t a stretch to say that it is definitely possible given the fact each record is aware of what its opposite record is, and you can establish a relationship to its opposite record quite easily. Through the use of scripts, and custom menus, you could easily control correct record deletion.&lt;/p&gt;
&lt;h4&gt;Areas Where We See This Being Used:&lt;/h4&gt;
&lt;p&gt;Prime uses we see for this would be things such as displaying records in a portal where the most recently created record is the one that is at the center of the users focus, ie:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Invoices&lt;/li&gt;
&lt;li&gt;Transactions&lt;/li&gt;
&lt;li&gt;Interactions with Customers or Contacts&lt;/li&gt;
&lt;li&gt;System log entries&lt;/li&gt;
&lt;li&gt;Records assigned # based on order, ie Jobs&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;We would love to hear of situations where you think you could make good use of this technique, and if you end up taking it further or build on it, we&#039;d love to hear about it and share it here, Cheers!&lt;/p&gt;
&lt;h4&gt;EXTRA: Easy Editing of Records&lt;/h4&gt;
&lt;p&gt;A few hours after this article was released, I had the thought of grabbing just the opposite records primary key value, and using that in an additional relationship for the purposes of easily editing records in a portal or layout using this technique. The example files have been subsequently updated to show this change, and the article has been tweaked to reflect it.&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/fastportalsort/FastPortalSort_10000.zip&quot;&gt;Download Example File With 10,000 Records (3.3mb)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/fastportalsort/FastPortalSort_100000.zip&quot;&gt;Download Example File With 100,000 Records (32mb)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Sat, 28 May 2011 18:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/super-fast-record-display-in-descending-creation-order/</guid>
		</item>
		
		<item>
			<title>Xero to Hero</title>
			<link>https://www.teamdf.com/blogs/xero-to-hero/</link>
			<description>&lt;p&gt;For a long time I was a bit of a doubting Thomas when it came to the online accounting package cleverly named Xero. I thought it was a good idea and was pretty impressed by what the NZ company based in Wellington were undertaking. But I guess I thought the product was still too immature to cover the full gambit of functionality required to replace our incumbent system (MoneyWorks) and be a useful business tool.&lt;/p&gt;
&lt;p&gt;Well, I&#039;m here to say I&#039;m a convert. We love Xero!&lt;/p&gt;
&lt;p&gt;I started easy, convincing my partner Ben to switch his business over just before Xmas - I thought we could see how that went and decide whether it&#039;d be a good fit for Digital Fusion. I didn&#039;t tell Ben he was my guinea pig, I thought that might influence his perspective.... Even so, I was expecting lots of the usual change-related frustrations - you know swearing, cursing, slamming of laptop lids etc. Ben does all that quite well usually.&lt;/p&gt;
&lt;p&gt;Our accountants Wood Walton set things up and brought all the historic information across from MoneyWorks. I showed Ben how to log in and we worked out how to add his company logo and create a debtor invoice then I left him to it. I braced myself for impact and hoped for the best.&lt;/p&gt;
&lt;p&gt;But there was nothing, not a peep. Next thing I know, he&#039;s loading in creditor invoices, creating new customers, receipting invoices, checking his aged debtors and bank balances. I almost felt... surplus to requirements.&lt;/p&gt;
&lt;p&gt;The benefits of changing from a desktop-based solution to the web were obvious from the outset, it&#039;s always backed up, we can both view the information all of the time (which is a biggie given the amount of travel Ben does), and we can log in from any computer that has an internet connection. But there&#039;s extras, it&#039;s fast, really fast. I would estimate we&#039;ve reduced our financial administrative time by about 75%. The automatic bank feeds means that your cash position is always up to date and bank reconciliations are a joy.&lt;/p&gt;
&lt;p&gt;Given the success of Ben&#039;s transition, the plan was to switch Digital Fusion over at the start of the new financial year however the events of February 22nd brought our plans forward somewhat and we&#039;ve now been using Xero for several months.&lt;/p&gt;
&lt;p&gt;Digital Fusion may appear a simple business to the untrained eye, but there&#039;s some real hooks when you scratch beneath the surface. We operate in both Australia and New Zealand, use 4 different banks and need Xero to integrate with our in-house CRM. &lt;br&gt;For the most part Xero has stepped up, much like in Ben&#039;s business we&#039;re seeing big reductions in admin time (now that Elaine and Xero have bonded), and the sharing of information between admin and management is easy - we all just log in and look. We&#039;ve had a few difficulties with inter-bank transfers, the extraction of specific information is not always simple, and I&#039;m not sure we&#039;ve come to terms all of the reporting as yet.&lt;/p&gt;
&lt;p&gt;These are pretty minor in the big picture though and overall the gains are huge... bigger than Texas. So if you have been considering Xero and you&#039;re on the fence, get off it. This has been a really big win for us for relatively little effort.&lt;/p&gt;</description>
			<pubDate>Thu, 26 May 2011 15:56:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/xero-to-hero/</guid>
		</item>
		
		<item>
			<title>Making Your Windows Self-Aware (Mac Only!)</title>
			<link>https://www.teamdf.com/blogs/making-your-windows-self-aware-mac-only/</link>
			<description>&lt;p&gt;In this article the term &quot;self-aware window&quot; refers to a FileMaker window that can know in real-time whether or not it is the currently selected window, and act accordingly. We introduce a technique for allowing individual windows to calculate this, and some examples of what windows could do with that knowledge.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE: This technique only appears to work on a Mac - sorry Windows, back in the box!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/pc.png&quot; alt=&quot;pc&quot; width=&quot;227&quot; height=&quot;292&quot;&gt;&lt;/p&gt;
&lt;p&gt;There are a number of different wee bits and pieces that are used to tie this all together, so lets get stuck in with the first...&lt;/p&gt;
&lt;h4&gt;WindowNames function&lt;/h4&gt;
&lt;p&gt;One of my favorite functions, it can do some pretty &lt;a href=&quot;http://www.digitalfusion.co.nz/weetbicks/as-you-type-window-naming-and-selection/68/&quot;&gt;cool things.&lt;/a&gt; In this case, one of the unique properties of the WindowNames function is that the currently active window name always appears first in the list of window names returned by the function. To try this, you can open a few windows, and put the following function in the data viewer:&lt;/p&gt;
&lt;pre&gt;WindowNames ( Get ( FileName ) )&lt;/pre&gt;
&lt;p&gt;When you click from window to window, you&#039;ll notice that all though the function returns all window names open for that file, the one you click on is always moved to the top of the list.&lt;/p&gt;
&lt;p&gt;Now, why is this useful? Well, for one it gives us a test we can perform. If we can get each window to independently evaluate the WindowNames function, and compare its own window name to that which appears &lt;strong&gt;first&lt;/strong&gt; in the list, then we can tell whether or not that window is currently selected.&lt;/p&gt;
&lt;h4&gt;Web Viewers&lt;/h4&gt;
&lt;p&gt;It&#039;s no mystery that web viewers can do a lot more than just show web pages as may have been originally intended. Over the years they&#039;ve been used for all kinds of things, from simply displaying a web page, to used in plugins, to used as a substitute for calculation fields, the list goes on.&lt;/p&gt;
&lt;p&gt;In this situation we are going to make use of the fact that a web viewer is essentially an on-layout calculation engine. What sets the web viewer calculation engine apart from say perhaps a regular calculation field, or conditional formatting, is that the calculation in a web viewer &lt;strong&gt;is always evaluating&lt;/strong&gt;. That is to say, a web viewer does not require a manual or automatic refresh of a window to update its display.&lt;/p&gt;
&lt;p&gt;Consider conditional formatting, or an unstored calculation on a layout, these things in order to update their display require you to resize the window, run a refresh window script, enter into the field, and so on. Something must trigger the refresh. Web viewers are different. They do not require a refresh in order to update, which is great for us!&lt;/p&gt;
&lt;p&gt;Better yet, a calculation in a web viewer will re-evaluate even when:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The web viewer is hidden on the layout&lt;/li&gt;
&lt;li&gt;The web viewer returns no result&lt;/li&gt;
&lt;li&gt;The web viewer is &lt;strong&gt;not&lt;/strong&gt; in the active window&lt;/li&gt;
&lt;li&gt;The web viewer doesn&#039;t reference fields at all - only functions&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;All of these points make the web viewer calculation engine a perfect tool for us. If we can put our WindowNames checking calculation in a web viewer on layouts, then each window can become &quot;self-aware&quot; because &lt;strong&gt;the calculation will re-evaluate when the current window changes&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;Putting it all together&lt;/h4&gt;
&lt;p&gt;The idea here is that we put a check in the web viewer to test whether the current window is the selected one. We do this by comparing the &lt;strong&gt;Get ( WindowName )&lt;/strong&gt; function with that of the first value returned from the &lt;strong&gt;WindowNames&lt;/strong&gt; function. If they match, then that window is the currently selected window&lt;/p&gt;
&lt;p&gt;As a point of note - you can have two windows with the same name, so pay attention if using this technique that the window names appear unique otherwise it may yield incorrect results.&lt;/p&gt;
&lt;h4&gt;An Example Use&lt;/h4&gt;
&lt;p&gt;Below we have a calculation defined in a web viewer:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600247-selfawarewindows-1.png&quot; alt=&quot;selfawarewindows 1&quot; width=&quot;600&quot; height=&quot;247&quot;&gt;&lt;/p&gt;
&lt;p&gt;What we are doing here is constructing a data URL. This format allows us to display text direct within the web viewer instead of referencing a web site URL.&lt;/p&gt;
&lt;p&gt;Most of the calculation is concerning itself with setting up the data URL and formatting the resulting text, but the key line in all of this is:&lt;/p&gt;
&lt;pre&gt;If ( windowSelectionStatus ; &quot;Selected&quot;  ; &quot;Not Selected&quot; )&lt;/pre&gt;
&lt;p&gt;Here we have defined a custom function called &lt;strong&gt;windowSelectionStatus&lt;/strong&gt;. If it returns true, we have the web viewer display the word &quot;Selected&quot;, otherwise &quot;Not Selected&quot;. No prizes for guessing what the windowSelectionStatus function does :)&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/selfawarewindows-2.png&quot; alt=&quot;selfawarewindows 2&quot; width=&quot;412&quot; height=&quot;135&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is the calculation for this custom function, and it&#039;s basically what we have talked about to this point. We obtain the first window in the list of WindowNames, and compare it to the current windows name, returning true if they match, false otherwise.&lt;/p&gt;
&lt;p&gt;Every web viewer that evaluates this calculation is acting in its own window, and so the result of the calculation and thus the subsequent value shown in the web viewer is completely independent of any other window - and it updates in real time!&lt;/p&gt;
&lt;p&gt;If you were to place a web viewer on your layouts, and open up multiple windows, you would see the web viewer change its resulting text in real time as you click from window to window, without the assistance of a refresh.&lt;/p&gt;
&lt;h4&gt;So What&#039;s the Point?&lt;/h4&gt;
&lt;p&gt;While this is all nice and well, it&#039;s pointless if there is no real application for the technique. Perhaps you just want to show something different in the web viewer depending on whether the window is selected, in which case that&#039;s fine, the technique to this point is fine.&lt;/p&gt;
&lt;p&gt;This article came about because we were working on an issue in a client database, where the user was getting into a record locking situation when having multiple windows open on screen at once. Often, they would end up with two windows open on the same record, either a data record, or their Home record in an interface/data solution. The user may be modifying a record in one window, only to change to another, and upon trying to edit the same record, be presented with the following dialog:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/selfawarewindows-3.png&quot; alt=&quot;selfawarewindows 3&quot; width=&quot;500&quot; height=&quot;242&quot;&gt;&lt;/p&gt;
&lt;p&gt;The message is pretty self explanatory as to what has just occurred. Perhaps we can make use of this self-aware window functionality to allow windows to tidy up after themselves when deselected.&lt;/p&gt;
&lt;h4&gt;Having a Window Commit Itself&lt;/h4&gt;
&lt;p&gt;Wouldn&#039;t it be nice if when a window was deselected, it was able to commit its record right away. That way, the record is not left uncommitted and subsequent locking errors can be avoided.&lt;/p&gt;
&lt;p&gt;Now, in order to commit a record, we have to run a script, and in the web viewer we only have access to the calculation engine, so at this time we have to make use of a plugin that is capable of running a script from the calculation engine. There are various plugins out there which are capable of doing this so the choice is yours. In the example file supplied with this article, we include examples for &lt;a href=&quot;http://www.reactorized.com&quot;&gt;Digital Fusion&#039;s Reactor plugin&lt;/a&gt;, and &lt;a href=&quot;http://www.monkeybreadsoftware.de/&quot;&gt;MonkeyBread Software&#039;s MBS Plugin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ideally we want the window to commit itself when:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;It becomes the deselected window, and&lt;/li&gt;
&lt;li&gt;The record is in an uncommitted state&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Well, we already know how to test for the first case. The second case can be tested for using the &lt;strong&gt;Get ( RecordOpenState )&lt;/strong&gt; function - any result that is non-zero means we should run the commit.&lt;/p&gt;
&lt;h4&gt;The CommitWindow custom function&lt;/h4&gt;
&lt;p&gt;Below is the new custom function defined called &lt;strong&gt;commitWindow&lt;/strong&gt;. As you can see, it is setup in a similar way to the earlier function to test a windows active status.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600242-selfawarewindows-4.png&quot; alt=&quot;selfawarewindows 4&quot; width=&quot;600&quot; height=&quot;242&quot;&gt;&lt;/p&gt;
&lt;p&gt;There are a couple of points of difference. The first is that we also check &lt;strong&gt;Get ( RecordOpenState)&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The second is that the result of this function is a call to a plugin function capable of executing a script. The above is taken from the example file, so you can see a couple of different examples of function calls for the plugins used. In both cases the script run is called &quot;CommitRecord&quot;.&lt;/p&gt;
&lt;p&gt;The function is then placed inside the web viewer as a calculation. Because we are only concerned with running a script, and not with what the web viewer shows, there is no need for the function to return anything worth displaying in the web viewer, its job is to run a script and that&#039;s all it does.&lt;/p&gt;
&lt;h4&gt;Why not just use an onTimer?&lt;/h4&gt;
&lt;p&gt;Now where is the fun in that! While it is true you can set an onTimer running in all of your windows to monitor the windows active status and commit accordingly, there are issues!&lt;/p&gt;
&lt;p&gt;Firstly, onTimers require the script to continually be running after defined intervals. In order to safely commit the record fast enough before the user tries to modify in another window, the internal has to be sufficiently low. The smaller the interval, the more frequently the script runs. Perhaps this doesn&#039;t add overhead, but the idea of a script running in every window every 5 seconds doesn&#039;t sit well with me :-) The web viewer method - while requiring a plugin - is more passive. It only executes the script when it absolutely needs to, and in doing so, the effect is instant.&lt;/p&gt;
&lt;p&gt;Secondly, there is a peculiar bug/feature/issue with onTimer scripts that we noticed in writing this article.&lt;/p&gt;
&lt;p&gt;Each window has its own onTimer running, that is known. When the script is eventually run, &quot;parts&quot; of the script evaluate from the context of the window from which it was triggered, however other parts of the script execute in whatever the current window is. We haven&#039;t fully explored this, but in trying to produce an onTimer method, we found that each window can successfully determine whether it is the selected window via an onTimer. So, each window is able to evaluate windowNames, and Get(WindowName) from their own context.&lt;/p&gt;
&lt;p&gt;The problem however comes when the Commit Records/Requests step is run. This script step is always run from the context of whatever the current window is.&lt;/p&gt;
&lt;p&gt;So, if you have two windows open A &amp;amp; B, and you modify a record in window A, then navigate to window B, the onTimer that runs in window A will determine successfully that it is uncommitted, and no longer the active window, but the commit record step is executed in the newly selected window B - confused?&lt;/p&gt;
&lt;p&gt;To put it another way - in order for an onTimer implementation to work, the script must first navigate back to the window from which the script was executed, run the commit and then navigate back to the window that was (and now is) the currently selected window! (couple that with the fact script is still continually running...)&lt;/p&gt;
&lt;p&gt;In short, yes you could work a solution using onTimer, in conjunction with the windowNames first value method. Both are possible, but both come with their own pros and cons, choose wisely :)&lt;/p&gt;
&lt;p&gt;We have included an onTimer scenario in the example file so you can see this issue in action, and perhaps modify the file to work correctly, have a play and see what you come up with.&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/selfawarewindows/SelfAwareWindows.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Fri, 06 May 2011 15:33:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/making-your-windows-self-aware-mac-only/</guid>
		</item>
		
		<item>
			<title>Integrating Image Maps in FileMaker</title>
			<link>https://www.teamdf.com/blogs/integrating-image-maps-in-filemaker/</link>
			<description>&lt;p&gt;In this article I demonstrate how you can use image maps with web viewers in FileMaker. In doing so, you can display images that, when clicked, can report the coordinate chosen back to FileMaker to handle in whichever manner you wish.&lt;/p&gt;
&lt;h4&gt;What are Image Maps?&lt;/h4&gt;
&lt;p&gt;Wikipedia says that an image map is a list of coordinates relating to a specific image, created in order to hyperlink areas of the image to various destinations. The intention of an image map is to provide an easy way of linking various parts of an image without dividing the image into separate image files.&lt;/p&gt;
&lt;h4&gt;Can we use them in FileMaker?&lt;/h4&gt;
&lt;p&gt;Wouldn&#039;t it be great if we could use an image map in FileMaker. This would allow us to display an image, and have FileMaker know the exact location on that image the user clicked. In knowing this information, you could then program a response, perhaps via a script.&lt;/p&gt;
&lt;h4&gt;Lets establish an example&lt;/h4&gt;
&lt;p&gt;Below is a photograph of a farm, with the paddocks on that farm outlined. We have a database that is used to manage the farm and the paddocks on it. Each Paddock is a record in the database.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Image-Maps/imagemap-1.png&quot; alt=&quot;imagemap 1&quot; width=&quot;495&quot; height=&quot;412&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Wait, so why not just use buttons?&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;Well, we could (but c&#039;mon where is the fun in that!). A common method of making a clickable image in FileMaker would be to place the image direct on the layout, or in a container, and underly buttons beneath the image that when clicked, run a script.&lt;/p&gt;
&lt;p&gt;Here&#039;s the problem - paddocks are not necessarily rectangular, circular, or oval shaped. As such, to underly buttons beneath a paddock, you must use a combination of many buttons or shapes to replicate the paddocks shape, then group those objects and turn them into one large button.&lt;/p&gt;
&lt;p&gt;Furthermore to this issue, what happens if in future the paddock fence-line changes? What happens if two paddocks become one? What happens if more paddocks are added? Basically it all boils down to the fact that the layout is going to have to be changed - not a very nice soft-coded solution.&lt;/p&gt;
&lt;h4&gt;So why is an Image Map Different?&lt;/h4&gt;
&lt;p&gt;If the image of the farm were presented as an image map, then there would be some feedback as to the location on the image that was clicked. We could then leave it up to FileMaker to determine what to do with that coordinate such as find out the paddock chosen, and run an appropriate script. In doing so, there would be no need for hard-coding of buttons required.&lt;/p&gt;
&lt;h4&gt;Lets do it then!&lt;/h4&gt;
&lt;p&gt;Okay enough talk, lets get into the nitty gritty.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Image-Maps/imagemap-2.png&quot; alt=&quot;imagemap 2&quot; width=&quot;315&quot; height=&quot;96&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is some very basic html code to establish an image map. We have specified an image called &quot;Map.png&quot;. It is given width and height dimensions in pixels. The image is established as an image map via the use of the &quot;ismap&quot; attribute. the html file is called Map.html.&lt;/p&gt;
&lt;p&gt;Pretty simple, around 6 lines of code. Image maps are widely varied and can include more fanciful features, but for this example we are sticking to the basics. In the example file we offer a slight variation on the above but basically its the same code.&lt;/p&gt;
&lt;h4&gt;Using the Web Viewer&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;Web Viewers are the tool in FileMaker that allow you to display web content on a layout. Given image maps are used on the web, it only makes sense that we will be using the web viewer. Basically we require to display the above html file in the web viewer, this can be achieved in a few ways.&lt;/p&gt;
&lt;p&gt;The first is via a web server. If we host Map.html and Map.png on a web server then we simply need to point the web viewer to that URL and the image map will be displayed. Of course, this method requires the database have access to the web server location, either via local network or over the internet. In the demo file, we give an example of this method.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Image-Maps/imagemap-3.png&quot; alt=&quot;imagemap 3&quot; width=&quot;530&quot; height=&quot;56&quot;&gt;&lt;/p&gt;
&lt;p&gt;The second option for those not averse to using a plugin, is to use &lt;a href=&quot;http://www.reactorized.com&quot;&gt;Reactor plugin&lt;/a&gt;, or any other plugin capable of hosting up web content. The reactor plugin is perfect for this because it is exactly what it was designed to do.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Image-Maps/imagemap-4.png&quot; alt=&quot;imagemap 4&quot; width=&quot;360&quot; height=&quot;114&quot;&gt;&lt;/p&gt;
&lt;p&gt;For those not familiar with the Reactor plugin, what it does is emulate a web server within a plugin. You can pass any file to the plugin using ReactorFeed function, and it will in return give you a URL which you can then place in the web viewer to display that content.&lt;/p&gt;
&lt;p&gt;We normally use ReactorFeed for things such as displaying PDF documents or images within a web viewer, and it does a great job. In this situation we are going to pass it Map.html and Map.png, and it in turn gives us a URL to use in our web viewer.&lt;/p&gt;
&lt;p&gt;We have included a reactor example in the demo file for those readers who have Reactor installed. If you do not have Reactor, you can download a demo copy &lt;a href=&quot;http://fusionplugins.com/reactor&quot;&gt;Here.&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;An attempt at a third method&lt;/h4&gt;
&lt;p&gt;The above methods outlined require either a plugin or access to a web server hosting the content. Both methods work great, but in developing this technique we aimed to provide an all-encompassing self contained solution. Unfortunately we failed (someone take up the challenge!) but I thought I would mention that method here.&lt;/p&gt;
&lt;p&gt;We attempted to base-64 encode both Map.html and Map.png and serve it up in the web viewer by using a data url. While we were able to display the map in the web viewer, we were unable to obtain the selected clicked coordinate via this method, more on what I&#039;m talking about later...&lt;/p&gt;
&lt;h4&gt;The &quot;isMap&quot; image map and how it works&lt;/h4&gt;
&lt;p&gt;We are using the isMap attribute to setup an image map on the image. How this works is when the user clicks on a location on the image, the chosen coordinate in pixels is appended to the end of the URL of the page.&lt;/p&gt;
&lt;p&gt;When we defined the image map code, you&#039;ll notice we gave it a width and height in pixels. This defines the area of the image. The top-left corner of the image is given the x,y coordinate of 0,0, and from there the coordinates extend out to all four corners of the image.&lt;/p&gt;
&lt;p&gt;When the user clicks on a point on the image, the x,y coordinate is placed on the end of the link.&lt;/p&gt;
&lt;p&gt;For example if the URL to the image map page is:&lt;/p&gt;
&lt;p&gt; http://www.imagemap.test/Map.html&lt;/p&gt;
&lt;p&gt;and the user clicks at coordinate 100,200 then the resulting URL of the page becomes&lt;/p&gt;
&lt;p&gt; http://www.imagemap.test/Map.html?100,200&lt;/p&gt;
&lt;h4&gt;Grabbing this Coordinate in FileMaker&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;It all boils down to the GetLayoutObjectAttribute function. This FileMaker function allows you to obtain the source url of a web viewer. Thus if we are able to obtain the source URL of the web viewer after the user has clicked in it, then it will tell us the URL with the coordinate appended! Brilliant!&lt;/p&gt;
&lt;pre&gt;GetLayoutObjectAttribute ( &quot;WebViewer&quot; ; &quot;Source&quot; )&lt;/pre&gt;
&lt;h4&gt;How can we tell the user has clicked?&lt;/h4&gt;
&lt;p&gt;Web viewers generally offer up content that the user interacts with independently of FileMaker. What we need is a way for FileMaker to know the user has just clicked on a position in the image map.&lt;/p&gt;
&lt;p&gt;We can achieve this now using script triggers that were introduced in FileMaker 10. Specifically, the onObjectEnter script trigger can fire off a script to run when the user enters an object - including a web viewer. This is how we are going to go about obtaining the source URL of the web viewer after the user enters the web viewer.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Image-Maps/imagemap-5.png&quot; alt=&quot;imagemap 5&quot; width=&quot;583&quot; height=&quot;466&quot;&gt;&lt;/p&gt;
&lt;h4&gt;It&#039;s all a matter of timing:&lt;/h4&gt;
&lt;p&gt;Now, if we were to run a script triggered by onObjectEnter as soon as the user clicks into the web viewer, the problem is that the script runs before the users interaction with the web viewer occurs. So if we run a script that tries to evaluate the source of the web viewer, it&#039;s just going to tell us the original URL because the users click on the image map has not yet been registered. What we need to do instead is delay our script from evaluating the source URL of the web viewer - finally a great use for the onTimer script step!&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Image-Maps/_resampled/ResizedImage60066-imagemap-6.png&quot; alt=&quot;imagemap 6&quot; width=&quot;600&quot; height=&quot;66&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Setting up the onTimer delay&lt;/h4&gt;
&lt;p&gt;As you can see in the image above, we set an onTimer to run .25 seconds after the triggered script is run. The delay you specify depends upon various factors, mostly related to the speed of the web server hosting the image map, or your internet connection (Rector being local tends to be faster). We find that a quarter of a second is ample time for the URL to update, and short enough to not be noticeable by the user.&lt;/p&gt;
&lt;p&gt;The process of events that occurs from the moment the user clicks into the web viewer is:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;User Clicks into web viewer&lt;/li&gt;
&lt;li&gt;onObjectEnter triggers a script&lt;/li&gt;
&lt;li&gt;The script installs an onTimer for a main script to run&lt;/li&gt;
&lt;li&gt;The users click now happens, and the web viewers URL is updated&lt;/li&gt;
&lt;li&gt;Now the delayed script runs, and is able to reference the web viewers new updated URL&lt;/li&gt;
&lt;li&gt;The script will run a commit record step to put the user back out of the web viewer, ready for the next click&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;And there you have it!&lt;/h4&gt;
&lt;p&gt;So that&#039;s basically it. You have an image with a width and height in pixels, and by using script triggers, onTimers, and various FM functions you can obtain the x,y coordinate clicked. From there, you can parse out the coordinates from the end of the web viewers URL, and do with them whatever you want, great.... but is that the end?&lt;/p&gt;
&lt;p&gt;Well not really. Once you have the coordinates the question now becomes what do you do with them? Being able to obtain the coordinates is nice, but unless you can do something meaningful with them, whats the point.&lt;/p&gt;
&lt;h4&gt;Lets go back to the example:&lt;/h4&gt;
&lt;p&gt;So lets now return to the example originally established, and see if we can figure out a nice way to select paddocks using this technique.&lt;/p&gt;
&lt;p&gt;Recall that each paddock is a record in the database, and we know the x,y coordinate clicked, but we don&#039;t yet know which paddock the user clicked in. What we now need to do is establish a method of defining paddocks in terms of their coordinates on the image map, and then evaluating the chosen coordinate to determine if it falls within one of the paddock boundaries.&lt;/p&gt;
&lt;h4&gt;Defining a Paddock by its boundary coordinates&lt;/h4&gt;
&lt;p&gt;Paddocks are shapes, and shapes are called polygons. A polygon is simply a shape with many sides (according to the weetbicks big book of mathematics).&lt;/p&gt;
&lt;p&gt;Where two edges meet, you get a corner, and a corner is defined by an x,y coordinate. We can define a polygon by a series of x,y coordinates, obtained by traversing the polygon in a clockwise (or anti-clockwise) fashion, and grabbing the coordinates of the corners.&lt;/p&gt;
&lt;p&gt;Lets assume for example we have a paddock defined by:&lt;/p&gt;
&lt;p&gt;(x,y)&lt;br&gt;0,0&lt;br&gt;20,0&lt;br&gt;20,20&lt;br&gt;20,0&lt;/p&gt;
&lt;p&gt;This defines the paddock as a perfect square, 20x20 in size on the image map. The paddock begins in the upper left corner at 0,0. From there, the upper right edge of the paddock is at 20,0. the lower right corner at 20,20, and the lower left corner at 20,0.&lt;/p&gt;
&lt;p&gt;We can define paddocks in this fashion regardless of their shape or location simply by plotting the corners of that paddock in order. In the example file, these are recorded on the paddock records in return-delimited lists of both the X and Y coordinates respectively.&lt;/p&gt;
&lt;h4&gt;Determining if a coordinate is within a polygon&lt;/h4&gt;
&lt;p&gt;So now we have a paddock defined as a series of x,y coordinates. What we now need to determine is whether a given x,y coordinate lies within the boundaries of that polygon.&lt;/p&gt;
&lt;p&gt;For more information about this technique, you can check out &lt;a href=&quot;http://alienryderflex.com/polygon/&quot;&gt;this great site&lt;/a&gt; that explains how the process works, and gives a C function of how to achieve it. Also please check out the acknowledgements at the bottom of this article for those who helped me take this C function and turn it into a FileMaker custom function.&lt;/p&gt;
&lt;h4&gt;PointInPolygon function&lt;/h4&gt;
&lt;p&gt;In the example file you will find this function which can tell you if a given coordinate is inside or outside of a polygon. the pointinPolygon function treats coordinates that fall on the edge of a polygon as &lt;strong&gt;outside&lt;/strong&gt;. There is also an alternative function provided that treats boundary coordinates as &lt;strong&gt;inside&lt;/strong&gt; the polygon. The functions have been provided by Nick Orr and Jason DeLooze respectively.&lt;/p&gt;
&lt;h4&gt;Let the Paddocks Decide&lt;/h4&gt;
&lt;p&gt;With the function now in place, we can let each paddock determine if they were selected by adding a calculation field to each record, that calls the custom function, testing its own coordinates against that of the selected coordinate.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Image-Maps/_resampled/ResizedImage600279-imagemap-7.png&quot; alt=&quot;imagemap 7&quot; width=&quot;600&quot; height=&quot;279&quot;&gt;&lt;/p&gt;
&lt;p&gt;Each paddock now has basically a flag set that determines if it was chosen or not. What you do with that information is up to you. In the example file, I am grabbing the ID of the chosen paddock, and using it in a relationship to that record for editing purposes, but the possibilities for this application are huge.&lt;/p&gt;
&lt;h4&gt;Further Applications or Improvements&lt;/h4&gt;
&lt;p&gt;Hopefully this article has proved enlightening and helpful for people. This is very much a work in progress and one of the goals of this article is to get peoples minds thinking about how this technique can be used and applied to FileMaker solutions, and also how it can be refined and improved upon, I would love to see peoples examples of how they can take this technique and run with it. Possible applications or improvements might include:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;iPad applications (in fact this was the reason for its development in the first place)&lt;/li&gt;
&lt;li&gt;Improved image mapping techniques, highlight entire polygon chosen&lt;/li&gt;
&lt;li&gt;Figuring out how to make this scaleable - allowing you to resize web viewer &amp;amp; image and have the record coordinates gracefully scale (right now this is a fixed image size and paddock coordinates are also fixed to this scale)&lt;/li&gt;
&lt;li&gt;Using it for navigation&lt;/li&gt;
&lt;li&gt;Writing a script that lets you click on the image map to create your &quot;paddock&quot; records easily&lt;/li&gt;
&lt;li&gt;Generating an image based upon polygon coordinates in records (could then be served up with Reactor)&lt;/li&gt;
&lt;li&gt;Writing a Reactor black-box function to essentially &quot;do-it-all&quot; - the possibilities here are limitless depending on how much javascript and various other web technologies you know!&lt;/li&gt;
&lt;li&gt;Figuring out how to make an &quot;all-in-one&quot; solution without the need for a web server or plugins, perhaps you can crack the base-64 encoding solution...&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;hr&gt;&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Example file updated on 4/5/11 to fix an issue in alternate ptInPoly function.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/Image-Maps/ImageMaps.zip&quot; target=&quot;_blank&quot;&gt;&lt;span class=&quot;ss-download&quot;&gt;Download Example File&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;&lt;h4&gt;Readers Contributions: Douglas Adler&lt;/h4&gt;
&lt;p&gt;Douglas Adler from &lt;a href=&quot;http://www.hbase.net&quot;&gt;HomeBase Software&lt;/a&gt; has taken some ideas and techniques from this article and run with them. He has revitalized an earlier image map technique he had worked on and put a new spin on it.&lt;/p&gt;
&lt;p&gt;I encourage you to check out his great article outlining what he has done over at &lt;a href=&quot;http://hbase.net/2011/05/03/filemaker-and-image-maps-in-a-web-viewer/&quot;&gt;his blog site here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Thanks Douglas!&lt;/p&gt;
&lt;h4&gt;Readers Contributions: David Wikstram&lt;/h4&gt;
&lt;p&gt;David Wikstram from &lt;a href=&quot;http://www.camelcasedata.com&quot;&gt;CamelCase Data&lt;/a&gt; has produced &lt;a href=&quot;http://www.camelcasedata.com/ImageMapCreator.fp7.zip&quot;&gt;this awesome demo file&lt;/a&gt; showcasing his extension of the image map idea. In this example, David has taken it to the next level, using SVG technology to not only produce a clickable image in a web viewer, but he also demonstrates how you can very easily setup your polygons on the image - with live visual feedback! In addition to this, using SVG has allowed David to do other cool things like have the selected polygon highlight itself upon selection. Check it out, you won&#039;t be disappointed!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;hr&gt;&lt;h4&gt;A Huge Thank You to the Following:&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;In preparing for this article, I sought the help of a number of people and would like to thank them here:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stephen Baker&lt;/strong&gt; - &lt;a href=&quot;http://www.digitalfusion.co.nz&quot;&gt;Digital Fusion Ltd&lt;/a&gt;&lt;br&gt;Stephen is the one who deserves the most credit for this article as this was a technique he developed when working on a client solution. Steve has been the main source of reference in writing this article and also helped in writing the pointInPolygon function, cheers!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sam Sehnert&lt;/strong&gt; - &lt;a href=&quot;http://www.digitalfusion.co.nz&quot;&gt;Digital Fusion Ltd&lt;/a&gt;&lt;br&gt;Initially we were using a very simple image map which gave no visual feedback of the position clicked. Sam - our resident javascript guru - provided the alternative image map code to display the pin icon in the location clicked, thanks!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nick Orr&lt;/strong&gt; - &lt;a href=&quot;http://www.goya.com.au&quot;&gt;Goya Pty Ltd&lt;/a&gt;&lt;br&gt;After struggling to write a FileMaker version of the pointInPolygon function (I was working off a C code example), I put the word out on the FmExperts mailing list for help in writing a FileMaker equivalent. Nick was quick to jump in and help out and spent a great deal of his own time in helping to write the final pointInPolygon function, which is the one you see in the example file. I can&#039;t thank Nick enough for his willingness to help out - he is a real class act!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://www.linkedin.com/pub/jason-delooze/0/995/9a6&quot;&gt;Jason DeLooze&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;Jason responded to the call for help on the FmExperts mailing list and came up with another cracking version of pointInPolygon which has been included in the example file. Jason&#039;s version is slight different to Nicks in that it treats points that fall on the edge of a polygon as inside, rather than outside, so thanks to Jason you have two choices in which function you wish to use, thanks Jason!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://ru.linkedin.com/in/mikhailedoshin&quot;&gt;Mikhail Edoshin&lt;/a&gt;, &lt;a href=&quot;http://www.linkedin.com/pub/mike-duncan/6/23b/887&quot;&gt;Mike Duncan&lt;/a&gt; and &lt;a href=&quot;http://www.linkedin.com/pub/leland-long/b/45/660&quot;&gt;Leland Long&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;These 3 top blokes all answered the call on FmExperts and offered advice, suggestions, and even had a crack at the pointInPolygon function too, huge thanks for taking the time to help out, cheers!&lt;/p&gt;</description>
			<pubDate>Fri, 29 Apr 2011 16:04:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/integrating-image-maps-in-filemaker/</guid>
		</item>
		
		<item>
			<title>DF&#039;s World Famous Blogstar</title>
			<link>https://www.teamdf.com/blogs/dfs-world-famous-blogstar/</link>
			<description>&lt;p&gt;Back in December, Digital Fusion launched FileMaker Weetbicks - a section of the main site dedicated to FileMaker articles of a technical nature. The idea behind creating the site was to give something back to the wider FileMaker community, and act as a resource for developers of all skill levels. Digital Fusion has a number of certified developers and a large pool of collective knowledge, and so this was a way to make that knowledge accessible to other developers around the world.&lt;/p&gt;
&lt;p&gt;Since its launch, the site has turned out to be a huge success and exceeded our expectations, with daily visitor numbers averaging over a hundred. The comments left on article posts suggest that people are enjoying the content and learning new techniques along the way which is great to see.&lt;/p&gt;
&lt;p&gt;While the content may not appeal to most of our clients, if you have ever dabbled in FileMaker then you may like to check it out - &lt;a href=&quot;http://www.filemakerweetbicks.com&quot;&gt;www.filemakerweetbicks.com&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Tue, 19 Apr 2011 16:02:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/dfs-world-famous-blogstar/</guid>
		</item>
		
		<item>
			<title>Remembered</title>
			<link>https://www.teamdf.com/blogs/remembered/</link>
			<description>&lt;p&gt;The night after the earthquake, out checking on the state of my father&#039;s house, I started thinking about friends and acquaintances that I hadn&#039;t checked up on. I happened to be driving at the time past a street where I knew an ex-colleague lived. I hadn&#039;t seen him for some years, and the suburb was largely untouched, so I put it out of my mind.&lt;/p&gt;
&lt;p&gt;It was some days later that I heard that Stephen Wright had started work only the month before in the CTV building, one of two relatively modern buildings that suffered total collapse in the earthquake. Officially listed at the time as &#039;missing&#039;, the conclusion was sadly inevitable when the TV showed pictures of a small tightly-packed pile of still-smouldering rubble.&lt;/p&gt;
&lt;p&gt;Stephen was marketing manager at MagnumMac throughout the eight years I worked there, and only recently left to work in a similar role at CTV. In doing so he went to work again for his previously employer at MagnumMac, now part-owner and managing director of CTV, Murray Wood.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://digitalfusion.co.nz/images/remembered.jpg&quot; alt=&quot;&quot; title=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Murray was a man for whom the term &#039;larger than life&#039; might have been invented. Despite a healthy personal modesty, he was a local legend in multiple communities. A lifelong musician, many years as a musical director at TVNZ, leading light in the Mac community, businessman and mentor, in recent years he returned to the TV fold as a mover andÃ¢ÂÂdare I say itÃ¢ÂÂshaker in local television at CTV. As the online tributes and the 1,000+ attendance at his memorial service proved, Murray was the kind of guy who was known by just about everybody.&lt;/p&gt;
&lt;p&gt;Two of us here at Digital Fusion had the honour to work with these two men in our careers. They will be remembered, and sorely missed, by many many more.&lt;/p&gt;</description>
			<pubDate>Tue, 19 Apr 2011 15:51:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/remembered/</guid>
		</item>
		
		<item>
			<title>Suppressing Self-Referencing Auto Enter Fields</title>
			<link>https://www.teamdf.com/blogs/suppressing-self-referencing-auto-enter-fields/</link>
			<description>&lt;p&gt;Using an auto-enter calculation on a field is a great way to populate its contents when other fields are modified, including itself. But what do you do if you want to use a calculation that references itself without having it trigger its own auto-enter calculation? The answer lies in thinking outside the calculation....&lt;/p&gt;
&lt;h4&gt;Setup aof an Example&lt;/h4&gt;
&lt;p&gt;In the attached example file I have concocted a scenario which illustrates this dilemma, although there are many situations where this may become an issue.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/selfautoenter/selfautoenter-1.png&quot; alt=&quot;selfautoenter 1&quot; width=&quot;415&quot; height=&quot;246&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is a basic table of products. Each product has two rates. In another table I have a product ID field with a value list attached displaying products from the products table. The idea is that when a product is selected, the rate field is populated automatically with the correct rate from the products table. The rules are:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;If product has a Rate 1 use that, otherwise&lt;/li&gt;
&lt;li&gt;If product has a Rate 2 use that, otherwise&lt;/li&gt;
&lt;li&gt;We wish to leave whatever is in the rate field at the time unchanged.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Here are some examples of what we expect when a product is chosen:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/selfautoenter/selfautoenter-2.png&quot; alt=&quot;selfautoenter 2&quot; width=&quot;372&quot; height=&quot;53&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/selfautoenter/selfautoenter-3.png&quot; alt=&quot;selfautoenter 3&quot; width=&quot;373&quot; height=&quot;49&quot;&gt;&lt;/p&gt;
&lt;p&gt;There is one more key rule for our Rate field and that is &lt;strong&gt;the rate must be able to be modified once a default is auto-entered&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;Building an auto-enter calculation for the rate field&lt;/h4&gt;
&lt;p&gt;With all of the required rules known, the first attempt at formulating an auto-enter calculation looked as follows:&lt;/p&gt;
&lt;pre&gt;Let ( [&lt;br&gt;TriggerField = Product ID ;&lt;br&gt;RateOne = Home to Products for Rate Auto Entry::Rate 1 ;&lt;br&gt;RateTwo = Home to Products for Rate Auto Entry::Rate 2&lt;br&gt;];&lt;br&gt;Case (&lt;br&gt;not IsEmpty ( RateOne ) ; RateOne ;&lt;br&gt;not IsEmpty ( RateTwo ) ; RateTwo ;&lt;br&gt;Self&lt;br&gt;)&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;Note that auto-enter calculations will trigger and re-evaluate when any field that they reference within the same table context is modified. We wish for the rate to change whenever the product ID is changed, however the product ID is merely a means to lookup the correct rate, we don&#039;t actually make use of the product ID itself in the calculation results. In order to have it trigger the auto-enter calculation we simply need to reference. This has been done using a Let statement where we set the Product ID field into a trigger variable whose only purpose is to fire the auto-enter calculation into action.&lt;/p&gt;
&lt;p&gt;The rest of the calculation is straightforward and follows the rules defined. If there is a Rate 1 use it, otherwise if there is a Rate 2 use that, otherwise leave the field contents unchanged, as evidenced by using Self.&lt;/p&gt;
&lt;p&gt;When this auto-enter calculation is used, everything appears fine.. Modification of Product ID fires the auto-enter, and the correct rate from the products table is entered.&lt;/p&gt;
&lt;h4&gt;But what about the final rule allowing modification of the rate?&lt;/h4&gt;
&lt;p&gt;This is where this auto-enter calculation fails. Recall that an auto-enter calculation triggers when &lt;strong&gt;any&lt;/strong&gt; of its referenced fields are modified in the same table context. Well this even refers to its own self. If an auto-enter calculation references its own field, then any modification in the field itself will cause itself to auto-enter. Sometimes this can be a very useful behavior depending on your situation, but sometimes this can be a real pain in the arse!&lt;/p&gt;
&lt;p&gt;If we were to attempt to modify the rate field now, then because our auto-enter calculation references &lt;strong&gt;Self&lt;/strong&gt; then the auto-enter is re-evaluated. Given the current calculation, it is going to relookup the associated rate from the Products table, thus nullifying any modification we tried to make to the field - the auto-enter is essentially hijacked by our lookup from the products table, preventing any modification to the field by the user. The only time the user is free to modify the rate is if there is no associated default rate in the Products table. Again, this may be what you want, but sometimes it isn&#039;t.&lt;/p&gt;
&lt;h4&gt;So, how do we fix this?&lt;/h4&gt;
&lt;p&gt;Finally the answer, bit of an anti-climax perhaps after all of this build up :) If an auto-enter calculation triggers when any field it references in the given table is modified, including Self, then is there anyway to reference Self from somewhere other than the table context? The answer is of course yes, and can be achieved using a &lt;strong&gt;Self-Join relationship&lt;/strong&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/selfautoenter/_resampled/ResizedImage600576-selfautoenter-4.png&quot; alt=&quot;selfautoenter 4&quot; width=&quot;600&quot; height=&quot;576&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is a simple self-join relationship matching on primary key. Essentially a self-join is a 1-to-1 relationship with itself.&lt;/p&gt;
&lt;p&gt;Now, we make a slight tweak to the auto-enter calculation:&lt;/p&gt;
&lt;pre&gt;Let ( [&lt;br&gt;TriggerField = Product ID ;&lt;br&gt;RateOne = Home to Products for Rate Auto Entry::Rate 1 ;&lt;br&gt;RateTwo = Home to Products for Rate Auto Entry::Rate 2&lt;br&gt;];&lt;br&gt;Case (&lt;br&gt;not IsEmpty ( RateOne ) ; RateOne ;&lt;br&gt;not IsEmpty ( RateTwo ) ; RateTwo ;&lt;br&gt;Home to Home for Self Join::Rate Modifiable&lt;br&gt;)&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;The change is made on the last line. Instead of directly referencing the field using Self, we instead now reference it via the self-join relationship. By referencing self outside of the calculations context, we are able to use the value of Self, without having it trigger its own auto-enter calculation which is exactly what we want. Now, the only field in the auto-enter calculation which will trigger the calculation is Product ID.&lt;/p&gt;
&lt;p&gt;Back on the layout, if a product ID is chosen the rate will be auto-entered if there is one. Once done, the user is free to then modify the rate to whatever they wish, and because the auto-enter calculation no longer directly references Self from the calculation context, it can do so without having the value revert to the default rate.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;center&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/selfautoenter/selfautoenter-5.png&quot; alt=&quot;selfautoenter 5&quot; width=&quot;373&quot; height=&quot;51&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Script Triggers&lt;/h4&gt;
&lt;p&gt;Yes, this could have been achieved with a script trigger on the Product ID field, but sometimes a script trigger may not be applicable, able to be used, or easy enough to work with. Because the auto-enter is tied directly to the field itself, then wherever the field is used the auto-enter simply works. With the script trigger it must be attached to every place the field is used in the solution.&lt;/p&gt;
&lt;p&gt;I&#039;m not saying a script trigger is not a good way of achieving this type of result, it certainly is and could be used. However I think auto-enters as a means to set a default value into a field, or enforce data entry rules on a field is still a great technique and very useful - especially in solutions Pre-FileMaker 10.&lt;/p&gt;
&lt;h4&gt;Final Thoughts:&lt;/h4&gt;
&lt;p&gt;Auto-Enter calculations are a great method for enforcing data-entry restrictions or rules on a field and for pre-populating a field with a default value. However because of their triggering properties there can arise situations in which you wish to reference the fields on contents but not have the field re-trigger itself when modified. A self-join can be used to reference the field in its own calculation - or indeed any field on the table - without having those fields force the re-triggering of the auto-enter calculation.&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/selfautoenter/SelfAutoEnterSuppression.zip&quot; target=&quot;_blank&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Sun, 17 Apr 2011 08:07:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/suppressing-self-referencing-auto-enter-fields/</guid>
		</item>
		
		<item>
			<title>As-You-Type Window Naming and Selection</title>
			<link>https://www.teamdf.com/blogs/as-you-type-window-naming-and-selection/</link>
			<description>&lt;p&gt;In applications such as Mail, you may notice that window names can be dynamic, dependent upon the contents of a field. In the case of Mail, the subject dictates the window name. In this article I&#039;ll demonstrate a way this can be replicated for FileMaker, and more importantly, how these dynamic windows can easily be selected again once created.&lt;/p&gt;
&lt;h4&gt;Disclaimer: Things are just better on Mac&lt;/h4&gt;
&lt;p&gt;This technique works great on Mac platform, but on Windows it may give some undesired results especially later on in the article where window selection is addressed, you may see a square box in the window name among other things. To put it bluntly, it&#039;s a mac only technique being illustrated.&lt;/p&gt;
&lt;h4&gt;An Example of a Dynamic Window Name&lt;/h4&gt;
&lt;p&gt;By the phrase dynamic window name what I mean is a window whose name will be constantly changing, it&#039;s not set in stone. A classic example of this is the Mail application (and almost certainly other applications) when a new message is being composed:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600570-windownaming-1.png&quot; alt=&quot;windownaming 1&quot; width=&quot;600&quot; height=&quot;570&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can see the windows name is the same as the subject line. If I were to clear the subject line entirely, a default window name is used:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/windownaming-2.png&quot; alt=&quot;windownaming 2&quot; width=&quot;247&quot; height=&quot;46&quot;&gt;&lt;/p&gt;
&lt;p&gt;This would be a pretty cool thing to have in FileMaker - window names that change dynamically based on some value in a field. For example your window name could change to reflect the record you are viewing, whether you are in find mode or browse mode, or the subject of a note/task you are composing just to name a few.&lt;/p&gt;
&lt;h4&gt;The solution, and then the solution to the solutions problem:&lt;/h4&gt;
&lt;p&gt;This is a cool feature and would look very nice, but having this feature presents a new pitfall to think about. The next section will just demonstrate the method in which you can achieve live window naming, and it will then be followed by explaining what the situation is that arises and how you can go about resolving it.&lt;/p&gt;
&lt;h4&gt;Using Script Triggers to achieve the Window Name&lt;/h4&gt;
&lt;p&gt;You may have seen that one coming :) Script triggers are a great tool for introducing live and dynamic changes to a lot of different areas in FileMaker, and window names is just another of those.&lt;/p&gt;
&lt;p&gt;As an example (please refer to the included example file) I have created a sample solution containing an E-Mail table. Each E-Mail is a draft that is pending to be sent in the database, and contains a recipient, subject, and message:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/windownaming-3.png&quot; alt=&quot;windownaming 3&quot; width=&quot;484&quot; height=&quot;163&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here I have a list of the e-mails. Editing and sending of the e-mails is done in a special popup window. I wish to have just one of these popup windows open at any one time for editing emails.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/windownaming-4.png&quot; alt=&quot;windownaming 4&quot; width=&quot;448&quot; height=&quot;146&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the image above you can see the windows name is exactly the same as the selected records subject. If I were to change the record, I would expect the window name to also change.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/windownaming-5.png&quot; alt=&quot;windownaming 5&quot; width=&quot;448&quot; height=&quot;148&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we see an e-mail with no subject. In this situation a default window name is assigned. So how is this done?&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/windownaming-6.png&quot; alt=&quot;windownaming 6&quot; width=&quot;565&quot; height=&quot;530&quot;&gt;&lt;/p&gt;
&lt;p&gt;There are two triggers used here. The first is onRecordLoad, in which I am running a script whose purpose is to set the windows title. The onRecordLoad trigger is a useful one to use in this case because it handles various situations such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Changing Record&lt;/li&gt;
&lt;li&gt;Performing a Find&lt;/li&gt;
&lt;li&gt;Omitting, modifying found set etc&lt;/li&gt;
&lt;li&gt;When the popup is first opened&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;All of these operations cause a new record to load, and so the trigger will execute.&lt;/p&gt;
&lt;p&gt;The second trigger used is on the field that is responsible for the windows name. In this case it is the e-mail subject:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/windownaming-7.png&quot; alt=&quot;windownaming 7&quot; width=&quot;583&quot; height=&quot;466&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we are using an onObjectModify trigger so that the windows name will be updated after the users keystroke is entered.&lt;/p&gt;
&lt;p&gt;The script responsible for setting the window name is a very simple 1 line script which uses the Set Window Title script step. If the subject field is not empty, then the window name is set to that, otherwise the window name is set to a default value of &quot;(No Subject)&quot;.&lt;/p&gt;
&lt;h4&gt;Now the Issue: Selection of this Window once Open&lt;/h4&gt;
&lt;p&gt;As with most things in FileMaker there is always a catch, or something that will cause an issue that you need to workaround, and this technique is no different.&lt;/p&gt;
&lt;p&gt;With regular windows whose names do not change, the window name itself becomes a sort of identifier of that window, kind of like what a primary key is to a record. If the window needs to be selected at a later point in time, it can easily be selected because the window name will not be changing. The window name could thus be stored in a custom function, global variable, or global field as a way to obtain its name for selection.&lt;/p&gt;
&lt;p&gt;In this situation however, we don&#039;t know what the windows name is because it is dynamic. When the window first opens it may have the name of &quot;(No Subject)&quot;. Once the user enters a subject the window name has now changed to something entirely different, and similarly any change to the users current record will affect the window name also.&lt;/p&gt;
&lt;p&gt;So the problem now becomes how can we identify what the window name is even when the name itself is changing?&lt;/p&gt;
&lt;h4&gt;Window Names that are Lists&lt;/h4&gt;
&lt;p&gt;The solution to this issue devised makes use of a little quirk in FileMaker window naming. A window name can actually be a return-delimited list of values, however only the first value in that list is visible to the user as the windows title.&lt;/p&gt;
&lt;p&gt;What does this mean for us? It means if we can assign the window a name that is two values - the first being the visible window name, and the second being a constant identifier for the window, then this might just let us figure out the full windows name somehow.&lt;/p&gt;
&lt;h4&gt;A closer look at the set window title script step&lt;/h4&gt;
&lt;p&gt;Here is the code used for the set window title script step used:&lt;/p&gt;
&lt;pre&gt;Let (&lt;br&gt;Subject = Emails::Subject ;&lt;br&gt;List ( If ( IsEmpty ( Subject ) ; &quot;(No Subject)&quot; ; Subject ) ; window_Email )&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;You can see the use of the List function here in generating the windows name. The first value in the list is the visible window name, either the subject, or a default &quot;(No Subject)&quot; title. The second value however is a special custom function called window_Email. In this custom function I have placed a text string which I am confident has not been used as a window name elsewhere in the solution.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600511-windownaming-8.png&quot; alt=&quot;windownaming 8&quot; width=&quot;600&quot; height=&quot;511&quot;&gt;&lt;/p&gt;
&lt;p&gt;So, if we look back to the earlier picture of my popup windows window name, you will notice that the second value &quot;- Email Compose&quot; is not visible anywhere in the window title, yet it is still part of the overall windows name).&lt;/p&gt;
&lt;h4&gt;So what does this look like&lt;/h4&gt;
&lt;p&gt;If we were to take a look at the WindowNames function what you end up seeing is something like:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;LiveWindowNaming&lt;/li&gt;
&lt;li&gt;Don&#039;t Forget Morning Tea&lt;/li&gt;
&lt;li&gt;Email Compose&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;As you can see, the window name spans two lines in this function as you would expect because of the fact the window name itself spans two lines.&lt;/p&gt;
&lt;p&gt;This is something you may need to pay attention to especially if you use the WindowNames function to determine the number of open windows in a file, because in this case there is 2, but windowNames would suggest there were 3.&lt;/p&gt;
&lt;h4&gt;Obtaining the original window name&lt;/h4&gt;
&lt;p&gt;The original window name can be obtained with the help of some magic custom functions. To obtain the window name, we start with the fact that we know what the identifier is, we could then:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Find the position in WindowNames of the identifier&lt;/li&gt;
&lt;li&gt;Obtain the previous value in the list&lt;/li&gt;
&lt;li&gt;Combine that with the identifier to get the actual window name&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The example file has a custom function contained called window_OpenWindowName which accepts as a parameter the identifier, and will return the full window name if it is open, or blank if it is not.&lt;/p&gt;
&lt;h4&gt;Some other things to consider when using this technique&lt;/h4&gt;
&lt;p&gt;There are a couple of other things you may need to keep in mind when using this technique.&lt;/p&gt;
&lt;p&gt;The first is the selection of field/value to use as your visible window title. If you choose a field that may contain return characters, then you should probably substitute those for another character upon setting the window title, this will prevent any issues later on when trying to back-engineer the windows name. Substitute with a space or comma and that should be fine.&lt;/p&gt;
&lt;p&gt;Secondly is the choice of identifier to use. This should be something that you know will not appear as a window name on another window. It is ok if the identifier appears as part of a windows name, so long as it is not the actual window name, the reason being that the custom functions employed to determine the original window name are looking for the identifier as its own value in the WindowNames list, not as part of a value.&lt;/p&gt;
&lt;p&gt;Lastly is another little quirk that occurs with this method and creation of windows. Generally if you have a window whose name is 1-value, and you create a new window via Windows -&amp;gt; New Window, the new window name is appended with a number so that the new window name is different to the original. This is FileMakers way of trying to ensure you don&#039;t end up with two window names the same.&lt;/p&gt;
&lt;p&gt;However you are not restricted in FileMaker to having unique window names. When this 2-value window name technique is used, the &quot;- 2&quot; appendage is not appended to either value of the window name, so you essentially create a new window whose name is exactly the same as the first.&lt;/p&gt;
&lt;p&gt;For this reason, the technique still works, but it will always be the first window created that is considered to the be found window. subsequent windows will not be identified as the main window because of the way the custom functions work to obtain the windows name - they seek out the first occurrence of the identifier in WindowNames....&lt;/p&gt;
&lt;h4&gt;Back to Creation/Selection of the Popup Window&lt;/h4&gt;
&lt;p&gt;With all that said, we can now employ this technique to handle both creation of this special popup if it is not already open, or selection of the window if is already open. Looking at the example file as a guide, the script to open/select the window does the following (condensed):&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Set Variable [ $Window ; window_OpenWindowName ( window_Email ) ]&lt;br&gt;If [ not isEmpty ( $Window ) ]&lt;br&gt;  Select Window [ Name: $Window ; Current File ]&lt;br&gt;Else&lt;br&gt;  // Create the Window, onRecordLoad takes care of window title&lt;br&gt;End If&lt;br&gt;// Correct record navigation is done afterwards, again onRecordLoad takes care of window title&lt;/pre&gt;
&lt;p&gt;The first thing is the potentially open window name is determined using the custom function. If it is found, that window is selected, if not, the window is created. After that the record the user wishes to view is selected via a find, GTRR or whatever other means, because we have the onRecordLoad trigger assigned to set the window title, we need not worry about setting it ourselves.&lt;/p&gt;
&lt;h4&gt;Handling the Windows Menu&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;So far we have talked about the visible window title and the fact the first value is only shown there. However the other place window names are visible is in the Window menu itself. If you have this disabled via custom menu then this is not a problem, but if not read on:&lt;/p&gt;
&lt;p&gt;In the Window menu, the name displayed is one of the following:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The full window name if short enough, otherwise&lt;/li&gt;
&lt;li&gt;~ first 14 characters start of window name, and last 14 of window name, separated by three dots.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;In our case, the end of the window name is the identifier, which actually works out quite well. We can choose an identifier that is about the required length, so that when the user views the Window names from the Window menu what they see is something like:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/windownaming-9.png&quot; alt=&quot;windownaming 9&quot; width=&quot;312&quot; height=&quot;256&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is a great window name to see here because it lets you see the start of the visible window name for easy selection, but if the visible window title is not enough to tell what the actual window is, the identifier makes it very easy to see the purpose of the window. Imagine if you had 10 open windows, each with very arbitrary window names based on a field value, knowing which window is which in the Window menu would be a nightmare, but using the identifier you can very easily see what the windows are.&lt;/p&gt;
&lt;p&gt;As a side note, the reason the identifier of &quot; - Email Compose&quot; was chosen as such, was for this purpose. In the case of a very short window name, this nicely formats the visible window name in the Window menu to:&lt;/p&gt;
&lt;p&gt;&quot;Short Name - Email Compose&quot;&lt;/p&gt;
&lt;p&gt;Which is much nicer to read.&lt;/p&gt;
&lt;p&gt;Further to this, if the file is hosted on a server, then typically in the Window menu you will see the server name appear in brackets after the window name (if the window is hidden). In this situation the window name comprises of the last 25 some odd characters in the following:&lt;/p&gt;
&lt;p&gt;(Server Name)&lt;/p&gt;
&lt;p&gt;So if you have a short server name, you can expect to see your identifier suffixed by it, ie:&lt;/p&gt;
&lt;p&gt;Email Compose (FM Server)&lt;/p&gt;
&lt;p&gt;Which again is quite nice.&lt;/p&gt;
&lt;h4&gt;Taking it further, multiple popups&lt;/h4&gt;
&lt;p&gt;This article is only really concerned with explaining the dynamic window technique and a way in which you can then reference these windows for selection or creation. The example chosen assumes that one popup window is required at any one time, and the user should not be allowed multiple email popup windows. But what if this is not the case, and we want the user to have as many popups as they want?&lt;/p&gt;
&lt;p&gt;While I have not explored this area fully, I thought I would put my thoughts in on how you could achieve this. Fairly straightforward, it would just mean an adjustment to the way the identifier part of the window name is generated. The identifier would instead contain the primary key value of the record being viewed, as well as an textual component for ease of reading in the window menu, i.e.:&lt;/p&gt;
&lt;p&gt;&quot;(No Subject) - 58282 - Email Compose&quot;&lt;/p&gt;
&lt;p&gt;In this situation, the identifier is now:&lt;/p&gt;
&lt;p&gt;&quot; - 58282 - Email Compose&quot;&lt;/p&gt;
&lt;p&gt;Rather than the identifier being stored in a custom function, it would now be dynamically generated itself in the script responsible for window creation/selection, and in the script responsible for setting the windows title.&lt;/p&gt;
&lt;h4&gt;Final Thoughts&lt;/h4&gt;
&lt;p&gt;This technique was originally conceived because of the need to replicate a Mail composition type dialog in FileMaker, but it can be applied to all kinds of window types. I have found the combination of onRecordLoad and onObjectModify triggers to be pretty robust, though more testing may need to be done in the areas of find/preview mode usage.&lt;/p&gt;
&lt;p&gt;The technique whereby a window name consists of a multi-line value is a great way to have a visible window name, and an invisible window name component for the purpose of window identification.&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/windownaming/LiveWindowNaming.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 14 Mar 2011 17:08:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/as-you-type-window-naming-and-selection/</guid>
		</item>
		
		<item>
			<title>Thinking Outside the Loop</title>
			<link>https://www.teamdf.com/blogs/thinking-outside-the-loop/</link>
			<description>&lt;p&gt;If you have spent any time developing in FileMaker, or programming in almost any language, you will be familiar with the concept of a loop. When scripting your loops you probably have a favorite method that you use. This article presents and compares a number of looping techniques that can be used in FileMaker in an attempt to locate the fastest method.&lt;/p&gt;
&lt;h4&gt;Establishing our Test Scenario&lt;/h4&gt;
&lt;p&gt;Lets assume that our solution is a CRM which has a Contacts table. The CRM also has a letter writing screen where we can compose letters.&lt;/p&gt;
&lt;p&gt;To make the best use of this facility, we should be able to compose a letter and print a personalized version for each contact.&lt;/p&gt;
&lt;p&gt;In order to print these personalized letters we require three important things:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;A Letters table to store the personalized letters.&lt;/li&gt;
&lt;li&gt;Records for each individual letter&lt;/li&gt;
&lt;li&gt;A Contact ID field to link to a Contact&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The goal of our loop then is to generate Letter records, each personalized for a specific contact which is determined by the fact that each record will have a different Contact ID.&lt;/p&gt;
&lt;h4&gt;A Note:&lt;/h4&gt;
&lt;p&gt;This article makes heavy use of the example file that accompanies it. It might be a good idea to download the example and reference it while reading this article :-)&lt;/p&gt;
&lt;p&gt;The code in this article is also a simplified version of what appears in the example file and is to illustrate the basic loop structure. If you want to see it in action then the example file is the best place to look.&lt;/p&gt;
&lt;h4&gt;Method #1: Layout Switching&lt;/h4&gt;
&lt;p&gt;Perhaps the simplest method and the one most beginners to FileMaker would use. The method involves looping through contact records, grabbing information from each in order to create letter records. The loop ends when all records have been traversed.&lt;/p&gt;
&lt;pre&gt;Set Variable [ $LetterContents ; Home::Letter Contents ]&lt;br&gt;Freeze Window&lt;br&gt;Go to Layout [ &quot;Contacts&quot; (Contacts) ]&lt;br&gt;Show All Records&lt;br&gt;Go to Record/Request/Page [ First ]&lt;br&gt;Loop&lt;br&gt;  Set Variable [ $ContactID ; Value: Contacts::Contact ID ]&lt;br&gt;  Go to Layout [ &quot;Letters&quot; (Letters) ]&lt;br&gt;  New Record/Request&lt;br&gt;  Set Field [ Letters::Letter Contents ; $LetterContents ]&lt;br&gt;  Set Field [ Letters::ContactID ; $ContactID ]&lt;br&gt;  Go to Layout [ &quot;Contacts&quot; (Contacts) ]&lt;br&gt;  Go to Record/Request/Page [ Next ; Exit After Last ]&lt;br&gt;End Loop&lt;/pre&gt;
&lt;p&gt;One of the biggest problems with the above method is the number of layout switches it involves. For each letter created, there are two layout switches - from contacts to letters &amp;amp; back. If you are generating 20,000 letters, that&#039;s 40,0000 layout switches which all adds up. This method might be fine for small numbers of letters only, but when the number of records generated gets large, an impact on performance can be seen.&lt;/p&gt;
&lt;h4&gt;Method #2: Chopping a List&lt;/h4&gt;
&lt;p&gt;This method differs from the first in that there is little or no layout switching involved, rather the looping is done by using a list of Contact IDs which is defined before the loop begins. This method is one that is quite common, but it too suffers from some inefficiencies.&lt;/p&gt;
&lt;pre&gt;Set Variable [ $LetterContents ; Home::Letter Contents ]&lt;br&gt;Set Variable [ $ContactIDs ; List ( Home to Contacts::Contact ID ) ]&lt;br&gt;Set Variable [ $Total ; ValueCount ( $ContactIDs ) ]&lt;br&gt;Go to Layout [ &quot;Letters&quot; (Letters) ]&lt;br&gt;Loop&lt;br&gt;  New Record/Request&lt;br&gt;  Set Field [ Letters::Letter Contents ; $LetterContents ]&lt;br&gt;  Set Field [ Letters::ContactID ; GetValue ( $ContactIDs ; 1 ) ]&lt;br&gt;  Set Variable [ $ContactIDs ; RightValues ( $ContactIDs ; ValueCount ( $ContactIDs ) - 1 ) ]&lt;br&gt;  Exit Loop If [ IsEmpty ( $ContactIDs ) ]&lt;br&gt;End Loop&lt;/pre&gt;
&lt;p&gt;During each iteration of the loop, the first contact ID in the list is set into the new record. The list is them trimmed of its first value, so that the second value now becomes the first. When the loop next iterates, the new first value is used, and so on until the list is empty.&lt;/p&gt;
&lt;p&gt;The big issue with this method is the overhead in trimming the list during each loop. In particular the use of the RightValues function is a particularly costly function call. The more letters you create, the more calls to this function required. Also, consider generating a large set of letters such as 20,000. Your initial list is 20,000 values. After the first iteration the RightValues function is being told to grab the 19,999 right-most values from that list to make the new list - that can&#039;t be good!&lt;/p&gt;
&lt;p&gt;So, is there any way we can still use a list of contact IDs, but perhaps avoid using these costly function calls during each iteration of the loop? Fortunately there is...&lt;/p&gt;
&lt;h4&gt;Method #3: The Counter Approach&lt;/h4&gt;
&lt;p&gt;You may have noticed in Method #2 that we used the GetValue function to obtain the first value in the list. GetValue takes two parameters, the second of which is the value # in the list to obtain. We were just using the first value, but there is no reason why we can&#039;t grab any value.&lt;/p&gt;
&lt;p&gt;So, we are now going to maintain a running counter variable for each iteration of the loop. We will use this in conjunction with GetValue. This lets us obtain a contact ID during each iteration, without needing to modify the original list:&lt;/p&gt;
&lt;pre&gt;Set Variable [ $LetterContents ; Home::Letter Contents ]&lt;br&gt;Set Variable [ $ContactIDs ; List ( Home to Contacts::Contact ID ) ]&lt;br&gt;Set Variable [ $Total ; ValueCount ( $ContactIDs ) ]&lt;br&gt;Set Variable [ $Counter ; 1 ]&lt;br&gt;Go to Layout [ &quot;Letters&quot; (Letters) ]&lt;br&gt;Loop&lt;br&gt;  New Record/Request&lt;br&gt;  Set Field [ Letters::Letter Contents ; $LetterContents ]&lt;br&gt;  Set Field [ Letters::ContactID ; GetValue ( $ContactIDs ; $Counter ) ]&lt;br&gt;  Set Variable [ $Counter ; $Counter + 1 ]&lt;br&gt;  Exit Loop If [ $Counter &amp;gt; $Total ]&lt;br&gt;End Loop&lt;/pre&gt;
&lt;p&gt;This method has eliminated the need for the RightValues function call, and instead requires one GetValue function call per iteration of the loop.&lt;/p&gt;
&lt;p&gt;One thing I noticed in building this particular loop was that during each iteration, I was carrying out two &quot;Set Field&quot; operations - one to set the Contact ID, and one the letter itself. This means that if we generate 20,000 records, then there are 40,000 set field operations. Is there another way to set field contents en-mass? Why yes there is...&lt;/p&gt;
&lt;h4&gt;Method #4: Replacing&lt;/h4&gt;
&lt;p&gt;The premise behind this method is as follows - we generate all the letter records using a standard loop as we have seen in the above methods, however we don&#039;t set any field values during this loop. Once all records are generated, we then run two &quot;Replace Field Contents&quot; steps across the found set, one to set contact IDs, and the other to set letter contents.&lt;/p&gt;
&lt;p&gt;The question is - are two replace field content steps faster than X &quot;set field&quot; steps - where X is 2-times the # of records generated?&lt;/p&gt;
&lt;pre&gt;Set Variable [ $LetterContents ; Home::Letter Contents ]&lt;br&gt;Set Variable [ $ContactIDs ; List ( Home to Contacts::Contact ID ) ]&lt;br&gt;Set Variable [ $Total ; ValueCount ( $ContactIDs ) ]&lt;br&gt;Set Variable [ $Counter ; 1 ]&lt;br&gt;Go to Layout [ &quot;Letters&quot; (Letters) ]&lt;br&gt;Show All Records&lt;br&gt;Show Omitted Only&lt;br&gt;Loop&lt;br&gt;  New Record/Request&lt;br&gt;  Set Variable [ $Counter ; $Counter + 1 ]&lt;br&gt;  Exit Loop If [ $Counter &amp;gt; $Total ]&lt;br&gt;End Loop&lt;br&gt;Replace Field Contents [ No Dialog ; Letters::Contact ID ; GetValue ( $ContactIDs ; Get ( RecordNumber ) ]&lt;br&gt;Replace Field Contents [ No Dialog ; Letters::Letter Contents ; $LetterContents ]&lt;/pre&gt;
&lt;p&gt;Here you can see the loop creating essentially blank records. When done, the created records then have their fields populated. GetValue is used in conjunction with Get(RecordNumber) to populate Contact ID.&lt;/p&gt;
&lt;p&gt;When the replace happens, Get(RecordNumber) is evaluated from the context of each record, so when the 50th record is being replaced, Get(RecordNumber) will be 50, and so on.&lt;/p&gt;
&lt;p&gt;Note also that before looping we ensure the found set is empty so we don&#039;t interfere with other letter records when we do the replace.&lt;/p&gt;
&lt;h4&gt;Looping methods without actually looping at all...&lt;/h4&gt;
&lt;p&gt;Up until this point, all four looping methods have used Loop constructs - that being the Loop and End Loop script steps. We are traversing items, whether they be records, or values in a list.&lt;/p&gt;
&lt;p&gt;There is however another way in which records can be generated in a table without explicitly looping or using the New Record/Request script step, and that method is using an Import.&lt;/p&gt;
&lt;p&gt;The Import Records script step can be used to Import records from a file, such as a CSV, tab delimited etc. It can also be used to import from another FileMaker file. Even more specifically, it can be used to import from a different table within the same file, and it is this method we will be making use of.&lt;/p&gt;
&lt;h4&gt;So how do we create multiple records using Import?&lt;/h4&gt;
&lt;p&gt;The conventional idea behind an import is you start with X records in the source table, and after the import you now have X records in the destination table. In this situation however we don&#039;t have X records to begin with.&lt;/p&gt;
&lt;p&gt;The way in which we will create the letter records is to make use of a particular setting of the Import Records script step:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/thinkingoutsidetheloop-1.png&quot; alt=&quot;thinkingoutsidetheloop 1&quot; width=&quot;428&quot; height=&quot;293&quot;&gt;&lt;/p&gt;
&lt;p&gt;When importing values in a repeating field, you have the option to either keep them in one record, or Split them into separate records.&lt;/p&gt;
&lt;p&gt;So, if we have 20,000 contacts for example, if we can somehow get each contact ID into a repetition of a repeating field, and then import that repeating field choosing to split into separate records, we can effectively generate 20,000 letter records!&lt;/p&gt;
&lt;h4&gt;Method #5: Import Madness&lt;/h4&gt;
&lt;p&gt;And here it is:&lt;/p&gt;
&lt;pre&gt;Go to Layout [ &quot;Home&quot; (Home) ]&lt;br&gt;Show All Records&lt;br&gt;Omit Record&lt;br&gt;Show Omitted Only&lt;br&gt;Set Variable [ $$ContactIDs ; List ( Home to Contacts::Contact ID ) ]&lt;br&gt;Import Records [ No Dialog ; &quot;ThinkingOutsideTheLoop.fp7&quot; ; Add; Mac Roman ]&lt;/pre&gt;
&lt;p&gt;It&#039;s a little hard to deduce what is happening here so I&#039;ll explain. The first few steps are to ensure that we are in a found set of 1 records. This is to ensure that the import step generates the correct number of letter records. This is to do with how the import step works when dealing with repeating fields. If we have a repeating field of 20,000 repetitions, each with a contact ID in them, and we import from a found set of 1, we get 20,000 letter records. if however we had a found set of 2 records, we will get 20,000 letter records per record so in effect we end up with 40,000 letters! We always need to be on a found set of 1.&lt;/p&gt;
&lt;p&gt;The setting of the global variable $$ContactIDs is the way in which I am setting the repeating field which is part of the import, lets have a look at that repeating field:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600523-thinkingoutsidetheloop-2.png&quot; alt=&quot;thinkingoutsidetheloop 2&quot; width=&quot;600&quot; height=&quot;523&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is a live unstored calculation that is setting each repetition to a value in the list in $$ContactIDs. So if $$ContactIDs were to contain 20,000 values, then the first 20,000 repetitions in this calculation field will have values, any others will be blank.&lt;/p&gt;
&lt;p&gt;It is important here to note also that only repetitions with a value in them will be imported, and thus have a record generated for them.&lt;/p&gt;
&lt;p&gt;In the import record step itself, the repeating field is being mapped onto the Contact ID field in the Letters table, and the Letters contents is also mapped accordingly.&lt;/p&gt;
&lt;h4&gt;Some inefficiencies with this Import Method&lt;/h4&gt;
&lt;p&gt;The above method is great, it&#039;s simple, cuts down on the number of lines of code, and is quite reliable. However there is an inefficiency here. This is the fact that the repeating field we are using in the import is an unstored calculation. When the import is occurring, each repetition has to be evaluated, so in effect there are X calculations being evaluated, where X is the number of letters being created.&lt;/p&gt;
&lt;h4&gt;Some Testing and Results, What Do We Learn&lt;/h4&gt;
&lt;p&gt;Now would be a good time to look at the example file. In it, I have setup each of the 5 looping methods mentioned so far.&lt;/p&gt;
&lt;p&gt;Here, I present the average time to create 20,000 letters for each of the 5 methods presented. This first test is done on a local copy of the database.&lt;/p&gt;
&lt;p&gt;Layout Switching: 45 Seconds&lt;br&gt;Chopping a List: 72 Seconds&lt;br&gt;Counter Approach: 30 Seconds&lt;br&gt;Replacing: 31 Seconds&lt;br&gt;Import Madness: 32 Seconds&lt;/p&gt;
&lt;p&gt;The following test was done over a slow internet connection to a copy of the database hosted on FileMaker Server 11 Advanced. Due to internet connection speeds, I have reduced the number of records created in this test to 500 letters. It&#039;s not ideal using a reduced record set because this affects the interpreting of results, but I&#039;ll do my best:&lt;/p&gt;
&lt;p&gt;Layout Switching: 210 Seconds&lt;br&gt;Chopping a List: 209 Seconds&lt;br&gt;Counter Approach: 209 Seconds&lt;br&gt;Replacing: 313 Seconds&lt;br&gt;Import Madness: 110 Seconds&lt;/p&gt;
&lt;h4&gt;Interpreting the Results&lt;/h4&gt;
&lt;p&gt;First thing I notice is that times vary more significantly in the local test than the WAN test. My assumption here is that this is because of the different in letters generated, 20,000 compared to 500. In the local test, the main reason for the large differences comes down to the script steps themselves and the looping methods, not the actual process of creating the records. In the WAN test, fewer records means the overhead of the looping constructs becomes less, as indicated by the fairly consistent speeds for the first 3 methods. The overhead in this case is the method of record creation, and the number of calls between server and client required.&lt;/p&gt;
&lt;p&gt;Looking at the WAN results, the layout switching, chopping a list, and counter methods are all very similar in times, in fact, only a second separates them. This would indicate the overhead in these 3 cases is in the New Record/Request action. The methods of looping have little overhead. In fact if you think about it, layout switching, and list manipulation are all happening on the client-side anyway and there is no server interaction in this process. The only interaction with server is first obtaining the list, and then the committing of the new records back to server.&lt;/p&gt;
&lt;p&gt;The Replace method is an interesting one. Here in the WAN test, it is by far the slowest, and if you think about it this kind of makes sense. If we keep the assumption that the overhead here is in server/client calls, or more specifically the setting and getting of data between the two, then this method has 3 explicit send/get operations compared to 1 with the rest. The first is the loop to generate the records. The second and third are the two replace field contents script steps. There are three separate sends of data to the server as opposed to one for the rest.&lt;/p&gt;
&lt;p&gt;Finally is the import method which has proven to be the fastest of all. The calculation that determines the repetition values is done on client once the contact IDs have been set into the global variable $$ContactIDs. So the overhead here is again the creation of records via the import.&lt;/p&gt;
&lt;p&gt;I can only deduce that record creation via import is more efficient than a loop, perhaps it reduces on the number of packets sent back and forth between server and client, I&#039;m not sure, but compared to looping methods, the import method proved significantly faster in WAN testing, and in local copy testing the difference in speed was negligible compared to that of looping methods.&lt;/p&gt;
&lt;h4&gt;And for the Local Copy Results...&lt;/h4&gt;
&lt;p&gt;As always with using more records, the results are going to be more distinctly different. If we tested a local copy with 500 records then the time difference between all methods is negligible to the point of under 1/100th of a second. It is only when using very large data sets do these differences present themselves, and the truly efficient methods present themselves.&lt;/p&gt;
&lt;h4&gt;So what does this all mean?&lt;/h4&gt;
&lt;p&gt;What this means for real world practices? Basically, if using a solution over WAN, you should probably look at using an import as a way to generate your records if you can as it is a more efficient method of record creation. If using a local copy, OR only generating a small set of records, then any looping method is probably OK, but if you want to use a truly efficient method, either the import, or a counter looping method would be advised.&lt;/p&gt;
&lt;h4&gt;Added Bonus: Looking for the Ultimate Speed&lt;/h4&gt;
&lt;p&gt;Looking at the results shown above, the import method is fastest over WAN, but the Counter approach is fastest over local copy (and with large record sets). Is there a way to combine these two approaches to produce an even faster method?&lt;/p&gt;
&lt;h4&gt;Lets compare a loop vs import for simple record creation&lt;/h4&gt;
&lt;p&gt;For this test, I am using a local copy of the database and 20,000 records to generate. The goal is to compare the speeds of a simple loop, with that of a simple import to generate records.&lt;/p&gt;
&lt;p&gt;The first thing I did was to create a very simple loop to generate 20,000 blank records:&lt;/p&gt;
&lt;pre&gt;Set Variable [ $Counter ; 1 ]&lt;br&gt;Loop&lt;br&gt;  New Record/Request&lt;br&gt;  Set Variable [ $Counter ; $Counter + 1 ]&lt;br&gt;  Exit Loop If [ $Counter &amp;gt; 20000 ]&lt;br&gt;End Loop&lt;/pre&gt;
&lt;p&gt;The second method is a single import records script step. Note that to create the 20,000 records I am using a Stored repeating field with values 1 thru 20,000 in the repetitions.&lt;/p&gt;
&lt;pre&gt;Import Records [ No Dialog ; &quot;ThinkingOutsideTheLoop.fp7&quot; ; Add; Mac Roman]&lt;/pre&gt;
&lt;p&gt;Simple Loop: 12 Seconds&lt;br&gt;Simple Import: 3 Seconds&lt;/p&gt;
&lt;p&gt;That&#039;s a whole 4x faster to create 20,000 records using an import as opposed to the simplest loop possible.&lt;/p&gt;
&lt;p&gt;So, the import is clearly the best way to create the records that was already known, but why is this method so much faster than the loop? The key here is that our repeating field is Stored.&lt;/p&gt;
&lt;p&gt;Recall the original Method #5 was using an unstored calculation as the repeating field, so there was overhead involved in calculating each repetition. What if we instead used a loop to set the Contact IDs into a stored repeating field, instead of having them unstored?&lt;/p&gt;
&lt;h4&gt;Method #6: The Need for Speed&lt;/h4&gt;
&lt;p&gt;This method uses a simple loop to set each repetition of a stored repeating field. The repeating field is then used in an import records script step to generate the records.&lt;/p&gt;
&lt;p&gt;The hope is that this combines the best of both methods. We are hoping a loop to set 20,000 repetitions will have less overhead than the evaluation of 20,000 unstored calculations.&lt;/p&gt;
&lt;p&gt;We also hope then that the import of a stored repeating field is faster than a loop of 20,000 record creations (we already know this to be true from the earlier test).&lt;/p&gt;
&lt;p&gt;So, here we go!&lt;/p&gt;
&lt;pre&gt;Set Variable [ $LetterContents ; Home::Letter Contents ]&lt;br&gt;Set Variable [ $Counter ; 1 ]&lt;br&gt;Set Variable [ $ContactIDs ; List ( Home to Contacts::Contact ID ) ]&lt;br&gt;Set Variable [ $Total ; ValueCount ( $ContactIDs ) ]&lt;br&gt;Loop&lt;br&gt;  Set Field [ Home::ContactIDs_Stored[$Counter] ; GetValue ( $ContactIDs ; $Counter ) ]&lt;br&gt;  Set Variable [ $Counter ; $Counter + 1 ]&lt;br&gt;  Exit Loop If [ $Counter &amp;gt; $Total ]&lt;br&gt;End Loop&lt;br&gt;Commit Records/Requests [ Skip data entry validation; No Dialog ]&lt;br&gt;Import Records [ No Dialog; ThinkingOutsideTheLoop.fp7; Add; Mac Roman ]&lt;/pre&gt;
&lt;p&gt;The Need For Speed: 22 Seconds&lt;/p&gt;
&lt;p&gt;That&#039;s a whole 10 seconds faster than the earlier Import method which used an unstored repeating field. Not too shabby!&lt;/p&gt;
&lt;p&gt;Again, overhead comes with the loop when dealing with a local copy. So when dealing with small record counts over WAN you may notice no difference between the two import methods. The difference is achieved when working with large record counts.&lt;/p&gt;
&lt;h4&gt;Limitations using the Import Method&lt;/h4&gt;
&lt;p&gt;While the import methods may be more efficient for creating records, they do have some limitations from other aspects. For starters, you are using a repeating field, and repeating fields have a limit to the number of repetitions they can hold - 32,000. So you are limited to 32,000 records created at any one time. You can of course modify your import script to be contained within a loop which itself loops for each block of 32,000 records if you need to generate more.&lt;/p&gt;
&lt;p&gt;The other limitation to this is that while the records are being generated you have no way of keeping track of what number of records have been created. All you will see is an import dialog which says it is importing 1 record (which technically it is, but it is splitting it into many records).&lt;/p&gt;
&lt;p&gt;One good thing about using a scripted loop is that during each iteration of the loop you can know exactly what point you are up to, so you can do things such as progress dialogs or visual cues as to progress.&lt;/p&gt;
&lt;h4&gt;Final Thoughts...&lt;/h4&gt;
&lt;p&gt;Hopefully this article has presented some alternate styles of record creation and looping you may not have thought to use.&lt;/p&gt;
&lt;p&gt;While some are more efficient than others, the performance gain depends on a number of factors such as your connection method to the database, internet speed, number of records being created and so on. So don&#039;t feel bad if you are using a looping method that may be slower than another, that difference in speed may be unnoticeable.&lt;/p&gt;
&lt;p&gt;I am very keen to hear of other people&#039;s looping methods, or whether you can take the example file and expand on it, or come up with other faster ways. Some things to explore may be:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;&lt;li&gt;SQL Creation of records&lt;/li&gt;
&lt;li&gt;Exporting to CSV/Tab and Importing back in&lt;/li&gt;
&lt;li&gt;Alternate methods of setting the repeating field, faster calculations&lt;/li&gt;
&lt;li&gt;Ways of optimizing scripted loops&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;If you have any feedback or suggestions please leave a comment, or get in touch directly via e-mail. I&#039;ll do my best to add them to the article.&lt;/p&gt;
&lt;h4&gt;=======================================&lt;/h4&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h4&gt;EXTRA! Reader feedback and New Looping Suggestions&lt;/h4&gt;
&lt;p&gt;Thank you to everyone for your feedback, with it has come a couple of new methods of record creation. I actually feel a little silly at this point because one of them now appears so glaringly obvious I wonder why I completely omitted it, so much for thinking outside the loop as it were :)&lt;/p&gt;
&lt;h4&gt;Method #7 - Contact Import&lt;/h4&gt;
&lt;p&gt;Instead of putting all of your contact IDs into a repeating field, why not just go direct to the contact records and import them into letters, why not indeed! In fact I even made mention to the fact that FileMaker can import from one table to another, yet seemed to glance over that aspect :)&lt;/p&gt;
&lt;p&gt;So, to do this I have put a global field into the contacts table to store the letter contents for purpose of the import. Then, a Go to Related Record step is used to put the user on the contact records, the import is done, and that is that:&lt;/p&gt;
&lt;pre&gt;Set Field [ Contacts::zg Letter Contents ; Home::Letter Contents ]&lt;br&gt;Go to Related Records [ Show only related records; From table: &quot;Home to Contacts&quot; ; Using layout: &quot;Contacts&quot; (Contacts); New window]&lt;br&gt;Import records [ No Dialog; &quot;ThinkingOutsideTheLoopExtra.fp7&quot;; Add; Mac Roman ]&lt;br&gt;Close Window [ Current Window ]&lt;/pre&gt;
&lt;p&gt;Turns out, this method is by far the fastest method tested so far, there is no processing of repeating field required, and no looping, it is just a pure import. Testing with 20,000 records on a local copy took an average of 8 seconds, a full 14 seconds faster than my &quot;need for speed&quot; method :)&lt;/p&gt;
&lt;h4&gt;Method #8 - Auto Enter&lt;/h4&gt;
&lt;p&gt;This method makes use of field-level auto-enter calculations to populate the contact ID and letter contents of letter records. The key involves the fact that local variables exist for the duration of a script, and that applies to records created during the processing of the script, thus auto-enter calculations can reference those local variables.&lt;/p&gt;
&lt;p&gt;The script itself appears as a basic loop:&lt;/p&gt;
&lt;pre&gt;Set Variable [ $LetterContents ; Home::Letter Contents ]&lt;br&gt;Set Variable [ $ContactIDs ; List ( Home to Contacts::Contact IDs ) ]&lt;br&gt;Set Variable [ $Counter ; 1 ]&lt;br&gt;Set Variable [ $Total ; ValueCount ( $ContactIDs ) ]&lt;br&gt;Go to Layout [ &quot;Letters&quot; (Letters) ]&lt;br&gt;Loop&lt;br&gt;  New Record/Request&lt;br&gt;  Exit Loop If [ Let ( $Counter = $Counter + 1 ; $Counter &amp;gt; $Total ]&lt;br&gt;End Loop&lt;/pre&gt;
&lt;p&gt;From the scripts perspective contact ID and Letter contents are not set, but they are in fact being set via the auto-enter calculations, each of which are set to $LetterContents and $ContactIDs respectively.&lt;/p&gt;
&lt;p&gt;Testing of this method has shown that it takes around 22 seconds to generate the 20,000 records on a local copy, so comparable with need for speed method 6, but nowhere near as fast as method #7.&lt;/p&gt;
&lt;h4&gt;Revised Conclusion&lt;/h4&gt;
&lt;p&gt;If you are able to generate your records by importing direct form a found set of records in another table then you should definitely look at doing that as it is the fastest method. There is no overhead in looping, setting a repeating field and so on.&lt;/p&gt;
&lt;p&gt;However that is not to discredit the repeating field import method which still has its place. This would be a good method to use if you had to set many fields on the new records from globals, or if you don&#039;t have the ability to go to a found set of records. Perhaps you are not specifying contacts, but instead you have an arbitrary list of items that need to be turned into records, in this case there is no found set available so your options are a loop or an import.&lt;/p&gt;
&lt;p&gt;Thank you to those who contributed to this extra section!&lt;/p&gt;
&lt;h4&gt;Example Files&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/thinkingoutsidetheloop/ThinkingOutsideTheLoop.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This next example file contains methods 7 and 8 that were added after the article was published, thank you to Mike and Stephen for contributing these two methods.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/thinkingoutsidetheloop/ThinkingOutsideTheLoopExtra.zip&quot;&gt;Download Extra Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Thu, 03 Mar 2011 13:58:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/thinking-outside-the-loop/</guid>
		</item>
		
		<item>
			<title>A Lightweight Cross-Tabular Data Entry Method</title>
			<link>https://www.teamdf.com/blogs/a-lightweight-cross-tabular-data-entry-method/</link>
			<description>&lt;p&gt;One of the shortcomings of FileMaker is its inability achieve easy cross-tabular reports and data entry in a normalized structure. There are various techniques to replicate cross-tabular interfaces, but they often involve many relationships for either the columns/rows, or are for display only. The goal of this article is to present a lightweight method for cross-tabular data entry using as few relationships &amp;amp; fields as possible.&lt;/p&gt;
&lt;h4&gt;Disclaimer:&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;My apologies for the length of this article. To try and make this as easy to follow as possible I have tried to make it as clear as possible, and have tried to explain every step of the process with pictures. As a result, it turned into a bit of a monster :) Hopefully you don&#039;t switch off half way through - if you do, book mark it and come back later, or you can skip to the example file and just get stuck in :) - Daniel&lt;/p&gt;
&lt;h4&gt;What is Cross Tabulation?&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;Displaying data in a cross-tabular format basically means representing data in a grid 2-dimensional format. Think of a spreadsheet with rows and columns. Each cell is defined by a row number and a column number&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/crosstab-1.png&quot; alt=&quot;crosstab 1&quot; width=&quot;548&quot; height=&quot;368&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the image above, the rows are defined by the people, and columns are numbered 1 through 7. Each cell is a piece of information.&lt;/p&gt;
&lt;h4&gt;What is the Ideal Underlying FileMaker Structure?&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;The underlying format ideally should be a normalized structure of tables &amp;amp; records with 1 record per &quot;cell&quot;. This is why cross-tab in FileMaker is so difficult - we can easily display the vertical component of a cross-tab with a portal, but the horizontal component is the hard part. FileMaker has no horizontal portals, and so to display the columns one must resort to other methods...&lt;/p&gt;
&lt;h4&gt;Other Structures That Should be Avoided&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;I have seen cross-tab been done in the past where the columns are done as repeating fields, or even individual fields. Consider a grid of 10x10. The 10 rows are done with 10 records in a list or portal which is fine. For the 10 columns, a repeating field may be built with 10 repetitions, or even 10 individual fields added to the table responsible for the rows.&lt;/p&gt;
&lt;p&gt;This is a huge no no! Repeating fields should never be used for storing actual data in this manner, it will only lead to nightmares, cold sweats, and post repeating-field trauma in later life. Repeating fields are not good normalization structure for any database.&lt;/p&gt;
&lt;h4&gt;The Solution - use Repeating Fields&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;Okay, you may be scratching your head at this stage. &quot;Didn&#039;t you just tell me NOT to use a repeating field? Won&#039;t I have nightmares if I do?&quot; Well, yes you will, but only if you use them for Data Entry&lt;/p&gt;
&lt;p&gt;Repeating fields are perfectly fine to use as an interface tool for displaying data, or as a means to manipulate data, just so long as they are not the source of that data! I love the repeating field so much in fact that I try to talk about them any chance I get, much to the chagrin of my colleagues :)&lt;/p&gt;
&lt;p&gt;The rest of this article is going to show a method of using repeating fields to achieve a nice cross-tab data entry portal, in fact the same portal you saw at the beginning of this article.&lt;/p&gt;
&lt;h4&gt;Setting the Scene for What We Want to Achieve&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;Lets have a look at what the end result should be:&lt;/p&gt;
&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/_resampled/ResizedImage544371-crosstab-2.png&quot; alt=&quot;crosstab 2&quot; width=&quot;544&quot; height=&quot;371&quot;&gt;&lt;/p&gt;
&lt;p&gt;Each cell here is to be a record containing its piece of information. In this example we have 2 tables:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Parent - This is what constitutes each row, 1 parent record per row&lt;/li&gt;
&lt;li&gt;Child - Each child record is a cell in a column.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;One parent record has 7 children records, and we can assume this is established at the point the parent record is created. Children are categorized as 1 thru 7, so for any given parent we know it will have 7 children numbered 1 thru 7.&lt;/p&gt;
&lt;p&gt;To begin, we can build a portal whose context is based on a parent table occurrence, this gives the following:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/_resampled/ResizedImage600132-crosstab-3.png&quot; alt=&quot;crosstab 3&quot; width=&quot;600&quot; height=&quot;132&quot;&gt;&lt;/p&gt;
&lt;p&gt;We know that each row has 7 associated children record that will need to have their value shown as columns. How can this be done?&lt;/p&gt;
&lt;h4&gt;A Common Method of Relationships &amp;amp; Fields&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;As mentioned in the abstract, one method of cross-tab production is to construct a series of relationships to each specific record for the purpose of showing it in the portal. This method is works fine when the number of child records is known, but one of its downfalls is the large number of relationships required, and the fields required to build those relationships.&lt;/p&gt;
&lt;p&gt;Have a look at how this might look if we were to pursue this method:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/crosstab-4.png&quot; alt=&quot;crosstab 4&quot; width=&quot;584&quot; height=&quot;252&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this graph you can see our home context, and the table occurrence for the parent that is showing Parent records. Related to the portal table occurrence is 7 individual child relationships, each one to a different one of the 7 children.&lt;/p&gt;
&lt;p&gt;In order to establish a relationship to each specific and unique child record, 7 fields are required, each containing a unique identifier which lets the parent record relate to each child individually:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/crosstab-5.png&quot; alt=&quot;crosstab 5&quot; width=&quot;345&quot; height=&quot;118&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is an awful lot of management required to build your cross-tab. Think of a cross-tab with 50 or 60 columns, can you imagine what the graph is going to look like, let alone the parent table with all of these interface fields!&lt;/p&gt;
&lt;h4&gt;Back to Repeating Fields as the Solution&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;If only we could just stick a repeating field in the portal and be done with it. This would give us a nice cross-tab appearance, as repeating fields can easily be shown horizontally. If the number of columns ever changed, then it would simply be a case of extending the # of repetitions and widening the portal, simple stuff.&lt;/p&gt;
&lt;p&gt;Here&#039;s how we will do it....&lt;/p&gt;
&lt;h4&gt;Get ( ActiveRepetitionNumber ) &amp;amp; GetNthRecord&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;Two of FileMakers most awesomest functions. The GetNthRecord function allows us to obtain field contents from any field of any specific record through a relationship. The Get ( ActiveRepetitionNumber ) Allows us to know at any point in time what repetition number of a repeating field the user is in. More on these two functions later.&lt;/p&gt;
&lt;h4&gt;Step One: Get the children record data displaying in the portal&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;The first step to this method involves being able to display values from the 7 children records in the portal using a repeating field. If we can at least display the data, then this will give us a good platform for modifying that data.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/_resampled/ResizedImage600473-crosstab-6.png&quot; alt=&quot;crosstab 6&quot; width=&quot;600&quot; height=&quot;473&quot;&gt;&lt;/p&gt;
&lt;p&gt;We have added the repeating field to the Parent table as shown above, and given it 7 repetitions, 1 per child record. This is a calculation field so live child record information can be displayed. The calculation is:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/crosstab-7.png&quot; alt=&quot;crosstab 7&quot; width=&quot;378&quot; height=&quot;154&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here you can see both the GetNthRecord and Get(CalculationRepetitionNumber) functions being used. GetNthRecord allows us to obtain a specific records value, and the record for which it is obtained is dependent upon the repetition in which each calculation is evaluated. As an example, for the 5th repetition of the field, Get(CalculationRepetitionNumber) will return 5. When this is used in conjunction with GetNthRecord, the value in record # 5 is returned.&lt;/p&gt;
&lt;p&gt;Note that the extend function is required when referencing non-repeating fields in a repeating field calculation.&lt;/p&gt;
&lt;h4&gt;What we end up with:&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;The image below shows what we end up with when we put this display repeating field in the portal:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/crosstab-8.png&quot; alt=&quot;crosstab 8&quot; width=&quot;532&quot; height=&quot;147&quot;&gt;&lt;/p&gt;
&lt;p&gt;Look familiar? (It should, I&#039;ve shown it 3 times now!) What we end up with is a pretty looking cross-tabular display of our data. Great. If we merely want to show this children information then we might as well stop here because we are done. But this is only half the story. We now need to be able to allow editing of these values within the cross-tab structure, and have the underlying children records be updated, and this is where things get interesting:&lt;/p&gt;
&lt;h4&gt;Step Two: Building a Repeating Field we can Modify&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;The problem with the current repeating field is that it is a calculation for display only, and we cannot modify the contents of a calculation. Instead, we require another repeating field that is not a calculation, so that we can enter values into it.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/_resampled/ResizedImage600177-crosstab-10.png&quot; alt=&quot;crosstab 10&quot; width=&quot;600&quot; height=&quot;177&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/crosstab-9.png&quot; alt=&quot;crosstab 9&quot; width=&quot;583&quot; height=&quot;466&quot;&gt;&lt;/p&gt;
&lt;p&gt;The first image shows the new repeating field for data entry in the Parent table. The second image shows how both repeating fields are positioned within the portal. Note that the display field is placed on top of the entry field and has a fill color so that the entry field is completely hidden from the users view. I have highlighted the entry field in green purely so you can see it.&lt;/p&gt;
&lt;p&gt;Note also that entry into the display repeating field is disabled. This has the effect as such that when the user clicks onto it, they are in fact entering the data entry field underneath.&lt;/p&gt;
&lt;h4&gt;Step Three: Display value when clicking into entry field&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;Currently, if the user were to click into a data entry repetition, they would get a blank box, and it would appear that the value has disappeared. Instead, we wish for the value they see prior to entering a cell (the display value) remains upon clicking into the data entry repetition.&lt;/p&gt;
&lt;p&gt;We will achieve this with the use of an onObjectEnter script trigger attached to the data entry repeating field:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/crosstab-11.png&quot; alt=&quot;crosstab 11&quot; width=&quot;468&quot; height=&quot;461&quot;&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/_resampled/ResizedImage600492-crosstab-12.png&quot; alt=&quot;crosstab 12&quot; width=&quot;600&quot; height=&quot;492&quot;&gt;&lt;/p&gt;
&lt;p&gt;When the user clicks into any given repeating field, we want the associated display value to show in the entry field. The first line of the script achieves this:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/crosstab-13.png&quot; alt=&quot;crosstab 13&quot; width=&quot;280&quot; height=&quot;59&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here you can see the field and repetition to be set. We are setting our data entry field, and the repetition being set is the one we have just clicked our mouse into - which can be obtained using the Get ( ActiveRepetitionNumber ) function.&lt;/p&gt;
&lt;p&gt;The value that we will set into this repetition, is the value in the corresponding repetition of the display calculation.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/crosstab-14.png&quot; alt=&quot;crosstab 14&quot; width=&quot;374&quot; height=&quot;180&quot;&gt;&lt;/p&gt;
&lt;p&gt;Still awake over there? Yes? Good! The end result of the above is that when the user clicks into a repetition, they see exactly what they saw prior to clicking. In fact, the data entry field now contains the value that is in the corresponding child record. The user is now able to type freely and modify this value to whatever they want.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/_resampled/ResizedImage600511-crosstab-15.png&quot; alt=&quot;crosstab 15&quot; width=&quot;600&quot; height=&quot;511&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Step Four: Exiting the Field &amp;amp; Updating the Child Record&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;The user has now entered the cell, modified the value in it, and is ready to exit out of the field. When they do this, we are going to need to update the associated child record with the new value. Remember that each repeating field corresponds to a specific child record.&lt;/p&gt;
&lt;p&gt;While obtaining a specific records value using GetNthRecord was easy, going back the other way is not quite as easy. There is no SetNthRecord function, nor is there a script step to set a specific record in a relationship. So in order to achieve this we employ some other smarts.&lt;/p&gt;
&lt;p&gt;GetNthRecord is able to obtain the value of any field from any related record. Well, we know what record we are dealing with when the user is in the data entry field, because we obtained the value put into that field in the first place, right? So why don&#039;t we grab that child records primary key value while we&#039;re at it. That way, we can establish a relationship &quot;on the fly&quot; to that specific record as a means to update it? Make sense? No? Keep reading...&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/_resampled/ResizedImage600283-crosstab-16.png&quot; alt=&quot;crosstab 16&quot; width=&quot;600&quot; height=&quot;283&quot;&gt;&lt;/p&gt;
&lt;p&gt;Two new fields have been added to the Parent table. The first of these is &quot;Active Child ID&quot;. This is a live unstored calculation that at any point in time contains the child ID (primary key) of the child record that the user currently thinks they are modifying in the cross-tab interface. It&#039;s calculation is very similar to that of the Display repeating field calcualtion, but instead of returning the child records value, it returns its primary key instead:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/crosstab-17.png&quot; alt=&quot;crosstab 17&quot; width=&quot;556&quot; height=&quot;432&quot;&gt;&lt;/p&gt;
&lt;h4&gt;The purpose of zRelationship Refresh Field&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;You may have seen this field lurking in some of the earlier screenshots. The main purpose behind this field is to force a refresh of the relationship between the Active Child ID field, and its associated child record. The Associated Child ID field is an unstored calculation, which doesn&#039;t reference any field on the Parent table. Because of this, when it is used in a relationship, the relationship is unaware of any change to the calculations contents, and thus the relationship does not re-evaluate.&lt;/p&gt;
&lt;p&gt;You may have read an earlier article describing this exact issue, and the proposed solution was to use a Cartesian-Join in the relationship as a means to force the refresh. This is exactly what is being used here, and is the purpose of this refresh field. &lt;a href=&quot;http://www.digitalfusion.co.nz/weetbicks/ditch-those-flush-caches-use-cartesian-join-instead/42/&quot;&gt;You can read that article here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When the user clicks into the data entry repetition, the last step of the script is to set our refresh field to 1, this forces a refresh of the relationship to that specific child record. Now it is correctly established, when the user leaves the entry field, we can very quickly and painlessly set the new value into that child record.&lt;/p&gt;
&lt;p&gt;Here is script that is run upon onObjectExit of the repeating field via script trigger:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/_resampled/ResizedImage600485-crosstab-18.png&quot; alt=&quot;crosstab 18&quot; width=&quot;600&quot; height=&quot;485&quot;&gt;&lt;/p&gt;
&lt;p&gt;We have a direct relationship to the child record to update:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/_resampled/ResizedImage60055-crosstab-19.png&quot; alt=&quot;crosstab 19&quot; width=&quot;600&quot; height=&quot;55&quot;&gt;&lt;/p&gt;
&lt;p&gt;And we set it to current field contents:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Cross-Tabular/_resampled/ResizedImage600576-crosstab-20.png&quot; alt=&quot;crosstab 20&quot; width=&quot;600&quot; height=&quot;576&quot;&gt;&lt;/p&gt;
&lt;p&gt;Below you can see the relationship from the portal context to the child record that is being updated.&lt;/p&gt;
&lt;p&gt;(Image)&lt;/p&gt;
&lt;p&gt;And these are the two predicates in that relationship - the first is the direct relationship to the child being updated. The second is to force the refresh of this relationship&lt;/p&gt;
&lt;p&gt;(Image)&lt;/p&gt;
&lt;p&gt;Finally, you will note that the last script step is to clear the data entry field. This is because once the user leaves the data entry field, there is no need for it to contain a value, in fact if we kept the values in there, then the size of the database would get large over time. To avoid this, we clear the data entry field contents. If the user ever does click back into that field, it gets set again anyway so no harm done.&lt;/p&gt;
&lt;h4&gt;To put it all in Summary&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;Step One: Display the live data in display repeating field&lt;br&gt;Step Two: Build the data entry repeating field&lt;br&gt;Step Three: Script triggers to set data entry field contents&lt;br&gt;Step Four: Update record upon exiting field &amp;amp; tidy up after yourself.&lt;/p&gt;
&lt;p&gt;The overall expense in terms of relationships &amp;amp; fields required is:&lt;/p&gt;
&lt;p&gt;1x Portal&lt;br&gt;1x Relationship to single child record being updated&lt;br&gt;2x Repeating fields, 1 display, 1 data entry&lt;br&gt;1x refresh field (this could be worked around using scripting if you wish)&lt;br&gt;1x current Child ID field for updating child record via relationship&lt;br&gt;2x scripts onObjectEnter and onObjectExit&lt;/p&gt;
&lt;p&gt;Overall I think the expense is pretty small for a 7 column cross-tab. using the other method would have required 7x relationships and 7x fields so this method already has that method beat in terms of cost.&lt;/p&gt;
&lt;p&gt;But the best feature of this method is the ease at which it can be scaled. Once all of the basic components are in place, adding extra columns is a case of adding repeating fields to your data entry &amp;amp; display fields.&lt;/p&gt;
&lt;p&gt;If the child records don&#039;t exist initially, then you can modify your onObjectEnter script to test for this via the relationship, and if no child record exists you can create it - it&#039;s all good!&lt;/p&gt;
&lt;h4&gt;Final Thoughts:&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;If you are still here reading this then well done! Give yourself a pat on the back! This was tough one to write and while I&#039;m sure if I spent a bit more time on it I could have cut down the size of the article, hopefully it wasn&#039;t too much of a mission to get through it :) Thanks!&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;&lt;br&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/slimcrosstab/CrossTabEntry.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 21 Feb 2011 21:20:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/a-lightweight-cross-tabular-data-entry-method/</guid>
		</item>
		
		<item>
			<title>Hide Custom Menu Elements Dynamically</title>
			<link>https://www.teamdf.com/blogs/hide-custom-menu-elements-dynamically/</link>
			<description>&lt;p&gt;When FileMaker 11 was released, one of the lesser documented changes in behavior concerned the defining of menu names when dealing with Custom Menus. When any menu element has an empty name, an interesting thing happens:&lt;/p&gt;
&lt;h4&gt;So, tell me what happens already!&lt;/h4&gt;
&lt;p&gt;Well, when an item has no name, the item disappears entirely from the custom menu, and from any custom menu it may appear in. Why is this so significant you ask?&lt;/p&gt;
&lt;p&gt;Well for starters, this was not the behavior in FileMaker 10. In 10, any menu item with no name would still appear in the list as an item with no name (funny that).&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60018-menuhiding-1.png&quot; alt=&quot;menuhiding 1&quot; width=&quot;600&quot; height=&quot;18&quot;&gt;&lt;/p&gt;
&lt;p&gt;Have a look at the custom menu set above. There is a menu in this which has no name, can you see it?&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/menuhiding-2.png&quot; alt=&quot;menuhiding 2&quot; width=&quot;188&quot; height=&quot;74&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here it is, did you find it? Well done! Ahem, so anyway, as you can see the menu is still there and still selectable.&lt;/p&gt;
&lt;p&gt;Now lets see what happens when the same custom menu is viewed in FileMaker 11:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60020-menuhiding-3.png&quot; alt=&quot;menuhiding 3&quot; width=&quot;600&quot; height=&quot;20&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can now see, the menu is entirely gone in 11, it cannot be selected at all.&lt;/p&gt;
&lt;h4&gt;What does FileMaker say about it?&lt;/h4&gt;
&lt;p&gt;After having a rummage through the FileMaker 11 documentation of new features, I could only find the following mention &lt;a href=&quot;http://help.filemaker.com/app/answers/detail/a_id/7593/~/custom-menu-user-interface-improvements&quot;&gt;here:&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;Users can no longer remove the item title and action checkboxes dynamically when the menu item is not based on a command. This means that it is possible to have a menu item have no item name or action.&lt;/blockquote&gt;
&lt;p&gt;I don&#039;t really understand the first part, but the last sentence would indicate that they acknowledge the lack of menu item name as a change.&lt;/p&gt;
&lt;h4&gt;Oh, the possibilities!&lt;/h4&gt;
&lt;p&gt;The potential to make use of this feature is limited only by your imagination. This is because menus and commands that are used in custom menus can have their name defined via calculation.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60018-menuhiding-4.png&quot; alt=&quot;menuhiding 4&quot; width=&quot;600&quot; height=&quot;18&quot;&gt;&lt;/p&gt;
&lt;p&gt;Have a look at the custom menu above. The Giraffe menu actually has its name defined in a global field in the solution, and the menu name is derived from that global:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/menuhiding-5.png&quot; alt=&quot;menuhiding 5&quot; width=&quot;410&quot; height=&quot;31&quot;&gt;&lt;/p&gt;
&lt;p&gt;So, whatever I enter into the global field is what the menu name is. If I remove the contents of the global entirely, the menu will disappear as it will no longer have a name.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/menuhiding-6.png&quot; alt=&quot;menuhiding 6&quot; width=&quot;321&quot; height=&quot;31&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Hiding Parts of Menus&lt;/h4&gt;
&lt;p&gt;Basically any component of a custom menu can have its name defined via calculation. Consider the following example:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/menuhiding-7.png&quot; alt=&quot;menuhiding 7&quot; width=&quot;129&quot; height=&quot;73&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Giraffe menu contains both a command, and a sub-menu with further commands in it.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/menuhiding-8.png&quot; alt=&quot;menuhiding 8&quot; width=&quot;125&quot; height=&quot;55&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here, I have removed the Lion commands name using the same global method. The Lion command no longer exists within the Giraffe menu.&lt;/p&gt;
&lt;p&gt;Note:The Lion command has actually been removed from the Giraffe menu, and every other location it is used in the custom menu set, or any other custom menu set it is used in. The item either has a name or doesn&#039;t, and if it doesn&#039;t, it&#039;s gone everywhere.&lt;/p&gt;
&lt;p&gt;Now having said that, given you are able to define an item name via calculation, you can build a calculation that will give the menu item a name under certain circumstances for example: based on your privilege set, layout you are on, flags defined in fields, global variable contents, etc. It may not disappear everywhere depending on how you build your calculation.&lt;/p&gt;
&lt;h4&gt;Hiding Sub-Menus&lt;/h4&gt;
&lt;p&gt;A sub-menu is simply a menu that is used within another menu. When this is done, the sub-menu expands to reveal its menu items contained within it.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/menuhiding-9.png&quot; alt=&quot;menuhiding 9&quot; width=&quot;305&quot; height=&quot;195&quot;&gt;&lt;/p&gt;
&lt;p&gt;Again, sub-menus when defined can have their name set via calculation, after all, sub-menus are simply menus.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600432-menuhiding-10.png&quot; alt=&quot;menuhiding 10&quot; width=&quot;600&quot; height=&quot;432&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here I have the menu name in a global.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/menuhiding-11.png&quot; alt=&quot;menuhiding 11&quot; width=&quot;96&quot; height=&quot;57&quot;&gt;&lt;/p&gt;
&lt;h4&gt;A cautionary table about sub-menus&lt;/h4&gt;
&lt;p&gt;One thing to be aware of if trying to show or hide a sub-menu is the following option you are given when using a sub-menu:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/menuhiding-12.png&quot; alt=&quot;menuhiding 12&quot; width=&quot;490&quot; height=&quot;246&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here, I have defined a sub-menu Zebra. The Zebra menu has its name defined via calculation and the name of which is contained within a global field. Also, for this particular sub-menu definition, I have chosen to place it in the parent menu Elephant.&lt;/p&gt;
&lt;p&gt;Pay attention to the Override Default Behaviors option. Here I have specified an overriding title for the sub-menu. You may expect in this situation that the sub-menu should appear as &quot;MAXIMUM ZEBRA OVERDRIVE&quot; under all circumstances, for an override should replace any default name for the Zebra menu.&lt;/p&gt;
&lt;p&gt;This is not the case when the menus actual name is empty. In the case where the Zebra menu has no default name, the override is NOT applied, and the menu will still disappear.&lt;/p&gt;
&lt;p&gt;This is unfortunate because the override item name would have been the perfect convenient way to keep a sub-menu in one menu, and have it hide in others.&lt;/p&gt;
&lt;p&gt;When the Zebra menu does have a default name, the override will be applied.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/menuhiding-13.png&quot; alt=&quot;menuhiding 13&quot; width=&quot;290&quot; height=&quot;75&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Potential uses of this Feature&lt;/h4&gt;
&lt;p&gt;As mentioned earlier, the possibilities are endless. Here at Digital Fusion, we have used this feature in some of our custom solutions as a way to introduce a Developer menu into the solutions custom menus.&lt;/p&gt;
&lt;p&gt;Rather than create separate menu sets for developers and users, we just have a user series of menu sets. Within each menu set is a Developer menu, whose name is only defined if the logged in user is deemed to be a developer (we check the privilege set name, and the user record for verification).&lt;/p&gt;
&lt;p&gt;The end result is the developer menu appears for us, but not for regular users.&lt;/p&gt;
&lt;p&gt;This has saved a great amount of time because we didn&#039;t need to replicate all of the custom menus for us. It also means we can get the best of both worlds, when testing and debugging a solution, we can use the custom menus the user sees, and we can also have access to our own developer menu which contains useful debugging tools.&lt;/p&gt;
&lt;p&gt;I would love to hear of anyone else&#039;s ideas for using this feature.&lt;/p&gt;
&lt;h4&gt;Final Thoughts:&lt;/h4&gt;
&lt;p&gt;While this is a lesser documented feature of FileMaker 11 - to the point of barely being documented at all - I think it is one of the coolest features and one that has limitless applications.&lt;/p&gt;
&lt;p&gt;... Just be sure that you are building it for solutions that use FileMaker 11, otherwise you may not get the desired effect!&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/menuhiding/CustomMenuHiding.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Sat, 19 Feb 2011 12:07:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/hide-custom-menu-elements-dynamically/</guid>
		</item>
		
		<item>
			<title>Quick Tips: Commenting Your Value Lists</title>
			<link>https://www.teamdf.com/blogs/quick-tips-commenting-your-value-lists/</link>
			<description>&lt;p&gt;Pretty much everything in FileMaker comes with some form of comment box to let you add more information - such as fields, menus, custom functions, calculations, scripts, and the graph. However the one area lacking in a comment box is value lists, unless that is, you think a little outside of the box:&lt;/p&gt;
&lt;h4&gt;Where is the comment box?&lt;/h4&gt;
&lt;p&gt;If you are anything like me, then you are an obsessive commenter of anything and everything in FileMaker. So when it comes to value lists, the lack of a dedicated comment box is somewhat annoying. Fear not, FileMaker graciously gave us a large comment box, they just got the name wrong.&lt;/p&gt;
&lt;h4&gt;&quot;Custom Values&quot;&lt;/h4&gt;
&lt;p&gt;If you use &quot;custom values&quot; value lists often, then it&#039;s pretty obvious what they are for given you can see the values right in front of you.&lt;/p&gt;
&lt;p&gt;However sometimes a &quot;custom values&quot; list is simply not going to cut the mustard, especially when dealing with values from records, related data, conditional value lists and so on. So why not just use the custom values box as a comment box in this situation? Well fortunately you can.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/valuelistcomment-1.png&quot; alt=&quot;valuelistcomment 1&quot; width=&quot;571&quot; height=&quot;514&quot;&gt;&lt;/p&gt;
&lt;h4&gt;It&#039;s Easy&lt;/h4&gt;
&lt;p&gt;Just choose the &quot;Custom Values&quot; option, type in your comment, and set your value list option back to its original type. Your comment be left greyed out, but still clearly visible&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/valuelistcomment-2.png&quot; alt=&quot;valuelistcomment 2&quot; width=&quot;571&quot; height=&quot;514&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Final Thoughts;&lt;/h4&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/valuelistcomment-3.png&quot; alt=&quot;valuelistcomment 3&quot; width=&quot;264&quot; height=&quot;235&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Fri, 18 Feb 2011 21:38:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/quick-tips-commenting-your-value-lists/</guid>
		</item>
		
		<item>
			<title>Ditch those Flushes, Use Cartesian Join Instead!</title>
			<link>https://www.teamdf.com/blogs/ditch-those-flushes-use-cartesian-join-instead/</link>
			<description>&lt;p&gt;All too often, the Refresh Window script step is used with the &#039;Flush Cached Join Results&#039; option checked. Sometimes this is through lack of understanding, but other times it is required to refresh those pesky relationships which have trouble re-evaluating. This article explains why Flush Cache can be detrimental on performance, and offers an alternative and more efficient method for refreshing relationships...&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.digitalfusion.co.nz/news/weetbicks/ditch-those-flush-caches-use-cartesian-join-instead/42/&quot;&gt;Check out the full article here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 31 Jan 2011 11:58:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/ditch-those-flushes-use-cartesian-join-instead/</guid>
		</item>
		
		<item>
			<title>Ditch Those Flush Cashes, Use Cartesian Join Instead!</title>
			<link>https://www.teamdf.com/blogs/ditch-those-flush-caches-use-cartesian-join-instead/</link>
			<description>&lt;p&gt;All too often, the Refresh Window script step is used with the &#039;Flush Cached Join Results&#039; option checked. Sometimes this is through lack of understanding, but other times it is required to refresh those pesky relationships which have trouble re-evaluating. This article explains why Flush Cache can be detrimental on performance, and offers an alternative and more efficient method for refreshing relationships.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is Flushing Cached Join Results?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The FileMaker documentation describes this as the following:&lt;/p&gt;
&lt;blockquote&gt;Select Flush cached join results to delete the results of queries for related records and cause related records to be refreshed. Do not select this option if you know your script does not affect related data, and if you want to minimize the performance impact of re-accessing related data (particularly when sharing a database over a network).&lt;/blockquote&gt;
&lt;p&gt;Whenever a relationship is evaluated (the query) the related records found are cached (downloaded) to your computer. If you are accessing the database over LAN or WAN, then the speed at which this happens depends upon your connection speed. Once cached, the relationship should perform much faster because the records now reside on your machine.&lt;/p&gt;
&lt;p&gt;However, by flushing the cached join results, all results of relationships that have been done (i.e. all the records downloaded through relationships) are cleared from your cache, and you basically have to start all over again re-downloading related records when viewing them.&lt;/p&gt;
&lt;p&gt;The reason why FileMaker states this should be avoided over network, is because of this re-download factor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When is a Flush Cached Join Results needed?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Most of the time, a flush of the cached join results is not necessary at all, and typically it is used in error. People may think that because a calculation is not refreshing on their layout, it will require a refresh of the window to display correctly. While this may be true, all too often I have seen the &quot;Flush Cached Join Results&quot; option checked at the same time, merely for added insurance that the desired result will be achieved. Sometimes the performance hit is negligible so it goes unnoticed, but once the solution goes up on the network, that is when the real fun begins!&lt;/p&gt;
&lt;p&gt;Flushing of the Cached Join Results should really only be used when dealing with a particularly complex relationship whose results are not re-evaluating as desired.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What causes problematic relationships to not refresh?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I have found over the years that the most problematic relationships are those which make use of globals, and unstored calculations whose calculations reference related records. Sometimes it may be necessary to build these types of relationships to achieve a desired result (notably when using an interface/data model).&lt;/p&gt;
&lt;p&gt;The particular situations in which relationships have refresh issues always tends to elude me, but when it happens, the reasons are usually clear, and include one or more of the reasons above.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So, why not just flush the cached join results when it happens?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Well for starters, as mentioned earlier, &lt;strong&gt;every single downloaded record&lt;/strong&gt; that you have downloaded and cached since you first open a file, will be cleared. This basically means that you are starting from scratch since the file was opened, and any record you viewed will be re-downloaded.&lt;/p&gt;
&lt;p&gt;Over WAN this is where it is most noticed. When using a WAN hosted database, you may notice upon first use that portals and relationships may load slowly as the record is downloaded - scrolling portals may be slow, that sort of thing. But after more use, things speed up because the records are now being accessed from your cache. Flushing the cache puts you back to square 1.&lt;/p&gt;
&lt;p&gt;In 99% of the cases your intention for wanting to flush the cached join results is merely to refresh &lt;strong&gt;one particular relationship&lt;/strong&gt;, not the entire database. If only there was a way to do this...... well there is !&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution: Using a Cartesian Join in your Relationship&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The refresh problem arises because the relationship is unaware of its own need to refresh the results. The trick here is to tell the relationship that it should refresh itself.&lt;/p&gt;
&lt;p&gt;Relationships will re-evaluate themselves if one or more fields on the source side of the relationship change explicitly. However, we know that any field put on the source side of a relationship will actually affect the results of that relationship.&lt;/p&gt;
&lt;p&gt;The exception here is a cartesian join.&lt;/p&gt;
&lt;p&gt;Cartesian join predicates, by definition, find &lt;strong&gt;ALL&lt;/strong&gt; records through a relationship:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600576-cartesianrefresh-1.png&quot; alt=&quot;cartesianrefresh 1&quot; width=&quot;600&quot; height=&quot;576&quot;&gt;&lt;/p&gt;
&lt;p&gt;The above relationship uses a cartesian join, so will find all contact records through this relationship.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600576-cartesianrefresh-2.png&quot; alt=&quot;cartesianrefresh 2&quot; width=&quot;600&quot; height=&quot;576&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this relationship, a standard &quot;=&quot; predicate is used. The result of this relationship will be all contacts whose status is &quot;Active&quot;.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600576-cartesianrefresh-3.png&quot; alt=&quot;cartesianrefresh 3&quot; width=&quot;600&quot; height=&quot;576&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here lies the key in this technique. The above relationship uses a standard &quot;=&quot; predicate, AND a cartesian join predicate. The result of this relationship? All active contacts. The cartesian has no effect on the relationship, &lt;strong&gt;EXCEPT&lt;/strong&gt; as a means to refresh it.&lt;/p&gt;
&lt;p&gt;We have managed to add a field into the relationship, which has no detrimental effect on the relationship, does not affect the relationships intended results, but is a field nonetheless which we can use to refresh the relationship.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600142-cartesianrefresh-4.png&quot; alt=&quot;cartesianrefresh 4&quot; width=&quot;600&quot; height=&quot;142&quot;&gt;&lt;/p&gt;
&lt;p&gt;So, how does it work?&lt;/p&gt;
&lt;p&gt;Simple, just set the field you have used in your cartesian join predicate to any arbitrary value (non-empty). Ideally, you should create a field whose sole purpose is for the refresh of relationships. You could create one field per relationship if you wish to control specific relationships, otherwise you can use one field for all relationships that require refreshing. I have created one in this example called &quot;PortalRefresh&quot;.&lt;/p&gt;
&lt;p&gt;The field can be set either via a script, or more ideally using a script trigger. The script trigger would be perfect if you wish the relationship to re-evaluate upon changing the contents of another field (which itself indirectly affects the result of the relationship).&lt;/p&gt;
&lt;p&gt;The refresh field you choose can be global or non-global depending upon your needs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;An Example for you to play with&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I have included at the bottom of this article an example file which you can use to see the method in action.&lt;/p&gt;
&lt;p&gt;Because these refresh issues are sometimes contrived, I have come up with a similarly contrived relationship to illustrate the purpose.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60092-cartesianrefresh-5.png&quot; alt=&quot;cartesianrefresh 5&quot; width=&quot;600&quot; height=&quot;92&quot;&gt;&lt;/p&gt;
&lt;p&gt;The example file comprises 2 tables - Home, and Contacts. There are 3 relationships on the graph as shown in the above image:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;The first is a standard cartesian join to find all contacts through a relationship&lt;/li&gt;
&lt;li&gt;he second makes use of the cartesian join technique for refresh&lt;/li&gt;
&lt;li&gt;The third leaves off the cartesian technique and just finds a particular record.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;On the Home table there is a calculation which obtains the Contact ID of the &lt;em&gt;Nth&lt;/em&gt; record through the first relationship. The user enters a number into a global field which corresponds to the contact record they wish to view.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/cartesianrefresh-6.png&quot; alt=&quot;cartesianrefresh 6&quot; width=&quot;90&quot; height=&quot;90&quot;&gt;&lt;/p&gt;
&lt;p&gt;To cause the refresh issue, the global field the user enters the record # into resides on the Contacts table, and is pulled through to the Home table for use in the unstored calculation.&lt;/p&gt;
&lt;p&gt;What it all boils down to is a relationship to a particular contact, which will not refresh without a little nudge :)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Using the Example File, a Demonstration&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the example file you will see a portal of all contacts, and their record number displayed beside them:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/cartesianrefresh-7.png&quot; alt=&quot;cartesianrefresh 7&quot; width=&quot;246&quot; height=&quot;331&quot;&gt;&lt;/p&gt;
&lt;p&gt;You will also see the following entry fields:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/cartesianrefresh-8.png&quot; alt=&quot;cartesianrefresh 8&quot; width=&quot;342&quot; height=&quot;111&quot;&gt;&lt;/p&gt;
&lt;p&gt;Enter a number into the &lt;em&gt;Record # to show&lt;/em&gt; box. If you click out of this box, you will notice that the &lt;em&gt;Found Record&lt;/em&gt; value does not change to the record you entered. This is the refresh issue. Due to the nature of the relationship &amp;amp; the fact it is based on an unstored calc that references globals in the contacts table, the relationship is not refreshing.&lt;/p&gt;
&lt;p&gt;The button beside the field will run a script that either uses the flush cache method, or the cartesian refresh method, depending upon which tab you are using.&lt;/p&gt;
&lt;p&gt;Beneath each record entry field is a script-trigger version of the field, which runs the associated script using an OnObjectModify trigger.&lt;/p&gt;
&lt;p&gt;Both versions in the example file (flush cache &amp;amp; cartesian) exhibit the same issues, but each uses a different method of solution.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;You should always use the flush cached join results option on the Refresh Window script step with caution. Don&#039;t just check it willy nilly to guarantee your refresh issue will be solved. Understand what it really means and what impact it has on your solution, especially when deployed over LAN or WAN.&lt;/p&gt;
&lt;p&gt;Finally, consider the alternative method of refreshing a relationships results by using a cartesian join - you will retain your cached results, and only &quot;flush&quot; the specific relationship you need flushed, improving WAN performance in the long run.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example File:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/cartesianrefresh/CartesianRefresh.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Sat, 29 Jan 2011 11:51:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/ditch-those-flush-caches-use-cartesian-join-instead/</guid>
		</item>
		
		<item>
			<title>Quick Checkbox Selection of Portal Records for Users</title>
			<link>https://www.teamdf.com/blogs/quick-checkbox-selection-of-portal-records-for-users/</link>
			<description>&lt;p&gt;There are many ways in which users can select records, so that each user can keep their own unique selection. This particular method uses a portal showing related records as a selection tool. The main technique involves using a value list &amp;amp; checkbox to easily achieve selection with no scripting required.&lt;/p&gt;
&lt;p&gt;Setting the scenario:&lt;/p&gt;
&lt;p&gt;Quite often it is necessary in a solution to let users select one or more records for a certain purpose. Because this is a user-level process, each user should be allowed to have their own lists of records without interfering with other users selections - this is a perfect use of a global field! Global fields are user-specific, so one users global field contents will differ from that of another user.&lt;/p&gt;
&lt;p&gt;So, how can we make use of a global field to select records? One of the most common techniques simply involves maintaining a list of selected record IDs in the global field, and this is the technique that we will be using in this article.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/portalrecordselect-1.png&quot; alt=&quot;portalrecordselect 1&quot; width=&quot;149&quot; height=&quot;106&quot;&gt;&lt;/p&gt;
&lt;p&gt;A little bit about checkboxes:&lt;/p&gt;
&lt;p&gt;The easiest way to construct a checkbox in FileMaker is to simply make use of FileMakers existing features. Value lists have a visual display option to show as checkboxes. Typically when you see a checkbox value list it looks something like the following:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/portalrecordselect-2.png&quot; alt=&quot;portalrecordselect 2&quot; width=&quot;142&quot; height=&quot;109&quot;&gt;&lt;/p&gt;
&lt;p&gt;The first box shows a standard checkbox value list containing 3 values. The second box shows what is actually stored in the field when options are checked. When a value is checked, it is either added or removed from the field. The field itself is just a return-delimited list of checked values.&lt;/p&gt;
&lt;p&gt;So, with that said, is there any way to maintain our return-delimited list of selected records using a checkbox?&lt;/p&gt;
&lt;p&gt;&quot;Single-Value&quot; Value Lists&lt;/p&gt;
&lt;p&gt;To further help understand the technique (which I will eventually explain!) it pays to demonstrate the following technique that you can use with value-lists that only contain a single value:&lt;/p&gt;
&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/portalrecordselect-3.png&quot; alt=&quot;portalrecordselect 3&quot; width=&quot;140&quot; height=&quot;106&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the picture above, the value list now contains just the single value &quot;Apple&quot;. You can see that everything still works as expected - unchecking the apple box will remove apple from the field just as it did previously.&lt;/p&gt;
&lt;p&gt;So, if a value list contains only one value, is it really necessary to show the label &quot;Apple&quot; beside it? If it is only one value, then surely the user knows what the checkbox pertains to depending on where the checkbox is located on the layout?&lt;/p&gt;
&lt;p&gt;With a little jiggery-pokery, the checkbox field can be reformatted to give the appearance of a lone checkbox with no label:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/portalrecordselect-4.png&quot; alt=&quot;portalrecordselect 4&quot; width=&quot;145&quot; height=&quot;95&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is achieved by doing a few things:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Reduce the width of the checkbox field so the label is hidden&lt;/li&gt;
&lt;li&gt;Increase the font size of the field to make the checkbox larger&lt;/li&gt;
&lt;li&gt;Remove field borders to remove the &quot;double box&quot; effect.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;We now have a checkbox which when toggled, will select/deselect the word &quot;Apple&quot;.&lt;/p&gt;
&lt;p&gt;Applying this now to the portal:&lt;/p&gt;
&lt;p&gt;So, we have shown how to build a single checkbox to toggle a value in a field. Applying this to our problem, it stands that to solve our issue we simply need to place this checkbox in our portal so it appears on every row. Toggling the checkbox in each portal row will need to toggle the selected portal rows record ID in our global field.&lt;/p&gt;
&lt;p&gt;In order to do this, the value list is going to need to contain a single value - the portal rows record ID. Each portal row is going to require a different value attached to its checkbox - that being its record ID.&lt;/p&gt;
&lt;p&gt;So, how do we produce different value lists for each portal row? You may think the answer would be to create many value lists - fortunately there is a MUCH easier and MUCH less time consuming way (note - creating many value lists will&lt;/p&gt;
&lt;p&gt;Value lists have a context&lt;/p&gt;
&lt;p&gt;This is key. The contents of a value list will change depending upon the context in which they are evaluated. Most value lists you see have a layout-level record context. This means that the values contained within the value list will change from record to record, depending on what record you are on. Other value lists may be contextless, such as ones that use custom values. For these, they will show the same values regardless of the record they are on.&lt;/p&gt;
&lt;p&gt;A portal is a context, and as such you can have a value list evaluate within a portal on a row-by-row basis. This means in just the same way a value list can change its values on found-set records, they can also change on portal rows.&lt;/p&gt;
&lt;p&gt;This property of defining a value lists context is achieved using the value list option Use Values from Field combined with the option to Include only related values starting from: - the latter of which provides the context for the value lists evaluation.&lt;/p&gt;
&lt;p&gt;Because a related value is needed for this feature, we are going to require a new relationship to obtain the value lists values from. We only wish our value list to have 1 value which will be the records primary key value, so we need to create a self join relationship:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60043-portalrecordselect-5.png&quot; alt=&quot;portalrecordselect 5&quot; width=&quot;600&quot; height=&quot;43&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the picture above you can see the layouts context Home, related to the portal of contacts we will be using. From the portal table occurrence, we have created a self-join relationship to a new Contacts table occurrence in blue. The relationship here is simply from primary key to primary key (Contact ID = Contact ID).&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600514-portalrecordselect-6.png&quot; alt=&quot;portalrecordselect 6&quot; width=&quot;600&quot; height=&quot;514&quot;&gt;&lt;/p&gt;
&lt;p&gt;The image above shows how the value list that we will be using for the checkbox is setup. Note that the value list is set to show each portal rows Primary key Contact ID through the self-join relationship. The Starting context of the value list is the portals table occurrence. This means the value list contents will be evaluated at the portal level, giving unique value list contents on each row.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/portalrecordselect-7.png&quot; alt=&quot;portalrecordselect 7&quot; width=&quot;228&quot; height=&quot;325&quot;&gt;&lt;/p&gt;
&lt;p&gt;The picture above shows the result of putting our global field in the portal, and attaching our value list to it. I have expanded the width of the field so you can see the actual value of each value list. You can see that on each portal row, the contents of the value list changes to reflect that rows Contact ID.&lt;/p&gt;
&lt;p&gt;The end result:&lt;/p&gt;
&lt;p&gt;Putting it all together we end up with a nice checkbox on each portal row, which when checked will toggle that contacts record ID in our global field.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/portalrecordselect-8.png&quot; alt=&quot;portalrecordselect 8&quot; width=&quot;399&quot; height=&quot;369&quot;&gt;&lt;/p&gt;
&lt;p&gt;Final Thoughts:&lt;/p&gt;
&lt;p&gt;The thing I like about this method is that it is quick, requires no scripting, and makes use of FileMakers existing checkbox as a selection tool.&lt;/p&gt;
&lt;p&gt;While there are many other great methods out there for record selection in portals, hopefully this has given you yet another tool for this process. It really is a case of using the right technique for the right situation. This checkbox technique works best when the number of records in your portal is relatively small, otherwise visualising the selected records becomes more difficult. You could combine this technique with some conditional formatting in each portal row to achieve a better indication of the selected records, but generally if you were to go that far then other techniques that involve scripted maintenance of your list of IDs is probably more suitable :-)&lt;/p&gt;
&lt;p&gt;Example File:&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/portalrecordselect/PortalRecordSelectionUsingCheckboxes.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Wed, 19 Jan 2011 07:51:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/quick-checkbox-selection-of-portal-records-for-users/</guid>
		</item>
		
		<item>
			<title>The Case of the Disappearing Sub-Summary</title>
			<link>https://www.teamdf.com/blogs/the-case-of-the-disappearing-sub-summary/</link>
			<description>&lt;p&gt;Recently I was working on building a large layout which is used for both printing and data-entry. One of the requirements was I needed to show a lot of &quot;private&quot; information that the data-entry person needed to see, but was not to be printed. The issue was solved using a very cool property of sub-summary parts.&lt;/p&gt;
&lt;p&gt;First, the alternative possibilities:&lt;/p&gt;
&lt;p&gt;Before I show the actual solution used, it pays to mention a couple of other possible solutions to the problem just to outline why they were not suitable.&lt;/p&gt;
&lt;p&gt;Putting the information off to the side:&lt;/p&gt;
&lt;p&gt;The first one would have been to just put all the private information off the right-hand side of the layout, beyond the edge of the page break.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/hiddensubsummary-1.png&quot; alt=&quot;hiddensubsummary 1&quot; width=&quot;369&quot; height=&quot;149&quot;&gt;&lt;/p&gt;
&lt;p&gt;This method would work, and would be fine depending on the situation. However it was not ideal for this example:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Small monitors would need to resize window and/or scroll to see it&lt;/li&gt;
&lt;li&gt;Breaks the flow of the layout, vision is not drawn to a section off to the side&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The main issue was that I wanted to keep the dimension of the layout the same as the printable space, to prevent the layout having to be widened during data entry.&lt;/p&gt;
&lt;p&gt;The &quot;Sliding and Hiding&quot; method:&lt;/p&gt;
&lt;p&gt;Another option would have been to put the information on the layout in a particular section, and then mark everything in it as &quot;Hide When Printing&quot; this would solve the issue of not printing the information. However, now I end up with a gap in the layout when printing.&lt;/p&gt;
&lt;p&gt;So, can everything be made to slide up and fill the gap left by the now hidden information? The answer is yes, kind of...&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/hiddensubsummary-2.png&quot; alt=&quot;hiddensubsummary 2&quot; width=&quot;346&quot; height=&quot;256&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is an example of some private contents in-line with the layout contents. Everything has been set to slide up &amp;amp; reduce size of enclosing part. The private contents have been set to do not print.&lt;/p&gt;
&lt;p&gt;You can see green boxes in between the contents of the private section to indicate the white-space. The key point here is that this white space does not slide or disappear, it remains, leaving a gap.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/hiddensubsummary-3.png&quot; alt=&quot;hiddensubsummary 3&quot; width=&quot;218&quot; height=&quot;205&quot;&gt;&lt;/p&gt;
&lt;p&gt;The solution to this particular problem is to group the entire contents of the private section into a single object, and set that object to do not print, and slide:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/hiddensubsummary-4.png&quot; alt=&quot;hiddensubsummary 4&quot; width=&quot;428&quot; height=&quot;238&quot;&gt;&lt;/p&gt;
&lt;p&gt;The result is that the entire grouped object is treated as one object, so when it disappears, the only white space remaining will be the gap between the sections above and below the private section:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/hiddensubsummary-5.png&quot; alt=&quot;hiddensubsummary 5&quot; width=&quot;348&quot; height=&quot;126&quot;&gt;&lt;/p&gt;
&lt;p&gt;The problem I have with this however:&lt;/p&gt;
&lt;p&gt;The sliding &amp;amp; hiding method would actually work quite well, and in some situations it would be perfect, such as if the private data section is located at the bottom of the layout.&lt;/p&gt;
&lt;p&gt;However, my biggest problem with this was the affect it has on page-breaks, or more specifically, trying to construct the layout to fit properly on the pages.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600107-hiddensubsummary-6.png&quot; alt=&quot;hiddensubsummary 6&quot; width=&quot;600&quot; height=&quot;107&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can see in the picture above, because I have now added this section in-line, everything has been moved down, and the layout I worked so hard to build to fit on my pages, is now all out of alignment. Now it&#039;s all a case of trial &amp;amp; error when building the layout to ensure that the page breaks in the correct locations, I have to constantly accommodate the sliding and hiding of the private information section!&lt;/p&gt;
&lt;p&gt;What I really want is a combination of the following:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The off-to-the-side method which does not affect page boundaries, AND&lt;/li&gt;
&lt;li&gt;The in-line method which lets me see it, and let the layout flow.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Using a Sub-Summary part to show &amp;amp; hide the information&lt;/p&gt;
&lt;p&gt;Finally, the solution was to use a sub-summary part!&lt;/p&gt;
&lt;p&gt;I created a sub-summary part, and chose my tables primary key field as the break field. In fact, it doesn&#039;t matter what break-field you choose, so primary key is as good as any.&lt;/p&gt;
&lt;p&gt;The key to this technique is as follows:&lt;/p&gt;
&lt;p&gt;While in browse mode and form view, sub-summary part(s) will remain visible even if the records are not sorted&lt;/p&gt;
&lt;p&gt;In order for a sub-summary part to actually print, the records have to be sorted, so lets just not sort the records! Amazingly, the sub-summary remains visible in browse mode, which is perfect as a means to let use it for data entry, putting in links, showing important information etc.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600476-hiddensubsummary-7.png&quot; alt=&quot;hiddensubsummary 7&quot; width=&quot;600&quot; height=&quot;476&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/hiddensubsummary-8.png&quot; alt=&quot;hiddensubsummary 8&quot; width=&quot;562&quot; height=&quot;274&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can see in the image above, the sub-summary is placed at the top of the layout.&lt;/p&gt;
&lt;p&gt;Best of all, the sub-summary part has no adverse effect on existing page-break boundaries, so I can still construct the layout using the page boundaries, making building the layout so much easier for printing purposes.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/hiddensubsummary-9.png&quot; alt=&quot;hiddensubsummary 9&quot; width=&quot;287&quot; height=&quot;82&quot;&gt;&lt;/p&gt;
&lt;p&gt;A note for FileMaker 9 users&lt;/p&gt;
&lt;p&gt;Please note that because this technique makes use of sub-summaries in browse mode, this technique will not work for users of FileMaker 9 or sooner. Browse-mode sub-summary viewing was introduced in FileMaker 10. In this situation, the sliding &amp;amp; hiding method would be more appropriate.&lt;/p&gt;
&lt;p&gt;Final thoughts:&lt;/p&gt;
&lt;p&gt;To be honest I was completely surprised when I jumped into browse mode and saw the sub-summary part staring me in the face with the records unsorted. My original intention was to ensure the records were sorted by the break-field so that the sub-summary would appear in browse mode, and then use script triggers and custom-menu overrides for printing to ensure the records were then unsorted prior to printing.&lt;/p&gt;
&lt;p&gt;However as things happened I was spared all of that work by an unusual quirk of FileMaker, I love it when that happens!&lt;/p&gt;
&lt;p&gt;Example File:&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/hiddensubsummary/HiddenSubSummary.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Sat, 15 Jan 2011 09:34:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/the-case-of-the-disappearing-sub-summary/</guid>
		</item>
		
		<item>
			<title>Creating Tidy Popup Windows</title>
			<link>https://www.teamdf.com/blogs/creating-tidy-popup-windows/</link>
			<description>&lt;p&gt;Using Popup windows is common FileMaker technique for showing more information, managing dialogs, and running wizards to name a few. However, all to often little care is given to the aesthetics of creating and positioning a popup, leading to an unpolished and half-finished feel. This article gives some pointers on how you can create popups that are clean, efficient, and correctly positioned.&lt;/p&gt;
&lt;p&gt;Why would you want tidy popups?&lt;/p&gt;
&lt;p&gt;Consider any standard application on your computer, such as iTunes, Mail, Safari etc. When you open new windows in these applications, such as entering the preferences, what do you see? Typically, you will see the popup windows appear centered in front of your current window. They appear right away, and they appear all setup and ready to go.&lt;/p&gt;
&lt;p&gt;Now, if an application can do it, then why shouldn&#039;t your database? Databases are just as critical as applications, if not more, so why skimp on the detail?&lt;/p&gt;
&lt;p&gt;Having tidy popups makes your entire database feel tidy and polished, and can be achieved very easily.&lt;/p&gt;
&lt;p&gt;All too often I see popup windows created in FileMaker with no care. How many popups have you seen in databases that appear in seemingly random positions, with the incorrect size, showing scrollbars or status area. Then, how many do their setup on-screen, so you see the hiding of the status area, the resizing of the popup, layout changes and so on? I don&#039;t know about you, but I see it all the time and it is one of my biggest bug-bears about database design - the lack of care taken on the user interface and design side of a system.&lt;/p&gt;
&lt;p&gt;If you are building any kind of commercial database, then how it looks and behaves should be one of your top priorities, no one wants to buy a database that looks half-finished !&lt;/p&gt;
&lt;p&gt;Setting up a popup without the user seeing&lt;/p&gt;
&lt;p&gt;The creation of new popup windows that are not visible to the user has already been covered in one of my previous articles - &lt;a href=&quot;http://www.digitalfusion.co.nz/news/weetbicks/using-an-offscreen-window-to-do-a-scripts-work-/13/&quot;&gt;&quot;Using an Offscreen Window to do a Scripts Work&quot;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The idea is that new windows are created with a large negative left coordinate value, this ensures the new window appears at a coordinate not visible by monitors, and so is not on-screen.&lt;/p&gt;
&lt;p&gt;The article above concerns using these windows as temporary workspaces which can be closed when done, but the same idea can apply to creation of popups the user will eventually see. The popups can be created with it&#039;s width, height, and top coordinate set correct for the popup, but with the large negative left coordinate. When the popup is ready to be displayed, it can be shifted back on-screen in a single step using the &quot;Move/Resize Window script step.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/popupwindows-1.png&quot; alt=&quot;popupwindows 1&quot; width=&quot;566&quot; height=&quot;409&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/popupwindows-2.png&quot; alt=&quot;popupwindows 2&quot; width=&quot;600&quot; height=&quot;472&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the images above, you can see how the new popup window can be created. Local variables have been used to store the default top/left coordinates, and the popups default width and height.&lt;/p&gt;
&lt;p&gt;Positioning the popup where you want&lt;/p&gt;
&lt;p&gt;Depending on the purpose of the popup window you are creating, there may be many different initial locations on screen where you want the popup to appear. If you know the actual coordinates, such as wanting the popup to always appear in the top left corner of screen, you can obviously enter 0/0 as your coordinates.&lt;/p&gt;
&lt;p&gt;However, more often than not the position of a new popup will be dependent upon the location of your current window. For example, if you wish to have the popup appear directly centered in front of your current window, then the initial coordinates of the popup are dependent upon the current coordinates of your main window.&lt;/p&gt;
&lt;p&gt;Similarly, you may wish to position the popup in a location relative to an object on your layout. Small popup windows may be used to carry out an action specific to a location such as a particular button, or field. In this case, your popups initial coordinates are dependent upon the coordinates of the layout object.&lt;/p&gt;
&lt;p&gt;Center-Aligning a popup window&lt;/p&gt;
&lt;p&gt;To create a center-aligned popup window, I have created a couple of helpful custom functions that perform the necessary calculations to derive a top and left coordinate for your new window:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600455-popupwindows-3.png&quot; alt=&quot;popupwindows 3&quot; width=&quot;600&quot; height=&quot;455&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600455-popupwindows-4.png&quot; alt=&quot;popupwindows 4&quot; width=&quot;600&quot; height=&quot;455&quot;&gt;&lt;/p&gt;
&lt;p&gt;The popup_CenterLeft function takes your popups initial width as its parameter. This is required to position the popup correctly horizontally. Similarly, popup_CenterTop requires the popup height to center vertically.&lt;/p&gt;
&lt;p&gt;I won&#039;t go into great detail as far as dissecting the functions, suffice to say they produce the coordinates using the popups dimensions, compared to the current windows dimensions and location on screen.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/popupwindows-5.png&quot; alt=&quot;popupwindows 5&quot; width=&quot;393&quot; height=&quot;61&quot;&gt;&lt;/p&gt;
&lt;p&gt;The image above shows how you can establish your popups coordinates in variables. Here, $Width and $Height have been previously set to the popups initial dimensions.&lt;/p&gt;
&lt;p&gt;Establishing the popups initial dimensions&lt;/p&gt;
&lt;p&gt;This is the most crucial part of the process in my opinion. In order to prevent visible scrollbars when you popup is displayed, you should set your width and height exactly correct for the popup. This is going to involve determining the exact dimensions. Some may think that this &quot;hard-coding&quot; of dimensions into your script is a bad thing, but I say that if you are creating a popup window, it is highly unlikely its dimensions will change unless you manually make changes to the layout, in which case your script should change accordingly. It is also important to get correct dimensions so you see no window resizing toward the end of the process.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/popupwindows-6.png&quot; alt=&quot;popupwindows 6&quot; width=&quot;332&quot; height=&quot;57&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the image above I have set my width and height into variables. You&#039;ll notice the use of two more custom functions popup_GetWidth and popup_GetHeight. These functions help correctly determine your windows dimensions.&lt;/p&gt;
&lt;p&gt;The reason for using these functions is because there is a difference in window dimensions depending on whether you are on a PC or a mac. On a PC, scrollbars are thicker and so the window will be larger. These functions take as their parameter the raw layout-mode width/height of your layout, and produce the resulting windows dimensions based upon what platform is being used.&lt;/p&gt;
&lt;p&gt;To determine your layout height, you will need to obtain the pixel heights of your layout parts. If your layout has a header of height 50 pixels, and body part of 100 pixels, then your parameter to popup_GetHeight is going to be 150. Of course, if your popup is using list/table view, this becomes less important, and your popup dimensions should just be determined by what you wish the size of the popup to be initially.&lt;/p&gt;
&lt;p&gt;To determine your layout width, select every object on the layout using cmd+A (ctrl+A) and in the inspector/object info panel, look for the right coordinate.&lt;/p&gt;
&lt;p&gt;If you only ever use one platform, you can skip using the custom function and directly set your window width &amp;amp; height. To do this, open the popup window in browse mode &amp;amp; resize to fit, using your data viewer, obtain the values of Get(WindowLeft) and Get(WindowTop) functions respectively.&lt;/p&gt;
&lt;p&gt;Putting it all together&lt;/p&gt;
&lt;p&gt;All the required components are now known, and we can create the window, set it up, and move it back on-screen when ready.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600488-popupwindows-7.png&quot; alt=&quot;popupwindows 7&quot; width=&quot;600&quot; height=&quot;488&quot;&gt;&lt;/p&gt;
&lt;p&gt;The script above sets the required coordinates and dimensions of the new window. The window is created off-screen. Then follows the setup of the window, in this case switching to the desired layout. Finally, the window is moved back into its exact correct location using Move/Resize window.&lt;/p&gt;
&lt;p&gt;Aligning popups relative to a layout object&lt;/p&gt;
&lt;p&gt;The last type of popup I will be dealing with is those that are to be initially positioned relative to a layout object. Whereas the center-aligned method uses the dimensions of the current window, this will use the dimensions and coordinates of a layout object.&lt;/p&gt;
&lt;p&gt;Again, two custom functions have been produced to assist in the correct positioning of the window, popup_ObjectLeft and popup_ObjectTop.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/popupwindows-8.png&quot; alt=&quot;popupwindows 8&quot; width=&quot;450&quot; height=&quot;58&quot;&gt;&lt;/p&gt;
&lt;p&gt;These functions take 3 parameters respectively:&lt;/p&gt;
&lt;p&gt;-ObjectName - The object name of layout object to position relative to.&lt;br&gt;-Orientation - a keyword &quot;top&quot;, &quot;left&quot;, &quot;bottom&quot;, or &quot;right&quot; to position popup.&lt;br&gt;-PopupWidth/Height - dimensions of popup depending on function used.&lt;/p&gt;
&lt;p&gt;Again, not going into much detail about the functions, but just to say the functions make use of the GetLayoutObjectAttribute function to obtain coordinates &amp;amp; dimensions of the layout object, all information required to correctly determine the popups initial coordinates.&lt;/p&gt;
&lt;p&gt;From here, once the coordinates are known, it&#039;s just a case of creating the window, setting it up, and then moving it back on screen as shown earlier.&lt;/p&gt;
&lt;p&gt;A note about dock positioning on OS X&lt;/p&gt;
&lt;p&gt;While writing this article I noticed a peculiar bug in FileMaker concerning obtaining a windows coordinates versus a layout objects coordinates. This is most apparent when your os x dock is positioned on the left edge of your screen.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/popupwindows-9.png&quot; alt=&quot;popupwindows 9&quot; width=&quot;467&quot; height=&quot;203&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the picture above, my dock is on the left edge of my screen. You can see the left coordinate of the window when positioned right beside the dock is 0 pixels. This would suggest that when the dock is on the left of screen, window coordinates begin from the edge of the dock, rather than the screen itself.&lt;/p&gt;
&lt;p&gt;However this is not the case for left coordinates of layout objects. As you can see, the gap between the edge of the window and the object is 126 px. You would think that this would mean the left edge of the button would be 126 px, you would be wrong! The left edge is in fact 176 px, a full 50 pixels more. So it turns out that when obtaining object coordinates, they do in fact begin from the left edge of your screen, and not from the edge of the dock as a window coordinate will.&lt;/p&gt;
&lt;p&gt;This causes some problems in determining a correct popup window position because you cannot determine in FileMaker whether your dock is on the bottom of screen, or on left of screen. The functions mentioned in this article are assuming that the dock is at the bottom of screen, and thus the window coordinates and the object coordinates use the same 0 pixel coordinate location.&lt;/p&gt;
&lt;p&gt;If your dock is on left of screen, you will find that the left coordinate of the popup window is slightly offset to the right of the object when using the object-aligning technique. This can be modified in the functions themselves, but is not a good solution, as users can always change their dock location whenever they want.&lt;/p&gt;
&lt;p&gt;Note that the coordinate bug is not a factor when center-aligning a popup in front of the parent window.&lt;/p&gt;
&lt;p&gt;Final Thoughts:&lt;/p&gt;
&lt;p&gt;If any database is to be taken seriously as a professional looking, polished solution, then care needs to be taken in how you create your popup windows. Unnecessary window flashing, resizing, or visual setup of a popup should be avoided, as it makes a database feel unpolished and even unfinished. Correct positioning of popups is not a difficult thing to do given the proper tools, and can go a long way to improving the usability of your solution.&lt;/p&gt;
&lt;p&gt;Example File&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/popupwindows/PopupWindows.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Sun, 09 Jan 2011 07:38:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/creating-tidy-popup-windows/</guid>
		</item>
		
		<item>
			<title>Complex Filtering Using Related Record Information</title>
			<link>https://www.teamdf.com/blogs/complex-filtering-using-related-record-information/</link>
			<description>&lt;p&gt;This article demonstrates how you can filter a relationship to one table, by using information located in a related table. The example we will be using is filtering a relationship to a Customer table, but by searching on a customers related Contacts, which are in an entirely different table.&lt;/p&gt;
&lt;p&gt;What are you Talking About?&lt;/p&gt;
&lt;p&gt;We are talking about the filtering of a relationship. There are a few various methods as to how this can be done, but we will be using a search field, that will match the contents of a key field generated on the related table.&lt;/p&gt;
&lt;p&gt;This article is going to assume you have knowledge about basic concepts behind filtering. If you are unfamiliar with the concepts, there are a number of sites offering techniques on how to achieve this. A quick google search for &quot;FileMaker Relationship Filter&quot; will yield some results, or you can check out &lt;a href=&quot;http://filemakerinspirations.com/2009/01/google-like-search-through-relationship-filtering/&quot;&gt;this great article on relationship filtering&lt;/a&gt; by Danny Kohn of &lt;a href=&quot;http://www.filemakerinspirations.com&quot;&gt;FileMaker Inspirations&lt;/a&gt;. This particular article does not use the exact technique mentioned in order to keep the complexity level to a minimum, but the technique mentioned in the article is a great one nonetheless.&lt;/p&gt;
&lt;p&gt;Setting up the Example Case&lt;/p&gt;
&lt;p&gt;The example we will be using to demonstrate this technique is a simple one using two tables - Customers and Contacts. The relationship is that a Customer can have many Contacts, and so the foreign key field &quot;Customer ID&quot; is placed on the Contacts table.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/relatedfiltering-1.png&quot; alt=&quot;relatedfiltering 1&quot; width=&quot;360&quot; height=&quot;113&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/relatedfiltering-2.png&quot; alt=&quot;relatedfiltering 2&quot; width=&quot;270&quot; height=&quot;169&quot;&gt;&lt;/p&gt;
&lt;p&gt;Both tables contain basic fields you would expect to find in these types of tables. Primary keys are Customer ID and Contact ID respectively.&lt;/p&gt;
&lt;p&gt;The zLocatorKey fields found in both tables, are special key fields used to accomplish the filtering of the relationship. While this type of key is not exactly the most efficient in terms of size, it is relatively easy to grasp how it works to achieve the filtering. In order to build this key, we have used a couple of custom functions, which we will not be going into detail about given the scope of this article, suffice to say you can check them out in the example file.&lt;/p&gt;
&lt;p&gt;The Goal We are Trying to Achieve:&lt;/p&gt;
&lt;p&gt;So, with all of this said, what is it we are actually trying to achieve here? The goal is to produce a portal based on the Customers table, which can be filtered by typing into a search field.&lt;/p&gt;
&lt;p&gt;We wish to allow the user to search by customer name, which should be a fairly straightforward task given that it is the customers table being filtered, and so the customers name resides on the table we are filtering.&lt;/p&gt;
&lt;p&gt;HOWEVER, we also wish for the user to type in a contacts name, and have matching customers also appear. How would we do this? Contact information is not kept on the Customer table at all. The only association between the two is via the primary/foreign key relationship.&lt;/p&gt;
&lt;p&gt;You might think the answer would be to place the related contact information on the Customers table, but stop! Any calculation placed on the Customer table to pull through related contact information is going to be unstored, and thus any relationship based on this calculation would break. The destination side of any relationship must have all predicates stored.&lt;/p&gt;
&lt;p&gt;Perhaps the answer then is to store contact information on the Customer table, thus allowing us to filter customers directly. Well, in order to do this, a great deal of extra work and scripting will be required:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Any change to a contact name would have to be updated on the Customer record&lt;/li&gt;
&lt;li&gt;Any adding/deleting of contacts would have to be updated also&lt;/li&gt;
&lt;li&gt;This would have to be done via script triggers, scripts, server-side scripting etc.&lt;/li&gt;
&lt;li&gt;In addition, you are essentially storing the same data twice.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The Proposed Solution:&lt;/p&gt;
&lt;p&gt;To best illustrate the solution to this problem, have a look at the following diagram:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600342-relatedfiltering-3.png&quot; alt=&quot;relatedfiltering 3&quot; width=&quot;600&quot; height=&quot;342&quot;&gt;&lt;/p&gt;
&lt;p&gt;Step one is to carry out the filtering on a Contacts table occurrence. The filtering is setup just as if we were filtering contacts. The users enter a value into the search field, and matching contacts are found. If the relationship yields matching contacts, then we know which customer they belong to by way of their Customer ID foreign key.&lt;/p&gt;
&lt;p&gt;Step two involves obtaining the contact results. The important piece of information concerns the customer the results belong to - Customer ID. This information is pulled back to the base context which in this case is &quot;Home&quot;. The results are pulled back by using the List function to produce a return-delimited list of Customer IDs.&lt;/p&gt;
&lt;p&gt;The final step now uses these resulting customer IDs in the relationship to the customers table. Any customers found through this relationship, we know have contacts that match the entered search term, because the customer IDs were obtained originally from a search for contacts.&lt;/p&gt;
&lt;p&gt;That is the basic process in a nutshell. Depending on how you tweak these relationships further, you can achieve your desired behavior.&lt;/p&gt;
&lt;p&gt;Example File Explained:&lt;/p&gt;
&lt;p&gt;In the example file provided, the context for these relationships is &quot;Home&quot;. The Home table contains the following fields:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/relatedfiltering-4.png&quot; alt=&quot;relatedfiltering 4&quot; width=&quot;303&quot; height=&quot;118&quot;&gt;&lt;/p&gt;
&lt;p&gt;Filter Search: Global text field the user enters search term into&lt;br&gt;Filter Key:Match field used in relationship to Customers to drive the portal&lt;br&gt;Filter Customer IDs: Return delimited list of Customer IDs obtained from the match through the Contacts relationship.&lt;/p&gt;
&lt;p&gt;The relationship graph is setup as follows:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60097-relatedfiltering-5.png&quot; alt=&quot;relatedfiltering 5&quot; width=&quot;600&quot; height=&quot;97&quot;&gt;&lt;/p&gt;
&lt;p&gt;The first relationship is between Home &amp;amp; Contacts, and is used to obtain matching contacts based on the search value the user enters:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600576-relatedfiltering-6.png&quot; alt=&quot;relatedfiltering 6&quot; width=&quot;600&quot; height=&quot;576&quot;&gt;&lt;/p&gt;
&lt;p&gt;The relationship is to the Contacts zLocatorKey field. This field has been setup as a basic return delimited list of possible search terms for a contact, mainly just their given, family, and full names.&lt;/p&gt;
&lt;p&gt;The second relationship is between Home &amp;amp; Customers, and is used to display the desired results in the portal.&lt;/p&gt;
&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600576-relatedfiltering-7.png&quot; alt=&quot;relatedfiltering 7&quot; width=&quot;600&quot; height=&quot;576&quot;&gt;&lt;/p&gt;
&lt;p&gt;This relationship is from a special key field called Filter Key.&lt;/p&gt;
&lt;pre&gt;If ( IsEmpty ( Filter Search ) ; &quot;*All*&quot; ; List ( Filter Search ; Filter Customer IDs ) )&lt;/pre&gt;
&lt;p&gt;If the user enters nothing into the search field, a special keyword &quot;*All*&quot; is used. The purpose of this is purely to determine how the portal will look when the user has not searched for anything. There are two possibilities here, either the portal shows nothing, or the portal shows all records. In this case, we have decided to show all records.&lt;/p&gt;
&lt;p&gt;In order for the portal to show all records, we need to ensure the relationship is setup to find all records. In the zLocatorKey field in the Customers table, we have ensured every customer record contains the &quot;*All*&quot; identifier in its key, thus every record will be found through the relationship in this case.&lt;/p&gt;
&lt;p&gt;Back to the calculation, if the user HAS in fact entered a search term, the following is used:&lt;/p&gt;
&lt;pre&gt; List ( Filter Search ; Filter Customer IDs )&lt;/pre&gt;
&lt;p&gt;This is a return delimited list of both the users search value, and a return-delimited list of customer IDs obtained via the search on contacts earlier.&lt;/p&gt;
&lt;p&gt;The end result is a key which should find all matching customers by both the customer names, AND by contacts that were matched by their names.&lt;/p&gt;
&lt;p&gt;The contents of the Filter Customer IDs calculation field is simply a list of customer IDs through the Contacts relationship.&lt;/p&gt;
&lt;p&gt;NOTE: About use of List function:&lt;/p&gt;
&lt;p&gt;While this is a useful technique, it needs to be used with caution in some situations. This is because of the use of the list function to pull back customer IDs from matching contact records.&lt;/p&gt;
&lt;p&gt;Whenever the list function is used, FileMaker downloads the entire record from records being listed, not just the field being listed. Because of this, if you search for &quot;David&quot; for example, and there are hundreds of David contacts in the system, then FileMaker will download all of those records in order to achieve the list of their Customer IDs. Over a local file, or LAN, this might be acceptable. Over WAN however, this may exhibit itself as slow filtering, given all records need to be downloaded.&lt;/p&gt;
&lt;p&gt;For this reason, the example file has not been implemented with a live filtering functionality.&lt;/p&gt;
&lt;p&gt;Final Thoughts:&lt;/p&gt;
&lt;p&gt;This is a useful concept for carrying out complex filtering of relationships. The core idea is that you can filter relationships using other related tables, by pulling the results back to your main context, and then using them in your primary relationship.&lt;/p&gt;
&lt;p&gt;As with most techniques, there are always drawbacks, the primary one in this case being the use of the List function to pull back results. This can have implications in solutions distributed over WAN or even LAN depending on the size of the tables concerned.&lt;/p&gt;
&lt;p&gt;Example File&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/relatedfiltering/RelatedFiltering.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Sat, 08 Jan 2011 10:10:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/complex-filtering-using-related-record-information/</guid>
		</item>
		
		<item>
			<title>FileMaker Weetbicks Arrives</title>
			<link>https://www.teamdf.com/blogs/filemaker-weetbicks-arrives/</link>
			<description>&lt;p&gt;Digital Fusion is proud to announce the arrival of &lt;a href=&quot;http://www.digitalfusion.co.nz/news/weetbicks/&quot;&gt;FileMaker Weetbicks&lt;/a&gt;. This is our gift back to the FileMaker community, and is where we will be publishing FileMaker related tips, techniques and example files, for users and developers alike.&lt;/p&gt;
&lt;p&gt;Created originally by our developer Daniel Wood, the articles have been published before on a few other websites, but are now all in one place on our website for everyone to enjoy.&lt;/p&gt;
&lt;p&gt;If you are a FileMaker developer, user, or just have a keen interest in FileMaker, be sure to check back regularly for new articles. We will also be using both &lt;a href=&quot;http://www.facebook.com/pages/FileMaker-Weetbicks/174484482591376&quot;&gt;Facebook&lt;/a&gt; and &lt;a href=&quot;http://www.twitter.com/FMweetbicks/&quot;&gt;Twitter&lt;/a&gt; as ways to keep people up to date when new articles are released.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.facebook.com/pages/FileMaker-Weetbicks/174484482591376&quot;&gt;Follow us on Facebook&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;http://www.twitter.com/FMweetbicks&quot;&gt;Follow us on Twitter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;</description>
			<pubDate>Mon, 03 Jan 2011 14:53:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-weetbicks-arrives/</guid>
		</item>
		
		<item>
			<title>Build a Navigation System Part One - Starting Out Simple</title>
			<link>https://www.teamdf.com/blogs/build-a-navigation-system-part-one-starting-out-simple/</link>
			<description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The first in a series on the subject. This article presents a very simple and easy to setup method of navigation for a database, making use of repeating fields.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why do I need to create a navigation system, why not just use the layout menus?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Good question. Of course there is nothing stopping you from just giving users access to the layout menu via the status area, or Layouts menu, but there are a number of reasons why this is not always an ideal method of navigation:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Large number of layouts may confuse the user&lt;/li&gt;
&lt;li&gt;User may not be required to see all layouts&lt;/li&gt;
&lt;li&gt;Layouts may be placed in groups, increasing time required to navigate&lt;/li&gt;
&lt;li&gt;Developer may use their own layout naming scheme for manageability, but will only confuse the user&lt;/li&gt;
&lt;li&gt;Makes a solution feel less polished&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/navigationsimple-1.png&quot; alt=&quot;navigationsimple 1&quot; width=&quot;155&quot; height=&quot;76&quot;&gt;   &lt;/p&gt;
&lt;p&gt;It is my opinion that while the layout menus could be useful in a very simple solution, if you are designing a solution where you want it to look good, and have it feel more like an actual solution, then the layout menus should be avoided, keep them for the developers!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Method of Navigation: The Navigation Bar&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The navigation system that will be built in this article is a very simple navigation bar, build using global repeating fields.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60048-navigationsimple-2.png&quot; alt=&quot;navigationsimple 2&quot; width=&quot;600&quot; height=&quot;48&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So, How Is It Built?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The navigation bar pictured above contains 10 different screens. Each screen in the navigation bar comprises of both an icon, and a text label that appears underneath.&lt;/p&gt;
&lt;p&gt;This is achieved using 2 global repeating fields, each containing 10 repetitions, and positioned horizontally across the top of the layout. The first repetition is for the icons, and the second is for the labels:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/navigationsimple-3.png&quot; alt=&quot;navigationsimple 3&quot; width=&quot;458&quot; height=&quot;94&quot;&gt;&lt;/p&gt;
&lt;p&gt;These repeating fields have been placed in a table called &quot;Navigation&quot;. This table only contains one record (though in actuality it need not contain any given all fields in it are global).&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/navigationsimple-4.png&quot; alt=&quot;navigationsimple 4&quot; width=&quot;380&quot; height=&quot;94&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/navigationsimple-5.png&quot; alt=&quot;navigationsimple 5&quot; width=&quot;456&quot; height=&quot;93&quot;&gt;&lt;/p&gt;
&lt;p&gt;When setting up the navigation bar, remember that corresponding repetitions in both fields make up a single screen on the navigation bar. For example the fourth repetition of both fields will be the icon &amp;amp; label for the fourth screen on the navigation bar.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/navigationsimple-6.png&quot; alt=&quot;navigationsimple 6&quot; width=&quot;134&quot; height=&quot;99&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Importance of Being Global&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By having the navigation system based upon global fields, it means we can easily copy/paste our navigation bar onto any layout and it should just work. We will not need to re-point any of the component fields to any other table occurrence. The relationship graph simply requires one table occurrence for Navigation, and this is what is used at all times.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So How Does It Actually Navigate?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Another good question. What we currently have is the appearance of a navigation bar, but no functionality. We need to attach a script or script step to each screen in the navigation bar so we can actually go to that screen.&lt;/p&gt;
&lt;p&gt;This is done by placing a button over top of each screen (corresponding repetitions) in the navigation bar. Unfortunately, you cannot simply turn a repeating field into a button and have each repetition act a its own button, which is what we want (though that would be a great feature, c&#039;mon FileMaker!)&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/navigationsimple-7.png&quot; alt=&quot;navigationsimple 7&quot; width=&quot;444&quot; height=&quot;96&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the picture above, the black outlines are the buttons that have been placed on top of each &quot;screen&quot; in the navigation bar. By having individual buttons, we can tailor each one to go to its correct screen.&lt;/p&gt;
&lt;p&gt;In order to navigate to a layout, we need to know what that layout is. We cannot hard-code navigation to a layout, because the very nature of this navigation bar means it is built in a &quot;soft&quot; manner - we can completely customize it based on what is put into the repeating fields. For this reason we also need to soft-code the layouts.&lt;/p&gt;
&lt;p&gt;This is done by the introduction of a new repeating field into the Navigation table, for the purpose of storing the layout names corresponding to each screen:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/navigationsimple-8.png&quot; alt=&quot;navigationsimple 8&quot; width=&quot;374&quot; height=&quot;113&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/navigationsimple-9.png&quot; alt=&quot;navigationsimple 9&quot; width=&quot;447&quot; height=&quot;119&quot;&gt;&lt;/p&gt;
&lt;p&gt;With the navigation table now complete, I can setup the buttons for each screen in the navigation bar. Here is an example of how the fourth screen is setup:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600513-navigationsimple-10.png&quot; alt=&quot;navigationsimple 10&quot; width=&quot;600&quot; height=&quot;513&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/navigationsimple-11.png&quot; alt=&quot;navigationsimple 11&quot; width=&quot;227&quot; height=&quot;72&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can see, &lt;em&gt;Go to layout by Name&lt;/em&gt; is the method of navigation. We obtain the correct layout name by referencing the repetition of the Layout field, that corresponds to the screen clicked. Each button is placed over a specific set of repetitions, so we can use that number on each button. Indeed each button is setup to go to a different layout repetition.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is a Layout Field Required?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The answer is yes and no. This depends on how you name your layouts.&lt;/p&gt;
&lt;p&gt;If you have a very simple layout naming scheme, and your label names are exactly the same as your layout names, you can just use the label repeating field in your &lt;em&gt;Go to layout by name&lt;/em&gt; step.&lt;/p&gt;
&lt;p&gt;However, even if this is the case, I would recommend always using the layout repeating field. More often than not, the layout names will differ from the label you wish to present. Label length is constrained by how wide your navigation bar is, and so you must choose your labels carefully. For example consider a screen for Purchase Ordering. That is a pretty long label, so you may wish to shorten it to &quot;Purchases&quot;. However, you would really want to keep the layout name as &quot;Purchase Orders&quot; so you know exactly what it is when developing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What if I Want to Use a Script For Navigation?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sometimes you may need to do something upon navigating to a layout, such as showing all records, establishing a found set, etc.&lt;/p&gt;
&lt;p&gt;If you wish to use a script for your navigation purposes, then you can easily do so. You can pass the selected screens repetition number as a &lt;em&gt;script parameter&lt;/em&gt; to the script, and then that script can carry out the navigation to that screen using the repeating field when it is ready to do so.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/navigationsimple-12.png&quot; alt=&quot;navigationsimple 12&quot; width=&quot;368&quot; height=&quot;30&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;    &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Taking Things Further&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The navigation bar built in this article is a pretty basic, straightforward, bare bones type of navigation bar. There are a wide number of things that can be done with it to extend its usability, design, and flexibility.&lt;/p&gt;
&lt;p&gt;In the next article in this series, I will demonstrate some of these extensions, such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Colouring/Bolding the selected screens label&lt;/li&gt;
&lt;li&gt;Background fill under selected screen in navigation bar&lt;/li&gt;
&lt;li&gt;Increasing flexibility of colours/formatting using additional fields&lt;/li&gt;
&lt;li&gt;A script to quickly and painlessly reorder screens in the navigation bar&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;And future articles will cover areas such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Customised Navigation for each user&lt;/li&gt;
&lt;li&gt;Integrating as a Custom Menu&lt;/li&gt;
&lt;li&gt;Alternative Navigation Styles, ie Portals&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While using layout menus is a quick solution for navigation of a database, there are a number of drawbacks.&lt;/p&gt;
&lt;p&gt;The main benefit of the navigation bar demonstrated, is that it is global, and fully customizable. It is setup once, and in one place, which is reflected across all layouts containing the navigation bar.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example File&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/navigationsimple/NavigationBarSimple.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 03 Jan 2011 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/build-a-navigation-system-part-one-starting-out-simple/</guid>
		</item>
		
		<item>
			<title>Sorting Records Using Your Own Custom Ordering</title>
			<link>https://www.teamdf.com/blogs/sorting-records-using-your-own-custom-ordering/</link>
			<description>&lt;p&gt;You may be familiar with the Sort Records dialog in FileMaker which allows you to display records sorted by one or more fields. What you may be less familiar with is the ability to more explicitly define a sort order with the assistance of a value list. This article gives an introduction to this often overlooked feature, and provides a few examples along the way.&lt;/p&gt;
&lt;p&gt;Sorting Records&lt;/p&gt;
&lt;p&gt;Sorting of records in FileMaker is achieved using the Sort Records dialog.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600427-sortingbyvaluelists-1.png&quot; alt=&quot;sortingbyvaluelists 1&quot; width=&quot;600&quot; height=&quot;427&quot;&gt;&lt;/p&gt;
&lt;p&gt;The dialog is available via Sort-&amp;gt;Records in the file menu, and as a script step. You can also sort records by right-clicking while in browse mode somewhere on the layout, and choosing &quot;Sort Records&quot;. The shortcut key ctrl+S (command+S on mac) will also bring up the sort dialog.&lt;/p&gt;
&lt;p&gt;Move fields from the left side to the right side in order to sort by those fields. You can choose to sort by one or more fields, in either ascending or descending order. For most cases this is enough, and these sort options give you what you want.&lt;/p&gt;
&lt;p&gt;There are however some situations where you wish to sort by a field, but the resulting sort is not what you want. This occurs when the sort order is to be custom, and not alphabetical.&lt;/p&gt;
&lt;p&gt;As an Example:&lt;/p&gt;
&lt;p&gt;An example of this situation may be sorting records by month name. If you were to simply sort your records by the month name, the resulting order would be:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;April&lt;/li&gt;
&lt;li&gt;August&lt;/li&gt;
&lt;li&gt;December&lt;/li&gt;
&lt;li&gt;February&lt;/li&gt;
&lt;li&gt;January&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;.....&lt;/p&gt;
&lt;p&gt;Months are being sorted alphabetically, which is meaningless as a sort order. Ideally your sort order should be in correct chronological order, so how is this achieved?&lt;/p&gt;
&lt;p&gt;The answer is to use the Custom Order Based on Value List option that is available when sorting:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/sortingbyvaluelists-2.png&quot; alt=&quot;sortingbyvaluelists 2&quot; width=&quot;468&quot; height=&quot;73&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here, I have specified to reorder based on a new value list called &quot;Month List&quot;, lets take a look at that value list:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/sortingbyvaluelists-3.png&quot; alt=&quot;sortingbyvaluelists 3&quot; width=&quot;571&quot; height=&quot;629&quot;&gt;&lt;/p&gt;
&lt;p&gt;The value list is setup as a custom value list, and in the correct chronological order. It is this order that the record sort will use. Any matching value found in our sort field will be placed in the order as specified by the value list.&lt;/p&gt;
&lt;p&gt;An Important Thing to Note Here:&lt;/p&gt;
&lt;p&gt;One of the downsides of value lists I find is that when constructing a value list using values in a field, or from a related field or table, any sort order is lost and the values will display in the value list in alphabetical order. If you were to use this method in constructing your value list, and then apply it to a sort as your order, you may find that you lose the sort order you want given the fact the value list is alphabetical.&lt;/p&gt;
&lt;p&gt;This method of reordering sorted records based on a value list is most suited when using a custom values value list. When using this option, you can specify the exact order you want, and the value list will retain your order.&lt;/p&gt;
&lt;p&gt;As always there is a downside - you must explicitly define these values within the value list itself, meaning the value list contents cannot be stored in a field. However, in most situations this is acceptable. For example, the months case is fine because there are only ever 12 months, and their order never changes.&lt;/p&gt;
&lt;p&gt;Back to the Example - Sorting Job Statuses&lt;/p&gt;
&lt;p&gt;For this example I have constructed a simple database containing 10 jobs. Each job has some basic details such as customer, date raised, month raised, job status and priority.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600539-sortingbyvaluelists-4.png&quot; alt=&quot;sortingbyvaluelists 4&quot; width=&quot;600&quot; height=&quot;539&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this solution, I wish for the user to be able to sort jobs by their status. Job statuses however have a very specific order to them - not alphabetical. The status order of jobs has been defined earlier by the owner of this database to be:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Pending&lt;/li&gt;
&lt;li&gt;In Progress&lt;/li&gt;
&lt;li&gt;In Invoicing&lt;/li&gt;
&lt;li&gt;Completed&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;No problem! All that is required is to construct a value list of job statuses in that order. In fact, it is very likely that the value list would already exist as a method for selecting a jobs status.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600427-sortingbyvaluelists-5.png&quot; alt=&quot;sortingbyvaluelists 5&quot; width=&quot;600&quot; height=&quot;427&quot;&gt;&lt;/p&gt;
&lt;p&gt;You will note that a sort field has a little icon that appears beside it. The icon is either the standard for ascending or descending order. However if you choose a custom order, the icon appears different:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/sortingbyvaluelists-6.png&quot; alt=&quot;sortingbyvaluelists 6&quot; width=&quot;135&quot; height=&quot;103&quot;&gt;&lt;/p&gt;
&lt;p&gt;This icon indicates that a custom sort order has been used that is neither ascending nor descending.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600539-sortingbyvaluelists-7.png&quot; alt=&quot;sortingbyvaluelists 7&quot; width=&quot;600&quot; height=&quot;539&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can see in the above picture, the records have been sorted by job status, and are now displayed not in alphabetical order, but a custom defined order as specified by the value list.&lt;/p&gt;
&lt;p&gt;A Final Example, Sorting by Job Priority&lt;/p&gt;
&lt;p&gt;Up until this point, when we have reordered our sort by value list, the exact order of the value list itself has been used.&lt;/p&gt;
&lt;p&gt;Jobs also have a job priority. A jobs priority from lowest to highest is:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Low&lt;/li&gt;
&lt;li&gt;Medium&lt;/li&gt;
&lt;li&gt;High&lt;/li&gt;
&lt;li&gt;Urgent&lt;/li&gt;
&lt;li&gt;Critical&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;A value list has been set up of job priorities in this order, and has been used elsewhere in the solution as the value list used when selecting a jobs status. It is in this order because from a data-entry perspective, the user of this database has requested it from lowest to highest.&lt;/p&gt;
&lt;p&gt;However, when jobs are displayed sorted by their priority, it would make sense to show the highest priority jobs at the top of the list. This will ensure that high priority jobs are not missed at the bottom of the list. Having them at the top makes them clearly visible to users. Lower priority jobs can appear further down the list given that they are not as important.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600427-sortingbyvaluelists-8.png&quot; alt=&quot;sortingbyvaluelists 8&quot; width=&quot;600&quot; height=&quot;427&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is the sort order defined for this example. Records are sorted by job priority, and the custom order based on value list has been used.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600539-sortingbyvaluelists-9.png&quot; alt=&quot;sortingbyvaluelists 9&quot; width=&quot;600&quot; height=&quot;539&quot;&gt;&lt;/p&gt;
&lt;p&gt;The jobs are sorted however from lowest priority to highest, which is not what we want, but is what we would expect given the order of the value list.&lt;/p&gt;
&lt;p&gt;So, is there any way to reverse the order? The answer is yes, but unfortunately there is no nice option to reverse the order.&lt;/p&gt;
&lt;p&gt;The only way to achieve the opposite order is to create a new value list of job priorities in reverse order, and reorder using that list instead. The Sort dialog does not allow you to order by value list in that value lists reversed order.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600427-sortingbyvaluelists-10.png&quot; alt=&quot;sortingbyvaluelists 10&quot; width=&quot;600&quot; height=&quot;427&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here I have specified the order based on a new value list called Job Priorities Reversed&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600539-sortingbyvaluelists-11.png&quot; alt=&quot;sortingbyvaluelists 11&quot; width=&quot;600&quot; height=&quot;539&quot;&gt;&lt;/p&gt;
&lt;p&gt;End result is jobs sorted by priority in order from highest priority to lowest priority.&lt;/p&gt;
&lt;p&gt;Multiple Sort Order Fields using Custom Orders&lt;/p&gt;
&lt;p&gt;You can extend this further to have a sort which uses more than one sort order, and have each use a custom order.&lt;/p&gt;
&lt;p&gt;Consider the following example:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600427-sortingbyvaluelists-12.png&quot; alt=&quot;sortingbyvaluelists 12&quot; width=&quot;600&quot; height=&quot;427&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here I have chosen to sort my jobs by month name, using the custom month order defined in the value list. The second order is job priorities, where I have chosen to sort using the custom value list of job priorities from highest to lowest, the end result is:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600539-sortingbyvaluelists-13.png&quot; alt=&quot;sortingbyvaluelists 13&quot; width=&quot;600&quot; height=&quot;539&quot;&gt;&lt;/p&gt;
&lt;p&gt;Looking at the months first, you can see they are sorted in chronological order from July thru December. Within each month, the jobs are then sorted by priority from highest to lowest. Looking at December as an example jobs are shown from Critical thru Urgent thru to Low.&lt;/p&gt;
&lt;p&gt;Not Just for Sorting Records on a Layout:&lt;/p&gt;
&lt;p&gt;The option to reorder based on a value list is available wherever records can be sorted, this extends to:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Records on a Layout (as shown in this article)&lt;/li&gt;
&lt;li&gt;Sorting a Relationship&lt;/li&gt;
&lt;li&gt;Sorting a Portal&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;In these three situations, the reorder option behaves just like as described in the article.&lt;/p&gt;
&lt;p&gt;Final Thoughts:&lt;/p&gt;
&lt;p&gt;The option to reorder by value list is an often overlooked sort feature, but a very powerful one. It excels when the field(s) being sorted contain relatively few possible values, such as month names, statuses or priorities. The reason being that a custom value list must be used, where explicitly entered values are put directly into the value list. This method would not work quite as well if the field contained many hundred possible values - unless you decided to create a value list containing every possible value in its correct order!&lt;/p&gt;
&lt;p&gt;Example File&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/sortingbyvaluelists/SortingByValueLists.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Tue, 21 Dec 2010 07:41:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/sorting-records-using-your-own-custom-ordering/</guid>
		</item>
		
		<item>
			<title>A Very Nice Way to Format a Sorted Portal Using Conditional Formatting</title>
			<link>https://www.teamdf.com/blogs/a-very-nice-way-to-format-a-sorted-portal-using-conditional-formatting/</link>
			<description>&lt;p&gt;In this article I will demonstrate a very nice way to format a portal using conditional formatting. This method is suitable for portals whose underlying relationship is sorted by a grouping/category field - similar to if it were like a sub-summary report. The easiest way to explain it is to just get stuck in with an example, so here we go....&lt;/p&gt;
&lt;p&gt;In this example I will be using a very simple Customers table. In this table, there are 3 main fields:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Customer ID - the primary key&lt;/li&gt;
&lt;li&gt;Customer Name&lt;/li&gt;
&lt;li&gt;Region&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Each customer has a specific region, so it stands that a region may contain multiple customers. On our layout, we have a portal showing all customers. The relationship this portal is based upon, is sorted by Region, so that in our portal, all customers who belong to the same region, will appear together as shown:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/sortedportalformat-1.png&quot; alt=&quot;sortedportalformat 1&quot; width=&quot;455&quot; height=&quot;319&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now, this could be the end of the story - the records are sorted as you wish, and you can clearly see the region for each customer, but is it really that nice visually? The region name is appearing multiple times in each row, which is quite distracting, and also makes the portal feel cluttered. Also, is there any reason for the region to appear in each row? What if we could have the region appear in the first row for those customers only? Indeed, this is possible with a little conditional formatting.&lt;/p&gt;
&lt;p&gt;The Conditional Formatting&lt;/p&gt;
&lt;p&gt;The conditional formatting calculation I am going to attach to the Region field in the portal is as follows:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Let ([&lt;br&gt;This = Customers Filter::Region ;&lt;br&gt;Record = Customers Filter::zRecordNumber ;&lt;br&gt;Previous = GetNthRecord ( Customers Filter::Region ; Record - 1 )&lt;br&gt;];&lt;br&gt;This = Previous&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;So, what is going on here? The calculation is broken down into simpler chunks using a Let statement to make it easier to follow:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;This = Customers Filter::Region&lt;/pre&gt;
&lt;p&gt;The variable &quot;this&quot; is simply set to the region of the portal row this conditional formatting is evaluating in. Note that each portal row calculates it&#039;s conditional formatting independently of the others, so when I reference the Region, it is evaluating the region for its own portal row only.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Record = Customers Filter::zRecordNumber&lt;/pre&gt;
&lt;p&gt;Perhaps the most complex step in the calculation. zRecordNumber is a special unstored calculation field that is required on the Customers table to achieve this desired effect. The calculation is set to Get ( RecordNumber ). Why? The reason will hopefully become clear soon.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Previous = GetNthRecord ( Customers Filter::Region ; Record - 1 )&lt;/pre&gt;
&lt;p&gt;So, this is the step that ties everything together. This variable will be set to the Region of the previous portal row to the one currently being evaluated, or in other words, the portal row directly above the one evaluating. The GetNthRecord function is able to return the value from a record through a relationship, where you define the exact record number to obtain.&lt;/p&gt;
&lt;p&gt;Going back to the second step now - zRecordNumber is the way in which our conditional formatting calculation is able to obtain it&#039;s own record number in the relationship. So, the 10th record in the relationship (ie the 10th portal row) is able to know that it is #10 by referencing this calculation, the second row knows it is #2, and so on. This is the only way I could find to obtain this information for each portal row. Sadly, there is no Get ( PortalRowNumber ) function, and the closest one - Get ( ActivePortalRowNumber ) - only works if a portal row is active (funny that!).&lt;/p&gt;
&lt;p&gt;When Get ( RecordNumber ) is evaluated through a relationship, the result is the record number of the portal row being evaluated. The function has to be in an unstored calculation on the table - simply referencing &quot;Get ( RecordNumber )&quot; in the conditional formatting calculation will always return 1 for each row - because in this situation it is obtaining the record number of the parent record, which is the same for all portal rows.&lt;/p&gt;
&lt;p&gt;Back to Step:&lt;/p&gt;
&lt;p&gt;So, with that known, the conditional formatting calculation now knows it&#039;s own record number. This is then used in conjunction with GetNthRecord to obtain the previous records Region.&lt;/p&gt;
&lt;p&gt;The Final Step&lt;/p&gt;
&lt;p&gt;The final step in the calculation is the actual conditional test to determine whether the formatting is applied or not. Now, remember that our aim here is to show the region on the first portal row for that regional group. Taking the opposite of this - we wish to HIDE the region on all rows which are not the first row for that region.&lt;/p&gt;
&lt;p&gt;We know the region of the current row, and we know the region of the previous row. Thus, if the current rows region is the same as the previous, then the current row cannot possibly be the first row for that region, and as a result we wish to hide it. Hiding it is done by setting the text colour of the conditional formatting to white.&lt;/p&gt;
&lt;p&gt;If in fact it was the first portal row for a given region, then the previous portal row will be different, thus the conditional formatting test returns false, and no formatting is applied, leaving the region visible.&lt;/p&gt;
&lt;p&gt;What About the First Portal Row&lt;/p&gt;
&lt;p&gt;The first portal row is handled gracefully, as there is no previous portal row, so the region in the first portal row will always be different from the previous. GetNthRecord of the 0 record will return blank.&lt;/p&gt;
&lt;p&gt;Some Limitations:&lt;/p&gt;
&lt;p&gt;It should be noted that there are some limitations to this method. First, it is the relationship that must be sorted here, not the portal itself. The reason is that both the zRecordNumber calculation, and GetNthRecord function, all work at the relationship level, not the portal level.&lt;/p&gt;
&lt;p&gt;Second, this method will not work with portal filtering in FileMaker 11. The reason again is that filtering occurs at the portal level, while the conditional formatting is working at the relationship level. If you wished to use filtering, you would have to filter the relationship instead.&lt;/p&gt;
&lt;p&gt;The End Result&lt;/p&gt;
&lt;p&gt;Putting it all together you end up with something like this:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/sortedportalformat-2.png&quot; alt=&quot;sortedportalformat 2&quot; width=&quot;463&quot; height=&quot;320&quot;&gt;&lt;/p&gt;
&lt;p&gt;Some Further Formatting to Make it Even Nicer&lt;/p&gt;
&lt;p&gt;The above is nice, but it is still lacking something. What it is lacking is some kind of separation between the regions. One region just follows on to the next without any kind of dividing line. Fortunately, we can make a slight adaptation of the conditional formatting we already have used, to produce a separating line.&lt;/p&gt;
&lt;p&gt;First things first - you cannot conditionally format a line object. For this reason, we need to somehow hide the line under some circumstances. This is exactly the same as what we did for the region field.&lt;/p&gt;
&lt;p&gt;In this case, we hide the line by overlaying a conditionally formatted object (a button/text label) , which fills itself the portal background colour:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60053-sortedportalformat-3.png&quot; alt=&quot;sortedportalformat 3&quot; width=&quot;600&quot; height=&quot;53&quot;&gt;&lt;/p&gt;
&lt;p&gt;The picture has been zoomed &amp;amp; exaggerated to illustrate the effect. The green box is a button with no action attached. It sits in front of a grey line. Both objects will be in the portal. The best place to put them is at the top of the first row as close to the top as you can get. Make sure the button has 0 line width (it has one here just so you can see it). The minimum height of the button you can achieve is 4 pixels so make it this.&lt;/p&gt;
&lt;p&gt;The conditional formatting calculation on this is very similar to that of the region field, with one slight modification:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Let ([&lt;br&gt;This = Customers Filter::Region ;&lt;br&gt;Record = Customers Filter::zRecordNumber ;&lt;br&gt;Last = GetNthRecord ( Customers Filter::Region ; Record - 1 )&lt;br&gt;];&lt;br&gt;This = Last or Customers Filter::zRecordNumber = 1&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;The difference here is the last line. We wish to hide the line on the first portal row as it is not required there, so we test if the record number is 1, and if so, we hide the line.&lt;/p&gt;
&lt;p&gt;Putting it all Together&lt;/p&gt;
&lt;p&gt;Here is what you end up with when all the pieces are put together:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/sortedportalformat-4.png&quot; alt=&quot;sortedportalformat 4&quot; width=&quot;451&quot; height=&quot;323&quot;&gt;&lt;/p&gt;
&lt;p&gt;Looks very tidy and nice if I do say so myself! Each regional grouping is separated by a line. No need for region to appear on every line here, and it is clearly obvious what customers belong to what region.&lt;/p&gt;
&lt;p&gt;Taking it Even Further, More Possibilities&lt;/p&gt;
&lt;p&gt;This concludes the article, but if you were wanting to take it further, there are more possibilities to explore:&lt;/p&gt;
&lt;p&gt;Modifying the conditional formatting, so that the regional name is shown every Xth row for that region. This would be useful for example if a region had a large number of customers. If this was the case, then as the user scrolled the portal, they may no longer be able to see the region name, and thus not know what region the customer belongs to. If this were the case, then putting the region name on every 10th row of that region would solve this problem.&lt;/p&gt;
&lt;p&gt;Adapting for use in List-view on a layout. This could be achieved fairly easily given the fact both GetNthRecord, and Get ( RecordNumber ) will operate quite nicely on a found set of records as well as through relationships.&lt;/p&gt;
&lt;p&gt;Example File&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is fully commented to help you fully understand what is going on in the file.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/sortedportalformat/FormattingSortedPortals.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:37:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/a-very-nice-way-to-format-a-sorted-portal-using-conditional-formatting/</guid>
		</item>
		
		<item>
			<title>How Many FM Dialogs Can I Open in 60 seconds... and other Musings</title>
			<link>https://www.teamdf.com/blogs/how-many-fm-dialogs-can-i-open-in-60-seconds-and-other-musings/</link>
			<description>&lt;p&gt;I&#039;ve always wondered how many FileMaker dialogs you can have open at once, or more specifically, how many can you &quot;string&quot; together before hitting the limit, if there is one. So, though a little trial and error, I set out about trying to find the path to the most dialogs, and here is what I came up with:&lt;/p&gt;
&lt;p&gt;What follows is my string of dialogs, and how to get to each:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;File -&amp;gt; Manage -&amp;gt; Custom Menus Manage Custom Menus&lt;/li&gt;
&lt;li&gt;New Menu Set Edit Custom Menu Set&lt;/li&gt;
&lt;li&gt;Click add to select menu Select Menu&lt;/li&gt;
&lt;li&gt;You are now in the Edit Custom Menu&lt;/li&gt;
&lt;li&gt;add a menu item, check &quot;Action&quot; Specify Script Step&lt;/li&gt;
&lt;li&gt;Select &quot;perform script&quot;, hit specify Specify Script&lt;/li&gt;
&lt;li&gt;Hit + to create new script Edit Script &quot;New Script&lt;/li&gt;
&lt;li&gt;8. Add Set Field Script step and go to Specify Field Specify Field&lt;/li&gt;
&lt;li&gt;Click &quot;Specify&quot; next to repetition number Specify Calculation&lt;/li&gt;
&lt;li&gt;Click the TO list &amp;amp; go to &quot;Manage Database&quot; Manage Database&lt;/li&gt;
&lt;li&gt;Select/Add a Text field &amp;amp; go to options Options for Field&lt;/li&gt;
&lt;li&gt;Go to Validation, Member of Value List, manage value lists&lt;/li&gt;
&lt;li&gt;Create a New Value List Edit Value List&lt;/li&gt;
&lt;li&gt;Click &quot;Use values from field&quot; Specify Fields for Value List&lt;/li&gt;
&lt;li&gt;Click use values from first field, manage relationships&lt;/li&gt;
&lt;li&gt;Create a relationship &amp;amp; click on relationship Edit Relationship&lt;/li&gt;
&lt;li&gt;Click sort records Sort Records&lt;/li&gt;
&lt;li&gt;Select field, &quot;reorder based on summary field specify&quot; Specify Field&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;... That&#039;s about as far as I got, before I hit an interesting point, because once you get here, you can then...&lt;/p&gt;
&lt;p&gt;19. Manage Relationships&lt;br&gt;20. Repeat from Step 16-20 ad infinite&lt;/p&gt;
&lt;p&gt;Indeed, you can keep repeating this step and opening more and more and more manage relationships dialogs - of course they&#039;re all modal so you can only work in one at a time.&lt;/p&gt;
&lt;p&gt;Then I got to thinking - well, what happens if I make a change in one of my manage relationships dialogs, and then &quot;wind back&quot; the dialogs to the previous manage relationships dialog, what would I find?&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600264-howmanydialogs-1.png&quot; alt=&quot;howmanydialogs 1&quot; width=&quot;600&quot; height=&quot;264&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here are two manage relationship dialogs I have open. The one on the left is the front-most and the only one I can edit at this time. I have added the Yellow TO. From here, I wound back the dialogs by clicking &quot;OK&quot; on them all, effectively saving my changes rather than discarding.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600450-howmanydialogs-2.png&quot; alt=&quot;howmanydialogs 2&quot; width=&quot;600&quot; height=&quot;450&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now I have wound back to my first manage relationships dialog. Interesting to note, the yellow TO is nowhere to be found - does this mean it has not yet been created? Is the TO just failed to show up because of a FileMaker bug? In any event, I leave my mark in this dialog by adding another green TO. Finally I wind my way allllllll the way back to the start, OK&#039;ing every dialog I come across.&lt;/p&gt;
&lt;p&gt;When I finish, I go back into the relationship graph to see what I have:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600449-howmanydialogs-3.png&quot; alt=&quot;howmanydialogs 3&quot; width=&quot;600&quot; height=&quot;449&quot;&gt;&lt;/p&gt;
&lt;p&gt;Interesting - both TO&#039;s are there ! by committing every dialog all the way back to the start, basically everything I did was saved, including both changes to the relationship graph from different dialogs.&lt;/p&gt;
&lt;p&gt;Hmmm, I think to myself:&lt;/p&gt;
&lt;p&gt;This leads me to try a few more tests, what happens if:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;I delete a table occurrence in the front-most dialog, but then try to use it in a previous dialog&lt;/li&gt;
&lt;li&gt;I add a Table occurrence in the front-most dialog, then try to add one with the exact same name in the previous one&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Here&#039;s What Happened:&lt;/p&gt;
&lt;p&gt;In the first case, interestingly, when I deleted a few table occurrences in my front-most relationship dialog, and then rolled back to the previous one, they did disappear from the dialog when I returned to it. Granted, I did have one of the relationships selected of the deleted Table occurrence which may have had a factor, but in any event they disappeared.&lt;/p&gt;
&lt;p&gt;This time, I cancelled my changes as I rolled back in an attempt to get them back, were they really gone? the answer was no. Once I returned to the original main &quot;Manage Database&quot; dialog I had open, and tried to cancel this, I was asked to revert my changes, and upon doing so, the table occurrences came back.&lt;/p&gt;
&lt;p&gt;FileMaker does a great job at keeping it&#039;s transactions nicely separated, even though it appears I have many many dialogs going, They always all relate back to a single dialog, and anything done in subsequent dialogs can always be reverted.&lt;/p&gt;
&lt;p&gt;And in the Second Scenario?&lt;/p&gt;
&lt;p&gt;This one was particular unexpected. In my front-most relationship dialog, I added a table occurrence &quot;Test&quot;. I then OK&#039;d my dialogs back to the previous one. Test was not on it, and when I went to add another Table occurrence called &quot;Test&quot;, FileMaker automatically renamed it to Test 2 - even though visibly there was no &quot;Test&quot; table occurrence on the graph. Filemaker knew I had created the Test TO in another dialog, and even though this one was not showing it, it was still smart enough to not let me name another Test. Upon OK&#039;ing all the dialogs and then jumping back into the relationship graph, both Test, and Test 2 were present.&lt;/p&gt;
&lt;p&gt;Final Thoughts:&lt;/p&gt;
&lt;p&gt;If you want to play around with this, you don&#039;t need to repeat all the steps I mention above, you can bring up multiple relationship dialogs by:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Going into relationship graph&lt;/li&gt;
&lt;li&gt;Ensure you have a relationship, click on it and click sort&lt;/li&gt;
&lt;li&gt;Choose a field and choose &quot;reorder based on summary field&quot;&lt;/li&gt;
&lt;li&gt;In this dialog, click the To list and choose &quot;manage relationships&quot;&lt;/li&gt;
&lt;li&gt;Repeat...&lt;/li&gt;
&lt;/ol&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:36:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/how-many-fm-dialogs-can-i-open-in-60-seconds-and-other-musings/</guid>
		</item>
		
		<item>
			<title>The Replace Field Contents Command - Why It Is So Cool</title>
			<link>https://www.teamdf.com/blogs/the-replace-field-contents-command-why-it-is-so-cool/</link>
			<description>&lt;p&gt;The Replace Field Contents command/script step is a very powerful tool for updating field values across records in your found set.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/replacefieldcontents-1.png&quot; alt=&quot;replacefieldcontents 1&quot; width=&quot;502&quot; height=&quot;417&quot;&gt;&lt;/p&gt;
&lt;p&gt;The above version of the dialog, is the one that you will see when using the script step. The dialog appears slightly different when running it via the command from the Records menu. There are three possible options you can use:&lt;/p&gt;
&lt;p&gt;Replace with Current Contents&lt;/p&gt;
&lt;p&gt;This refers to whatever the value is in the field you are replacing on the current record you are on.&lt;/p&gt;
&lt;p&gt;This is quite useful, most particularly when you are running the replace manually using the command. Imagine you are on a layout and wish to set &quot;Hello&quot; into records in your found set. The easiest way, is to put &quot;Hello&quot; into the field on your current record, then run the command.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/replacefieldcontents-2.png&quot; alt=&quot;replacefieldcontents 2&quot; width=&quot;502&quot; height=&quot;417&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can see the dialog will show you what records in the found set will be set to. There is another way to get the word &quot;Hello&quot; into the field using a calculation, but this is the fastest way when using the menu command.&lt;/p&gt;
&lt;p&gt;Some things to note:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The # of records that will be updated is displayed in the first sentence.&lt;/li&gt;
&lt;li&gt;The command works on a found set of records, if you have no found set, the command is unavailable.&lt;/li&gt;
&lt;li&gt;When using the command, it is required your cursor be in the field you wish to update. For the script step option, this is not required, because the script step allows you to specify the field being replaced.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Replace with Serial Numbers&lt;/p&gt;
&lt;p&gt;Use this option to set sequential numbers into each record in your found set. The first record in the found set is assigned the initial value. Note that it does not matter what record of the found set you are on initially, numbers will always begin from the first record.&lt;/p&gt;
&lt;p&gt;If the field you are updating has the auto-enter serial number option enabled, you are given the ability to update the next serial number for that.&lt;/p&gt;
&lt;p&gt;Some things to note:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Both the next serial number, AND the increment value will be updated within the fields auto-entry option, providing the update option is checked.&lt;/li&gt;
&lt;li&gt;If checked, the next serial value is value of last record in the found set serial number, plus the new increment value set in the command you just run.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Replace with Calculated Result&lt;/p&gt;
&lt;p&gt;Perhaps the most powerful option,this allows you to define a calculation which will then be applied to each record in the found set. The calculation you define is evaluated independently for each record.&lt;/p&gt;
&lt;p&gt;For example, take a table with 2 fields - A and B. The table contains 3 records. Lets say now that on our found set of all records, we wish to replace the contents of field A. The calculation used is &quot;B + 10&quot;:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table cellspacing=&quot;0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Value of A&lt;/th&gt;&lt;th&gt;Value of B&lt;/th&gt;&lt;th&gt;New Value of A&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;99&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;As you can see, the calculation is applied to each record individually.&lt;/p&gt;
&lt;p&gt;Some things to note:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Referencing related values within the calculation works on a per-record basis.&lt;/li&gt;
&lt;li&gt;As mentioned in the &quot;current contents&quot; section - the other way to put the word &quot;Hello&quot; into the field on each record, would be to make the calculation be the string &quot;Hello&quot;.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;After the replace, a cautionary table about record locking.&lt;/p&gt;
&lt;p&gt;If the replace runs successfully, you will see nothing afterwards - the fact that you see no dialog means it all worked. However, if something went wrong, you may see the following kind of message:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/replacefieldcontents-3.png&quot; alt=&quot;replacefieldcontents 3&quot; width=&quot;500&quot; height=&quot;310&quot;&gt;&lt;/p&gt;
&lt;p&gt;This dialog - as informative as it tries to be - only tells you that one or more of the records in your found set, were unable to be updated. There are two reasons why this can happen. The first is that another user of the database is modifying one of the records in your found set. Because of this, they have the lock on that record, and so you are unable to update the record.&lt;/p&gt;
&lt;p&gt;Important Note about Errors&lt;/p&gt;
&lt;p&gt;FileMaker unfortunately does not tell you which record(s) failed. This is a shame, especially if your replace is run using the script step. If you are updating hundreds of records with important data, then having some fail could cause significant issues later on. Not knowing which ones failed means you either have to re-run the replace at a later time, or bite the bullet and hope nothing bad crops up :) In some cases, the replace field contents step might not be the best method of record updating, and you may instead opt for a looping script, that tries to obtain record lock on each record before attempting to update the field contents.&lt;/p&gt;
&lt;p&gt;Even more perilous, is running the replace field contents script step, with the &quot;perform without dialog&quot; option checked. While this will suppress the initial parameters dialog, it will NOT suppress the error dialog if any records were not be updated. To suppress this dialog, you must prefix the replace field contents step, with the Set Error Capture step.&lt;/p&gt;
&lt;p&gt;If you suppress the error dialog, you may still need to check for errors in your script. You can do this by evaluating the Get(LastError) function. If the replace failed to update record(s), the error code is 201.&lt;/p&gt;
&lt;p&gt;Replacing Related Field Contents&lt;/p&gt;
&lt;p&gt;The Replace Field Contents step is perhaps more used, and easier to understand, when it is used on a field which is on the found set table. What you may not know, is that the command can work on related fields as well.&lt;/p&gt;
&lt;p&gt;If running the replace via command, the rule is the same - place your mouse cursor in a related field on the layout, and run the command.&lt;/p&gt;
&lt;p&gt;The replace will update EVERY related record of EVERY record in the found set!&lt;/p&gt;
&lt;p&gt;This concept is critical, you may end up replacing more related records than you had anticipated. Often, you may wish to only update all related records of a single record. To do this, you must make the found set your current record only. You can do this by using the following three commands/script steps in order:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Show All Records&lt;/li&gt;
&lt;li&gt;Omit Record&lt;/li&gt;
&lt;li&gt;Show Omitted Only&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;The power of the replace field contents step to update related record values - as well as records in the found set - is very useful and can save time in scripting, but it must be used with great care because it suffers from the same record updating issues as previously mentioned - if not more so !&lt;/p&gt;
&lt;p&gt;With all it&#039;s potential pitfalls, it can greatly reduce the number of script steps you need to use to achieve certain tasks.&lt;/p&gt;
&lt;p&gt;As a final example, consider a parent table &quot;Customer&quot; , and child table &quot;Contacts&quot;. For various reasons, the customer name is needed to be stored on each of the Contact records. The name can intially be set onto the child records using an auto-enter calculation on the contacts &quot;customer name&quot; field. But what if the customers name changes after the contact record is created? The auto-enter calculation will not pick up the change. Instead, the change must be forcibly updated on each of the child contact records.&lt;/p&gt;
&lt;p&gt;Assuming you are currently on the customer record, you can achieve this many ways, here are 4:&lt;/p&gt;
&lt;p&gt;#1: A long way, but potentially safer way&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Set Variable [ $CustomerName ; Customers::Name ]&lt;br&gt;Set Variable [ $CustomerID ; Customers::Customer ID ]&lt;br&gt;Go to Layout [ Contacts ]&lt;br&gt;Enter Find Mode []&lt;br&gt;Set Field [ Contacts::CustomerID ; $CustomerID ]&lt;br&gt;Set Error Capture [ ON ]&lt;br&gt;Perform Find&lt;br&gt;Set Error Capture [ OFF ]&lt;br&gt;Loop&lt;br&gt;Set Field [ Contacts::Customer Name ; $CustomerName ]&lt;br&gt;Go to Record/Request/Page [ Next ; Exit After Last ]&lt;br&gt;End Loop&lt;br&gt;Go to Layout [ Original Layout ]&lt;/pre&gt;
&lt;p&gt;#2: Another long way&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Set Variable [ $CustomerName ; Customers::Name ]&lt;br&gt;Set Variable [ $CustomerID ; Customers::Customer ID ]&lt;br&gt;Go to Layout [ Contacts ]&lt;br&gt;Enter Find Mode []&lt;br&gt;Set Field [ Contacts::CustomerID ; $CustomerID ]&lt;br&gt;Set Error Capture [ ON ]&lt;br&gt;Perform Find&lt;br&gt;Set Error Capture [ OFF ]&lt;br&gt;Replace Field Contents [ No Dialog ; Customer Name ; $CustomerName ]&lt;br&gt;Go to Layout [ original layout ]&lt;/pre&gt;
&lt;p&gt;#3: A shorter way (but essentially the same way)&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Set Variable [ $CustomerName ; Customers::Name ]&lt;br&gt;If [ not isEmpty ( Contacts::Contact ID ) ]&lt;br&gt;  Go to Related Records [ Contacts ; using layout &quot;Contacts&quot; ]&lt;br&gt;  Replace Field Contents [ No Dialog ; Customer Name ; $CustomerName ]&lt;br&gt;  Go to Layout [ Original Layout ]&lt;br&gt;End If&lt;/pre&gt;
&lt;p&gt;#4: Short, sweet, possibly nasty (setting thru relationship)&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Replace Field Contents [ No Dialog ; Contacts::Customer Name ; Customer Name ]&lt;/pre&gt;
&lt;p&gt;Final Thoughts:&lt;/p&gt;
&lt;p&gt;Hopefully this article has shone some light on the replace field contents step, and what can and cannot be achieved with using it. While it is a very powerful step, with that comes a responsibility to ensure that it is used correctly and without error.&lt;/p&gt;
&lt;p&gt;Looking at the various methods in the code above, #4 is definitely the method that I use the most, even though I have rated it as one of the most dangerous. In fact, it is no more or less dangerous than methods 2,3 and 4 - given that all of these steps use the replace step. So if you are going to use any of those 3 methods, you may as well go with the easiest one to write !&lt;/p&gt;
&lt;p&gt;I rated method 1 as the safest. It is not shown in the code, but that method - of doing each record update explicitly - allows you the ability to check for record locking before doing your field update. This may be considered overkill for most simple solutions, but depending on how critical it is that records are updated with the correct field values, this may be the safest approach.&lt;/p&gt;
&lt;p&gt;Be careful out there !&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:35:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/the-replace-field-contents-command-why-it-is-so-cool/</guid>
		</item>
		
		<item>
			<title>Safe Scripting: Check Before You Do Anything!</title>
			<link>https://www.teamdf.com/blogs/safe-scripting-check-before-you-do-anything/</link>
			<description>&lt;p&gt;When writing a script to carry out a particular task, ask yourself&lt;/p&gt;
&lt;blockquote&gt;&quot;What conditions need to be true for this script to run properly?&quot;&lt;/blockquote&gt;
&lt;p&gt;Sometimes, a script will do something which can potentially fail, and cause a cascade effect or errors, IF the initial conditions were incorrect. It is always a good idea to check for suitable conditions before doing anything in the script.&lt;/p&gt;
&lt;p&gt;Updating a record&lt;/p&gt;
&lt;p&gt;Consider a script that carries out a number of various operations on the current record. What do we need for the script to run properly? The answer is - a record. If your found set consists of 0 records, then why bother running the script? This is a potential scenario, for example, if you do a search which yields no results, your found set will be empty. If a user then tries to run the script, chances are pretty much every script step is going to fail.&lt;/p&gt;
&lt;p&gt;This can be avoided by inserting the following few lines of code at the beginning of your script:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;If [ Get ( FoundCount ) = 0 ]&lt;br&gt; Exit Script []&lt;br&gt;End If&lt;/pre&gt;
&lt;p&gt;This simple If statement will check if you have at least one record in your found set, otherwise it will exit immediately.&lt;/p&gt;
&lt;p&gt;In fact, it is good practice to follow this guideline when writing all of your scripts. You should first carry out any checks or tests to ensure conditions are right for the script to begin executing. Exit the script immediately if any of the conditions are not right. After your error checking, just begin the script as usual - if execution reaches the point beyond your tests, you know that the tests all passed.&lt;/p&gt;
&lt;p&gt;Structuring your error checking&lt;/p&gt;
&lt;p&gt;Consider the following example - you have a script that is programmed to duplicate the current record, and do some various actions on the new record such as setting fields, BUT ONLY if the value of the &#039;status&#039; field is &quot;Completed&quot;.&lt;/p&gt;
&lt;p&gt;Quite often, this script is written in the following style:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;If [ Status â  &quot;Completed&quot; ]&lt;br&gt;   Show Custom Dialog [ &quot;Error&quot; ; &quot;Cannot duplicate if record is completed&quot; ]&lt;br&gt;Else&lt;br&gt;   Duplicate Record&lt;br&gt;   Set Field [ a ; &quot;a&quot; ]&lt;br&gt;   Set Field [ b ; &quot;b&quot; ]&lt;br&gt;   etc.....&lt;br&gt;   Show Custom Dialog [ &quot;Done&quot; ; &quot;Record Duplicated&quot; ]&lt;br&gt;End If&lt;/pre&gt;
&lt;p&gt;While there is nothing particularly wrong with this style, it can make for a script that is difficult to read. Now, consider the alternate style, of error checking, followed by carrying out the action:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;/* Check for suitable conditions */&lt;br&gt;If [ Status â  &quot;Completed&quot; ]&lt;br&gt;   Show Custom Dialog [ &quot;Error&quot; ; &quot;Cannot duplicate if record is completed&quot; ]&lt;br&gt;   Exit Script []&lt;br&gt;End If&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;/* If script execution gets here, all tests successful */&lt;br&gt;Duplicate Record&lt;br&gt;Set Field [ a ; &quot;a&quot; ]&lt;br&gt;Set Field [ b ; &quot;b&quot; ]&lt;br&gt;etc.....&lt;br&gt;Show Custom Dialog [ &quot;Done&quot; ; &quot;Record Duplicated&quot; ]&lt;/pre&gt;
&lt;p&gt;The main difference is readability - all of your error tests are at the start of the script, and can quite easily be separated for ease of reading. You can group many checks by using &quot;Else If&quot; , or you can keep them individual using separate If/End If blocks.&lt;/p&gt;
&lt;p&gt;The other difference is indenting of script steps - the majority of script steps are in the duplication area of the script, it is nicer to have the majority of the script not indented, rather than nested inside an If statement.&lt;/p&gt;
&lt;p&gt;Checks within your script execution&lt;/p&gt;
&lt;p&gt;Checking for suitable conditions may not necessarily only occur at the beginning of your script, sometimes they are required mid-way through your scripts execution.&lt;/p&gt;
&lt;p&gt;Taking the first example one step further, lets assume this time that the record we are duplicating has potentially many child records that are displayed in a portal on the layout. When we duplicate the parent record, we also need to create duplicates of all of the children records also.&lt;/p&gt;
&lt;p&gt;Our first check still stands - we can only duplicate when the record status is Completed. Even if the record has no child records, we still need to duplicate the parent record. So what happens when it comes time to duplicate the children?&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;/* Check for suitable conditions */&lt;br&gt;If [ Status â  &quot;Completed&quot; ]&lt;br&gt;   Show Custom Dialog [ &quot;Error&quot; ; &quot;Cannot duplicate if record is completed&quot; ]&lt;br&gt;   Exit Script []&lt;br&gt;End If&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;/* If script execution gets here, all tests successful */&lt;br&gt;Duplicate Record&lt;br&gt;Set Field [ a ; &quot;a&quot; ]&lt;br&gt;Set Field [ b ; &quot;b&quot; ]&lt;br&gt;Set Variable [ $ParentID ; Parent::ID ]&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;/* Now, duplicate the children records */&lt;br&gt;Go to Related Record [ show only related records; from table &quot;Child&quot; ; using layout (Child) ]&lt;br&gt;Loop&lt;br&gt;   Duplicate Record/Request&lt;br&gt;   Set Field [ Child::Parent ID ; $ParentID ]&lt;br&gt;   Omit Record&lt;br&gt;   Go to Record/Request/Page [ First ]&lt;br&gt;   Omit Record&lt;br&gt;   Exit Loop If [ Get ( FoundCount ) = 0 ]&lt;br&gt;End Loop&lt;br&gt;Go to Layout [ Original Layout ]&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Show Custom Dialog [ &quot;Done&quot; ; &quot;Record Duplicated&quot; ]&lt;/pre&gt;
&lt;p&gt;Here, we test for the parent records condition, then we duplicate the parent record. Next, the script uses the go to related record step to make the found set be that of the children records, on the children layout, it then loops through the records, duplicating them and linking them to the new parent record, before returning to the original layout.&lt;/p&gt;
&lt;p&gt;NEVER DO THIS !!!!&lt;/p&gt;
&lt;p&gt;The script above fails to test whether there are any children records before it executes the duplication part! If there are no children records, then the Go to Related Records script step will NOT switch layout.&lt;/p&gt;
&lt;p&gt;As a result, after the go to related record step, the layout &amp;amp; found set will remain exactly what it is on the Parent layout - the script continues and starts to duplicate parent records - duplicating every single parent record in the found set ! - This is a classic example of failing to check for error, and a script cascading out of control.&lt;/p&gt;
&lt;p&gt;It is crucial that you script defensively, checking for any potential issue before it happens!&lt;/p&gt;
&lt;p&gt;Now, consider the same script, with a small modification before the Go to Related Record code:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;/* Now, duplicate the children records */&lt;br&gt;If [ not isEmpty ( Child::Child ID ) ]&lt;br&gt;   Go to Related Record [ show only related records; from table &quot;Child&quot; ; using layout (Child) ]&lt;br&gt;   Loop&lt;br&gt;      Duplicate Record/Request&lt;br&gt;      Set Field [ Child::Parent ID ; $ParentID ]&lt;br&gt;      Omit Record&lt;br&gt;      Go to Record/Request/Page [ First ]&lt;br&gt;      Omit Record&lt;br&gt;      Exit Loop If [ Get ( FoundCount ) = 0 ]&lt;br&gt;   End Loop&lt;br&gt;   Go to Layout [ Original Layout ]&lt;br&gt;End If&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Show Custom Dialog [ &quot;Done&quot; ; &quot;Record Duplicated&quot; ]&lt;/pre&gt;
&lt;p&gt;Here, we are making use of the fact that a relationship exists between the parent &amp;amp; child records. We are doing a test to ensure that there exists at least one child record through the relationship. This is done by using the isEmpty function, checking the primary key field on the children table. A primary key field is guaranteed to have a value in it for every record. So by checking for the existence of a value through the relationship - we are actually checking for the existence of a record. All we care about is if there is at least one record, so this test is sufficient.&lt;/p&gt;
&lt;p&gt;If there is a record through the relationship, then the block of code for duplicating child records can execute, otherwise the If statement contents is not executed at all.&lt;/p&gt;
&lt;p&gt;Earlier, I noted that you should try to avoid indenting large blocks of code if at all possible - unfortunately this is one time where it is not possible when doing a check like this (FileMaker lacks the ability to &quot;go to&quot; a specific part of a script, thus bypassing a block of code).&lt;/p&gt;
&lt;p&gt;One alternative you could employ however, is to create a new script which is responsible for duplicating child records, and your code can then be tidied up as such:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;/* Now, duplicate the children records */&lt;br&gt;If [ not isEmpty ( Child::Child ID ) ]&lt;br&gt;   Perform Script [ &quot;Duplicate Child Records&quot; ]&lt;br&gt;End If&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Show Custom Dialog [ &quot;Done&quot; ; &quot;Record Duplicated&quot; ]&lt;/pre&gt;
&lt;p&gt;Final Thoughts:&lt;/p&gt;
&lt;p&gt;The more defensive you are with your scripting, the less problems you will have later on. It is a good idea to ensure at the beginning of your script that you test for the conditions (or lack of) that need to be present for the script to execute correctly, such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Whether you have a record&lt;/li&gt;
&lt;li&gt;Whether one or more field contents is what you need them to be&lt;/li&gt;
&lt;li&gt;Whether you have any related records if required&lt;/li&gt;
&lt;li&gt;Anything else you can think of that may need to be true in order for the script to run properly&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Create yourself a section at the beginning of your script to place these checks, you can use comment script steps to detail each test, and to keep the tests separate from the actual execution of the rest of the script.&lt;/p&gt;
&lt;p&gt;Checking for tests at the beginning of the script not only saves the script executing incorrectly later on, it also saves time by not running the script if conditions are not right. While some scripts might run without trouble even if conditions are not right, it will save time to not run them at all rather than run them and have them do nothing of any use !&lt;/p&gt;
&lt;p&gt;Error and condition checking is not restricted to just the beginning of your scripts, it may be necessary to test for conditions mid-way through a scripts execution. If possible, try to test for the condition before running the script action - this will save you post-action error checking. Better to not do the action at all, rather than do it, and then have to check if something went wrong, and restore anything that may have happened.&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:35:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/safe-scripting-check-before-you-do-anything/</guid>
		</item>
		
		<item>
			<title>Join My Table Pt 3 - Putting on the Finishing Touches &amp; Extra Features</title>
			<link>https://www.teamdf.com/blogs/join-my-table-pt-3-putting-on-the-finishing-touches-extra-features/</link>
			<description>&lt;p&gt;In part two, I demonstrated how to implement the basics of the join table solution in FileMaker. While the solution works fine as an illustration for join tables, it lacked many of the basic interface features that would make it a usable solution.&lt;/p&gt;
&lt;p&gt;In part three, I will show how to implement some of these features, namely the following:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Better selection of a Student for an Enrollment&lt;/li&gt;
&lt;li&gt;Deletion of Enrollments&lt;/li&gt;
&lt;li&gt;Prevention of over-enrolling a course&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Better Selection of a Student:&lt;/p&gt;
&lt;p&gt;In part two, selection of a student for a new enrollment consisted of knowing the students ID number and entering it into the field. There was no feedback of whom the student was at any point not very useful for anybody.&lt;/p&gt;
&lt;p&gt;A much better way would be to build a value list of students, and allow the user to pick from a pre-defined list. This will give them a visual on the student names. For starters, we will just create a basic value list for students.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Join-My-Table-Part-3/joinmytable-3-1.png&quot; alt=&quot;joinmytable 3 1&quot; width=&quot;500&quot; height=&quot;405&quot;&gt;&lt;/p&gt;
&lt;p&gt;We have used the existing Students table occurrence to build the value list, which has also been setup to show all students. This value list uses the option to display a second value. Rather than deal with the students ID number, we have chosen to display the students full name as the displayed field. Underneath, the students ID is still being chosen and inserted into our Enrollments::Student ID field.&lt;/p&gt;
&lt;p&gt;Now, attach the value list to the Enrollments::Student ID field in the Enrollments portal. You will see that the students full name is instantly displayed if you are using the pop-up menu option.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Join-My-Table-Part-3/joinmytable-3-2.png&quot; alt=&quot;joinmytable 3 2&quot; width=&quot;500&quot; height=&quot;218&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now students can be selected for an enrollment via the pop-up menu. Now, this implementation is still not perfect. For example, there is no restriction on enrolling the same student twice. Also, if you have a large number of students, a pop-up menu is not the best option. A better option would be to use a drop-down menu, which brings with it some advantages and disadvantages. For now, we will stick with the popup-menu to demonstrate the technique, but may come back to these issues in a future article.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;Deletion of an Enrollment:&lt;/p&gt;
&lt;p&gt;This is a simple one, but a necessary one. We need some way to delete an enrollment. By far the easiest way is to insert a button into the enrollments portal, and attach to it the single script action Delete Portal Row. If you disable the dialog within this script step, the enrollment will be deleted instantly.&lt;/p&gt;
&lt;p&gt;Sometimes however, this might be a dangerous action. Hitting the delete button by accident will cause the enrollment to be deleted right away, so you might want to ask the user for confirmation before deleting. Whether a confirmation is ever required is a topic that could be debated endlessly, but the technique would be as follows. First, it is going to require a new script, called Delete Enrollment. The script itself would look something like:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Join-My-Table-Part-3/joinmytable-3-3.png&quot; alt=&quot;joinmytable 3 3&quot; width=&quot;500&quot; height=&quot;230&quot;&gt;&lt;/p&gt;
&lt;p&gt;A custom dialog is presented to the user, asking them if they really wish to delete the enrollment. The users action is then captured via the Get ( LastMessageChoice ) function. 1 corresponds to the default button action, typically (though you can specify any action for the default button). If the user has clicked OK, we delete the portal row, otherwise we don&#039;t.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Prevention of Over Enrolling a Course:&lt;/p&gt;
&lt;p&gt;For this feature, we are going to need to record exactly how many enrollments are permitted for a given course. This is going to be done by introducing a new field into the Courses table called Max Enrollments, type number.&lt;/p&gt;
&lt;p&gt;We create enrollments currently by using the relationship option Allow creation of records in this table via this relationship. This has been fine up until this point. But now that we wish to control how many enrollments are created, it is going to make more sense to disable this feature, and script our enrollment creation instead. By scripting the creation process, we can check whether the maximum number of enrollments has been reached, and prevent the user from adding more gracefully. (also, not to mention that having a blank portal row in the enrollments portal as a means to create enrollments is not exactly intuitive for users).&lt;/p&gt;
&lt;p&gt;For this, we will need to do three things:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Disable the relationship creation option.&lt;/li&gt;
&lt;li&gt;Place an Add Enrollment button to the layout&lt;/li&gt;
&lt;li&gt;Create a script Add Enrollment to handle the creation of enrollments.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The script is going to need to do the following things:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Determine if the maximum number of enrollments reached&lt;/li&gt;
&lt;li&gt;If yes, then do not create a new enrollment.&lt;/li&gt;
&lt;li&gt;If no, then create an enrollment.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Here is the script might look like:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Join-My-Table-Part-3/joinmytable-3-5.png&quot; alt=&quot;joinmytable 3 5&quot; width=&quot;500&quot; height=&quot;280&quot;&gt;&lt;/p&gt;
&lt;p&gt;The first thing this script does is two error checks:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;If the max number of enrollments field has not been set, then do not proceed, exit.&lt;/li&gt;
&lt;li&gt;If the number of course enrollments matches the limit, then do not proceed, exit.&lt;/li&gt;
&lt;li&gt;If these error checks pass, then create the enrollment, and set the course ID into it.&lt;/li&gt;
&lt;li&gt;Finally, go back to the Courses layout, and place the user on the new enrollment.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Join-My-Table-Part-3/joinmytable-3-6.png&quot; alt=&quot;joinmytable 3 6&quot; width=&quot;498&quot; height=&quot;250&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here you can see the new layout design. The blank portal row for creation of enrollments is gone. In its place is an Add Enrollment button. The new field Max Enrollments is also present, and has been set to 3. This means that we should only be allowed to create three enrollments.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Join-My-Table-Part-3/joinmytable-3-7.png&quot; alt=&quot;joinmytable 3 7&quot; width=&quot;499&quot; height=&quot;230&quot;&gt;&lt;/p&gt;
&lt;p&gt;It may be a little difficult from this picture to tell what has happened, but I have reached my limit of three enrollments. Now, clicking the Add Enrollment button does nothing.&lt;/p&gt;
&lt;p&gt;Can this be made any more intuitive to the user? Well, we could easily place a custom dialog into our Add Enrollment script when the user tries to click the button when the maximum number of enrollments is reached. OR, we can use conditional formatting to convey to the user visually that this is the case, saving them the attempt at clicking the button.&lt;/p&gt;
&lt;p&gt;First, we can conditionally format the button to appear inactive when the maximum number of enrollments is reached:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Join-My-Table-Part-3/joinmytable-3-8.png&quot; alt=&quot;joinmytable 3 8&quot; width=&quot;499&quot; height=&quot;89&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Join-My-Table-Part-3/joinmytable-3-9.png&quot; alt=&quot;joinmytable 3 9&quot; width=&quot;500&quot; height=&quot;358&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Join-My-Table-Part-3/joinmytable-3-10.png&quot; alt=&quot;joinmytable 3 10&quot; width=&quot;500&quot; height=&quot;242&quot;&gt;&lt;/p&gt;
&lt;p&gt;The same type of conditional formatting can be applied to the Max Enrollments field also if you wish.&lt;/p&gt;
&lt;p&gt;Every solution presents its own problems. As you may have realised, there is nothing stopping a user from increasing the max enrollments number, creating enrollments, and then reducing the max enrollments number. This is a way for a user to bypass the restriction imposed on the Add Enrollment button. I won&#039;t go into detail as to how this can be resolved, but some options would be:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Field Validation on the Max Enrollments field, so it can never be less than the number of enrollments that exist&lt;/li&gt;
&lt;li&gt;Script the setting/changing of the Max Enrollments Field&lt;/li&gt;
&lt;li&gt;Script Triggers to prevent a user from modifying it to a number less than the number of enrollments that exist.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;All would be viable solutions, and perhaps might be discussed in a future article.&lt;/p&gt;
&lt;p&gt;This concludes the series on Join Tables for now. Hopefully you have learned something out of these articles, and perhaps picked up a few tips and techniques along the way which will help you turn your basic join table, into something more powerful and user friendly.&lt;/p&gt;
&lt;p&gt;Example File:&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and the other two parts to the &quot;Join My Table&quot; series of articles. It is fully commented to help you fully understand what is going on in the file.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/blog-images/Join-My-Table-Part-3/JoinMyTable.zip&quot; target=&quot;_blank&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:33:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/join-my-table-pt-3-putting-on-the-finishing-touches-extra-features/</guid>
		</item>
		
		<item>
			<title>Join My Table Pt 2 - Building the Example Solution</title>
			<link>https://www.teamdf.com/blogs/join-my-table-pt-2-building-the-example-solution/</link>
			<description>&lt;p&gt;This implementation assumes you have a basic concept of relational database theory, in particular the use of primary and foreign keys in tables.&lt;/p&gt;
&lt;p&gt;As a brief catchup, a primary key is a field in a table which has a unique value for each record. A perfect example would be a serial number field, which has a different number for each record. As good database practice, every table in your solution should have a primary key field, regardless of whether it is used or not.&lt;/p&gt;
&lt;p&gt;A foreign key on the other hand, is a field in a table, which contains the primary key value of a record from another table. This is how two records in different tables are linked/related to one another, and indeed is how we are going to link an ENROLLMENT to both a STUDENT and a COURSE.&lt;/p&gt;
&lt;p&gt;Table Setup&lt;/p&gt;
&lt;p&gt;This solution is going to require the three tables mentioned above. It is very straightforward to create the tables. Each table will require a primary key, plus whatever fields you wish to capture information for, as a very basic example:&lt;/p&gt;
&lt;h4&gt;STUDENTS:&lt;/h4&gt;
&lt;ul&gt;&lt;li&gt;Student ID (Primary key)&lt;/li&gt;
&lt;li&gt;First Name&lt;/li&gt;
&lt;li&gt;Last Name&lt;/li&gt;
&lt;li&gt;Phone Number&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;COURSES:&lt;/h4&gt;
&lt;ul&gt;&lt;li&gt;Course ID (Primary key)&lt;/li&gt;
&lt;li&gt;Course Name&lt;/li&gt;
&lt;li&gt;Location&lt;/li&gt;
&lt;li&gt;Start Time&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;ENROLLMENTS:&lt;/h4&gt;
&lt;ul&gt;&lt;li&gt;Enrollment ID (Primary key)&lt;/li&gt;
&lt;li&gt;Enrollment Date&lt;/li&gt;
&lt;li&gt;Fee&lt;/li&gt;
&lt;li&gt;Grade&lt;/li&gt;
&lt;li&gt;Student ID (Foreign key)=&lt;/li&gt;
&lt;li&gt;Course ID (Foreign key)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;You can see that ENROLLMENTS has two foreign key fields, because we wish to relate an enrollment record to both a STUDENT record and a COURSE record.&lt;/p&gt;
&lt;p&gt;Relationship Setup&lt;/p&gt;
&lt;p&gt;How you setup your relationship graph is dependent upon personal preference. In fact, you can successfully implement this solution without having any relationships between the tables at all. However if you want to be able to see enrollments for either a student or course perspective on your layouts, you will need relationships.&lt;/p&gt;
&lt;p&gt;In this example I will setup the most simplest of relationships. I have related ENROLLMENTS to both STUDENTS and COURSES via the key field associations as mentioned in the above section.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Enrollments::Student ID = Students::Student ID&lt;br&gt;Enrollments::Course ID = Courses::Course ID&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;Building a Course Layout&lt;/p&gt;
&lt;p&gt;This solution is going to require layouts for data entry. It will most likely have a Students layout, a Courses layout, and an Enrollments layout.&lt;/p&gt;
&lt;p&gt;For this section I will focus on the Course layout only. Adding course-specific fields to this layout is easy. The layout is based on the Courses table occurrence, and so you can place course fields straight onto it.&lt;/p&gt;
&lt;p&gt;A useful thing to have on this layout would be a list of all the enrollments for the current course. This can be achieved by placing a portal on the layout. The portal will be based on the Enrollments table occurrence. Be sure to select the related Enrollments table occurrence the one that has the relationship between itself and the Courses table occurrence.&lt;/p&gt;
&lt;p&gt;The fields you will want to put in the portal are basically all the fields from the Enrollments with the exception of a couple. First, it makes little sense to put Enrollment ID in the portal unless you are using this to identify your enrollments. Second, putting Course ID into the portal is redundant, since we are guaranteed that every record that displays in the portal will have the same Course ID as the parent course record, the relationship defines this condition.&lt;/p&gt;
&lt;p&gt;I have pre-populated all tables with a few records to illustrate how this will look. You can see here that the course has three enrollments.&lt;/p&gt;
&lt;p&gt;This layout is fine for viewing course enrollments, but more often than not users wish to directly add enrollments from this layout. The easiest way to allow this is to turn on the Allow creation of records in this table via this relationship option on the relationship dialog. You will want to turn it on for the Enrollments side of the relationship, since it is these records you want to create.&lt;/p&gt;
&lt;p&gt;Now, enrollment records can be created directly from the Courses layout by entering information into the last portal row.&lt;/p&gt;
&lt;p&gt;While this is a fully workable solution so far, it lacks many nice features which make it usable for the average user. Current limitations include:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;User must know a Students ID to add an enrollment&lt;/li&gt;
&lt;li&gt;No visible way to delete enrollments&lt;/li&gt;
&lt;li&gt;No restriction on number of enrollments created&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This solution can be taken much further with a few simple techniques, some of which will be discussed in part three to this article coming soon!&lt;/p&gt;
&lt;p&gt;Example File:&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and the other two parts to the &quot;Join My Table&quot; series of articles. It is fully commented to help you fully understand what is going on in the file.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/joinmytable/JoinMyTable.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:32:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/join-my-table-pt-2-building-the-example-solution/</guid>
		</item>
		
		<item>
			<title>Join My Table Pt 1 - Intro</title>
			<link>https://www.teamdf.com/blogs/join-my-table-pt-1-intro/</link>
			<description>&lt;p&gt;Perhaps one of the most asked questions that I see asked here on the &lt;a href=&quot;http://filemakertoday.com/com/forum.php&quot;&gt;FileMaker Cafe&lt;/a&gt; is in regards to join tables. While some users have an understanding of what they are, they may lack the FileMaker skills to implement them. Others are unfamiliar with the concept altogether, but will explain their real world example. Usually it is a prime candidate for a join table. This article provides a real world example that will give you an understanding of why join tables are important, and in what circumstances they should be used. The example will then be implemented in a simple FileMaker solution.&lt;/p&gt;
&lt;p&gt;Lets get started&lt;/p&gt;
&lt;p&gt;Ponder this real world scenario:&lt;/p&gt;
&lt;blockquote&gt;Joe wants to build a database to manage the computer courses he offers to senior citizens. Being a one-man business, he only offers five courses. He wishes to capture information on his students, his courses, and who has enrolled in which courses.&quot;&lt;/blockquote&gt;
&lt;p&gt;This scenario is very easy to understand when reading in plain english. Now lets deconstruct this scenario further.&lt;/p&gt;
&lt;p&gt;When building a database from a users specification, one of the first things you should do is identify the potential tables:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Joe wants to record info about his students, so we will need a STUDENTS table.&lt;/li&gt;
&lt;li&gt;Joe wants to record info about his courses, so we will need a COURSES table.&lt;/li&gt;
&lt;li&gt;Joe wants to record who has enrolled, so we will need an ENROLLMENTS table.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;With the main tables identified, can you begin to spot what might be the join table? Perhaps one last step will make it more apparent. Lets define in more specific terms which each table will capture within a single record:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;STUDENTS: Information about a particular student.&lt;/li&gt;
&lt;li&gt;COURSES: Information about a particular course&lt;/li&gt;
&lt;li&gt;ENROLLMENTS: Information about a particular student AND a particular course&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;How about now? Can you spot the join table? I think it is time to let the cat out of the bag. A join table is a tool by which you link two other tables together, or to put it in more defined terms:&lt;/p&gt;
&lt;blockquote&gt;A join table is used to establish a many to many relationship between two tables.&lt;/blockquote&gt;
&lt;p&gt;What does many to many mean? Well, in terms of the scenario it means this:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;A student can take MANY courses&lt;/li&gt;
&lt;li&gt;A course can be taken by MANY students&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;By using a join table, you are giving yourself much more freedom to capture as much information as you want, without compromising the integrity of your other tables. The STUDENTS table should only capture information about the student, such as their contact details. Likewise, the COURSES table should only capture information specific to a course, such as it&#039;s name, location, and start time.&lt;/p&gt;
&lt;p&gt;An ENROLLMENT is a thing, it&#039;s a tangible, legitimate thing that you will want to capture information about, so it should have its own table.. It will capture who the student is, and which course they are enrolling in. In addition to that, it could capture information such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Enrollment Date&lt;/li&gt;
&lt;li&gt;Fee&lt;/li&gt;
&lt;li&gt;Grade&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This information only makes sense if it is pertaining to a person for a specific course a grade is meaningless to a course if you don&#039;t know whose grade it is. Alternatively a grade is meaningless to a student if you don&#039;t know for which course it was obtained.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;Please Do Not Try This At Home:&lt;/p&gt;
&lt;p&gt;So why not capture this enrollment information on the students table, and save us the extra table?&lt;/p&gt;
&lt;p&gt;Doing this is bad. It is so bad in fact, that words cannot describe that badness it brings, on a badosity meter it would be off the charts. If someone were to try it, lets see how it would go.&lt;/p&gt;
&lt;p&gt;Right, so we want to capture enrollment information on the Students table. Well, lets start by capturing information about the first enrollment a student takes in a course. We will probably need some fields to capture this information:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Course ID (foreign key)&lt;/li&gt;
&lt;li&gt;Enrollment Date&lt;/li&gt;
&lt;li&gt;Fee&lt;/li&gt;
&lt;li&gt;Grade.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;So far so good. Oh look, Peter Jones just enrolled Join Tables for Dummies which has a Course ID of 5. So I will now go to Peter Jones record, and fill in my information:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Course ID = 5&lt;/li&gt;
&lt;li&gt;Enrollment Date = 11/06/2009&lt;/li&gt;
&lt;li&gt;Fee = 25.00&lt;/li&gt;
&lt;li&gt;Grade =&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Great. I have successfully captured all the enrollment information I need for Peter Jones enrolling in this course. When the course ends, I can fill in his Grade and all will be good: But wait.. Peter also wants to enroll in Bad Database Design. Where am I going to record THAT enrollment information? Well lets see, I could just create more fields to capture it, so all do that.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Course ID 2 = 10&lt;/li&gt;
&lt;li&gt;Enrollment Date 2 = 11/06/2009&lt;/li&gt;
&lt;li&gt;Fee 2 = 50.00&lt;/li&gt;
&lt;li&gt;Grade 2 = C&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Phew, glad that is over. I have still managed to capture information on his two enrollments:&lt;/p&gt;
&lt;p&gt;6 Months Later:&lt;/p&gt;
&lt;p&gt;WHAT?? Peter wants to enroll AGAIN in MORE COURSES??? What am I going to do?? I know: MORE AND MORE FIELDS !!!!!&lt;/p&gt;
&lt;p&gt;Wrong.&lt;/p&gt;
&lt;p&gt;Already this method has gone down the toilet. I am making the problem much worse by adding a new set of fields to the table for every enrollment. Every time a student enrolls in a course, the database schema must be modified. In short, avoid this like the plague. You don&#039;t want to know what kind of problems you will get into when you want to start running reports! Some people who have tried this method have also gone the way of repeating fields. Rather than 1 field per enrollment, they create 1 field, with many repetitions one repetition per enrollment. This is just as bad.&lt;/p&gt;
&lt;p&gt;Please see part two where I begin to build a system making use of join tables for this example.&lt;/p&gt;
&lt;p&gt;Example File&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and the other two parts to the &quot;Join My Table&quot; series of articles. It is fully commented to help you fully understand what is going on in the file.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/joinmytable/JoinMyTable.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:31:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/join-my-table-pt-1-intro/</guid>
		</item>
		
		<item>
			<title>Making Creation of Records in a Portal More User Friendly</title>
			<link>https://www.teamdf.com/blogs/making-creation-of-records-in-a-portal-more-user-friendly/</link>
			<description>&lt;p&gt;FileMaker provides us with the ability to create related records directly from a portal. This is a great and easy way to generate records without the need to script the process, and for that reason it is a popular technique among both new users and Developers alike.&lt;/p&gt;
&lt;p&gt;In this example I have a simple relationship setup between customers and contacts. A customer can have many contacts. In order to create records through a portal, the option Allow creation of records in this table via this relationship must be checked on the portal side of the relationship.&lt;/p&gt;
&lt;p&gt;Creation of related records works because FileMaker automatically populates fields on the new record that are in the relationship. So in the example above, the field Customer ID will be automatically set on the new record created, thus making it a related record of the current Customer.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600576-niceportalcreate-1.png&quot; alt=&quot;niceportalcreate 1&quot; width=&quot;600&quot; height=&quot;576&quot;&gt;&lt;/p&gt;
&lt;p&gt;However, with great power comes great user interface responsibility :) The default interface is not the most intuitive of designs:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/niceportalcreate-2.png&quot; alt=&quot;niceportalcreate 2&quot; width=&quot;440&quot; height=&quot;298&quot;&gt;&lt;/p&gt;
&lt;p&gt;But, with a little bit of conditional formatting, you can make this interface more presentable for users.&lt;/p&gt;
&lt;p&gt;FileMaker places a blank row as the last row for creation of records. But to the average user, this might just look like a blank record. It would be nice to show the user that this row is for adding a new record. There are numerous ways to do this, but here is a simple method:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/niceportalcreate-3.png&quot; alt=&quot;niceportalcreate 3&quot; width=&quot;374&quot; height=&quot;203&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here, I have placed a label on the last row which tells the user to enter the name of a new contact into this row. Because everything you place inside a portal will potentially show on every row, we need to hide this label on every row except the last row, here&#039;s how:&lt;/p&gt;
&lt;p&gt;First, place the label inside the portal, ensuring it is placed behind the field.&lt;/p&gt;
&lt;p&gt;Next, make the field transparent fill, allowing you to see the label behind.&lt;/p&gt;
&lt;p&gt;Now, add a conditional formatting clause to the field. Remember we want to hide the label, so filling the field with a solid colour such as white, will accomplish this.&lt;/p&gt;
&lt;p&gt;We wish for every row to fill the field white except for the last row. In order to achieve this, we need to find a distinction between the last row, and all the others. Fortunately there is one - the last row is not actually a record at all. You can tell a record from a non-record by whether or not the row has a primary key value. For contacts - our primary key field is the Contact ID field. Primary key fields should always have a value in them, so we can test whether our row has a value for the Primary Key - if it doesn&#039;t then the row must not be a record at all:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600480-niceportalcreate-4.png&quot; alt=&quot;niceportalcreate 4&quot; width=&quot;600&quot; height=&quot;480&quot;&gt;&lt;/p&gt;
&lt;p&gt;The conditional formatting evaluates true for any row that contains an actual record, and false for our special row used for the creation of a record.&lt;/p&gt;
&lt;p&gt;Deletion of Records&lt;/p&gt;
&lt;p&gt;Finally, using the same idea for the label, we can make deletion of records more intuitive. Consider a simple &quot;X&quot; piece of text in the portal which represents deletion of a portal row:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/niceportalcreate-5.png&quot; alt=&quot;niceportalcreate 5&quot; width=&quot;380&quot; height=&quot;193&quot;&gt;&lt;/p&gt;
&lt;p&gt;Again, there is no point in showing the X on our special portal row, because we can&#039;t delete it - it isn&#039;t even a record!&lt;/p&gt;
&lt;p&gt;We can however use conditional formatting to hide the X - this time, we can set it&#039;s text colour to the same background colour as the portal&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600480-niceportalcreate-6.png&quot; alt=&quot;niceportalcreate 6&quot; width=&quot;600&quot; height=&quot;480&quot;&gt;&lt;/p&gt;
&lt;p&gt;This time, we wish to apply the formatting on just the blank row only, so we do this if the primary key field is Empty.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/niceportalcreate-7.png&quot; alt=&quot;niceportalcreate 7&quot; width=&quot;391&quot; height=&quot;204&quot;&gt;&lt;/p&gt;
&lt;p&gt;The end result is quite nice. In this situation I have attached the &quot;Delete Portal Row&quot; script step to the X. However you should note that if you choose to run a script to handle your record deletion, it is always a good idea to check whether the row you have chosen is an actual record, or the special portal creation record, ie:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;If [ isEmpty ( Contacts::Contact ID ) ]&lt;br&gt;  Exit Script []&lt;br&gt;End If&lt;/pre&gt;
&lt;p&gt;This block of text should go as the first thing in your script. By doing so, you script will never run it&#039;s steps if the user happens to try to delete the special row. Certain actions within your script can in fact create a record rather than delete it ! For example, if your script tries to set a field on the blank row, this will create a record right away. to avoid all issues, do your existence check as the very first step.&lt;/p&gt;
&lt;p&gt;Example File&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is fully commented to help you fully understand what is going on in the file.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/niceportalcreate/PortalRecordCreation.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:30:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/making-creation-of-records-in-a-portal-more-user-friendly/</guid>
		</item>
		
		<item>
			<title>Conditional Value Lists Pt 2 - Building for Use in Portals</title>
			<link>https://www.teamdf.com/blogs/conditional-value-lists-pt-2-building-for-use-in-portals/</link>
			<description>&lt;p&gt;Part two in this three-part series deals with constructing conditional value lists that are to be used within a portal. In part one, the conditional value lists built were for use on a single record on a layout. Portals however may contain many rows, each row being a record with it&#039;s own field values.&lt;/p&gt;
&lt;p&gt;When a portal is setup, you have the option to specify fields to go into the portal, and the option to attach one value list to each field. This means that the value list you assign must be setup in a way so that it&#039;s values can change per portal row as opposed to per record as illustrated in part one.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600145-conditionalvl-2-1.png&quot; alt=&quot;conditionalvl 2 1&quot; width=&quot;600&quot; height=&quot;145&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is the relationship graph of the example file. The two table occurrences in blue are those used in part one to build the conditional value lists.&lt;/p&gt;
&lt;p&gt;In this example, the two table occurrences in purple will be used to construct the conditional value lists for use within a portal.&lt;/p&gt;
&lt;p&gt;Looking at the graph, you will notice these purple table occurrences are related to a table occurrence that is one-step away from the base table occurrence (home). This table occurrence is that of a portal. So the first thing to note is that the table occurrences are related to the portals context, not that of the layout as shown by the blue table occurrences.&lt;/p&gt;
&lt;p&gt;The notion of context is important when building value lists. In part one, our context was the layout (Home). Value lists were constructed related to the context.&lt;/p&gt;
&lt;p&gt;In this example, the value lists context will be the portal, and so our relationships must be constructed related to the portal context. The reason why will be shown next. Also note that the conditions in the relationships are no different than used in part one - still relating from Sport Category to Sport Category to produce the Sport Name value list, and to produce the Sport Equipment value list - two conditions are used - Sport Category matching Sport Category, and Sport Name matching Sport name.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600453-conditionalvl-2-2.png&quot; alt=&quot;conditionalvl 2 2&quot; width=&quot;600&quot; height=&quot;453&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is the setup for the Sport Name value list for use in the portal. The field chosen is &quot;Sport Name&quot; from the first Purple table occurrence. The important thing to pay attention to here is the &quot;show only related values from&quot; option. This is equivalent to the context we want the value list to operate in. For this example, our context is that of the portal, and so I have chosen the portals table occurrence as the context.&lt;/p&gt;
&lt;p&gt;By choosing the portal as the context, each row of the portal will build it&#039;s value list independent of other rows, and so each row will have it&#039;s own value list based on the values of the other fields in the row. So in the same way that the value lists in Part one of this article were built to change on a per record basis on the layout, this value list is built to change on a per portal row basis.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600194-conditionalvl-2-3.png&quot; alt=&quot;conditionalvl 2 3&quot; width=&quot;600&quot; height=&quot;194&quot;&gt;&lt;/p&gt;
&lt;p&gt;The portal above shows many records, each of which contains a sport category, name and equipment item. Value lists are attached to all three fields, and values were chosen on each row using the same set of 3 value lists.&lt;/p&gt;
&lt;p&gt;Final Thoughts:&lt;/p&gt;
&lt;p&gt;The trick to having a conditional value list change per portal row, lies within the context you define when setting up the value list. The context (ie the source/left hand side of your relationship) is no longer the layout, but rather the portal. By changing the context to the portal, the value list is generated for each individual portal row so that each row can produce it&#039;s own value list contents.&lt;/p&gt;
&lt;p&gt;Example File:&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is fully commented to help you fully understand what is going on in the file.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/conditionalvl/ConditionalValueLists.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:29:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/conditional-value-lists-pt-2-building-for-use-in-portals/</guid>
		</item>
		
		<item>
			<title>Conditional Value Lists Pt 3 - Assisting with the Selection Process</title>
			<link>https://www.teamdf.com/blogs/conditional-value-lists-pt-3-assisting-with-the-selection-process/</link>
			<description>&lt;p&gt;Note, reading the first two articles will help your understanding of part three greatly. If you already know what value lists are then you should probably be able to follow this article.&lt;/p&gt;
&lt;p&gt;In part one, we built a couple of basic conditional value lists to select sport names &amp;amp; equipment items. Part two demonstrated how the conditional value lists could be tweaked for use within a portal. The last part in the series gives some basic techniques to help the selection process from your drop-downs, and ensure that the chosen values remain consistent and correct.&lt;/p&gt;
&lt;p&gt;A Possible Scenario:&lt;/p&gt;
&lt;p&gt;Typically when using conditional value lists, the whole idea is that the user will select values in a specified order. In this case, the user should select a sport category first, followed by a sport name, and finally a sport equipment item. If the user were to try and choose a sport name without a category, the value list would not be present, given that no category was chosen. The same applies when choosing a sport equipment item without a name or category chosen.&lt;/p&gt;
&lt;p&gt;By placing the fields in order on the layout, this provides an intuitive order for the user to select items, and in most cases this is sufficient, the user will quickly learn the order in which to select items.&lt;/p&gt;
&lt;p&gt;Lets assume now that a user has chosen a category, name and equipment item. What happens now if they decide they chose the wrong item, and have to repeat the process?&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/conditionalvl-3-1.png&quot; alt=&quot;conditionalvl 3 1&quot; width=&quot;280&quot; height=&quot;87&quot;&gt;&lt;/p&gt;
&lt;p&gt;If the user now chooses a different sport category, this may happen:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/conditionalvl-3-2.png&quot; alt=&quot;conditionalvl 3 2&quot; width=&quot;284&quot; height=&quot;85&quot;&gt;&lt;/p&gt;
&lt;p&gt;The new category is chosen, but the sport name &amp;amp; item remain unchanged. The name &amp;amp; item no longer match the chosen category.&lt;/p&gt;
&lt;p&gt;Because the user is going to proceed and select a name &amp;amp; item in most cases, this may not seem like an issue. But we can automatically clear the name &amp;amp; item fields to ensure they do not leave it as it stands. This can be done with simple auto-enter calculations.&lt;/p&gt;
&lt;p&gt;Putting it into English, we want the following to happen:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;When Sport Category changes, clear Sport Name&lt;/li&gt;
&lt;li&gt;When Sport Name changes, clear Sport Equipment&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;By way of inference, when sport category changes, we would expect sport equipment to also clear.&lt;/p&gt;
&lt;p&gt;Auto-Enter calculations are calculations which will re-evaluate themselves when any referenced field within the calculation changes it&#039;s value - so long as the referenced field is a) in the same table, and b) is a stored (indexed) value.&lt;/p&gt;
&lt;p&gt;The auto-enter calculation for the Sport Name field looks like:&lt;/p&gt;
&lt;pre&gt;Let ( Trigger = Sport Category ; &quot;&quot; )&lt;/pre&gt;
&lt;p&gt;In this calculation, the referenced field is set as Sport Category, and the result is to set the field (Sport Name) to blank. Note that a Let statement has been used, for the sole purpose of referencing another field, without having to use that field in the calculations result. this is a great technique for any auto-enter calculation you want to trigger.&lt;/p&gt;
&lt;p&gt;Similarly, the Sport Equipment fields auto-enter calculation is:&lt;/p&gt;
&lt;pre&gt;Let ( Trigger = Sport Name ; &quot;&quot; )&lt;/pre&gt;
&lt;p&gt;Whenever sport name value changes, sport equipment is cleared.&lt;/p&gt;
&lt;p&gt;By way of inference, changing Sport Category forces Sport name to re-evaluate, clearing itself - and this action forces Sport Equipment to re-evaluate, also clearing itself.&lt;/p&gt;
&lt;p&gt;To see this in action, check out the example file.&lt;/p&gt;
&lt;p&gt;Script Triggers to Ensure Correct Selection of Fields in Order:&lt;/p&gt;
&lt;p&gt;Script triggers can also be used to ensure that the user selects fields in the specified order. Imagine a simple layout with our 3 fields on it. The user must choose the category, name, and item in that order.&lt;/p&gt;
&lt;p&gt;If the user clicks into either the sport name field, or the sport equipment field, without having a category chosen, this action should be disallowed.&lt;/p&gt;
&lt;p&gt;A simple script can be written to achieve this, and attached to the onobjectEnter trigger for each field. Consider the script for the Sport Name field:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;If [ isEmpty ( Sport Category ) ]&lt;br&gt; Go to Field [ Sport Category ]&lt;br&gt;End If&lt;/pre&gt;
&lt;p&gt;If the user tries to enter the sport name field, without there being a value in sport category, the script will automatically put the user into the sport category field, in the hope they will then select a category.&lt;/p&gt;
&lt;p&gt;A similar script can be written for the Sport equipment field:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;If [ isEmpty ( Sport Category ) ]&lt;br&gt; Go to Field [ Sport Category ]&lt;br&gt;Else If [ isEmpty ( Sport Name ) ]&lt;br&gt; Go to Field [ Sport Name ]&lt;br&gt;End If&lt;/pre&gt;
&lt;p&gt;In this case, the script first ensures a category is chosen, and if not, the user is taken to the category field. If a category is chosen, but a name is not, the user is put into that field. If both category &amp;amp; name are chosen, the user is allowed to proceed and choose a sport equipment item.&lt;/p&gt;
&lt;p&gt;Example File&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is fully commented to help you fully understand what is going on in the file.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/conditionalvl/ConditionalValueLists.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:29:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/conditional-value-lists-pt-3-assisting-with-the-selection-process/</guid>
		</item>
		
		<item>
			<title>Building a Timed-Delay Search Filter for WAN Performance</title>
			<link>https://www.teamdf.com/blogs/building-a-timed-delay-search-filter-for-wan-performance/</link>
			<description>&lt;p&gt;Please note that this article is not in regards to portal-level filtering introduced in FileMaker 11. It concerns filtering of relationships by altering contents of fields that are used in the relationship.&lt;/p&gt;
&lt;p&gt;This article is also aimed at an intermediate level user. It assumes you already know the basic ideas behind filtering relationships using a filter field.&lt;/p&gt;
&lt;p&gt;Introduction&lt;/p&gt;
&lt;p&gt;With the introduction of script triggers in FileMaker 10, live filtering or portals was made possible. Numerous techniques were introduced to help achieve this. In conjunction with existing filtering techniques, the &quot;Live&quot; aspect was achieved usually by introducing an OnObjectModify script trigger to the filter entry field. As soon as the user enters a value into the field, the triggered script would force a save of the fields contents, thus updating the relationship in question, which in turn updated results in a portal on screen.&lt;/p&gt;
&lt;p&gt;These filtering techniques work fine on local solutions, and solutions over a Local Area Network, but what happens when the same techniques are used on systems that are used over a wide Area Network - such as the internet?&lt;/p&gt;
&lt;p&gt;A basic live filter example&lt;/p&gt;
&lt;p&gt;A typical implementation of a live filter is using an OnObjectModify trigger in conjunction with a script. For example:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Time-Delay/wanfiltering-1.jpg&quot; alt=&quot;wanfiltering 1&quot; width=&quot;529&quot; height=&quot;157&quot;&gt;&lt;/p&gt;
&lt;p&gt;This script first remembers the cursor position &amp;amp; selection. It then sets the active field to itself, which is sufficient to save the field contents and so force a portal to update its results. The final part of the script restores the mouse cursor position.&lt;/p&gt;
&lt;p&gt;When this script is attached to a field using the OnObjectModify trigger you have a basic live filter field ready to be used in a relationship.&lt;/p&gt;
&lt;p&gt;Some drawbacks over WAN&lt;/p&gt;
&lt;p&gt;The above method updates the field contents after EVERY character inputted. Locally or over LAN, this operation is usually unnoticeable, but over WAN it can be crippling.&lt;/p&gt;
&lt;p&gt;In FileMaker, when a record is displayed in a sorted portal, EVERY record in a portal is downloaded to the client machine - regardless of whether it is visible in the portal or not. In addition to this, the ENTIRE record (excluding unstored calcs &amp;amp; container fields) is downloaded to the client. If you have a portal showing 10,000 sorted records, then all 10,000 records are downloaded to your client. If you are connecting over the Internet, then this can be a time consuming operation. They must all be downloaded in order to achieve the sort - an action that happens on the client machine&lt;/p&gt;
&lt;p&gt;If you are filtering a portal as you type, then after every keystroke, FileMaker needs to obtain any new records now showing thru the relationship by downloading them. During which time, you will be unable to continue typing into the field until this is done.&lt;/p&gt;
&lt;p&gt;When filtering portals there are two ways you can begin - with the portal showing NO records, or showing ALL records. If a portal begins by showing no records, then as soon as you begin typing into the filter field and records are found thru the relationship, they&#039;ll need to be downloaded, and this will cause a major slowdown on the initial keypress (or whenever the first set of records are found thru the relationship).&lt;/p&gt;
&lt;p&gt;If the portal/relationship begins by showing all records, and you narrow down that set, the slowdown effects of filtering the portal are reduced, but at the cost of a large performance hit in initially loading the portal.&lt;/p&gt;
&lt;p&gt;For relationships/portals that are unsorted, FileMaker will download visible records in the portal, so initial load times might be faster, but it still suffers the same fate as you begin to filter, because new records are potentially being displayed in the visible portal which must be downloaded.&lt;/p&gt;
&lt;p&gt;The overall performance hit over WAN is noticeable. Users who use filter fields tend to type at a reasonable speed into the filter field - if the speed at which they can do this is reduced due to download times of records, the filter field becomes sluggish and feels unresponsive, which can lead to user frustration.&lt;/p&gt;
&lt;p&gt;A nice alternative for WAN performance&lt;/p&gt;
&lt;p&gt;Think about a users end goal when typing in a filter field. Most users will know the word/s they want to enter into the field, and will go about typing the entire word until it&#039;s entered. For example, if you wanted to locate all people in a database whose name is &quot;Daniel&quot;, would you be more inclined to just type &quot;Daniel&quot; and look at the results, OR would you begin typing .... D - (look at results) - A - (look at results) - N (look at results) ... and so on until you see the record you want? I think the first approach is the more common.&lt;/p&gt;
&lt;p&gt;So, what about a filter entry field that only shows results once the user finishes typing whatever they want to type? How can FileMaker detect when a user finishes typing into a field? Well, prior to script triggers, a user would have to manually exit the field in order for FileMaker to update the portal. But, by a cunning use of the OnTimer script step in conjunction with an OnObjectModify script trigger, it is easy to detect a pause in a users typing pattern. This pause can be used to update the portal.&lt;/p&gt;
&lt;p&gt;This method will allow the user to type their search term at full speed, without constant portal refreshing impeding their data entry. It will then show results when it detects the user has finished typing, or paused for a period of time.&lt;/p&gt;
&lt;p&gt;So, how does it work:&lt;/p&gt;
&lt;p&gt;At it&#039;s most basic level, the method requires two scripts, and a filter entry field.&lt;/p&gt;
&lt;p&gt;Script A - Typing Trigger&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Time-Delay/wanfiltering-2.png&quot; alt=&quot;wanfiltering 2&quot; width=&quot;527&quot; height=&quot;122&quot;&gt;&lt;/p&gt;
&lt;p&gt;Script B - OnTimer Trigger&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/blog-images/Time-Delay/wanfiltering-3.jpg&quot; alt=&quot;wanfiltering 3&quot; width=&quot;468&quot; height=&quot;199&quot;&gt;&lt;/p&gt;
&lt;p&gt;What&#039;s Going on in The Scripts?&lt;/p&gt;
&lt;p&gt;Lets start with Script A. In this script, you can see it is being passed a script parameter which is set into a variable $ObjectName. The parameter passed is the object name assigned to the filter entry field - this is useful because it makes these two scripts completely generic and they can be reused for any number of filter entry fields in your solution.&lt;/p&gt;
&lt;p&gt;The main part of the script is the installation of the OnTimer Script - Script B. We pass the object name to the second script also. I have set a delay of 0.25 seconds on the ontimer. Note that this delay will be the delay between when the user finishes typing, and when the portal results are updated.&lt;/p&gt;
&lt;p&gt;The key aspect of this whole thing is that this particular script is the one that is attached to the filter entry field as an OnObjectModify script trigger.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The first time the user enters a character into the field, the onObjectModify script is triggered&lt;/li&gt;
&lt;li&gt;The triggered script installs an OnTimer of the second script with a delay of 0.25 seconds.&lt;/li&gt;
&lt;li&gt;This means that after 0.25 seconds of no activity, script B will run&lt;/li&gt;
&lt;li&gt;HOWEVER, if the user enters another character into the field before the 0.25 second delay, Script A runs again&lt;/li&gt;
&lt;li&gt;When it runs again, it RESETS the onTimer for Script B back to 0.25 seconds.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;To put it simply, every time the user enters a character, the time to which script B will run is reset to 0.25 seconds. Script B will only run once the user stops typing for that 0.25 seconds.&lt;/p&gt;
&lt;p&gt;Script B is responsible for doing the normal filtering tasks. The last step of the second script is to disable the OnTimer script for itself. This ensures that once the user stops typing, this script will run once and once only. If the user then continues typing, then Script A runs and the process repeats itself all over again.&lt;/p&gt;
&lt;p&gt;The end result&lt;/p&gt;
&lt;p&gt;the end result is a portal which updates it&#039;s results after 1/4 second pause of data input by the user into the filter entry field. While the user is typing, nothing happens to the relationship or the portal, resulting in no slowdown of data entry due to records being downloaded. Once the user stops typing, only then is the field contents saved and the relationship/portal updated.&lt;/p&gt;
&lt;p&gt;Taking it a step further&lt;/p&gt;
&lt;p&gt;I implemented this method in a rather large solution with great results. The system had upwards of 20 filter entry fields on various screens. It soon became apparent however, that for some filter entry fields, numbers were the common type of data entry, whereas others were text/words. For most users, the entry of numbers via a keyboard is a slower task than typing a word. I quickly found that the 0.25 second delay was sufficient for text filter entry fields, but not for those that required number entry, or a combination of text and numbers.&lt;/p&gt;
&lt;p&gt;The solution was to pass the Delay to the Typing Trigger script (Script A) as a second script parameter. Now, this script accepts two parameters - the object name, and a delay. For numeric entry fields, a delay of 1 second is more useful because it gives the user time to type in their number. For text fields, the delay can be decreased. To go even one step further, you could make the delay a user preference in the database, so touch typists could have a shorter delay, while a longer delay could be given to &quot;two finger&quot; typists.&lt;/p&gt;
&lt;p&gt;Final Thoughts:&lt;/p&gt;
&lt;p&gt;While &quot;instant&quot; live filtering is looks great, and provides great visual feedback when filtering, it does have some performance drawbacks most notable over wide area network deployments of FileMaker solutions. Sorting of the relationship/portal also has a great drawback in these situations.&lt;/p&gt;
&lt;p&gt;By implementing a short delay between when the user enters into the filter entry field, and when the relationship/portal is updated, an increase in filtering performance can be achieved.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Data entry into the filter field is faster because while the user is typing, no actual filtering is occurring&lt;/li&gt;
&lt;li&gt;When the user finishes typing, the results that will be found will typically be fewer and more specific records given that the filtering is now occurring on a full word, or more characters.&lt;/li&gt;
&lt;/ul&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:27:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/building-a-timed-delay-search-filter-for-wan-performance/</guid>
		</item>
		
		<item>
			<title>Quick Tips #1: Quick Select/Deselect of Mapping Fields in FM11 Import</title>
			<link>https://www.teamdf.com/blogs/quick-tips-1-quick-selectdeselect-of-mapping-fields-in-fm11-import/</link>
			<description>&lt;p&gt;The issue:&lt;/p&gt;
&lt;p&gt;&lt;br&gt;In versions of FileMaker prior to 11, working with the Import Records mappings dialog was easy. You could very quickly select and deselect all mappings by selecting all fields and then clicking one of the arrow mapping icons between any two fields in the mapping.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/importmapping-1.jpg&quot; alt=&quot;importmapping 1&quot; width=&quot;270&quot; height=&quot;260&quot;&gt;&lt;/p&gt;
&lt;p&gt;Clicking on any of the arrow icons above will deselect every arrow.&lt;/p&gt;
&lt;p&gt;The behaviour in FileMaker 11 has changed slightly, and so it may appear at first that this feature has been removed.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/importmapping-2.jpg&quot; alt=&quot;importmapping 2&quot; width=&quot;230&quot; height=&quot;245&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you try and click one of the arrow icons in 11, all you succeed in doing is deselecting the selected fields, the arrows remain. Of course you could click each arrow individually, but if you are dealing with large tables that can be a real pain.&lt;/p&gt;
&lt;p&gt;The 11 change is subtle - you must now hold down the shift key while clicking one of the arrows, this will select/deselect the mappings for all selected fields.&lt;/p&gt;
&lt;p&gt;If you hold the shift key down while selecting the records you can combine the steps. Start by selecting one of the fields, hold shift, and click on the arrow in the row which you want to be your end selection of rows. This will select all the rows between your two clicks, and select/deselect the mappings at the same time.&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:26:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/quick-tips-1-quick-selectdeselect-of-mapping-fields-in-fm11-import/</guid>
		</item>
		
		<item>
			<title>Putting One Object Into Multiple Tabs</title>
			<link>https://www.teamdf.com/blogs/putting-one-object-into-multiple-tabs/</link>
			<description>&lt;p&gt;Here is a nice quick technique that will allow you to place a layout object or objects into more than one tab on any given tab control object.&lt;/p&gt;
&lt;p&gt;The Problem&lt;/p&gt;
&lt;p&gt;With tab control objects, when you place an object inside a tab, then that object is now enclosed within that tab. Switching to a different tab will effectively hide the object, because being on the other tab it is no longer visible.&lt;/p&gt;
&lt;p&gt;The Reason&lt;/p&gt;
&lt;p&gt;Sometimes however, you may have a layout object or objects which you wish to remain consistent across multiple tabs. It could be a portal, web viewer, text label, or series of fields.&lt;/p&gt;
&lt;p&gt;The first solution that might come to mind would be to make copies of the layout object(s) and place them into each individual tab control object, there are some downsides to this method:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Having copies means any change you need to make to one object, you must repeat changes to all.&lt;/li&gt;
&lt;li&gt;Being unique layout objects, if you are naming objects for various purposes (ie scripting navigation), then each object requires it&#039;s own name, adding some complexity to navigation to the object.&lt;/li&gt;
&lt;li&gt;In the case of portals, being different objects means each will have their own scroll bar position, switching tabs may yield a different set of visible records in the portal if the scroll positions are different.&lt;/li&gt;
&lt;li&gt;Web viewers will load when first viewed, so when changing tabs you will have each web viewer loading itself, rather than loading once for all tabs.&lt;/li&gt;
&lt;li&gt;and so on....&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The Solution&lt;/p&gt;
&lt;p&gt;The solution to this issue lies in the rules surrounding when a layout object is considered &quot;in&quot; a tab control object, and when it is not. Basically, a layout object is considered outside of a tab if it&#039;s top coordinate lies outside of the tab.&lt;/p&gt;
&lt;p&gt;Note that a tab actually encompasses part of it&#039;s tab label area as well as the inner tab section (see photo).&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/objmultipletabs-1.jpg&quot; alt=&quot;objmultipletabs 1&quot; width=&quot;552&quot; height=&quot;297&quot;&gt;&lt;/p&gt;
&lt;p&gt;So, the goal is to somehow get the top coordinate of the layout object(s) positioned so that it lies outside of the tab control object&lt;/p&gt;
&lt;p&gt;The Method&lt;/p&gt;
&lt;p&gt;To do this, first start with the layout object you wish to place in each tab control, positioned outside of the tab object iself. In this example, I will be using a green circle object.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/objmultipletabs-2.jpg&quot; alt=&quot;objmultipletabs 2&quot; width=&quot;600&quot; height=&quot;285&quot;&gt;&lt;/p&gt;
&lt;p&gt;Next, create another layout object and place this directly above the other object, place it so that it lies above the tab control object.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/objmultipletabs-3.jpg&quot; alt=&quot;objmultipletabs 3&quot; width=&quot;600&quot; height=&quot;321&quot;&gt;&lt;/p&gt;
&lt;p&gt;For the sake of this example I have made the second object a green square. Note that this second object should be a very simple INVISIBLE object - a text label which is just a space, or a transparent no-line rectange, or even a 0pt line would all be acceptable.&lt;/p&gt;
&lt;p&gt;Next, you want to select both objects and group them using the group command - Arrange -&amp;gt; Group.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/objmultipletabs-4.png&quot; alt=&quot;objmultipletabs 4&quot; width=&quot;108&quot; height=&quot;191&quot;&gt;&lt;/p&gt;
&lt;p&gt;The reason why this is all done outside of the tab control object is that FileMaker will not allow you to group objects that are both inside and outside of a tab control object, it&#039;s either all in or all out.&lt;/p&gt;
&lt;p&gt;However, once grouped, you can place half the grouped object in the tab control, and half out, and this is what we will be doing.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/objmultipletabs-5.jpg&quot; alt=&quot;objmultipletabs 5&quot; width=&quot;553&quot; height=&quot;339&quot;&gt;&lt;/p&gt;
&lt;p&gt;With the grouped object placed in the correct position, it now appears as if the circle is in the first tab. Changing tabs will show the circle apparently in every tab. In actuality, the layout object - which is now the grouped object - is outside of all tab control objects. The rule in FileMaker is that if a layout object is both in and out of a tab control object, it will appear in front of any other object within the tab. The circle is basically in front of the tab control object in terms of layout ordering, and so appears in front of every tab.&lt;/p&gt;
&lt;p&gt;Final Thoughts:&lt;br&gt;This technique is great, and I use it all the time. You can use the same idea to produce fields/labels that appear beside tab names - rather than have to put the fields into every tab, group them with a single object above the tab control to keep them visible no matter what tab you have selected.&lt;/p&gt;
&lt;p&gt;Cheers.&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:25:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/putting-one-object-into-multiple-tabs/</guid>
		</item>
		
		<item>
			<title>Keeping Merge Fields Tidy on Your Layout</title>
			<link>https://www.teamdf.com/blogs/keeping-merge-fields-tidy-on-your-layout/</link>
			<description>&lt;p&gt;This is a quick and simple tip, and one of my favorites for keeping layouts tidy.&lt;/p&gt;
&lt;p&gt;Have you ever added a merge field to a layout, only to find it takes over half the layout, covering other layout objects?&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600208-mergefieldtidy-1.png&quot; alt=&quot;mergefieldtidy 1&quot; width=&quot;600&quot; height=&quot;208&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you try to reduce the width of the merge field, you only end up making it taller in height, and now it may overlap things beneath it.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/mergefieldtidy-2.png&quot; alt=&quot;mergefieldtidy 2&quot; width=&quot;469&quot; height=&quot;209&quot;&gt;&lt;/p&gt;
&lt;p&gt;Things only get worse if that merge field is used in combination with other merge fields, or other text, you will end up with a big chunk of ugly looking text on your layout - while in browse mode it may only be a few words.&lt;/p&gt;
&lt;p&gt;The quirky thing about merge fields however, is that the entire contents of the merge field will render in the font size of the first character of the merge field place holder. So in the example:&lt;/p&gt;
&lt;p&gt;So long as the very first character -&lt;/p&gt;
&lt;p&gt; &lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/mergefieldtidy-3.png&quot; alt=&quot;mergefieldtidy 3&quot; width=&quot;372&quot; height=&quot;215&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can always spot a merge field on the layout when using this technique because it has a very characteristic look about it. Once a merge field is set you can generally forget about it.&lt;/p&gt;
&lt;p&gt;If, however you do need to check what the merge field is, the easiest way to now do so is to copy/paste it elsewhere on the layout, and increase the font size of the copy version by 1pt, in doing so, the entire merge field place holder will increase in font size so you can read it again.&lt;/p&gt;
&lt;p&gt;When you want to reformat the existing merge field, just select the first &quot;&lt;/p&gt;
&lt;p&gt;You can still use this technique with merge fields that exist alongside regular text, for example:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage60053-mergefieldtidy-4.png&quot; alt=&quot;mergefieldtidy 4&quot; width=&quot;600&quot; height=&quot;53&quot;&gt;&lt;/p&gt;
&lt;p&gt;You don&#039;t have to set the rest of the merge field font size to 1-2pt if you don&#039;t want to. Normally if the font size you want is 18pt or over, you can get away with making the rest of it a readable font size like 10pt, that way you can still easily determine what the merge field is :)&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:24:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/keeping-merge-fields-tidy-on-your-layout/</guid>
		</item>
		
		<item>
			<title>Showing a Sub-Summary Part In-Line With Your Records</title>
			<link>https://www.teamdf.com/blogs/showing-a-sub-summary-part-in-line-with-your-records/</link>
			<description>&lt;p&gt;A sub-summary report, is a special kind of report where records are grouped together by a specified field known as the &quot;break&quot; field (because it acts as a break between groups of similar records).&lt;/p&gt;
&lt;p&gt;As an example for this article, consider a very basic table containing 3 fields:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Country&lt;/li&gt;
&lt;li&gt;City&lt;/li&gt;
&lt;li&gt;Population&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Each record comprises a country, a city within that country, and that cities population. There may be multiple records for a given country, as that country may have many large cities. Others however may only have one or two cities.&lt;/p&gt;
&lt;p&gt;A sub-summary report could be run on this table, with a break field of &quot;Country&quot;. The output would display countries, and their cities &amp;amp; populations beneath, such as the following:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/inlinesubsum-1.png&quot; alt=&quot;inlinesubsum 1&quot; width=&quot;396&quot; height=&quot;372&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is a very typical sub summary report. The sub summary part is in blue, and the body part is in green to illustrate the respective parts (this is just test data, the populations are well off).&lt;/p&gt;
&lt;p&gt;This is fine, but what happens if you have many countries with only one city? As you can see in the example picture, England, Japan, and Fiji all have one City listed. Each country thus requires 2 lines on the page - 1 for the country, and 1 for the city.&lt;/p&gt;
&lt;p&gt;Wouldn&#039;t it be nice if you could somehow show the country and the city on the same line in these situations? Well you can with a little jiggery pokery.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/inlinesubsum-2.png&quot; alt=&quot;inlinesubsum 2&quot; width=&quot;332&quot; height=&quot;259&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is the layout mode view of the report above, blown up to 300%. The key concept in this technique, is that as long as the top edge of the sub-summary field is in the sub-summary part, then it will render on screen when in preview mode.&lt;/p&gt;
&lt;p&gt;The technique thus involves reducing the size of the sub-summary part to 1-2 pixels in height, and placing just the top edge of the sub-summary field inside the sub-summary part, as shown below.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/inlinesubsum-3.png&quot; alt=&quot;inlinesubsum 3&quot; width=&quot;545&quot; height=&quot;209&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is a modified version of the original report, at 300% a couple of things have changed:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The Sub-Summary part has been reduced to 1 pixel in height.&lt;/li&gt;
&lt;li&gt;The &quot;Country&quot; sub summary break field has been positioned so it&#039;s top edge is still within the sub-summary part.&lt;/li&gt;
&lt;li&gt;City and Population fields have been moved up so their top coordinate is 1 pixel below that of country, and so they still lie within the body part.&lt;/li&gt;
&lt;li&gt;Fill colours on the sub-summary and body part have been removed (important!)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;As you can see, it appears as though the body-part records begin directly to the right of the sub-summary field. For those countries with 1 city, only one line is used. In actuality, the country is offset by 1 pixel higher than the city and population, but this is barely perceivable to the human eye.&lt;/p&gt;
&lt;p&gt;This is a great paper saver for long reports, and not to mention it looks tidier for sub-summary parts with only one record in them.&lt;/p&gt;
&lt;p&gt;A Couple of Things to Note¦&lt;/p&gt;
&lt;p&gt;As mentioned earlier, fill colours were removed from the sub summary part, and the body part. This is important because otherwise the technique does not work. The reason the technique works in the first place is due to the way preview mode renders the report. When it renders, it renders from the top down. Anything it renders is placed in the top of the ordering on the page.&lt;/p&gt;
&lt;p&gt;It just so happens that the sub-summary field renders over-top of the body part just fine, and this gives the illusion that the sub summary part, and body part are in-line with each other (albeit 1-2 pixels out). However when the body part then renders, it&#039;s contents are placed at the top of the order on the page. Thus anything in the body part will draw over anything already drawn. Most importantly this means any fill colours used in the body part will appear over top of the sub-summary field, hiding it from view (as an alternative, you can use things such as line separators for between records).&lt;/p&gt;
&lt;p&gt;Also note that while the sub-summary field, and body fields appear to be in-line, they can never truly be vertically aligned. The closest you can get is a 1 pixel difference in height, however when viewing a printed report, this difference is negligible.&lt;/p&gt;
&lt;p&gt;This technique does not work in Browse mode in FileMaker 10 or 11, and is only useful if you are viewing in preview mode or printing/saving the report. If you try to view in browse mode you will see something like the following:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/inlinesubsum-4.png&quot; alt=&quot;inlinesubsum 4&quot; width=&quot;324&quot; height=&quot;254&quot;&gt;&lt;/p&gt;
&lt;p&gt;Example File:&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is fully commented to help you fully understand what is going on in the file.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/inlinesubsum/InLineSubSummaries.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:21:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/showing-a-sub-summary-part-in-line-with-your-records/</guid>
		</item>
		
		<item>
			<title>A Lightning Fast Alternative to the Count() Function</title>
			<link>https://www.teamdf.com/blogs/a-lightning-fast-alternative-to-the-count-function/</link>
			<description>&lt;p&gt;Today, a colleague of mine here at &lt;a href=&quot;http://www.digitalfusion.co.nz&quot;&gt;Digital Fusion&lt;/a&gt; pointed me to a particular thread on the &lt;a href=&quot;http://www.filemaker.com&quot;&gt;FileMaker TechTalk Forum&lt;/a&gt; in which the poster - Morgan Jones of &lt;a href=&quot;http://www.onepartharmony.com&quot;&gt;One Part Harmony&lt;/a&gt; posed the following (abridged):&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;blockquote&gt;Dear Folks,
&lt;p&gt;I have for many years just used the &quot;Count&quot; function to determine how many related (child) records exist for a given parent record. I just point this function to the unique key in the child records to determine a related-record count.&lt;/p&gt;
&lt;p&gt;In cases where the number of related records for a given parent is large (a couple of thousand, for example), FileMaker pops up a progress bar saying &quot;Summarizing field: xxx&quot; when my app accesses a different parent record with many related child records. &quot;Summarizing&quot; can take 5 seconds for a couple of thousand child records when connected via a LAN, and much, much longer if connecting over the WAN.&lt;/p&gt;
&lt;p&gt;I&#039;m just wondering if there is a more efficient method for obtaining the count of related records, preferably one that can be done in a single calculation such that FileMaker doesn&#039;t have to traverse the list of values of the field referenced in the Count function call.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a classic problem with the summary functions that FileMaker provides. I&#039;m sure any developer has been frustrated with the slowness of the Count function across a large number of records.&lt;/p&gt;
&lt;p&gt;A brilliant solution was given by Tom Elliot:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;blockquote&gt;In child: unstored calc field = Get ( RecordNumber )&lt;br&gt;in parent: unstored field = Last ( )
&lt;p&gt;this is based on the *assumption* that neither Last() nor Get &lt;br&gt;( RecordNumber ) need to traverse records to get a result. Also, I believe that Count() returns the number of values that are non- &lt;br&gt;empty and valid (rather than unique) - at least that&#039;s what the &lt;br&gt;documentation says&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Simple, elegant, and it works unbelievably well. To understand why this method of counting related records works so well, it pays to first understand why Count performs the way it does.&lt;/p&gt;
&lt;p&gt;The Count Function&lt;/p&gt;
&lt;p&gt;The Count() function, according to the FileMaker help, returns the number of values that are non-empty and valid. The key word here is &quot;valid&quot;. This means for example, that if you run the Count function on a relationship of 500,000 records, then every single one of those 500,000 records must be scanned and validated before the total can be known.&lt;/p&gt;
&lt;p&gt;So what does this mean? Well, if the database is hosted on FileMaker server it means all 500,000 records must be downloaded from the server to the client machine, the validation check actually occurs on the client machine itself. The slowdown occurs with the downloading of records - slow on LAN, even slower on WAN. Indeed this is what is happening when you see the &quot;summarising record x&quot; dialog.&lt;/p&gt;
&lt;p&gt;That is all fine and good, but it is pointless when all we want to do is find the total number of records, without worrying about the validity of the field contents we are counting.&lt;/p&gt;
&lt;p&gt;Tom&#039;s solution is to skip the Count function and instead use a combination of Get(RecordNumber) and Last() functions.&lt;/p&gt;
&lt;p&gt;First, the Get(RecordNumber) function. Typically this function is used to display a records number within a found set of records. if a found count on a layout has 100 records, then the last record will have a record number of 100. that is not to say the record number will always be 100 for that specific record - the record number changes based on the contents of the found set.&lt;/p&gt;
&lt;p&gt;Tom has shown that the Get(RecordNumber) function can also be used through a relationship, in addition to a found set.&lt;/p&gt;
&lt;p&gt;In the example above, if there are 1,000 related child records, then if we find the contents of the Last records Get(RecordNumber) calculation, then this tells us how many records are in the related records.&lt;/p&gt;
&lt;p&gt;There is no need for the Last() function to evaluate any of the other records other than the very last single record. All it needs to do is evaluate Get(RecordNumber) for the last record, it&#039;s brilliant !&lt;/p&gt;
&lt;p&gt;So in a set of 500,000 related records, the count() function needs to validate 500,000 records , whereas Last() needs to reference one!&lt;/p&gt;
&lt;p&gt;Speed tests on 500,000 records in a local database, show that the Count() function takes about 90 seconds, whereas Last() takes less than one second!&lt;/p&gt;
&lt;p&gt;This is definitely one of the coolest techniques I have ever seen for FileMaker, and I can&#039;t wait to implement it in my solutions! If this technique is old news and been around for years then I apologise (it&#039;s new to me!)&lt;/p&gt;
&lt;p&gt;FOLLOWUP: An Even BETTER method!&lt;/p&gt;
&lt;p&gt;I have subsequently implemented this technique in a customers solution with great results. In the end I did not use the Last() implementation, rather I used the Get(FoundCount) method. This involves creating an unstored calculation on the table you want to count records from, and set it&#039;s calculation to &quot;Get ( FoundCount )&quot;.&lt;/p&gt;
&lt;p&gt;Subsequently, you can count records from any portal by placing on the layout this calculation field, obtained via the portal relationship you want to count. This method works brilliantly, and can be used on both unsorted and sorted portals (the last method requires the relationship to be unsorted.&lt;/p&gt;
&lt;p&gt;The solution I changed ended up having about 150 calls to the Count function that I had to change. this involved running a DDR on the solution, and searching for all instances of the &quot;Count&quot; function. It was incredibly fast to make the change, as it required removing the count function, and replacing the field that was being counted, with the new unstored calculation added to the table. Everything worked seamlessly after this change.&lt;/p&gt;
&lt;p&gt;The great thing about the using the Get(FoundCount) implementation, is that no additional calculation field is required. The foundcount calculation can be placed direct on the layout from the related table (via the relationship you want to count). Whereas using the Last() implementation, a secondary calculation is required to obtain the record number of the last record.&lt;/p&gt;
&lt;p&gt;This is why I now recommend the Get(FoundCount) method over the Last() method!&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:19:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/a-lightning-fast-alternative-to-the-count-function/</guid>
		</item>
		
		<item>
			<title>Keeping Things Organised by Using Separators</title>
			<link>https://www.teamdf.com/blogs/keeping-things-organised-by-using-separators/</link>
			<description>&lt;p&gt;There are four main areas of your database where you can use special separator lines to help keep information organised, these are:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Scripts&lt;/li&gt;
&lt;li&gt;Layouts&lt;/li&gt;
&lt;li&gt;Value Lists&lt;/li&gt;
&lt;li&gt;Custom Menus&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;A separator line is exactly what it sounds like - a line that separates one thing from another.&lt;/p&gt;
&lt;h3&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Scripts&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;To insert a separator line between scripts, this is done by creating a blank script - the title of which is a single hyphen line &quot;-&quot;. You can create these by using the drop-down arrow beside the &quot;New&quot; icon in the Manage Scripts dialog, and selecting &quot;Separator&quot;. Alternatively you can create a blank script yourself and assign it the &quot;-&quot; title.&lt;/p&gt;
&lt;p&gt;Separator lines can be seen when using the scripts menu. Any separator script that has been checked &quot;include in menu&quot; from the scripts menu, will appear as a single solid line.&lt;/p&gt;
&lt;h3&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Layouts&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;br&gt;This separator line is a little less obvious because it is not documented whereas the other ones are. The implementation however is the same as for scripts. You start by creating a blank layout and giving it the layout name of a single hyphen &quot;-&quot;. These special layouts can then be positioned in your layout list wherever a separator line is required. The line is then visible from the layout selector while in layout mode, and browse mode providing &quot;include in layout menus&quot; has been checked.&lt;/p&gt;
&lt;h3&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Value Lists&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;br&gt;Any entry in a value list which is a single hyphen line will be treated as a separator. These can be added when using a value list that uses custom values. It should be noted however that these separators will not function correctly if the value list is being generated from a field, or list of records. This is because value lists are automatically sorted in these scenarios. If a hyphen has been used in a record, or field value for use in the value list, it will sort incorrectly, and the separator will appear at the top of the value list.&lt;/p&gt;
&lt;h3&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Custom Menus&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;br&gt;When creating a custom menu, separators can be from the Custom Menus -&amp;gt; Edit Custom Menu Dialog, by using the &quot;Add Separator&quot; button provided. These separators will appear the same as those for layouts and scripts - a single solid line.&lt;/p&gt;
&lt;p&gt;Other Separators&lt;br&gt;There are other separators that you can create. While they aren&#039;t &quot;true&quot; separators, they nonetheless can assist in keeping your database organised:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;A blank custom function can help keep your custom functions organised&lt;/li&gt;
&lt;li&gt;Grouping on the relationship graph can be achieved using comment boxes strategically placed.&lt;/li&gt;
&lt;li&gt;Fields can be grouped by using special separator fields which can have hyphen or blank space names.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Note that for custom function and field separators, you will need to sort them in a custom order respectively.&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:17:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/keeping-things-organised-by-using-separators/</guid>
		</item>
		
		<item>
			<title>Let me Tell You &#039;Bout Let</title>
			<link>https://www.teamdf.com/blogs/let-me-tell-you-bout-let/</link>
			<description>&lt;p&gt;The Let function is one of the most brilliant and underrated functions in FileMaker, and I think it should be used whenever and wherever possible. This article will give an introduction to the function, some possible scenarios when it should be used, and give an example as to it&#039;s use.&lt;/p&gt;
&lt;p&gt;Since the dawn of time, man has sought ways in which to simplify his life. That&#039;s just a fact. Whether it is accurate or not is a question better left to the scholars. However someone at FileMaker was obviously adhering to this philosophy when they created the Let function.&lt;/p&gt;
&lt;p&gt;To put it simply, the Let function can be used to simplify a calculation? How you ask? Well it does this by splitting out parts of a calculation into simpler, more easily readable parts. Think of it like an instruction manual for building a desk: The first thing you need to know is what all the parts are you require, before jumping in and putting those parts together (or something like that... close enough!)&lt;/p&gt;
&lt;p&gt;FileMaker defines the format of the let function as follows:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Let({[}var1=expression1{;var2=expression2...]};calculation)&lt;/pre&gt;
&lt;p&gt;So let&#039;s break it down:&lt;/p&gt;
&lt;p&gt;1) The function always begins with the word &quot;Let&quot; followed by open bracket. Everything within the function is contained within the opening and closing brackets, i.e:&lt;/p&gt;
&lt;p&gt; Let ( )&lt;/p&gt;
&lt;p&gt;2) The function has two parameters, the first being variables, the second being the calculation itself, ie&lt;/p&gt;
&lt;p&gt;Let ( Parameters ; Calculation )&lt;/p&gt;
&lt;p&gt;3) The calculation part is simply a calculation that will be returned as the result. In fact, you could use a Let statement with no parameters. Doing this, would be pointless, but it illustrates what the calculation parameter does, ie:&lt;/p&gt;
&lt;p&gt;Let ( &quot;&quot; ; 3 + 4 ) = 7&lt;br&gt;Let ( &quot;&quot; ; &quot;Blah&quot; ) = &quot;Blah&quot;&lt;/p&gt;
&lt;p&gt;4) You may have noticed, had you tried the above two functions, that they don&#039;t actually work. The reason being that using a Let statement is pointless without having utilized the first parameter. Indeed it is the first parameter that is where the power of the Let statement lies.&lt;/p&gt;
&lt;p&gt;A Good Time to Introduce Variables&lt;/p&gt;
&lt;p&gt;The first parameter is Variables. Any programmer should be familiar with what variables are, and indeed any FileMaker developer should know or learn what they are also. In most simplest terms, a variable is something that stores the result of a calculation or function. Ponder the following:&lt;/p&gt;
&lt;p&gt; myVariable = 3 + 4&lt;/p&gt;
&lt;p&gt;Here, I have created a variable called &quot;myVariable&quot; and set it to 3 + 4. If I were to later check the contents of the variable, I would find it contains the number &quot;7&quot; as this is the result of 3 + 4.&lt;/p&gt;
&lt;p&gt; myVariable = &quot;String&quot;&lt;/p&gt;
&lt;p&gt;If I checked this variable, I would find exactly what it was set to, that being the word &quot;String&quot;. Variables can be set to literal text, numbers, calculations, functions you name it. Basically anything that can be specified within a calculation.&lt;/p&gt;
&lt;p&gt;It should be noted at this time that variables occur in three forms within FileMaker:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Local variables (ie $Variable) , used in scripts to store results, numbers, text and so on...&lt;/li&gt;
&lt;li&gt;Global Variables (ie $$Variable), also used in scripts, these retain their value for the duration of a users session once set.&lt;/li&gt;
&lt;li&gt;Let statement variables. These only exist within the scope of the calculation in which they are used.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Back to the Function&lt;/p&gt;
&lt;p&gt;Variables are defined within the Let function in one of two formats, depending upon whether you are defining one, or more variables.&lt;/p&gt;
&lt;p&gt;First, we will start with defining more than one variable, the format is as follows:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Let (&lt;br&gt;[&lt;br&gt;var1 = 1 + 2 ;&lt;br&gt;var2 = 2 + 3 ;&lt;br&gt;var3 = 3 + 4 &lt;br&gt;]&lt;br&gt;;&lt;br&gt;var1 + var2 + var3&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;You can see I have split things out onto separate lines to make it more visible the format. When defining multiple variables, they must always be enclosed in square brackets. Within those brackets, each variable defined is separated from the next by a semicolon. Note also that the last variable does not require a semicolon, as there are no more variables after it.&lt;/p&gt;
&lt;p&gt;Here, I have created three variables, and set them to various basic calculations. The first parameter of the function is everything contained within the square brackets. The second parameter you can see is the result I wish to return. I wish to return the three variables contents, added together.&lt;/p&gt;
&lt;p&gt;In this basic case, the contents of the three variables are 3, 5, and 7 respectively. With the result defined to be var1 + var2 + var3, the end result will be 3 + 5 + 7, giving an overall result to the function of 15.&lt;/p&gt;
&lt;p&gt;Another example:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Let ([&lt;br&gt;var1 = 4 ;&lt;br&gt;var2 = var1 * var1 ;&lt;br&gt;var3 = var2 / var1 ] ;&lt;br&gt;var3&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;This example, though completely pointless, illustrates the fact that once a variable has been defined, it can be used in subsequent variables that are defined. [B]You cannot use a variable in a definition unless previously defined[/B]. Here, I have referenced var1 in the definition of var2, and referenced both var1 and var2, in the definition of var3. The result is to be var3.&lt;/p&gt;
&lt;p&gt;And Finally&lt;/p&gt;
&lt;p&gt;Here is an example of a let statement in which only one parameter is defined:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Let (&lt;br&gt;param = Get ( ScriptParameter ) ;&lt;br&gt;Case (&lt;br&gt;param = 1 ; &quot;One&quot; ;&lt;br&gt;param = 2 ; &quot;Two&quot; ;&lt;br&gt;param = 3 ; &quot;Three&quot; ; &quot;I Don&#039;t Know&quot;&lt;br&gt;)&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;This example illustrates perhaps one of the most important reasons as to why you would want to use a Let function. Here, the Let function is only defining one parameter, called param. It has been set to the function Get ( ScriptParameter ) so this let statement is most likely being used in a script, where this function is used. The value of param is then checked for one of three values by using a Case statement, and the corresponding result is returned.&lt;/p&gt;
&lt;p&gt;First thing you should note is that with one parameter, square brackets are not required. There exists only one semicolon here, and that separates the single variable definition, from the second parameter (that being the case statement).&lt;/p&gt;
&lt;p&gt;Second thing you should ask yourself, is why bother using a Let statement here? The same calculation could just as easily have been done in the following manner:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Case (&lt;br&gt;Get ( ScriptParameter ) = 1 ; &quot;One&quot; ;&lt;br&gt;Get ( ScriptParameter ) = 2 ; &quot;Two&quot; ;&lt;br&gt;Get ( ScriptParameter ) = 3 ; &quot;Three&quot; ; &quot;I Don&#039;t Know&quot;&lt;br&gt;)&lt;/pre&gt;
&lt;p&gt;Both will return the exact same result. The reason why the Let function is better here, is for readability, and speed purposes. First, you will most likely see that the Let function is far more pleasing on the eye than the second function, as you don&#039;t see the large Get ( ScriptParameter ) function on every line - it appears only once.&lt;/p&gt;
&lt;p&gt;This leads into the second and most important reason - speed. In the Let function, we only reference the Get ( ScriptParameter ) function once, by setting it into a variable. From then on, it is the variable we are referencing, not the function. In the second calculation, we reference the Get ( ScriptParameter ) function three times.&lt;/p&gt;
&lt;p&gt;What if we were referencing a far more complex calculation, or custom function, which took half a second to give the result? Well, the first Let function would take half a second. The second one would take 1.5 seconds, because everytime we are calling it, it has to be evaluated.&lt;/p&gt;
&lt;p&gt;The key concepts here are:&lt;/p&gt;
&lt;p&gt;Ã¢ÂÂ¢ If part of a calculation is going to be repeated many times, then it should be defined as a variable within a Let function&lt;/p&gt;
&lt;p&gt;Ã¢ÂÂ¢ If a calculation is starting to look too complex or hard to understand, try splitting it into simpler components as variables using a Let function&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:15:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/let-me-tell-you-bout-let/</guid>
		</item>
		
		<item>
			<title>Creating a Graphics table for your User Interface</title>
			<link>https://www.teamdf.com/blogs/creating-a-graphics-table-for-your-user-interface/</link>
			<description>&lt;p&gt;Building layouts in FileMaker can involve adding a number of various elements such as fields, buttons, portals, tab controls, and graphics such as jpg and png images. It is the use of images on layouts that this article is all about.&lt;/p&gt;
&lt;p&gt;You may want to use image files on your layouts for a number of reasons, such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;A background fill, i.e. gradient image&lt;/li&gt;
&lt;li&gt;To be used as buttons, or links&lt;/li&gt;
&lt;li&gt;Images for design purposes, ie rounded edges, shapes, icons etc.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The simplest way to use images is to insert or paste them directly onto the layout. This can be done by pasting from the clipboard, or using the Insert -&amp;gt; Picture command from the FileMaker menu. When you use these options, the image is inserted directly onto the specific layout. If you then duplicate the image to be used on the layout, then 2,3,4.. and so on images will exist individually on the layout.&lt;/p&gt;
&lt;p&gt;What happens if you then have 10 layouts, and you want to use the same image on each layout as a button? You could insert it onto the 10 layouts. In doing so, the image now exists in 10 different locations within the file.&lt;/p&gt;
&lt;p&gt;FileMaker itself is smart enough to recognize that the same image has been used multiple times within the file, and so internally, it only retains one copy of the file. This means that a database file with 1 copy of an image in it, will be the same size as a duplicate version of the file, but with 50 copies of the image in it.&lt;/p&gt;
&lt;p&gt;This might all seem fine, but what if you then wished to alter any of the images used in your system? Worse still, what if it is a particularly large system, with the same images used on many layouts for purposes such as navigation, or buttons?&lt;/p&gt;
&lt;p&gt;If you were to follow the method above, it would require you to manually replace the image in question on every layout, a tedious and time consuming task. FileMaker does not give you any way to change the internally stored image within the file, when it has been inserted or pasted onto a layout.&lt;/p&gt;
&lt;p&gt;The Alternative Approach - Using a Table:&lt;/p&gt;
&lt;p&gt;There is, however, a way in which you can change images, and have them update everywhere in your system. This is achieved through using a special table called a Graphics table. In fact, any table will work fine, but it is good practice to keep your images that are used for User Interface purposes in their own separate table.&lt;/p&gt;
&lt;p&gt;This special Graphics table will contain fields that are of the Container type. Containers fields are special fields that allow you to store things such as images and video, as well as files such as PDF documents or excel spreadsheets.&lt;/p&gt;
&lt;p&gt;Let&#039;s consider a solution in which you have 10 icons you wish to use as buttons throughout the database. These icons will appear on many layouts. The first thing to do is create 10 container fields in the Graphics table, and name each field appropriately.&lt;/p&gt;
&lt;p&gt;You will also want to set the storage of the fields to be &quot;Global&quot;. Having the image fields as global, means that they will be able to be referenced from any layout within the file, without the need for a relationship between the layouts Table Occurrence, and the Graphics Table Occurrence.&lt;/p&gt;
&lt;p&gt;Once the table is created and setup, the next step is to insert the icon images into the relevant container fields. This process should be done when the file is offline (ie not being hosted on FileMaker Server). By setting the container fields offline, the icons will remain in the fields when that file is later hosted on Server.&lt;/p&gt;
&lt;p&gt;The icons are now all set and ready to be used. Rather than inserting images directly onto layouts, now you will be adding the relevant container field to the layout instead. It is the container field that will be displaying the icon now.&lt;/p&gt;
&lt;p&gt;The beauty of the whole setup is that to later change an icon, all you need to do is change the icon in the container field, and it will change on all layouts where that container field is displayed.&lt;/p&gt;
&lt;p&gt;Using this technique, you can take it further to achieve other kinds of functionality, such as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Multiple records in your graphics table. If your database has various levels of users, you can create a graphics record for each type of user. Each record contains slightly different graphics, and colours, so that the users have a different user experience, it can also be used as a way of distinguishing users in the system. The graphics record a user is assigned, and thus displayed, is managed internally in the system via relationships and other techniques.&lt;/li&gt;
&lt;li&gt;Very fast to alter a user interface experience. If you are developing a system for a user, this can be a great way to quickly change the look and feel of your solution, without completely redesigning the layouts. If you use container fields for background colours, fills, navigation, buttons and so on, then you can completely change the look of your layouts in a couple of minutes.&lt;/li&gt;
&lt;/ul&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:13:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/creating-a-graphics-table-for-your-user-interface/</guid>
		</item>
		
		<item>
			<title>Using an Offscreen Window to do a Scripts Work </title>
			<link>https://www.teamdf.com/blogs/using-an-offscreen-window-to-do-a-scripts-work/</link>
			<description>&lt;p&gt;This is a simple technique that I use all the time and find works very reliably. It involves having a script create a new window into which the script executes it&#039;s necessary steps, before closing it when done.&lt;/p&gt;
&lt;p&gt;Sometimes during a scripts execution it may be required to switch the current layout to another, perform some operations on that other layout, before returning back to the main layout. When this happens, the user should expect to see nothing out of the ordinary occur - to them, the layout didn&#039;t change at all.&lt;/p&gt;
&lt;p&gt;There are however a number of things that will change/happen when a layout loads:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Tab controls will revert to their default tab&lt;/li&gt;
&lt;li&gt;Portals will reset to the top of the list&lt;/li&gt;
&lt;li&gt;OnLayoutLoad and OnRecordLoad script triggers will execute if set.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Sometimes these are undesirable and you don&#039;t want them to happen when a script is run. To remedy this, you can use the offscreen window technique.&lt;/p&gt;
&lt;p&gt;As an example, consider a simple 2 table database, containing a Customer table, and an Invoice table. A one to many relationship exists between the two, that is to say, one Customer may have many Invoices.&lt;/p&gt;
&lt;p&gt;The customer &quot;Joe Bloggs&quot; has about 100 invoices, which are displayed in a portal on the layout. In addition to this, there is a tab control object with 4 tabs to separate information such as &quot;Personal Details&quot; , &quot;Banking&quot; , &quot;Relationships&quot; and &quot;Invoices&quot;.&lt;/p&gt;
&lt;p&gt;One of the databases features is a &quot;Duplicate Invoice&quot; button that is located inside the Invoices portal. When a user clicks the duplicate invoice button, the selected invoice needs to be duplicated.&lt;/p&gt;
&lt;p&gt;A typical script to duplicate the chosen invoice might look like this:&lt;/p&gt;
&lt;pre&gt;Set Variable [ $InvoiceNumber ; Get ( ScriptParameter ) ]&lt;br&gt;Go to Layout [ &quot;Invoices&quot; (Invoices) ]&lt;br&gt;Enter Find Mode []&lt;br&gt;Set Field [ Invoices::Invoice Number ; $InvoiceNumber ]&lt;br&gt;Perform Find []&lt;br&gt;Duplicate Record/Request&lt;br&gt;Go to Layout [ Original Layout ]&lt;/pre&gt;
&lt;p&gt;Here, the chosen Invoice number from the portal is passed as a script parameter. The script goes to the Invoices layout, finds the invoice in question, and duplicates it before returning back to the original layout.&lt;/p&gt;
&lt;p&gt;The trouble here lies with what happens when the script returns to the original layout:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The visible tab will no longer be &quot;Invoices&quot;, instead, it will revert back to the default tab, most likely &quot;Personal Details&quot;. For the user, all they will see is a tab change, with no other feedback, it is a very disorientating and unwanted result.&lt;/li&gt;
&lt;li&gt;The invoices portal will have jumped back to the top. If the Invoice the user clicked was halfway down the portal, it will no longer be visible.&lt;/li&gt;
&lt;li&gt;If the layout has any OnLayoutLoad, or OnRecordLoad triggers, they will run. This can be particularly annoying especially if these scripts do unintended user interface things (such as changing tabs, or record).&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;And the Alternative Approach:&lt;/p&gt;
&lt;p&gt;The alternative approach here is to first create a temporary offscreen window, have the script operate in that window, and close it when done. The main benefit of this approach is that the original window remains untouched, this means active tabs will be preserved, script triggers will not run, and no portal positions will be affected.&lt;/p&gt;
&lt;p&gt;The modified script is shown below, with new steps in bold:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Set Variable [ $InvoiceNumber ; Get ( ScriptParameter ) ]&lt;br&gt;New Window [Name: &quot;Temp&quot;; Height: 0; Width: 0; Top; 0 ; Left: -5000]&lt;br&gt;Go to Layout [ &quot;Invoices&quot; (Invoices) ]&lt;br&gt;Enter Find Mode []&lt;br&gt;Set Field [ Invoices::Invoice Number ; $InvoiceNumber ]&lt;br&gt;Perform Find []&lt;br&gt;Duplicate Record/Request&lt;br&gt;Close Window [ Current Window ]&lt;/pre&gt;
&lt;p&gt;Here, you can see a new window is created as the second step. It&#039;s left coordinate is set at a low negative number, ie -5000. The script executes in this window, before closing when done.&lt;/p&gt;
&lt;p&gt;It may be that -5000 may not work for you, it all depends on your screen size, or whether you operate dual monitors. Whatever the case, a negative number should be found that works for you. To abstract this, you could set this value into a global variable $$OffScreenLeft upon startup. This means you will only need to set it in one place in your solution.&lt;/p&gt;
&lt;p&gt;You should also note that given the fact an offscreen window is created, we don&#039;t want to end up in the situation where the script bombs out, leaving the user in this small offscreen window. Even worse, you don&#039;t want to leave this window open ever or it may create confusion later on. You will need to be smart in your scripting to ensure that no situation will arise where this window can be left open.&lt;/p&gt;
&lt;p&gt;In the case of the script above, I felt it safe enough not to include error checking on the find, however if you feel the script may be used elsewhere, or for another purpose, it may be useful to include error checking, such as the following (in bold):&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;Set Variable [ $InvoiceNumber ; Get ( ScriptParameter ) ]&lt;br&gt;New Window [Name: &quot;Temp&quot;; Height: 0; Width: 0; Top; 0 ; Left: -5000]&lt;br&gt;Go to Layout [ &quot;Invoices&quot; (Invoices) ]&lt;br&gt;Enter Find Mode []&lt;br&gt;Set Field [ Invoices::Invoice Number ; $InvoiceNumber ]&lt;br&gt;Set Error Capture [ On ]&lt;br&gt;Perform Find []&lt;br&gt;Set Variable [ $Error ; Get ( LastError ) ]&lt;br&gt;Set Error Capture [ Off ]&lt;br&gt;If [ Get ( LastError ) = 0 and Get ( FoundCount ) = 1 ]&lt;br&gt;  Duplicate Record/Request&lt;br&gt;End If&lt;br&gt;Close Window [ Current Window ]&lt;/pre&gt;
&lt;p&gt;Here, error checking has been added to the find to ensure that a) the find is successful, and b) that we are only going to duplicate 1 invoice only. Whether or not the script worked or not, a window was created, and thus must be closed as the final step.&lt;/p&gt;
&lt;p&gt;Final Thoughts..&lt;/p&gt;
&lt;p&gt;Remember, you are ultimately building databases for users, and so usability and the users experience should be one of your top priorities when developing a solution, more often than not it is the little things that matter!&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 10:06:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/using-an-offscreen-window-to-do-a-scripts-work/</guid>
		</item>
		
		<item>
			<title>Conditional Value Lists Pt 1 - What Are They &amp; How to Build Them</title>
			<link>https://www.teamdf.com/blogs/conditional-value-lists-pt-1-what-are-they-how-to-build-them/</link>
			<description>&lt;p&gt;Conditional Value lists may be the most asked about piece of functionality on the &lt;a href=&quot;http://filemakertoday.com/com/forum.php&quot;&gt;FileMaker Cafe&lt;/a&gt;. To try and provide a thorough and easy to follow explanation of what they are and how they work, I decided to write an article on the subject and build a small example file to help illustrate the technique.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is a conditional value list?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A conditional value list is any value list whose contents can dynamically change. The most common method to change a value lists values is to change the contents of another field. In this case, the values that are displayed in the value list are &lt;em&gt;dependent&lt;/em&gt; upon the value in the field. Indeed, the terms conditional and dependent can be interchangeable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why are they used?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Conditional value lists are a great way to narrow down the size of large value lists by breaking them down into smaller manageable lists. They also help when you need to select values for 2 or more fields. The easiest way to show this is to jump straight in with a straightforward example.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sport Equipment Example&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I have a database that is used for recording a large variety of sporting equipment. I have a sport table that contains the following fields:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Sport Category&lt;/li&gt;
&lt;li&gt;Sport Name&lt;/li&gt;
&lt;li&gt;Sport Equipment&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/conditionalvl-1-1.png&quot; alt=&quot;conditionalvl 1 1&quot; width=&quot;211&quot; height=&quot;109&quot;&gt;&lt;/p&gt;
&lt;p&gt;Each item of equipment can be categorised into a specific sport, and that sport falls into a specific sporting category. Examples of sporting categories might be Ball sports, stick sports, contact sports. A sport name might be Hockey, and for that sport the equipment could be a stick, a puck, a net, or gloves.&lt;/p&gt;
&lt;p&gt;Lets imagine now, that the database also acts as a way to hire out sporting equipment. When a piece of equipment is hired out to someone, a record is created in the database, and that item of equipment is captured on the record.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One field, one value list?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The piece of sporting equipment could be recorded into a single field. One of the problems with this is if there are many thousand items of sporting equipment, the value list is very large and may be tedious to select the item.&lt;/p&gt;
&lt;p&gt;Consider also, that many sports contain the same type of item. for example Netball, Basketball, and Ice Hockey all have nets, so if you chose &quot;net&quot; as the item of equipment, how would you know what type of net it is ?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Three fields, three value lists&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A more clear solution is to define the item of equipment as a category, name, and the item itself - basically use the fields already in the sport equipment table.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/conditionalvl-1-2.png&quot; alt=&quot;conditionalvl 1 2&quot; width=&quot;290&quot; height=&quot;83&quot;&gt;&lt;/p&gt;
&lt;p&gt;The first step is to select a category - there are far fewer sporting categories than there are items of equipment, so selecting a category should be very easy.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/conditionalvl-1-3.png&quot; alt=&quot;conditionalvl 1 3&quot; width=&quot;282&quot; height=&quot;100&quot;&gt;&lt;/p&gt;
&lt;p&gt;With a category chosen, the next step is to choose a sport. There is no value in showing EVERY sport, instead, what you would expect to see is just the sports that are of the category you have chosen. Again this will keep the list of sports much smaller and more manageable.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/conditionalvl-1-4.png&quot; alt=&quot;conditionalvl 1 4&quot; width=&quot;279&quot; height=&quot;127&quot;&gt;&lt;/p&gt;
&lt;p&gt;Lastly, to select an item of equipment, you would expect to only see items of equipment that belong to the sport you have chosen, which itself belongs to the category you have chosen.&lt;/p&gt;
&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/conditionalvl-1-5.png&quot; alt=&quot;conditionalvl 1 5&quot; width=&quot;288&quot; height=&quot;147&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Constructing the Value Lists&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The category value list is easy. It&#039;s just a straight up value list of all sport categories from the table. The &quot;All Values&quot; option is used in the value list.&lt;/p&gt;
&lt;p&gt;The sport Name value list is the first of the &quot;conditional&quot; lists. Conditional value lists are built using the &quot;Include only related values starting from&quot; option in the value list setup. Because of this, conditional value lists also require you to create a relationship for the purpose.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/conditionalvl-1-6.png&quot; alt=&quot;conditionalvl 1 6&quot; width=&quot;294&quot; height=&quot;29&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600123-conditionalvl-1-7.png&quot; alt=&quot;conditionalvl 1 7&quot; width=&quot;600&quot; height=&quot;123&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the image above, I have created a relationship between my main table (which contains the fields I am entering values into), and the Sport Equipment table. The &lt;strong&gt;condition&lt;/strong&gt; on the relationship is Sport Category = Sport Category. This means the relationship is setup to only find sport Equipment whose category is the same as the category I have chosen. That is the condition. By building a value list based on this relationship - the value list will also only show sport names which belong to the category I have chosen. Note that relationships &amp;amp; value lists are basically the same thing - the value list is showing records through the relationship you define.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600453-conditionalvl-1-8.png&quot; alt=&quot;conditionalvl 1 8&quot; width=&quot;600&quot; height=&quot;453&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here, you can see the value list built that is based on the relationship created above. The field the value list is displaying is Sport Name through the relationship. The most important part of the setup is the &quot;Include only related values starting from&quot; option - in this case it is set to &quot;Home&quot; which is the table occurrence on the left hand / source side of the relationship.&lt;/p&gt;
&lt;p&gt;The end result is a list of sport names for the chosen category.&lt;/p&gt;
&lt;p&gt;Taking this principle to the next step, the Sport Equipment field can have a value list built which shows just equipment for the chosen category AND name. In this case, the &lt;strong&gt;condition&lt;/strong&gt; is that my chosen sport category AND name, matches all Sport equipment records with the same category and equipment.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600517-conditionalvl-1-9.png&quot; alt=&quot;conditionalvl 1 9&quot; width=&quot;600&quot; height=&quot;517&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is the relationship created for the second value list construction. The two conditions are specified.&lt;/p&gt;
&lt;p&gt;The value list is built in the exact same way as the one for Sport Names, however this time the new relationship is chosen, and sport equipment will be the field in the value list.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600453-conditionalvl-1-10.png&quot; alt=&quot;conditionalvl 1 10&quot; width=&quot;600&quot; height=&quot;453&quot;&gt;&lt;/p&gt;
&lt;p&gt;(the results of all 3 value lists are shown in the earlier pictures).&lt;/p&gt;
&lt;p&gt;Final Thoughts:&lt;/p&gt;
&lt;p&gt;That&#039;s it, it&#039;s just that simple. Conditional value lists are built using relationships. the condition part refers to the fact that the values are dependent upon a value you choose in another field - that field is then used in the relationship to narrow down the records through the relationship - and thus the records in the value list.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example File&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Please find attached an example file. This file was used for all the screenshots in this article, and is fully commented to help you fully understand what is going on in the file.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.teamdf.com/assets/files/weetbicks/conditionalvl/ConditionalValueLists.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/conditional-value-lists-pt-1-what-are-they-how-to-build-them/</guid>
		</item>
		
		<item>
			<title>Weetbicks Gone Wild (and portals...)</title>
			<link>https://www.teamdf.com/blogs/weetbicks-gone-wild/</link>
			<description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;You may have noticed a lack of article postings over the last couple of months, and fewer articles overall this year. Please don&#039;t panic for it has not been through laziness or lack of content.&lt;/p&gt;
&lt;h4&gt;What have I been up to&lt;/h4&gt;
&lt;p&gt;Next year I am taking 5 months off work at Digital Fusion and heading to Africa where I am riding in the 2013 Tour d&#039;Afrique. This is a 12,000km cycle adventure that sees myself and around 50 other riders wind our way from Cairo to Cape Town. I have been saving for this trip since 2009, registered in 2010 and this year have finally paid for it and began preparing.&lt;/p&gt;
&lt;p&gt;Cycling is in my blood and this is definitely my biggest cycling adventure to date. A few years ago I cycled across the USA solo but that pales in comparison to the challenge ahead - but its challenge that is the primary motivator for me and I can&#039;t wait!&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/514/route.png&quot; alt=&quot;The TDA Route&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Cycling for a Cause&lt;/h4&gt;
&lt;p&gt;As part of my trip I have chosen to fundraise for a great charity in both New Zealand and Australia called The Heart Foundation.&lt;/p&gt;
&lt;p&gt;The Heart Foundation is a charity that relies on donations and funding to help sponsor their research into the prevention of heart disease, as well as promoting healthy eating and healthy lifestyles in general.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Please&lt;/strong&gt; consider making a donation in support of my ride for the heart foundation. Any amount will be greatly appreciated by myself and the foundation and you can be assured your money is going toward helping people to lead better and healthier lives.&lt;/p&gt;
&lt;p&gt;You can make a donation through the Weetbicks Gone Wild site here.&lt;/p&gt;
&lt;h4&gt;How you can follow along&lt;/h4&gt;
&lt;p&gt;With the help of my colleague Captain 404 (aka Phil Taylor) we have created a website for my trip which you can visit to check out all the info, donate, and keep up to date of preparations, and posts from the road.&lt;/p&gt;
&lt;p&gt;I will be taking a small amount of technology with me in the hope that I can post regular updates during the ride along with photos - as internet speed permits! You can check out the site here.&lt;/p&gt;
&lt;h4&gt;Now, this IS a FileMaker site after all?&lt;/h4&gt;
&lt;p&gt;You didn&#039;t think I would write a whole article and not make any mention of FileMaker did you? Okay here&#039;s a quick tip for something that has always bothered me in FileMaker but is now fixable in 12.&lt;/p&gt;
&lt;p&gt;Ever create a portal and want to suppress the grey (black on windows) highlight that appears when you click inside a portal row? Normally this is avoidable if your entire portal row is a button, perhaps for selection purposes, but in the case of a regular portal this highlight can be really annoying and detracts from the visual appeal of your portal.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/515/weetbicksgonewild1.png&quot; alt=&quot;Portal highlight&quot;&gt;&lt;/p&gt;
&lt;p&gt;I tried various methods to resolve this and found the following method all but eliminates the default portal row highlight:&lt;/p&gt;
&lt;p&gt;1. Place a text object in your portal and resize to to fill the portal row&lt;br&gt;2. Assign it the &#039;Exit Script[]&#039; step essentially making it a button&lt;br&gt;3. Change to the &#039;Pressed&#039; state, and set the fill to &#039;none&#039;&lt;br&gt;4. Set the button at the back of the portal and lock&lt;/p&gt;
&lt;p&gt;By removing the pressed visual cue on the button, the end result is from the users standpoint they are not clicking a button at all, rather just a blank space. The button suppresses the portal row highlight from appearing!&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/weetbicks-gone-wild/</guid>
		</item>
		
		<item>
			<title>Even Cooler InLine Labels</title>
			<link>https://www.teamdf.com/blogs/even-cooler-inline-labels/</link>
			<description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;One of the cool things that conditional formatting has allowed us to do ever since its introduction in FileMaker 9 is to build inline field labels that become hidden when the field contains text. With the introduction of field state formatting in FileMaker 12, we can take these inline labels even further and make them even more awesome.&lt;/p&gt;
&lt;h4&gt;The Conventional Label&lt;/h4&gt;
&lt;p&gt;Below is an example of a typical setup of an inline label.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/inline-1.png&quot; alt=&quot;inline 1&quot; width=&quot;375&quot; height=&quot;57&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here the label is &#039;Category&#039;. The label is simply placed underneath a transparent field, and conditional formatting is applied to the field itself:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600485-inline-2.png&quot; alt=&quot;inline 2&quot; width=&quot;600&quot; height=&quot;485&quot;&gt;&lt;/p&gt;
&lt;p&gt;The conditional formatting is very simple, and tells the field to fill itself with a solid colour if its contents is not empty.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/inline-3.png&quot; alt=&quot;inline 3&quot; width=&quot;390&quot; height=&quot;73&quot;&gt;&lt;/p&gt;
&lt;p&gt;This method works great and can be very useful particular for data entry fields. One issue it has however is that as soon as the user clicks into the field, the label disappears. This is because the field has its own in-focus fill set which could not be modified prior to FileMaker 12.&lt;/p&gt;
&lt;h4&gt;Keeping the Label Visible&lt;/h4&gt;
&lt;p&gt;So how can we keep the label visible even if the user clicks in the field? The solution lies in a couple of technologies being used together to achieve the desired result.&lt;/p&gt;
&lt;p&gt;First of all, we are going to keep the same field and and same label in the same spot, but we will remove the conditional formatting on the field, this will not be required. We will also keep the field with a transparent fill for its normal fill colour.&lt;/p&gt;
&lt;p&gt;Next, we are going to change the fill colour for when the field is in its &lt;strong&gt;&#039;in focus&#039;&lt;/strong&gt; state. When in this state, it basically means the mouse cursor is clicked in the field. For us, we essentially want the field to have no fill at all, thus revealing the inline label.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/inline-4.png&quot; alt=&quot;inline 4&quot; width=&quot;225&quot; height=&quot;148&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now, there are a couple of oddities here around selecting the fill colour. First, this technique won&#039;t work if you select &quot;no fill&quot; as the fill, nor will it work if you select a fill with 0% opacity (in other words transparent). I&#039;m not sure why, but as soon as you select either of these as the fields in focus fill colour, it will treat the field as having a solid fill when clicked in. What I mean here is that the underlying/overlaying label will be hidden.&lt;/p&gt;
&lt;p&gt;The workaround for this is to set the fill colour to a 1% opacity, so not quite transparent, but pretty damn close!&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/inline-5.png&quot; alt=&quot;inline 5&quot; width=&quot;189&quot; height=&quot;468&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now, when you click into the field you should see something like the below:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/inline-6.png&quot; alt=&quot;inline 6&quot; width=&quot;403&quot; height=&quot;75&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is the type of effect we are trying to achieve - having the label remain visible even if the cursor is placed in the field. The in-focus formatting is applied, which is a 1% opacity fill, thus revealing contents behind or in front of the field.&lt;/p&gt;
&lt;h4&gt;Now, what happens if we type?&lt;/h4&gt;
&lt;p&gt;Well, the result is not very pretty!&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/inline-7.png&quot; alt=&quot;inline 7&quot; width=&quot;392&quot; height=&quot;65&quot;&gt;&lt;/p&gt;
&lt;p&gt;As we type, there is no conditional formatting happening to make the label disappear. Also, we are unable to apply conditional formatting to a field state, so we cannot tell the field to fill itself if it is not empty while in the in focus state.&lt;/p&gt;
&lt;p&gt;So how do we make the label disappear upon typing? The answer here is to use a combination of conditional formatting &lt;strong&gt;on the label&lt;/strong&gt; and a very simple 1 line script that will trigger the conditional formatting with minimal interruption to the user.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600485-inline-8.png&quot; alt=&quot;inline 8&quot; width=&quot;600&quot; height=&quot;485&quot;&gt;&lt;/p&gt;
&lt;p&gt;First comes the conditional formatting. This is applied to the label directly. The formula will apply conditional formatting when the associated field is not empty.&lt;/p&gt;
&lt;p&gt;The formatting itself is a change in the labels font size, we will increase its font size to 500pt, this should be sufficiently large enough that the font will not render within the bounds of the text label object, basically hiding it.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600408-inline-9.png&quot; alt=&quot;inline 9&quot; width=&quot;600&quot; height=&quot;408&quot;&gt;&lt;/p&gt;
&lt;p&gt;So, if the field is not empty, the label disappears. In order to make this happen we run an onObjectModify triggered script on the field&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600486-inline-10.png&quot; alt=&quot;inline 10&quot; width=&quot;600&quot; height=&quot;486&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/_resampled/ResizedImage600400-inline-11.png&quot; alt=&quot;inline 11&quot; width=&quot;600&quot; height=&quot;400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The script simply does a Set field step and sets whatever the active field is to its own contents. This simple action is enough to trigger conditional formatting on the layout without the need for a refresh window step (which is slower).&lt;/p&gt;
&lt;h4&gt;So in Summary...&lt;/h4&gt;
&lt;ul&gt;&lt;li&gt;Set field to 1% opacity in focus fill&lt;/li&gt;
&lt;li&gt;Set label to font size 500pt if field not empty&lt;/li&gt;
&lt;li&gt;Set onObjectModify script trigger on field to conditionally format&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file is provided to help you fully understand what is going on in this article, and to let you experiment with your own labels.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/inlinelabels/InLineLabels.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;And Finally...&lt;/h4&gt;
&lt;p&gt;This will be my last article for the next 6 months. In January I am starting a cycling journey in Africa from Cairo Egypt all the way south to Cape Town South Africa. Suffice to say, internet connection will be sketchy and I won&#039;t have a copy of FileMaker with me :)&lt;/p&gt;
&lt;p&gt;Thanks to all the readers of this site for your support this year. I apologise for not having written more than I did the previous year, but this trip has really taken over my life and occupied my every waking minute, but I didn&#039;t want to leave you without one final article for the year so I hope you enjoy it.&lt;/p&gt;
&lt;p&gt;Please also remember that I am fundraising for the Heart Foundation as part of my adventure next year. These guys do amazing work in NZ and Australia for all ages and I would love it if you were able to make a small contribution toward the cause if you can.&lt;/p&gt;
&lt;p&gt;You can make a donation via the website I have created for the trip by clicking the logo below. Thank you again.&lt;/p&gt;
&lt;p&gt;Cheers,&lt;br&gt;Daniel&lt;a href=&quot;http://www.teamdf.com/gonewild&quot;&gt;&lt;br&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.teamdf.com/gonewild&quot;&gt;&lt;img title=&quot;&quot; src=&quot;http://www.teamdf.com/gonewild/assets/images/weetbicks-gone-wild-ls.png&quot; alt=&quot;&quot;&gt;&lt;/a&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/554/route.png&quot; alt=&quot;The TDA Route&quot;&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/even-cooler-inline-labels/</guid>
		</item>
		
		<item>
			<title>A Portal Grey Area</title>
			<link>https://www.teamdf.com/blogs/a-portal-grey-area/</link>
			<description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Ever wondered why when you place your mouse cursor in a portal row, the background fill of that row goes grey (or for our Windows friends it used to go a ghastly black colour)? Me too, in fact I have spent many restless nights pondering this baffling design quirk of portals. It may be useful if you temporarily forget which portal row your eyes are looking at and need to quickly re-align your vision but does that ever really happen? The fill is not a highlight either. The active portal row really has no significance in the selection of a record, nor is it of any benefit if running a script from the portal row - the script knows what the active row is without you first putting your cursor in it.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/greyarea-1.png&quot; alt=&quot;greyarea 1&quot; width=&quot;280&quot; height=&quot;113&quot;&gt;&lt;/p&gt;
&lt;p&gt;So why does this occur? I cannot answer that question, but what I can answer is how we can now get rid of it once and for all!&lt;/p&gt;
&lt;h4&gt;How we used to get rid of the fill&lt;/h4&gt;
&lt;p&gt;Back in 2012, I posted &lt;a href=&quot;http://www.teamdf.com/weetbicks/weetbicks-gone-wild/180/&quot;&gt;this article&lt;/a&gt; which gave a technique of how you can eliminate this fill colour. It involved adding a white filled object into the portal row with an &quot;Exit Script&quot; step attached and no hand cursor. The result was when a user clicked in a portal row they were in fact clicking a button unbeknownst to them, and never able to click the portal row to make it active.&lt;/p&gt;
&lt;p&gt;With FileMaker 13 this active portal row fill is now a customisable setting and we can completely eliminate it.&lt;/p&gt;
&lt;h4&gt;How can we do this&lt;/h4&gt;
&lt;p&gt;The first thing you need to do is to go into the portal setup and tick the &quot;Use active row state&quot; option. This may seem counter-intuitive - surely you would want to disable the active row state in order to prevent any fill. In actuality, keeping it disabled gives the default grey fill behaviour.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/greyarea-2.png&quot; alt=&quot;greyarea 2&quot; width=&quot;587&quot; height=&quot;445&quot;&gt;&lt;/p&gt;
&lt;p&gt;Next, select the portal and in the inspector go to the Appearance tab. Choose &quot;Portal: Row&quot; from the object drop-down (it defaults to Portal) and then choose the &quot;Active&quot; state underneath.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/greyarea-3.png&quot; alt=&quot;greyarea 3&quot; width=&quot;242&quot; height=&quot;420&quot;&gt;&lt;/p&gt;
&lt;p&gt;There is your grey fill! You can now chose no fill colour to get rid of it (or if you are sadistic any other colour of your choosing).&lt;/p&gt;
&lt;p&gt;Finally, you&#039;ll notice the borders are on by default for the active row. The border defaults to the same colour as the grey fill which is why you never notice a border. Now that we have removed the fill you will also need to disable borders otherwise clicking in the active row puts a visible border around that row and looks a bit weird.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;leftAlone&quot; title=&quot;&quot; src=&quot;https://www.teamdf.com/assets/Uploads/greyarea-4.png&quot; alt=&quot;greyarea 4&quot; width=&quot;234&quot; height=&quot;343&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Active portal row fills can have their uses in some situations, but in our experience they are just a nuisance. Typical highlights serve a purpose such as selecting a portal row record and are achieved using other methods such as conditional formatting. Knowing which portal row is the active row does not have many purposes aside from giving you a visual cue which portal row you last clicked on. If you have ever found this active row fill annoying then you can now get rid of it forever :)&lt;/p&gt;
&lt;h4&gt;Example File&lt;/h4&gt;
&lt;p&gt;Please find attached an example file. This file is provided to help you fully understand what is going on in this article. Note that FileMaker 13 is required to view this example file.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;ss-download&quot; href=&quot;https://www.teamdf.com/assets/files/weetbicks/greyarea/GreyArea.zip&quot;&gt;Download Example File&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 15 Dec 2010 00:00:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/a-portal-grey-area/</guid>
		</item>
		
		<item>
			<title>iPad is Go</title>
			<link>https://www.teamdf.com/blogs/ipad-is-go/</link>
			<description>&lt;p&gt;We&#039;ve just built our first solution for the iPad, a &quot;Farm Diary&quot; which allows a farmer to work from a map of the farm, tap on a paddock and see a history of what&#039;s happened - what fertiliser has been applied, how many stock are (supposed to be) in there, when it was cultivated, and so on. Another tap adds an action and captures details.&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;&quot; src=&quot;http://teamdf.com/files/display/2/7_1.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The diary will replace years of tatty old notebooks that the farmer has kept - while the notebooks are a vital tool on the farm, they&#039;re not able to be shared between staff (3 in this case), can&#039;t be searched or summarised (how many acres of maize have we got this year?), and are at risk of getting lost or soaked - one of the guys told us how he was repairing a flood pump when the gate opened and dowsed him in water flowing at something like a &quot;44 gallon drum every few seconds&quot; - of course that wouldn&#039;t be much good for an iPhone either but the difference is that the iPhone would be backed up and is easily reinstated.&lt;/p&gt;
&lt;p&gt;It&#039;s early days yet - we&#039;ve sent v1 out for field trials (so to speak!) One thing that&#039;s pretty obvious already is that details of workflow, such as minimising typing, having a back button, and having just enough information but not too much are vital in a mobile application.&lt;/p&gt;
&lt;p&gt;We&#039;ve designed each screen to be very big and clear without too much information so it&#039;s quick and easy at a glance to read. Likewise buttons and fields are oversized compared to a desktop database making it easy to tap with a finger.&lt;/p&gt;
&lt;p&gt;The farm diary is built using FileMaker Go, a version of FileMaker for the iOS devices as they&#039;re collectively known (i.e. the iPhone, iPod Touch and iPad). What&#039;s most amazing about FileMaker Go from a technical perspective is that it is very close to a full replica of FileMaker on the desktop - in other words, it&#039;s a very powerful database that can be highly customised.&lt;/p&gt;
&lt;p&gt;At the moment the database is designed for the iPad screen size, but since FileMaker Go works on iPhone too and iPhones are a lot easier to carry around in your pocket I can see that we&#039;ll need to create screens for the iPhone too very soon - that&#039;s easy enough to do with FileMaker Go; likewise for landscape and portrait views, but you end up with 4 versions of each screen. The catch then is that any change you make has to be made across all 4 versions of each screen, so for now we&#039;re just focussed on getting it right in one screensize and orientation (iPad / Portrait).&lt;/p&gt;
&lt;p&gt;We&#039;ll keep you posted on how it Goes...&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Tue, 30 Nov 2010 07:50:00 +1300</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/ipad-is-go/</guid>
		</item>
		
		<item>
			<title>FileMaker 11 Released</title>
			<link>https://www.teamdf.com/blogs/filemaker-11-released/</link>
			<description>&lt;p&gt;Continuing the onward and upward march was the recent release of FileMaker 11, featuring some very nice charting capabilities, and a raft of developer and user improvements. Here&#039;s a quick recap on the highlights:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Charting&lt;/strong&gt;&lt;br&gt;Graphs can now easily be produced from data, in an Excel-like manner. You have a choice of Bar, Horizontal bar, Line, Area and Pie graphs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;QuickFind&lt;/strong&gt;&lt;br&gt;There&#039;s a new version of Find available, which searches multiple fields on a screen for data that you enter. Up until now, a find has targeted just one field at a time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Quick Reports&lt;/strong&gt;&lt;br&gt;If you use Filemaker to create your own reports, you&#039;ll find the new spreadsheet functionality of Quick reports a boon. You can group and summarise data on the fly and easily modify reports by adding, sorting or hiding fields and records.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reduced Screen-flicker on Windows&lt;/strong&gt;&lt;br&gt;The annoying screen flicker that was present in some Windows operations has been much reduced.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FileMaker 11 Server&lt;/strong&gt;&lt;br&gt;In a testament to the superb project management at FMI, they updated Server at the same time: FileMaker Server Advanced now has no limit on the number of users apart from the limitations of your network and server hardware of course. This reflects FMI&#039;s confidence in the performance and reliability of their database engine: improvements made in the previous version are now well proven.&lt;/p&gt;
&lt;p&gt;FM Server includes an array of features and enhancements as well, including Backup to Clone, better security, better admin console stability, and more statistics.&lt;/p&gt;
&lt;p&gt;All-in-all FileMaker 11 is a solid and easy update that we recommend everyone take up. Let us know if you need a hand with licensing or installation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FAQs&lt;/strong&gt;&lt;br&gt;&lt;strong&gt;Can we have some of our users upgrade to FM11 and others remain on FM10?&lt;/strong&gt;&lt;br&gt;Yes, although it would pay to discuss it your developer, because if your system is being changed to take advantage of new FM11 features, we&#039;ll need to bear in mind that not all users will be able to use the features. It won&#039;t break anything for FM10 users if they encounter FM11 features, but they won&#039;t be able to use the new features.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do we need to upgrade FM10 Server if we upgrade some or all of our clients?&lt;/strong&gt;&lt;br&gt;No, FM11 will connect to a FM10 Server.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What are the systems requirements?&lt;/strong&gt;&lt;br&gt;Mac users: Mac OS X 10.5.7 or later; Windows: Windows Vista or 7&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is a conversion process necessary to migrate the data?&lt;/strong&gt;&lt;br&gt;No, FM11 will open a FM10 database without any conversion.&lt;/p&gt;</description>
			<pubDate>Thu, 27 May 2010 15:00:00 +1200</pubDate>
			
			
			<guid>https://www.teamdf.com/blogs/filemaker-11-released/</guid>
		</item>
		
	</channel>
</rss>
