<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <id>tag:buzz.beezwax.net,2005:/articles</id>
  <link rel="alternate" type="text/html" href="http://buzz.beezwax.net" />
  
  <title>the beezwax buzz : the beezwax buzz | beezwax.net</title>
  <subtitle type="html">beezwax.net</subtitle>
  <updated>2013-06-18T11:22:21Z</updated>
  <generator uri="http://www.typosphere.org" version="6.1.4">Typo</generator>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/beezwax/BUZZ" /><feedburner:info uri="beezwax/buzz" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:browserFriendly></feedburner:browserFriendly><entry>
    <id>urn:uuid:a4d1ee16-e8a7-4ba8-b6e9-678854f5b1cf</id>
    <published>2013-06-18T11:11:42Z</published>
    <updated>2013-06-18T11:22:21Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2013/06/18/re-thinking-is-the-new-rebuilding" />
    <author>
      <name>vince</name>
      <email>vince@beezwax.net</email>
    </author>
    <title type="html">Re-Thinking is the new Rebuilding</title>
    <category term="beezwax-news" label="beezwax news" scheme="http://buzz.beezwax.net/category/beezwax-news" />
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="filemaker-add-ons" label="filemaker add-ons" scheme="http://buzz.beezwax.net/category/filemaker-add-ons" />
    <category term="filemaker-news" label="filemaker news" scheme="http://buzz.beezwax.net/category/filemaker-news" />
    <category term="filemaker-resources" label="filemaker resources" scheme="http://buzz.beezwax.net/category/filemaker-resources" />
    <category term="filemaker-tips" label="filemaker tips" scheme="http://buzz.beezwax.net/category/filemaker-tips" />
    <content type="html">&lt;p&gt;&lt;em&gt;Republished from the original &lt;a href="http://inspector.beezwax.net"&gt;InspectorPro Wiki&lt;/a&gt; article&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Sometimes you just need to start over and to take a fresh look at how you are doing things. Many of you know that I usually like to start things anew, but its also understandable that this is impractical at times.&lt;/p&gt;

&lt;p&gt;However, with the release of FileMaker 12, I was inspired to dive deep into how InspectorPro 4 (IP4) was architected and change my way of thinking. It isn't about REBUILDING per se, but rather this is about RE-THINKING your solutions as you move to FM 12.&lt;/p&gt;

&lt;p&gt;At its core, InspectorPro is itself a FileMaker database. The previous version, Inspector Pro 3 (IP3) was originally architected as FileMaker Pro 7 file, and continuously remodeled as we moved all the way through FileMaker Pro 11. InspectorPro 4 on the other hand was built as a FileMaker 12 solution.&lt;/p&gt;

&lt;p&gt;I wanted to tell you more about the approach I used. Hopefully it will give you some ideas as you start to re-think, and ultimately rebuild, solutions in FileMaker 12.&lt;/p&gt;

&lt;h2&gt;Re-thinking InspectorPro 4 in FileMaker 12&lt;/h2&gt;
&lt;p&gt;In 're-thinking' IP4, with FileMaker 12, I was able to do a number of things. Primarily I was able to dramatically improve performance over IP3. There were a number of contributing factors that led to this improved performance. But one of the core changes was the very extensive use of the new ExecuteSQL function in FileMaker 12.&lt;/p&gt;

&lt;p&gt;Here is a side by side census of some of the changes from IP3 to IP4:&lt;/p&gt;

&lt;img src="/files/resource/275/ip4vsip3.png" width="551" alt="IP4 vs IP3"&gt;

&lt;br /&gt;
&lt;p&gt;FileMaker 12's Database Design Report (DDR) outputs more XML metadata than previous versions. IP4 processes this using 13 more XSL Files, and 8 more basetables than IP3.&lt;/p&gt;

&lt;p&gt;The big architecture change in IP4 is in the number of Table Occurrences (TOs) that we're able to do without: 491 fewer.&lt;/p&gt;
  
&lt;p&gt;Removing those TOs ended up removing 510 relationships between them as well. We also managed to make creative use of repeating calculations and drop the number of fields, scripts and calculations significantly. &lt;/p&gt;

&lt;p&gt;Here is what the Relationship graph looked like in the older product, IP3 (zoomed out to 25%):&lt;/p&gt;

&lt;img src="/files/resource/276/ip3rg.png" alt="IP3 Relationship Graph" /&gt;

&lt;br /&gt;
&lt;p&gt;One thing that really jumps out is the DEPENDENCY table. It's the Grand Central Station of the interconnections between entities.&lt;/p&gt;

&lt;p&gt;The big 'Ah-Ha!' moment during development was when we realized the bottlenecks in the DEPENDENCY table. It had the largest number of records imported, and had both many text and number fields that were indexed.&lt;/p&gt;

&lt;p&gt;Removing almost all the indexed text fields gave us a dramatic boost in performance. So, for example, if a field depends on a value list for validating a field, then a record exists in the DEPENDENCY table to represent this. &lt;/p&gt;

&lt;p&gt;With IP3 we stored the DDR IDs of these items, along with the names of the items ( all were indexed ). Similarly if a field could be referenced in a relationship, value list, script step, calculation, or simply on a layout. In each of these cases a record will exist in the DEPENDENCY table to represent this. &lt;/p&gt;

&lt;p&gt;So when looking into the dependency table it just means different things from the perspective from which you look.&lt;/p&gt;

&lt;h2&gt;Trimming the Graph with ExecuteSQL&lt;/h2&gt;
&lt;p&gt;Once we got rid of so many indexed text fields in IP4, how are we able to show the names of these items? Because we have the DDR ID of the item, we simply relied on ExecuteSQL ( 2,858 uses of it to be exact ) to pull through the name of an item when we need it. Here is an example of pulling the name of an account:&lt;/p&gt;

&lt;code&gt;ExecuteSQL ( "SELECT name FROM account WHERE id = " &amp; ACCOUNT_ID &amp; " AND database = 'Contact'" ; "|" ; "¶" )&lt;/code&gt;

&lt;p&gt;Here is what the graph looks like in IP4, also zoomed out at 25%:&lt;/p&gt;

&lt;img src="/files/resource/277/ip4rg.png" alt="InspectorPro 4 Relationship Graph" /&gt;

&lt;p&gt;The end result, as mentioned above, is many fewer table occurrences and relationships. Another big benefit is that this database has fewer elements to track and navigate around. There is simply less code to maintain.

&lt;p&gt;The trade off with this approach, is that it relies on SQL statements. Using this approach, you need make sure these statements are not going to break if you change the names of your fields or tables. But there are great solutions to these challenges. You can use GetFieldName in a Custom Function, and by doing so you get the added benefit of knowing that this field is referenced by the ExecuteSQL function.

&lt;p&gt;You also need to be comfortable with SQL. Don't worry&amp;hellip;there are already some great resources available inside the FileMaker community for learning more about SQL. Here's a good &lt;a href="http://buzz.beezwax.net/2012/07/24/filemaker-12-sql-crafting-structural-beauty"&gt;summary of FileMaker 12 Execute SQL resources&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When FileMaker 7 was introduced there was so much new in that release that I often thought that 'Rebuilding' was the way to go. But after talking to many people over the years about their solution I have realized that sometimes that is an impossible and overwhelming task. Indeed, it is. So now the way I look at it is instead of 'Rebuilding' I like to think of it as 'Re-Thinking'. You can start over and look at what you had before ... move it into place, rework it slightly, or rebuild it using new techniques that you have learned. &lt;/p&gt;

&lt;h2&gt;From Worst To Best&lt;/h2&gt;
&lt;p&gt;One of my favorite sayings is: &amp;nquot;The worst developer is &lt;em&gt;me&lt;/em&gt;, 2 years ago&amp;nquot;. Hopefully your skills improve over time ( attending conferences, user groups, mailing lists, forums, etc&amp;hellip; ). FileMaker gains new features, like ExecuteSQL, where simply a shift in adopting a new feature can lead to dramatic changes. Plus sometimes it's essential to do some spring cleaning and lighten things up. &lt;/p&gt;

&lt;p&gt;With FileMaker 12 there are so many ways you can 'Re-Think' your databases. There's now support for External Container Fields, the new Layout Object Design Surface, many enhancements in the new FileMaker Server 12, and a new version of FileMaker Go ( free ) where you can build mobile solutions. &lt;/p&gt;

&lt;p&gt;I invite you to 'Re-Think' your solutions and hopefully free yourself from database baggage you don't need to keep carrying along. The result may be less code, that's easier to manager, and better solutions, that are easier and faster to debug. And hopefully you'll have more time to enjoy with family and friends.&lt;/p&gt;

&lt;p&gt;Thanks!&lt;/p&gt;
&lt;p&gt;&amp;#8212; Vince&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Vince Menanno is the creator of InspectorPro and Director of FileMaker Development at Beezwax.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;



</content>
  </entry>
  <entry>
    <id>urn:uuid:513c00db-ed91-4611-ac0f-e92681445c75</id>
    <published>2013-05-27T01:04:26Z</published>
    <updated>2013-06-04T05:13:24Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2013/06/03/button-up-2" />
    <author>
      <name>Brian</name>
      <email>brian_s@beezwax.net</email>
    </author>
    <title type="html">Button Up 2: Building State-Aware Buttons</title>
    <category term="design" label="design" scheme="http://buzz.beezwax.net/category/design" />
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="filemaker-resources" label="filemaker resources" scheme="http://buzz.beezwax.net/category/filemaker-resources" />
    <category term="filemaker-tips" label="filemaker tips" scheme="http://buzz.beezwax.net/category/filemaker-tips" />
    <category term="ios" label="iOS" scheme="http://buzz.beezwax.net/category/ios" />
    <category term="ui-ux" label="ui/ux" scheme="http://buzz.beezwax.net/category/ui-ux" />
    <category term="UI" scheme="http://buzz.beezwax.net/tag/ui" />
    <category term="UX" scheme="http://buzz.beezwax.net/tag/ux" />
    <category term="button" scheme="http://buzz.beezwax.net/tag/button" />
    <category term="css" scheme="http://buzz.beezwax.net/tag/css" />
    <category term="demo" scheme="http://buzz.beezwax.net/tag/demo" />
    <category term="design" scheme="http://buzz.beezwax.net/tag/design" />
    <category term="filemaker" scheme="http://buzz.beezwax.net/tag/filemaker" />
    <category term="layout" scheme="http://buzz.beezwax.net/tag/layout" />
    <category term="surface" scheme="http://buzz.beezwax.net/tag/surface" />
    <category term="tutorial" scheme="http://buzz.beezwax.net/tag/tutorial" />
    <content type="html">&lt;p&gt;
Our &lt;a href="http://buzz.beezwax.net/2012/12/15/button-up"&gt;previous post&lt;/a&gt; highlighted the new capabilities of the venerable FileMaker button. In FileMaker 12's Design Surface, the once-humble button gains newfound expressive power, enabling it to respond fluidly to user hovers, taps, and clicks via what we termed &lt;em&gt;interactive formatting&lt;/em&gt;. The catch: interactive buttons &amp;mdash; whether in FileMaker 12, or on any other platform &amp;mdash; are prone to &lt;em&gt;semantic misinformation&lt;/em&gt;, in which interactive formatting unintentionally misleads and confuses users.&lt;/p&gt;
&lt;p&gt;
In this post, we'll learn two lightweight techniques that will give full control of button appearance and behavior. With these two new tools in hand, we'll be able to fully &amp;mdash; and easily &amp;mdash; meet the semantic challenge, and create better, more intuitive solutions.&lt;/p&gt;
&lt;p&gt; 
Before getting started, we invite you to &lt;a href="http://buzz.beezwax.net/files/resource/274/ButtonUp2.fmp12.zip"&gt;download the companion demo file&lt;/a&gt;. This file provides a (sort of) real world demonstration of the challenge of semantic misinformation, and illustrates the solutions we'll present in this post.&lt;/p&gt;
&lt;img src="http://buzz.beezwax.net/files/resource/263/buttonup2__0.png" alt="buttons that don't yet show state" /&gt;
&lt;p class="header_lightblue"&gt;
&lt;strong&gt;The Challenge&lt;/strong&gt;: In the demo file, elements of a bottom button set independently change their availability as business rules act on live data. The first tab demonstrates how standard buttons offer no clues to their availability, forcing users to rely on mere trial and error. Here, a user learns that William Shatner, while spiffily attired, lacks the right stuff to provide secret decoder rings.&lt;/p&gt;
&lt;h1&gt;
Conditional Love&lt;/h1&gt;
&lt;p&gt;
Whenever we want to add state-aware behavior to interactively formatted buttons, the tool we'll reach for is &lt;em&gt;conditional formatting&lt;/em&gt;. FileMaker developers have long trusted this tool to provide real time visual feedback informing users of the state (condition) of data. Now, with the advent of FileMaker 12's Design Surface, &lt;em&gt;conditional formatting&lt;/em&gt; becomes the perfect complement to &lt;em&gt;interactive formatting&lt;/em&gt;. Used in concert, these two formatting tools will let us create interactive, state-aware buttons that remain semantically meaningful as data changes.&lt;/p&gt;
&lt;p&gt;
Let's begin with a basic approach, a technique we'll call a &lt;em&gt;conditional overlay&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
With a button selected, let's open Conditional Formatting and add a rule that will evaluate to &lt;em&gt;True&lt;/em&gt; when we want our button to be disabled. For a "delete" button, our rule might evaluate to true when the current record's status is anything other than "draft", while for an "OK" button in a modal dialog layout, our rule might evaluate to true until all required fields have valid values. Since conditional formatting rules evaluate from top to bottom; we'll place our state-aware rule last, to ensure button-disabling rules always take precedence.&lt;/li&gt;
  &lt;li&gt;
Assign a solid conditional fill color (and optionally text color) that will communicate a state of unavailability to users when our button is closed for business.&lt;/li&gt;
  &lt;li&gt;
Last, add this same conditional check to the button's code, so that the script linked to this button will also silently exit when our conditions are met. (In production, this test should be abstracted so that script and formatting rely on a single test. This might be an unstored calculated field, a script-triggered global variable, or perhaps best of all, a custom function, as we use in our companion demo file).&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="http://buzz.beezwax.net/files/resource/264/buttonup2__1.png" alt="applying a conditional fill to a button" /&gt;
&lt;p class="header_lightblue"&gt;
&lt;strong&gt;Tools of the Trade:&lt;/strong&gt; Applying a conditional fill is straightforward, particularly if we first set up a lightweight custom function to do any heavy lifting required, say, by one Bullwinkle J. Moose.&lt;/p&gt;
&lt;h2&gt;
To Tell the Truth&lt;/h2&gt;
&lt;p&gt;
Here's what we get for our efforts: When our disabling conditional rule evaluates to False (when our button is active) conditional formatting will have no effect, and our button will be unchanged. But now, when our conditional rule evaluates to True (when our button is inactive), conditional formatting will spring into effect, and our button will assume the "inactive" appearance defined in our conditional rule.&lt;/p&gt;
&lt;p&gt;
Having our button be visibly inactive in normal state is a good start. But here's the crucial bit: Our button's interactive behavior will also fundamentally change. When it's in effect, &lt;strong&gt;&lt;em&gt;conditional formatting will effectively "turn off" our button's interactive formatting, preventing it from visually responding to user actions&lt;/em&gt;&lt;/strong&gt;. Users can hover, click, tap, or even tickle our buttons to their hearts' content: As long as our disabling condition evaluates to True, our noble button will now stand as rigidly still as a highly trained royal guard. Minus the funny hat.&lt;/p&gt;
&lt;p&gt;
This gives us the ability to toggle at will between visually dynamic, active buttons and static, inactive objects. When one of our buttons is open for business, its interactive formatting will clearly advertise this to our users; when it's closed, our &lt;em&gt;conditional override&lt;/em&gt; will now clearly signal its inactive state to users. We've met our semantic button challenge. The enhancements we learn in the rest of this post will be further feathers in our buttons' already finely festooned fedoras. Huzzah!&lt;/p&gt;
&lt;img src="http://buzz.beezwax.net/files/resource/265/buttonup2__2.png" alt="buttons using a conditional fill to show state" /&gt;
&lt;p class="header_lightblue"&gt;
&lt;strong&gt;Success!&lt;/strong&gt; Thanks to the &lt;em&gt;Conditional Overlay&lt;/em&gt;, users immediately know that Fearless Leader can in fact receive evil-grams or supply us with a coveted decoder ring, but that other functions are off limits to this nefarious villain.&lt;/p&gt;
&lt;h2&gt;
The Mighty Cascade&lt;/h2&gt;
&lt;p&gt;
Our first technique works because conditional formatting rules supersede interactive formatting. This is what makes it possible for us to "turn off" our button's interactive formatting. Let's take a quick step back to see how and why this happens:&lt;/p&gt;
&lt;p&gt;
Design Surface is built on &lt;em&gt;Cascading Style Sheet&lt;/em&gt; (CSS) technology. The heart of CSS is the &lt;em&gt;cascade&lt;/em&gt;, an elegant and compact specification determining how object formatting (styles) will flow predictably from abstract, generalized rules to the most detailed object- and state-specific level. CSS is designed to anticipate &amp;mdash; and in fact encourage &amp;mdash; conflict at different levels of the cascade. This architecture allows us to apply general styles with a broad brush, and then hone in on specific objects as desired. CSS adjudicates conflicts using a simple test: the rule applied at the most specific level of the cascade always wins.&lt;/p&gt;
&lt;p&gt;
CSS's ability to assemble formatting rules applied at different levels and economically resolve conflicts between these rules is the basis of its elegance and power. Whether on the web in general, or in Design Surface specifically, best practice is to apply a lean set of "inexpensive" formatting rules at the most generalized level possible, then override these general settings on specific objects and states (where rules are more "expensive") only as needed.&lt;/p&gt;
&lt;p&gt;
Each specific implementation of a cascade has a specific hierarchy that determines its behavior. The Design Surface cascade looks like this:&lt;/p&gt;
&lt;img src="http://buzz.beezwax.net/files/resource/273/DesignSurfaceCascade.png" alt="The Design Surface Cascade" /&gt;
&lt;p class="header_lightblue"&gt;
&lt;strong&gt;Map of the Territory:&lt;/strong&gt; The Design Surface cascade gives us an essential master view of how objects will behave and interact throughout our solutions.&lt;/p&gt;
&lt;h2&gt;
Through the Looking Glass&lt;/h2&gt;
&lt;p&gt;
With that under our belts, let's try a quick pop quiz:&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;"FileMaker 12 conditional formatting can now assign transparent fills. What will happen when a conditional rule that 'fills' a button with a completely transparent color&lt;/strong&gt; &lt;em&gt;(RBGa 100%,100%,100%,0)&lt;/em&gt;&lt;strong&gt; evaluates to True?"&lt;/strong&gt;&lt;/p&gt;
&lt;p style="margin-left:20px"&gt;
 &lt;strong&gt;(a) &lt;/strong&gt;The button's appearance won't change. The transparent conditional fill will allow upstream fill properties to cascade through unaffected.&lt;/p&gt;
&lt;p style="margin-left:20px"&gt;
&lt;strong&gt;(b) &lt;/strong&gt;The button will become transparent. The transparent conditional fill will effectively "erase" upstream fill properties, completely removing them.&lt;/p&gt;
&lt;p style="margin-left:20px"&gt;
&lt;strong&gt;(c) &lt;/strong&gt; There's a "pop" &lt;em&gt;who&lt;/em&gt; now?&lt;/p&gt;
&lt;p&gt;
Scanning the virtual room, pretty much everyone chose &lt;strong&gt;(a)&lt;/strong&gt; &amp;mdash; except that kid in the corner who keeps mumbling to himself in proto Klingon. No surprise, really. Common sense tells us that a transparent layer will simply allow whatever's behind it flow through, like laying clear glass over another object. Group hug, high fives all around, and&amp;hellip; ruh roh&amp;hellip; the correct answer is &lt;strong&gt;(b)&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;
Why? It turns out that our young Trekkie simply applied the foundation principle of the cascade: In the cascade, &lt;strong&gt;when rules governing the same property conflict with each other, the more specific rule always wins outright&lt;/strong&gt;. So if we conditionally apply a transparent fill, its CSS fill attributes (specifically, its &lt;em&gt;background-image&lt;/em&gt; and &lt;em&gt;background-color&lt;/em&gt; properties) will completely replace all upstream values, whether they be solid fills, gradients, or images. As a result, a transparent conditional fill will indeed act as an "eraser", leaving an object truly transparent.&lt;/p&gt;
&lt;h2&gt;
Less is More&lt;/h2&gt;
&lt;p&gt;
The ability of conditionally-applied formatting to completely override upstream styles opens a door to our second technique, the "&lt;em&gt;conditional clear&lt;/em&gt;". Here, we apply conditional rules just as before, this time assigning transparent fills when our conditional tests evaluate to True.&lt;/p&gt;
&lt;p&gt;
What does this give us? For starters, conditionally cleared objects can completely disappear from our interfaces on demand, and this is very useful indeed. In practice, it's often preferable to completely remove these objects when they're not available to users. Some examples: Portal row delete buttons; Search field clear buttons; Action buttons not available to users of certain privilege sets. In cases like these, less is often more, both aesthetically and semantically.&lt;/p&gt;
&lt;p&gt;
The conditional clear also opens further doors to richer design possibilities. For example, we can use it to effectively "scratch off" a button to reveal objects hidden beneath it. As another example, we can apply a partially transparent conditional fill. Interestingly, unlike in our earlier example, this semi-transparent fill &lt;em&gt;will&lt;/em&gt; visually interact with the objects behind it (since they're separate objects and not part of the same object cascade).&lt;/p&gt;
&lt;p&gt;
A final bonus: Conditional clears are more maintainable than their conditional overlay cousins. If we change a layout's theme or copy buttons across layouts, objects using conditional fills may need to be updated one by one. In contrast, the conditional clear by definition is at home in any theme, be it dark, light, or filled with gradients or rich images.&lt;/p&gt;
&lt;img src="http://buzz.beezwax.net/files/resource/267/buttonup2__4.png" alt="Using a conditional clear to completely hide inactive buttons" /&gt;
&lt;p class="header_lightblue"&gt;
&lt;strong&gt; I Can See Clearly Now:&lt;/strong&gt; The conditional clear allows buttons simply to vanish when inactive. Our users now confidently send the ever-hip Austin Powers their groovy-grams, never missing the ability to send him an email or evil-gram, since these buttons are completely hidden.&lt;/p&gt;
&lt;h2&gt;
One More Thing&lt;/h2&gt;
&lt;p&gt;
The &lt;em&gt;conditional overlay&lt;/em&gt; and &lt;em&gt;conditional clear&lt;/em&gt; provide the needed tools to successfully meet the semantic challenge posed in our previous &lt;a href="http://buzz.beezwax.net/2012/12/15/button-up"&gt;Button. Up.&lt;/a&gt; blog post. We can now readily create and maintain buttons that communicate clearly and transparently, and our solutions and apps will be the better for it.&lt;/p&gt;
&lt;p&gt;
But the best is yet to come. In our next series post, we'll step things up another notch and take these techniques &lt;em&gt;beyond&lt;/em&gt; the button, creating complex and expressive native design patterns like state-aware toggle switches, progress bars, and status indicators.&lt;/p&gt;
&lt;p&gt;
Stay tuned&amp;hellip;&lt;/p&gt;
&lt;p&gt;
&amp;mdash;&amp;nbsp;&lt;a href="http://www.beezwax.net/beez/235"&gt;Brian&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;a href="http://twitter.com/brian_schick"&gt;Follow Brian on Twitter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;

</content>
  </entry>
  <entry>
    <id>urn:uuid:54298aee-d69c-4e77-b055-7022eb1977e1</id>
    <published>2013-05-30T22:22:40Z</published>
    <updated>2013-05-30T23:00:33Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2013/05/30/summarize-how-often-databases-are-opened-in-filemaker-server" />
    <author>
      <name>simon</name>
      <email>simon_b@beezwax.net</email>
    </author>
    <title type="html">Summarize how often databases are opened in FileMaker Server</title>
    <content type="html">&lt;p&gt;We needed to quickly know how often various databases were being opened on a client's server.&lt;/p&gt;
&lt;p&gt;If you have Access logging enabled and are using a Mac OS based system, this shell snippet will give you a nice summary of how often each database has been opened:&lt;/p&gt;
&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="CodeRay"&gt; awk -F\&amp;quot; '{ if($3 == &amp;quot; opening database &amp;quot;) print $4;}' '/Library/FileMaker Server/Logs/Access.log' | sort | uniq -c &lt;/span&gt;&lt;/notextile&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;br&gt;
&lt;p&gt;Unfortunately, it won't show you a count for databases that were never opened within the scope of the current access log.&lt;/p&gt;
&lt;p&gt;Simon.&lt;/p&gt;


</content>
  </entry>
  <entry>
    <id>urn:uuid:ec630366-dc6d-4d21-96cb-507c50be7817</id>
    <published>2013-05-06T14:49:08Z</published>
    <updated>2013-06-12T01:55:56Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2013/05/06/fail2ban-with-filemaker-server" />
    <author>
      <name>Jay G</name>
      <email>jay_g@beezwax.net</email>
    </author>
    <title type="html">Fail2Ban with FileMaker Server</title>
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="mac-os" label="Mac OS" scheme="http://buzz.beezwax.net/category/mac-os" />
    <category term="filemaker" scheme="http://buzz.beezwax.net/tag/filemaker" />
    <category term="security" scheme="http://buzz.beezwax.net/tag/security" />
    <content type="html">&lt;p&gt;I needed to configure an FileMaker Server (FMS) that would be an isolated system and accessible via the Internet.

&lt;p&gt;Besides other precautions, like locking it down on the firewall as much as possible, changing the default SSH port, etc., I wanted to give the system some ability to defend itself against malicious access. FMS will prevent this to some extent, largely due to how the FMS Admin Console and the FileMaker client are designed.

&lt;p&gt;But in order to get a bit more protection, I wanted to install Fail2Ban, an open source package that installs easily on Mac OSX, and scans your log files looking for suspicious activity. I couldn't find any filter files online for use with FMS however, so I'd have to create my own. The main task to do this is to create the needed regular expressions that will trigger an alarm. This is what I have so far in my filters.d/filemaker-client file:
&lt;br&gt;&lt;br&gt;
&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="CodeRay"&gt;# Fail2Ban configuration file
#
# Author: Simon Brown
#
# $Revision: 1 $
#

[INCLUDES]

# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf


[Definition]

_daemon = fmserverd

# Option:  failregex
# Notes.:  regex to match the password failures messages in the logfile. The
#          host must be matched by a group named &amp;quot;host&amp;quot;. The tag &amp;quot;&amp;lt;HOST&amp;gt;&amp;quot; can
#          be used for standard IP/hostname matching and is only an alias for
#          (?:::f{4,6}:)?(?P&amp;lt;host&amp;gt;[\w\-.^_]+)
# Values:  TEXT
#

# The filter for Administrator failures may not be useful,
# since in testing this always reported null as the IP when
# using the .jnlp based admin tool.   

failregex = .*\[&amp;lt;HOST&amp;gt;(:0)?\]\&amp;quot; authentication failed on database.*
            .*Administrator authentication failed: .*\[&amp;lt;HOST&amp;gt;\].*
# Option:  ignoreregex
# Notes.:  regex to ignore. If this regex matches, the line is ignored.
# Values:  TEXT
#
ignoreregex =&lt;/span&gt;&lt;/notextile&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;br&gt;
&lt;p&gt;This was based on what I saw when generating password failures and also the document at &lt;a href="http://help.filemaker.com/app/answers/detail/a_id/7275" title="FileMaker Server Event Log Messages"&gt;http://help.filemaker.com/app/answers/detail/a_id/7275&lt;/a&gt;. The administrator authentication, it turns out, may not be that useful, since oddly the FMS Admin Console failures only listed the IP address when using the command line tool fmsadmin (!). Also, I haven't verified yet whether there are any useful messages generated in the other log files. Because of Fail2Ban's design these would require separate filter files anyway.

&lt;p&gt;With the filter file done, I now needed to configure the jail.conf file to use my new filter. Although I used MacPorts to install Fail2Ban, I preferred the config file provided on our Ubuntu Linux systems, so I'll be relying default actions configured in jail.conf in my jail.conf file (which you will need to create):
&lt;br&gt;
&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="CodeRay"&gt;[filemaker-client]

enabled = true   
port    = 5003,http,https
filter  = filemaker-client
logpath  = /Library/FileMaker Server/Logs/Event.log
maxretry = 6   &lt;/span&gt;&lt;/notextile&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;br&gt;
&lt;p&gt;I had some additional work to do to get to this to work with rules or even the ones provided with MacPorts. The Fail2Ban source generally assumes you'll be using the iptables firewall for blocking bad addresses, but we need to use either ipfw or pf on Mac OSX. Since I'm using the action "macros" that Ubuntu uses, I can easily change that for all active filters by setting the banaction variable:
&lt;br&gt;
&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="CodeRay"&gt;banaction = ipfw&lt;/span&gt;&lt;/notextile&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;br&gt;

&lt;p&gt;The "ipfw" value corresponds to the file at action.d/ipfw. Unexpectedly to me, I needed to edit the localhost value there in order to get the ipfw rules written out correctly, so be sure to set it to your system's IP address instead of the 127.0.0.1 address that's in there by default.
&lt;br&gt;&lt;br&gt;
Simon.


</content>
  </entry>
  <entry>
    <id>urn:uuid:530afac5-4131-4d3e-b32a-2e2f8ac369f5</id>
    <published>2013-03-13T04:05:22Z</published>
    <updated>2013-03-13T04:48:31Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2013/03/13/curl-http-post-from-filemaker" />
    <author>
      <name>simon</name>
      <email>simon_b@beezwax.net</email>
    </author>
    <title type="html">Curl HTTP Post from FileMaker</title>
    <content type="html">&lt;p&gt;I was trying to test out some HTTP post transactions with the curl command, and things weren't working.

&lt;p&gt;One glitch was due to how the curl command parses its options. All characters, including spaces can be significant, so "-X POST" is not the same as "-XPOST". This difference might be hidden if calling from the shell, which trims extraneous spaces in parameters, but I was calling via the bBox plug-in's curl function, and this calls the command directly from FileMaker.

&lt;p&gt;After dealing with some extraneous double-quotes that were in the data (cutting &amp; pasting values a bit too quickly!) I ended up with a script step that looked something like this:
 
&lt;p&gt;&lt;strong&gt;Set Variable&lt;/strong&gt;&lt;br&gt;
[&lt;br&gt;
&amp;nbsp;&amp;nbsp;$r;&lt;br&gt;
&amp;nbsp;&amp;nbsp;Value:bBox_Curl ("-XPOST"; // use a http post transaction&lt;br&gt;
&amp;nbsp;&amp;nbsp;"-d {'type':'sample_data','targetModule':'bbox'}"; // data we are sending to http server&lt;br&gt;
&amp;nbsp;&amp;nbsp;"-H Content-Type: application/json"; // desired result type, which is JSON&lt;br&gt;
&amp;nbsp;&amp;nbsp;"http://httpbin.org/post") // server handling our request&lt;br&gt;
]
&lt;br&gt;
&lt;p&gt;Simon

</content>
  </entry>
  <entry>
    <id>urn:uuid:b96165b0-eb6c-4139-8e29-2598b7a0bad7</id>
    <published>2013-03-11T20:16:44Z</published>
    <updated>2013-03-11T21:16:34Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2013/03/11/bbox-0-56-now-available" />
    <author>
      <name>simon</name>
      <email>simon_b@beezwax.net</email>
    </author>
    <title type="html">bBox 0.56 Now Available</title>
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="filemaker-add-ons" label="filemaker add-ons" scheme="http://buzz.beezwax.net/category/filemaker-add-ons" />
    <category term="filemaker-news" label="filemaker news" scheme="http://buzz.beezwax.net/category/filemaker-news" />
    <category term="filemaker-utilities" label="filemaker utilities" scheme="http://buzz.beezwax.net/category/filemaker-utilities" />
    <content type="html">&lt;p&gt;I've just posted a maintenance release &lt;a href="http://www.beezwax.net/bbox/"&gt;version 0.56&lt;/a&gt; of bBox, a free utility plug-in for FileMaker.

&lt;p&gt;A few commands have been modified to accept more parameters. The curl command, in particular, now accepts up to 7 parameters for the complex calls required when doing SOAP transactions, for instance.

&lt;p&gt;Error handling has also been modified, with errors now getting written out via syslog. This change is generally transparent, but Python script and execution errors are now consistently written out, and the change to syslog also worked around some buggy behavior seen with the OS function perror printing portions of previous messages to the log.

&lt;p&gt;Python functions are now also using Python version 2.6.7, up from version 2.5.6 used in the previous release.

&lt;p&gt;A Python usage tidbit. Sometimes the needed module might not be available to the version of Python VM that the bBox plug-in uses. A way around this is to append the needed module to your Python path:
&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="CodeRay"&gt;&lt;span class="comment"&gt;# Must explicity add the PyObjC path.&lt;/span&gt;
sys.path.append (&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC/&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;/notextile&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;br&gt;
&lt;p&gt;Sadly, one thing has left us in order to move things forward: PowerPC support. This version requires as a minimum an intel based CPU and Mac OS X 10.6.
&lt;br&gt;
&lt;p&gt;Simon


</content>
  </entry>
  <entry>
    <id>urn:uuid:a57f5536-e7fe-4bd7-9443-2c4ac783e6e9</id>
    <published>2013-02-26T04:04:23Z</published>
    <updated>2013-05-30T22:58:38Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2013/02/26/debugging-apache-with-osxs-10-8-server-2-2" />
    <author>
      <name>simon</name>
      <email>simon_b@beezwax.net</email>
    </author>
    <title type="html">Debugging Apache with OSXS 10.8 Server 2.2</title>
    <category term="mac-os" label="Mac OS" scheme="http://buzz.beezwax.net/category/mac-os" />
    <category term="testing" label="testing" scheme="http://buzz.beezwax.net/category/testing" />
    <content type="html">Besides being a bit of a mouthful, debugging Apache configuration issues has gotten slightly more complicated after Apple released the Server 2.2 update for Mac OS X Server.

Formerly, you could do a basic configuration check this way:
&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="CodeRay"&gt;# apachectl -t&lt;/span&gt;&lt;/notextile&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;br&gt;
Now however you need to first set an environment variable and specify a path to the configuration file:
&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="CodeRay"&gt;# export SERVER_INSTALL_PATH_PREFIX=/Applications/Server.app/Contents/ServerRoot
# apachectl -t -f /Library/Server/Web/Config/apache2/httpd_server_app.conf -D WEBSERVICE_ON&lt;/span&gt;&lt;/notextile&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;br&gt;
The above assumes you are running as root, where "#" is prompt.
&lt;br&gt;&lt;br&gt;
Simon

</content>
  </entry>
  <entry>
    <id>urn:uuid:55a824c0-af32-4057-811d-98b189b1b682</id>
    <published>2013-02-22T17:13:38Z</published>
    <updated>2013-02-22T18:42:24Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2013/02/22/code-signing-a-filemaker-runtime" />
    <author>
      <name>simon</name>
      <email>simon_b@beezwax.net</email>
    </author>
    <title type="html">Code Signing a FileMaker Runtime</title>
    <content type="html">&lt;p&gt;
	I wanted to code sign a runtime to avoid issues with users who had the higher security level set on their 10.8 based systems. Although lowering these permissions or holding down the control key when the app is launched will all help with this issue, code signing seems a reasonable and desirable, and removed the support issue.&lt;/p&gt;
&lt;p&gt;
	There are a few ways to get the needed certificates, but in my case I got them as part of my Mac OS Developer account at Apple. I won't go in to the details right now (possibly I'll update this later to include this), so here I am assuming you've already gone through the needed steps to get the certificates into your keychain.&lt;/p&gt;
&lt;p&gt;
	I had tried this previously using the &lt;strong&gt;codesign&lt;/strong&gt; command, but kept hitting various issues. Recently however I updated to XCode 4.6, so I decided to try again. There is a possibility I could've gotten this to work by creating a dummy XCode project, and adding the needed build phases to copy the files over. But some testing on that front showed that it wasn't straightforward process to get this to happen. The codesign command is however pretty straightforward, but there was one unexpected step. I would get the following error:&lt;/p&gt;
&lt;blockquote&gt;
	object file format unrecognized, invalid, or unsuitable&lt;/blockquote&gt;&lt;br&gt;
&lt;p&gt;
	Turns out that before signing, you must first run the following in Terminal:&lt;/p&gt;
&lt;p&gt;
	&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="CodeRay"&gt;export CODESIGN_ALLOCATE=&amp;quot;/Applications/Xcode.app/Contents/Developer/usr/bin/codesign_allocate&amp;quot;&lt;/span&gt;&lt;/notextile&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;
	Then this is all you need to do to complete the signing process: &lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;notextile&gt;&lt;span class="CodeRay"&gt; codesign -s &amp;quot;Developer ID Application: Beezwax Datatools, Inc.&amp;quot; /Volumes/Data/Users/sibr/_Clients/beezwax/Code\ Sign\ Test/Code\ Sign\ Test/Code\ Sign\ Test.app&lt;/span&gt;&lt;/notextile&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;
	 Simon&lt;/p&gt;

</content>
  </entry>
  <entry>
    <id>urn:uuid:de540228-563c-442f-b541-dfc6aa8eff7d</id>
    <published>2012-12-15T00:13:22Z</published>
    <updated>2013-06-03T22:01:40Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/12/15/button-up" />
    <author>
      <name>Brian</name>
      <email>brian_s@beezwax.net</email>
    </author>
    <title type="html">Button. Up.</title>
    <category term="design" label="design" scheme="http://buzz.beezwax.net/category/design" />
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="filemaker-tips" label="filemaker tips" scheme="http://buzz.beezwax.net/category/filemaker-tips" />
    <category term="ipad" label="iPad" scheme="http://buzz.beezwax.net/category/ipad" />
    <category term="ui-ux" label="ui/ux" scheme="http://buzz.beezwax.net/category/ui-ux" />
    <category term="filemaker" scheme="http://buzz.beezwax.net/tag/filemaker" />
    <category term="UI" scheme="http://buzz.beezwax.net/tag/ui" />
    <category term="UX" scheme="http://buzz.beezwax.net/tag/ux" />
    <category term="tags" scheme="http://buzz.beezwax.net/tag/tags" />
    <category term="design" scheme="http://buzz.beezwax.net/tag/design" />
    <category term="surface" scheme="http://buzz.beezwax.net/tag/surface" />
    <category term="buttons" scheme="http://buzz.beezwax.net/tag/buttons" />
    <category term="navigation" scheme="http://buzz.beezwax.net/tag/navigation" />
    <category term="css" scheme="http://buzz.beezwax.net/tag/css" />
    <content type="html">&lt;p&gt;
	Consider the humble button.&lt;/p&gt;
&lt;p&gt;
	Since the very first moments of FileMaker cosmos, the button has been an essential element of our platform. Over the years, across major and minor product releases, the unassuming button has remained a trusted constant and a dependable workhorse.&lt;/p&gt;
&lt;p&gt;
	In daily practice, the button is as essential and transparent to our solutions as water to a fish. (As an interesting conceptual challenge, try envisioning a button-free solution). And yet, the button's heroics on our behalf go overlooked and unsung. We lavish design and development attention on fields, portals, tab controls, web viewers - virtually every interface element except the unassuming button.&lt;/p&gt;
&lt;p&gt;
	In this series, we'll offer our old friend some long overdue attention. We'll demonstrate several new techniques available in FileMaker 12 to greatly enhance its appearance, behavior, and meaningfulness. The button's simplicity will help us isolate and demonstrate several modern UI and UX concepts, which we'll then be able to apply not only to buttons, but throughout our interfaces.&lt;/p&gt;
&lt;p style="text-align:center;"&gt;
	&lt;img alt="" src="http://buzz.beezwax.net/files/buttonUp-1.jpg" /&gt;&lt;/p&gt;
&lt;h2&gt;
	It's Alive!&lt;/h2&gt;
&lt;p&gt;
	So why does the button get so little attention? Perhaps its utter simplicity infers that it's just too trivial for our consideration. Maybe since we FileMaker developers are &lt;em&gt;data&lt;/em&gt; developers, the unassuming button flies beneath our data-driven radar. Or perhaps we carry impressions and practices from the earlier history of our platform, when the button was limited to being a visually passive, static object in a world where users increasingly were expecting real time interaction.&lt;/p&gt;
&lt;p&gt;
	But the times, they've been a-changin'. As we know, the release of FileMaker 12 has brought a quiet revolution to the platform's interface structure and capabilities. The new CSS-driven Design Surface introduced what I'll term "&lt;em&gt;interactive formatting&lt;/em&gt;", enabling objects to visually interact with users in real time. This behavior comes for free with every modern CSS-based theme in FileMaker 12, and can, of course, be readily tuned and extended to add further expressive depth and nuance.&lt;/p&gt;
&lt;p&gt;
	No element in the FileMaker universe experienced a more profound upgrade in FileMaker 12 than the button, which was suddenly transformed into a visually active - and interactive - element. Its new ability to give users direct visual feedback as they hovered, tapped, and clicked, gave the button greatly expanded powers of expression. The invigorated button could now communicate information much more directly and succinctly. In response, buttons everywhere rolled over and popped up in celebration. Huzzah!&lt;/p&gt;
&lt;p style="text-align:center;"&gt;
	&lt;img alt="" src="http://buzz.beezwax.net/files/buttonUp-2.jpg" /&gt;&lt;/p&gt;
&lt;h2&gt;
	Of Mice and Semantics&lt;/h2&gt;
&lt;p&gt;
	The visual impact of Design Surface has been immediate and extremely positive. FileMaker 12 interfaces feel zippier, more modern, and more intuitive: In a word, users love them.&lt;/p&gt;
&lt;p&gt;
	But there's more happening here than just good looks. FileMaker 12's interactive formatting lets us create interfaces that are more &lt;em&gt;semantically meaningful&lt;/em&gt;. When objects - and especially buttons - respond interactively to user actions, they communicate who they are and what they will do for the user if clicked. We used to achieve this with tooltips, static explanatory text ("click this button if you want to do that…"), and changing the cursor from a pointer to a hand. Now, interactive formatting can handle this for us, much more succinctly and far more gracefully.&lt;/p&gt;
&lt;p&gt;
	This has a profound impact: When a FileMaker 12 button changes appearance in direct response to a user's hovers, clicks, or taps, it's telling to the user that it's an active, "living" object ready to perform an action on her behalf. Even more: As it interacts visually with the user, this button offers a tacit agreement: "Click or tap me, and I'll perform the action promised by my label or icon." &lt;/p&gt;
&lt;p&gt;
	As modern UI and UX theory informs us, interfaces that more directly communicate their purpose and function to users are more intuitive, require less training and support, and provide far greater user trust and satisfaction. While the updated button's good looks may be what first catches our eye, as developers and designers, the more subtle goal of honing and enhancing its semantic meaning is fully worthy of our ongoing attention and best efforts.&lt;/p&gt;
&lt;p style="text-align:center;"&gt;
	&lt;img alt="" src="http://buzz.beezwax.net/files/buttonUp-3.jpg" /&gt;&lt;/p&gt;
&lt;h2&gt;
	Clearly State Your Intentions&lt;/h2&gt;
&lt;p&gt;
	Out of the box, Design Surface does everything it can to help our buttons communicate their purpose to users clearly and accurately. But of course, there's a catch. (There's always a catch). In many cases, we developers will need to extend FileMaker 12's default button formatting to preserve our buttons' semantic meaningfulness and integrity.&lt;/p&gt;
&lt;p&gt;
	Buttons often need to alter their behavior as our solution's data changes. For example, a button to update a record's status might depend on our data having met certain milestones; A delete button may be available only for draft records, for users of an administrative privilege set, or as users hover over a portal line item; Or a browser-style search field may have a clear button only having meaning when search text is present.&lt;/p&gt;
&lt;p&gt;
	State-dependent buttons like these will at times be active and available for users to click, and at others be disabled and unavailable for their use. Because the rules of when state-dependent buttons will and won't be available are dependent on solution-specific business rules, we can't expect FileMaker - or any platform - to handle this automatically. Instead, it's our challenge to ensure that state-dependent buttons accurately communicate their availability in real time, as live conditions change.&lt;/p&gt;
&lt;p style="text-align:center;"&gt;
	&lt;img alt="" src="http://buzz.beezwax.net/files/buttonUp-4.jpg" /&gt;&lt;/p&gt;
&lt;h2&gt;
	Keeping the Faith&lt;/h2&gt;
&lt;p&gt;
	Remember a moment ago, when our buttons's interactive formatting made a tacit agreement with users?&lt;/p&gt;
&lt;p&gt;
	What happens as our state-dependent button becomes functionally inactive? If it continues to respond interactively to hovers, taps, and clicks - as it will do out of the box - our user will likely click it once again, still expecting the promised result. But this time, our button will break its agreement, failing to deliver as advertised.&lt;/p&gt;
&lt;p&gt;
	The result is &lt;em&gt;semantic misinformation&lt;/em&gt;. Our state-dependent button's interactive formatting is now misaligned with its functional behavior. To correct this, we might display an alert, ("You can't perform this action now"). The problem is, while this is true, it's no more satisfying than walking into a store displaying a prominent "Open" sign, only to be told, "Welcome. We're closed; please leave." Or perhaps our button will simply exit silently, leaving the user to wonder why the formerly trustworthy button has stopped working without an explanation. Again, this will be unsatisfactory to our user.&lt;/p&gt;
&lt;p style="text-align:center;"&gt;
	&lt;img alt="" src="http://buzz.beezwax.net/files/buttonUp-5.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;
	Semantic misinformation is jarring, confusing, and degrades trust. At best, users will construct an internal matrix of rules telling them when to ignore the visual cues our buttons are giving, ("Don't click the submit button unless you've entered something in this and that field…"). Even in this best case, daily use and new user training are much more difficult, as users must manually learn and convey rote rules that can't be inferred from the interface. At worst, users will lose trust, potentially avoiding our solutions, or viewing them as unreliable.&lt;/p&gt;
&lt;p&gt;
	Happily, once we've recognized this issue, it's easy to ensure that state-dependent objects always remain semantically meaningful, even as our data changes. And the simple steps we'll take to implement this will improve both our solutions and users' experience and confidence in using them.&lt;/p&gt;
&lt;h2&gt;
	Same Bat Time, Same Bat Channel…&lt;/h2&gt;
&lt;p&gt;
	Up next: We'll describe - and provide working examples - of two lightweight methods to implement dynamic, state-based formatting: The first, a time-honored conditional formatting standby that's still useful in many situations; The second, a new, nimble FileMaker 12-specific technique that takes full advantage of Design Surface's advanced capabilities. Stay tuned…&lt;/p&gt;
&lt;p style="text-align:center;"&gt;
	&lt;img alt="" src="http://buzz.beezwax.net/files/buttonUp-6.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
	Thoughts? Questions? Have a different point of view? Leave a comment and let me know - I look forward to your feedback. &lt;/p&gt;

&lt;p&gt;
- Brian&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
		&lt;a href="http://twitter.com/brian_schick"&gt;Follow Brian on Twitter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;

</content>
  </entry>
  <entry>
    <id>urn:uuid:684517dc-14f9-4e68-8686-06aeb0b63a7c</id>
    <published>2012-11-21T00:25:41Z</published>
    <updated>2013-01-18T03:34:02Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/11/21/notes-on-backing-up-a-wiki-in-lion" />
    <author>
      <name>simon</name>
      <email>simon_b@beezwax.net</email>
    </author>
    <title type="html">Notes on backing up a wiki in Lion</title>
    <category term="mac-os" label="Mac OS" scheme="http://buzz.beezwax.net/category/mac-os" />
    <content type="html">&lt;p&gt;Apple made some major changes under the hood for wikis with Lion (Mac OSX 10.7). If upgrading from a Snow Leopard (10.6) wiki, one issue you&amp;#8217;ll need to address is how your backups work. For some related background, see this technote from Apple: &lt;a href="http://support.apple.com/kb/HT5082?viewlocale=en_US"&gt;Lion Server: Migrating and copying wiki data from Mac OS X Server v10.6&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, verify in the Server application that the Service Data is where you think it is. If relocated from the default at /Library, you&amp;#8217;ll still see any earlier versions of the wiki data there, so you could easily be fooled into thinking this was the correct folder. The data is always stored in a Library folder at the root level of a volume however, so there shouldn&amp;#8217;t be too many places to look.&lt;/p&gt;

&lt;p&gt;Next is to consider what to use for making your backups. Time Machine is certainly viable here, and is aware of how to correctly save the wiki data. But if you haven&amp;#8217;t already done so, you should patch your system up to the latest version of Lion (or upgrade to 10.8), as there were issues with bad wiki backups in earlier versions of Lion. In our case, we use CrashPlan for most of our Mac OS backups. This means we had a little extra work to do to get consistent backups.&lt;/p&gt;

&lt;p&gt;Backing up wiki attachment data is quite straightforward &amp;#8211; just point your backup utility or script to the Library/Server/Wiki folder. The wiki posts are stored in a postgres database however. You &lt;em&gt;could&lt;/em&gt; just backup the data in Library/Server/PostgreSQL, but backing up a live database this is almost never recommended, and postgres is no exception.&lt;/p&gt;

&lt;p&gt;What I did instead was create a short Python script at /etc/periodic/daily/700.wiki_backup to dump the postgres collaboration database. Here&amp;#8217;s the script:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;&lt;span class="comment"&gt;#!/usr/bin/python&lt;/span&gt;

&lt;span class="comment"&gt;# NOTES&lt;/span&gt;
&lt;span class="comment"&gt;#   - should run as the _postgres user.&lt;/span&gt;
&lt;span class="comment"&gt;#   - the backupDir folder will need to be created and chowned to the pgUser user&lt;/span&gt;

&lt;span class="comment"&gt;# 2012-10-24 simon_b: created script&lt;/span&gt;

&lt;span class="keyword"&gt;import&lt;/span&gt; &lt;span class="include"&gt;os&lt;/span&gt;, &lt;span class="include"&gt;time&lt;/span&gt;

&lt;span class="comment"&gt;# GLOBALS&lt;/span&gt;

dbName = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;collab&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
backupDir = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;/Volumes/Data/Library/Server/PostgreSQL/Backup&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
backupFile = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;wiki_dump.sql&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
backupPath = backupDir + &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;/&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + backupFile
pgDumpCmd = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;/usr/bin/pg_dump&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
pgUser = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;_postgres&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
wikiDB = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;collab&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class="comment"&gt;# EXECUTE&lt;/span&gt;

&lt;span class="keyword"&gt;print&lt;/span&gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;backup path:&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, backupPath
&lt;span class="keyword"&gt;print&lt;/span&gt;
&lt;span class="keyword"&gt;print&lt;/span&gt; os.system (pgDumpCmd + &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt; -v -U &lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + pgUser + &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt; &lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + wikiDB + &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt; -c -f &lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + backupPath)&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This will create a sql dump every day. But in the off-chance the CrashPlan backups don&amp;#8217;t work as expected, I&amp;#8217;ve created another file at /etc/newsyslog.d/wiki_backup.conf:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;/Volumes/Data/Library/Server/PostgreSQL/Backup/wiki_dump.sql   &lt;span class="integer"&gt;640&lt;/span&gt;       &lt;span class="integer"&gt;3&lt;/span&gt;     *    &lt;span class="error"&gt;$&lt;/span&gt;D0   JB&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This will keep up to 4 copies of the sql dump, compressing the older copies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server 2.2 Update&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;ve applied this update, you need to make three changes to the above script. This is because the postgres daemon is no longer listening on port 5423 for connections. Also, the OS version of pg_dump is no longer in sync with the version used by Server.&lt;/p&gt;

&lt;p&gt;A stripped down version of the modified script looks like this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;&lt;span class="comment"&gt;#!/usr/bin/python&lt;/span&gt;

&lt;span class="keyword"&gt;import&lt;/span&gt; &lt;span class="include"&gt;os&lt;/span&gt;, &lt;span class="include"&gt;time&lt;/span&gt;
todayStr = time.strftime(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;%Y%m%d&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)

dbName = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;collab&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
backupDir = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;/Volumes/Data/Library/Server/PostgreSQL/Backup&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
backupFile = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;wiki_dump.sql&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
backupPath = backupDir + &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;/&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + backupFile
pgDumpCmd = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;/Applications/Server.app/Contents/ServerRoot/usr/bin/pg_dump&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
pgSocket = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;'/Library/Server/PostgreSQL For Server Services/Socket'&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
pgUser = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;_postgres&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
wikiDB = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;collab&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class="keyword"&gt;print&lt;/span&gt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;backup path:&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, backupPath
&lt;span class="keyword"&gt;print&lt;/span&gt;
&lt;span class="keyword"&gt;print&lt;/span&gt; os.system (pgDumpCmd + &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt; -v -h &lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + pgSocket + &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt; -U &lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + pgUser + &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt; &lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + wikiDB + &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt; -c -f &lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + backupPath)&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;– Simon&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:uuid:9e6e9c5b-f895-469a-bfc4-24c6c2182e73</id>
    <published>2012-10-29T18:28:21Z</published>
    <updated>2012-11-15T17:08:07Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/11/09/the-first-step-to-great-solutions" />
    <author>
      <name>donovan</name>
      <email>donovan_c@beezwax.net</email>
    </author>
    <title type="html">The First Step to Great Solutions</title>
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="design" scheme="http://buzz.beezwax.net/tag/design" />
    <category term="filemaker" scheme="http://buzz.beezwax.net/tag/filemaker" />
    <content type="html">&lt;p&gt;
	How do you begin designing a new database or application? If you start with an &lt;a href="http://en.wikipedia.org/wiki/Entityâ€“relationship_model" target="_blank"&gt;Entity Relationship Diagram&lt;/a&gt; (ERD), you&amp;#39;re doing it wrong.&lt;/p&gt;
&lt;p&gt;
	It&amp;#39;s natural for a technical person to begin categorizing things into entities &amp;ndash; a company has contacts, which have addresses, etc. But this process immediately narrows your perspective to a small subset of the issues at hand, blinding you to many more important challenges and opportunities.&lt;/p&gt;
&lt;p&gt;
	FileMaker is particularly suited to people who are overburdened with immediate business needs: &amp;quot;Get us out of this burdensome spreadsheet!&amp;quot; Bringing order to the chaos and easing labor demands is often a relatively quick task in FileMaker. But organization and automation are not the goals of a great consultant &amp;ndash; merely the means. &lt;strong&gt;Your biggest value as a consultant is&amp;nbsp;rooted in your ability to facilitate the creation of &lt;em&gt;better&lt;/em&gt; solutions to their problems, particularly those of which your client is not even aware.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
	So don&amp;#39;t begin mapping your solution in that handy ERD of yours, because you&amp;#39;re not mapping the real problems or solutions. It&amp;#39;s a sure way to let their existing assumptions and solutions crystalize into what is supposed to be a newer, better system.&lt;/p&gt;
&lt;p&gt;
	&lt;strong&gt;The most significant obstacles and victories are found behind the assumptions many people don&amp;#39;t think to question.&lt;/strong&gt; The consultant&amp;#39;s job is to help uncover and assess these assumptions, especially assumptions about what they do and how it&amp;#39;s measured. This involves questions like &amp;quot;What does this really &lt;em&gt;mean&lt;/em&gt;?&amp;quot; and &amp;quot;&lt;em&gt;Why&lt;/em&gt; is this important?&amp;quot;. Once you begin to understand their domain, your goal is to expand the realm of possibilities in search of better solutions. This is sometimes called&amp;nbsp;&lt;a href="http://creativegibberish.org/439/divergent-thinking/" target="_blank"&gt;&lt;em&gt;divergent thinking&lt;/em&gt;&lt;/a&gt;. &amp;quot;To have a good idea, you must first have lots of ideas,&amp;quot; as&amp;nbsp;two-time Nobel prize winner Linus Pauling put it.* It doesn&amp;#39;t need to be a long process of brainstorming, but you need to at least be sure that you&amp;#39;re not blindly following the first path that presents itself. Then you can begin honing in on a particular strategy and structure &amp;ndash; &lt;em&gt;convergent thinking&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;
	A successfull database or application will therefore help the client better understand their business before the system is even built.&amp;nbsp;This should teach you what is really important about their data before you begin solidifying the system architecure. The system itself can then help them quickly isolate and understand the key learnings provided by their data. In other words, &lt;strong&gt;the system will help users prioritize their data and tasks in a way most aligned with their company&amp;#39;s objectives&lt;/strong&gt;. Conventional interfaces can&amp;#39;t do this because conventional consultants don&amp;#39;t understand how to value what they&amp;#39;re organizing. The interfaces are therefore often built with an eye for uniformity and from the perspective of the architecture.&lt;/p&gt;
&lt;p&gt;
	&lt;strong&gt;Do your systems simply re-organize spreadsheets or do they bring to life the inner workings of the business?&lt;/strong&gt;&amp;nbsp;Don&amp;#39;t let a good ERD fool you into thinking you know what&amp;#39;s going on. If you want to build outstanding solutions, you need to begin by asking the right questions &amp;ndash; lots of them. And that&amp;#39;s the first step to great solutions; you need to play the fool.&lt;/p&gt;
&lt;p style="margin-left: 40px; "&gt;
	Ignorance is the most important component for helping others to solve any problem in any industry.... You probably don&amp;#39;t know much unless you&amp;#39;re willing to first play the fool.&amp;nbsp;Ignorance is not such a bad thing if one knows how to use it, and all managers must learn how to do this. You must frequently approach problems with your ignorance; not what you think you know from past experience, because not infrequently, what you think you know is wrong.&lt;/p&gt;
&lt;p style="margin-left: 40px; "&gt;
	- Peter Drucker (&lt;a href="http://www.amanet.org/training/articles/Peter-Drucker-on-The-Value-of-Ignorance.aspx"&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;
	&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
	* Brown, Tim. Change By Design: How Design Thinking Transforms Organizations and Inspires Innovation. 2009. p. 67.&lt;/p&gt;


</content>
  </entry>
  <entry>
    <id>urn:uuid:3335e3f9-6dd3-4ec2-abaf-4541647b1fce</id>
    <published>2012-08-17T15:34:57Z</published>
    <updated>2013-03-14T16:57:25Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/11/02/sending-html-email-from-filemaker" />
    <author>
      <name>donovan</name>
      <email>donovan_c@beezwax.net</email>
    </author>
    <title type="html">Sending HTML Email from FileMaker</title>
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="filemaker-tips" label="filemaker tips" scheme="http://buzz.beezwax.net/category/filemaker-tips" />
    <category term="ipad" label="iPad" scheme="http://buzz.beezwax.net/category/ipad" />
    <category term="iphone" label="iPhone" scheme="http://buzz.beezwax.net/category/iphone" />
    <category term="Email" scheme="http://buzz.beezwax.net/tag/email" />
    <category term="Go" scheme="http://buzz.beezwax.net/tag/go" />
    <category term="HTML" scheme="http://buzz.beezwax.net/tag/html" />
    <category term="filemaker" scheme="http://buzz.beezwax.net/tag/filemaker" />
    <category term="in" scheme="http://buzz.beezwax.net/tag/in" />
    <category term="plug" scheme="http://buzz.beezwax.net/tag/plug" />
    <content type="html">&lt;p&gt;
	It comes up time and again: &amp;quot;How can I send a formatted email from FileMaker?&amp;quot; You see, FileMaker natively supports only plain text emails; you&amp;#39;re on your own if you want rich text or HTML. But it is possible! Here&amp;#39;s a list of options for (nearly) painlessly sending HTML emails from FileMaker.&lt;/p&gt;
&lt;h2&gt;
	Apple Mail&lt;/h2&gt;
&lt;p&gt;
	In this scenario, FileMaker uses AppleScript to send an HTML email through the Apple Mail client on OS X. Pretty much the only requirement is that the person sending the email has an email account configured in Mail. Of course, this isn&amp;#39;t something you can often depend on. It&amp;#39;s also exploiting an undocumented behavior, so I would be skeptical of its dependability with future versions of Mail. Still, it&amp;#39;s handy for its ease of implementation.&lt;/p&gt;
&lt;p&gt;
	&lt;a href="http://buzz.beezwax.net/files/resource/259/Demo_Email_AppleMail_2013-03-08.zip"&gt;Email_with_Apple_Mail_2013-03-08.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
	EDIT 03/08/2013: Cleaned up test settings; updated ancillary custom functions.&lt;/p&gt;
&lt;h2&gt;
	ScriptMaster Plug-In&lt;/h2&gt;
&lt;p&gt;
	In this scenario, FileMaker uses an external function from the ScriptMaster plug-in to send an email. ScriptMaster provides an example function, but our demo provides an enhanced version that allows for pretty much every combination of features. You might even use it to send a plain text email with multiple attachments. (FileMaker natively support only a single attachment.) This approach gives you maximum features for relative ease of deployment. Oh, and it&amp;#39;s free! The catch is that Java is increasingly going out of fashion these days (speaking as an OS X user), so the plug-in may run into issues on some users&amp;#39; machines.&lt;/p&gt;
&lt;p&gt;
	&lt;a href="http://buzz.beezwax.net/files/resource/261/Demo_Email_ScriptMaster_2013.03.14.zip"&gt;Email_with_ScriptMaster_2013-03-14.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
	NOTE 3/14/13: The function provided in this example occassionally fails to send the message, encountering an error like &amp;quot;no object DCH for MIME type multipart/mixed.&amp;quot; I suspect the solution might be found in threads like &lt;a href="http://stackoverflow.com/questions/7521027/dch-class-error-with-javamail" target="_blank"&gt;this one&lt;/a&gt;, but I no longer use ScriptMaster and have thus not pursued any resolution.&lt;/p&gt;
&lt;p&gt;
	EDIT 3/14/13: Removed test addresses.&lt;/p&gt;
&lt;p&gt;
	EDIT 11/06/12: Added required body tag to several tests.&lt;/p&gt;
&lt;p&gt;
	EDIT 03/08/13: Updated test settings.&lt;/p&gt;
&lt;h2&gt;
	Web Service&lt;/h2&gt;
&lt;p&gt;
	In this scenario, FileMaker posts parameters to a web service that then sends the email for you. All the client needs to do is post the parameters to a web server, which is good for compatibility across various client configurations. The web service can be in any language capable of providing an API accepting GET or POST requests. We&amp;#39;ve done it using PHP and Ruby.&lt;/p&gt;
&lt;p&gt;
	GET is the easiest post method for FileMaker because all you need to do is load the URL in a web viewer. That means even FileMaker Go can send HTML emails using this approach. But the biggest drawback is that there&amp;#39;s an inherent character limit to GET requests. They&amp;#39;re also not as commonly supported as POST. POST requests are therefore the preferred method, provided your solution is capable of sending them. In FileMaker, this requires a plug-in. Most any utility plug-in will be able to send POST requests.&lt;/p&gt;
&lt;p&gt;
	You don&amp;#39;t need to write your own web service to use this approach. You can also post to free services such as &lt;a href="https://www.jangomail.com" target="_blank"&gt;JangoMail&lt;/a&gt;. This approach can yield more advanced features like campaign management and analytics. It also supports GET requests, so you can run the demo on your iPhone or iPad if you wish. (The following demo requires a free JangoMail account to function.)&lt;/p&gt;
&lt;p&gt;
	&lt;a href="http://buzz.beezwax.net/files/Email_with_Web_Service_2012-11-02.zip"&gt;Email_with_Web_Service_2012-11-02.zip&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
	Other Plug-Ins&lt;/h2&gt;
&lt;p&gt;
	If you don&amp;#39;t mind spending a few dollars, consider purchasing a plug-in built specifically for email handling. It might be worth the features and time saved. I have very little experience with these plug-ins, but I&amp;#39;ve added a few to our comparison table based on their marketing materials. (My apologies for the formatting.)&lt;/p&gt;
&lt;p&gt;
	EDIT 11/5/12: Also check out this handy &lt;a href="http://filemaker-plugins.com/compare/email-plugins/"&gt;plug-in comparison&lt;/a&gt; by filemaker-plugins.com.&lt;/p&gt;
&lt;p&gt;
	&amp;nbsp;&lt;/p&gt;
&lt;table border="1" cellpadding="1" cellspacing="1" style="width: 100%;"&gt;
	&lt;thead&gt;
		&lt;tr&gt;
			&lt;th scope="col"&gt;
				&lt;strong&gt;Method&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;To, From, Bcc&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;HTML&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;Rich Text&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;Plain Text&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;Edit in Client&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;Attachments&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;Header Support&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;SSL&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;iOS-Compatible&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;IWP-Compatible&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;Server-Side Compatible&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;Mac-Compatible&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;Win-Compatible&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;Plug-In Dependent&lt;/strong&gt;&lt;/th&gt;
			&lt;th&gt;
				&lt;strong&gt;Comments&lt;/strong&gt;&lt;/th&gt;
		&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
		&lt;tr&gt;
			&lt;th scope="col"&gt;
				&lt;strong&gt;AppleScript&lt;/strong&gt;&lt;/th&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				No&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes*&lt;/td&gt;
			&lt;td&gt;
				No&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				No&lt;/td&gt;
			&lt;td&gt;
				No&lt;/td&gt;
			&lt;td&gt;
				?&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				No&lt;/td&gt;
			&lt;td&gt;
				No&lt;/td&gt;
			&lt;td&gt;
				&amp;nbsp;&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;th scope="col"&gt;
				&lt;strong&gt;ScriptMaster&lt;/strong&gt;&lt;/th&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes*&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				No&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Full*&lt;/td&gt;
			&lt;td&gt;
				No&lt;/td&gt;
			&lt;td&gt;
				No&lt;/td&gt;
			&lt;td&gt;
				No&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Java-dependent&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;th scope="col"&gt;
				&lt;strong&gt;Web Service&lt;/strong&gt;&lt;/th&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes*&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				No&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Full*&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				No&lt;/td&gt;
			&lt;td&gt;
				No&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				No+&lt;/td&gt;
			&lt;td&gt;
				Ruby/PHP on server&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;th scope="col"&gt;
				&lt;strong&gt;360Works Email&lt;/strong&gt;&lt;/th&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				?&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				No&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Full&lt;/td&gt;
			&lt;td&gt;
				?&lt;/td&gt;
			&lt;td&gt;
				?&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				&amp;nbsp;&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;th scope="col"&gt;
				&lt;strong&gt;Mailit 5&lt;/strong&gt;&lt;/th&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Full&lt;/td&gt;
			&lt;td&gt;
				?&lt;/td&gt;
			&lt;td&gt;
				?&lt;/td&gt;
			&lt;td&gt;
				?&lt;/td&gt;
			&lt;td&gt;
				?&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				&amp;nbsp;&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;th scope="col"&gt;
				&lt;strong&gt;SMTPit&lt;/strong&gt;&lt;/th&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				?&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Custom window&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Partial&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				?&lt;/td&gt;
			&lt;td&gt;
				?&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				Yes&lt;/td&gt;
			&lt;td&gt;
				&amp;nbsp;&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
	* Feature possible, but not supported in our demo files&lt;/p&gt;
&lt;p&gt;
	+ You can post to a web server using JavaScript. (See Brian&amp;#39;s fmGo post on using the web viewer as a JavaScript engine.) Most of our implementations, however, use an existing plug-in or something like the free BaseElements plug-in.&lt;/p&gt;
&lt;h2&gt;
	Caveats&lt;/h2&gt;
&lt;p&gt;
	Mail clients will have varying support for HTML and CSS features. See Campaign Monitor&amp;#39;s &lt;a href="http://www.campaignmonitor.com/css/"&gt;handy reference&lt;/a&gt; for more detail on what many of the popular clients support.&lt;/p&gt;
&lt;p&gt;
	-Donovan&lt;/p&gt;


</content>
  </entry>
  <entry>
    <id>urn:uuid:2ebc5e01-c622-48a3-bef1-a5f964979a4b</id>
    <published>2012-08-13T21:02:26Z</published>
    <updated>2013-01-18T03:05:15Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/08/15/just-a-slice-please%C3%A2%E2%82%AC%C2%A6" />
    <author>
      <name>simon</name>
      <email>simon_b@beezwax.net</email>
    </author>
    <title type="html">Just a Slice, Please…</title>
    <category term="custom-functions" label="custom functions" scheme="http://buzz.beezwax.net/category/custom-functions" />
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="filemaker-tips" label="filemaker tips" scheme="http://buzz.beezwax.net/category/filemaker-tips" />
    <category term="filemaker-utilities" label="filemaker utilities" scheme="http://buzz.beezwax.net/category/filemaker-utilities" />
    <category term="columns" scheme="http://buzz.beezwax.net/tag/columns" />
    <category term="fields" scheme="http://buzz.beezwax.net/tag/fields" />
    <category term="filemaker" scheme="http://buzz.beezwax.net/tag/filemaker" />
    <category term="repeating" scheme="http://buzz.beezwax.net/tag/repeating" />
    <category term="spreadsheet" scheme="http://buzz.beezwax.net/tag/spreadsheet" />
    <content type="html">&lt;p&gt;
    Here&amp;#8217;s an interesting FileMaker challenge:&lt;/p&gt;


&lt;p&gt;
How can you dynamically slice off a set of values from a repeating field in a related table, the way you&amp;#8217;d grab a column of values in a spreadsheet?&lt;/p&gt;


&lt;p&gt;
It&amp;#8217;s easy enough to do this for a single repeating field in the current record, but how do you do this with a repeating field in a different table, operating not just on a single record, but an entire record set?&lt;/p&gt;


&lt;p&gt;
    While the solution to this challenge isn&amp;#8217;t immediately obvious, this post will explain how to handle this challenge quickly and elegantly with FileMaker 12. Follow along by &lt;a href="http://buzz.beezwax.net/files/Just_a_Slice.fmp12"&gt;downloading a copy of the completed demo file&lt;/a&gt;. Here&amp;#8217;s a quick peek at the finished solution:&lt;/p&gt;


&lt;p&gt;
    &lt;img src="http://buzz.beezwax.net/files/slice_530_parent.png" style="-webkit-user-select: none" /&gt;&lt;/p&gt;


&lt;h2&gt;
    Tools of the Trade&lt;/h2&gt;


&lt;p&gt;
    Repeating fields are one of FileMaker&amp;#8217;s great secret weapons. When properly used, they can help denormalize and condense related data into compact and flexible structures that can save space and boost performance. In this example, we&amp;#8217;ll use not only FileMaker&amp;#8217;s native repeating field functions, but also Will Baker&amp;#8217;s definitive set of&amp;nbsp;&lt;a href="http://buzz.beezwax.net/2011/10/29/working-with-repeating-fields"&gt;repeating field custom functions&lt;/a&gt;.&lt;/p&gt;


&lt;h2&gt;
    Flattening Repeating Data&lt;/h2&gt;


&lt;p&gt;
    As the screenshot above suggests, we&amp;#8217;ll create a matrix-like structure in the parent table from which we&amp;#8217;ll take slices as desired. To prepare for this, the first step will be to create a field in the child table that will translate the child table&amp;#8217;s repeating field into a flattened string, where each repetition&amp;#8217;s value will be nestled between delimiters, like this:&lt;/p&gt;


&lt;h6&gt;
    &amp;lt;rep1&amp;gt; | &amp;lt;rep2&amp;gt; | &amp;lt;rep3&amp;gt; | &amp;lt;rep4&amp;gt; | &amp;lt;rep5&amp;gt; |&lt;/h6&gt;


&lt;p&gt;
    We could try this using the native&amp;nbsp;&lt;em&gt;List()&lt;/em&gt;&amp;nbsp;function to translate repeating fields into list format, then use&amp;nbsp;&lt;em&gt;Substitute()&lt;/em&gt; to replace the list&amp;#8217;s carriage returns with delimiters.&amp;nbsp;This will fail, though, because List() omits null repetitions. So if, say repetition 2 is empty, repetitions 3-5 will jump forward a slot, which will defeat our downstream calculations.&lt;/p&gt;


&lt;div&gt;
    &lt;p&gt;
        Instead, we turn one of Will Baker&amp;#8217;s repeating list custom functions, &lt;em&gt;RepListOmitTrailingNulls(), &lt;/em&gt;which returns a complete list of repetition values including null entries. This ensures that empty values won&amp;#8217;t misalign the flattened structure, but will be properly delimited.&lt;/p&gt;
&lt;p&gt;
As a bonus, Will&amp;#8217;s function dynamically determines the last repetition that&amp;#8217;s populated and only returns list values up to that point, so the flattened values will scale perfectly for any number of repetitions, and will consume the minimum resources needed. Here&amp;#8217;s how the flattened string looks in our child table:&lt;/p&gt;
    &lt;p&gt;
        &lt;img src="http://buzz.beezwax.net/files/slice_530_child.png" style="-webkit-user-select: none" /&gt;&lt;/p&gt;
    &lt;h2&gt;
        Peeling Off a Slice&lt;/h2&gt;
    &lt;p&gt;
        With this in place, back in the parent table, we now assemble a matrix-like structure using &lt;em&gt;List ( child::flattenedValues )&lt;/em&gt;. This gives a list that&amp;#8217;s structured like this:&lt;/p&gt;
    &lt;h6&gt;
        &amp;lt;rep1&amp;gt; | &amp;lt;rep2&amp;gt; | &amp;lt;rep3&amp;gt; | &amp;lt;rep4&amp;gt; | &amp;lt;rep5&amp;gt; |&lt;br /&gt;
        &amp;lt;rep1&amp;gt; | &amp;lt;rep2&amp;gt; | &amp;lt;rep3&amp;gt; | &amp;lt;rep4&amp;gt; | &amp;lt;rep5&amp;gt; |&lt;br /&gt;
        &amp;lt;rep1&amp;gt; | &amp;lt;rep2&amp;gt; | &amp;lt;rep3&amp;gt; | &amp;lt;rep4&amp;gt; | &amp;lt;rep5&amp;gt; |&lt;/h6&gt;
    &lt;p&gt;
        Now we need a way to take a vertical slice. For this, we&amp;#8217;ll create a custom function that accepts our list of flattened values and a target repetition number. Our function will step recursively through each value in our list, using the delimiters to locate and then extract the target repetition of the current line. Then, we&amp;#8217;ll need it to recursively call itself, repeating this action for each line, and finally returning a list of these extracted values. Here&amp;#8217;s our custom function, &lt;em&gt;GetRepValuesFromList()&lt;/em&gt;:&lt;/p&gt;
    &lt;pre style="line-height:.8em;padding:10px;"&gt;Let ( 

[ 

count_values = ValueCount ( values ) ;

value_1 = GetValue ( values ; 1 ) ;

values_other = MiddleValues ( values ; 2 ; count_values-1 ) ;


pos_start = Position ( value_1 ; &amp;quot;|&amp;quot; ; 1 ; rep-1 ) + 1 ;

pos_end = Min ( Position ( value_1 ; &amp;quot;|&amp;quot; ; 1 ; rep )  ; Length ( value_1 ) ) ;

chars = pos_end - pos_start ;

rep_value = Middle ( value_1 ; pos_start ; chars )

] ;


Case ( 

  count_values = 0 ; 

    &amp;quot;&amp;quot; ;


  count_values = 1 ;

    rep_value ;


  List (

    rep_value ;

    GetRepValuesFromList ( values_other ; rep )

  )

)&lt;/pre&gt;
    &lt;h2&gt;
        The String&amp;#8217;s Not the Thing&lt;/h2&gt;
    &lt;p&gt;
        Our custom function works perfectly, letting us fluidly slice any vertical set of repetions at will, and returning these values to us as a list. Now all we need to do is to get the returned column&amp;#8217;s total. Easy peezy&amp;hellip; just replace our list&amp;#8217;s carriage returns with semi-colons and pop it into a native &lt;em&gt;Sum()&lt;/em&gt; function, right?&lt;/p&gt;
    &lt;p&gt;
        Well, no, not so fast. &lt;em&gt;Sum (&amp;lt;slicedValues&amp;gt; )&lt;/em&gt; may produce a perfectly valid-looking expression when viewed in a Data Viewer. But it&amp;#8217;s not a valid expression, because a sliced value string like &amp;quot;22;11;21;&amp;quot; is, well, just a string, rather than an actual set of delimited numeric values, as aggregate functions require.&amp;nbsp;Happily, this is quickly resolved by assembling our full expression as a string and then wrapping that string in turn within&amp;nbsp;an &lt;em&gt;Evaluate() &lt;/em&gt;function, like so:&lt;/p&gt;
    &lt;h6&gt;
        Evaluate ( &amp;quot;Sum ( &amp;quot; &amp;amp; values &amp;amp; &amp;quot; ) &amp;quot; )&lt;/h6&gt;
    &lt;p&gt;
        &lt;em&gt;Evaluate()&lt;/em&gt; kindly transforms our string into a valid expression, and our&amp;nbsp;&lt;em&gt;Sum() &lt;/em&gt;function now works like a champ. Et &lt;em&gt;vÃ³ila&lt;/em&gt;! We&amp;#8217;re finished!&lt;/p&gt;
    &lt;h2&gt;
        Worth Repeating&lt;/h2&gt;
    &lt;p&gt;
        This is a simple example of how flexible and powerful FileMaker 12 repeating functions can be. Our technique is light and fast, and it can scale flexibly to any number of child repetitions or child records without modifications. &lt;/p&gt;
&lt;p&gt;
Note also that this technique can be readily extended in several ways. For example, to allow users to search from a parent table for child records containing values in a specific repetition, or to use aggregate functions to further analyze the related repeating data.&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://buzz.beezwax.net/files/Just_a_Slice.fmp12"&gt;Download the demo file&lt;/a&gt;&amp;nbsp;&amp;hellip; and let us know what you think.&lt;/p&gt;
    &lt;p&gt;
        &amp;nbsp;&lt;/p&gt;
    &lt;p&gt;
        Enjoy!&lt;br /&gt;
        &lt;em&gt;- Brian&lt;/em&gt;&lt;br /&gt;
        &lt;br /&gt;
        &lt;a href="http://twitter.com/brian_schick"&gt;Follow Brian on Twitter&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;


</content>
  </entry>
  <entry>
    <id>urn:uuid:ac01eed3-673a-4f2f-b6ca-ea9cce7a5643</id>
    <published>2012-08-04T02:17:23Z</published>
    <updated>2012-08-04T16:42:58Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/08/04/xml-parsing-with-filemaker-and-bbox" />
    <author>
      <name>simon</name>
      <email>simon_b@beezwax.net</email>
    </author>
    <title type="html">XML Parsing with FileMaker and bBox</title>
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="filemaker-add-ons" label="filemaker add-ons" scheme="http://buzz.beezwax.net/category/filemaker-add-ons" />
    <category term="filemaker-utilities" label="filemaker utilities" scheme="http://buzz.beezwax.net/category/filemaker-utilities" />
    <category term="ruby" label="ruby" scheme="http://buzz.beezwax.net/category/ruby" />
    <content type="html">&lt;p&gt;In order to more easily work with XML data, I&amp;#8217;ve added the libxml2 library to version 0.54 of the &lt;a href="http://www.beezwax.net/products/bbox"&gt;bBox plug-in&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Among other things, libxml2 provides support for XPath 1.0 queries, which can be used to easily extract or set values from XML data, so XPath was my first choice. Although XML has lost a bit of its shine as JSON has come into vogue, XML is still integral to many systems, including FileMaker. Also, the XPath routines can be used for similar syntaxes, so for instance, you might find it helpful for scraping data from a HTML page.&lt;/p&gt;

&lt;p&gt;The first two functions aren&amp;#8217;t very interesting, but they are essential. XPathInitialize is used to intialize the XPath environment (surprise!) and do the initial parsing of the XML source. XPathFinalize releases the memory used for the tokenized XML and the XPath environment. XPathEvaluate is where most of the fun happens, as this is where we pass in our XPath statements and get back our results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting Started&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even with a few script steps and some simple XPath statements we can do some interesting stuff. To start off, we&amp;#8217;ll need some XML to experiment with. I&amp;#8217;ll use a modified version of the example XML from wikiboooks.org:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;&lt;span class="tag"&gt;&amp;lt;library&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;A list of books useful for people first learning how to build web XML web applications.&lt;span class="tag"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;book&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;XQuery&lt;span class="tag"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;author&amp;gt;&lt;/span&gt;Priscilla Walmsley&lt;span class="tag"&gt;&amp;lt;/author&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;description&lt;/span&gt; &lt;span class="attribute-name"&gt;lang&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;spanish&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;Este libro es un recorrido muy detallado, a travÃ©s de y completo del Lenguaje de Consulta del W3C. Cubre todos los aspectos clave de la lengua.&lt;span class="tag"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;format&amp;gt;&lt;/span&gt;Trade press&lt;span class="tag"&gt;&amp;lt;/format&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;license&amp;gt;&lt;/span&gt;Commercial&lt;span class="tag"&gt;&amp;lt;/license&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;list-price&amp;gt;&lt;/span&gt;49.95&lt;span class="tag"&gt;&amp;lt;/list-price&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;/book&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;book&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;XQuery Examples&lt;span class="tag"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;author&amp;gt;&lt;/span&gt;Chris Wallace&lt;span class="tag"&gt;&amp;lt;/author&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;author&amp;gt;&lt;/span&gt;Dan McCreary&lt;span class="tag"&gt;&amp;lt;/author&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;description&lt;/span&gt; &lt;span class="attribute-name"&gt;lang&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;english&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;This book provides a variety of XQuery example programs and is designed to work with the eXist open-source native XML application server.&lt;span class="tag"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;format&amp;gt;&lt;/span&gt;Wiki-books&lt;span class="tag"&gt;&amp;lt;/format&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;license&amp;gt;&lt;/span&gt;Creative Commons Sharealike 3.0 Attribution-Non-commercial&lt;span class="tag"&gt;&amp;lt;/license&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;list-price&amp;gt;&lt;/span&gt;29.95&lt;span class="tag"&gt;&amp;lt;/list-price&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;/book&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;book&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;XForms Tutorial and Cookbook&lt;span class="tag"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;author&amp;gt;&lt;/span&gt;Dan McCreary&lt;span class="tag"&gt;&amp;lt;/author&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;description&lt;/span&gt; &lt;span class="attribute-name"&gt;lang&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;english&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;This book is an excellent guide for anyone that is just beginning to learn the XForms standard.  The book is focused on providing the reader with simple, but complete examples of how to create XForms web applications.&lt;span class="tag"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;format&amp;gt;&lt;/span&gt;Wikibook&lt;span class="tag"&gt;&amp;lt;/format&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;license&amp;gt;&lt;/span&gt;Creative Commons Sharealike 3.0 Attribution-Non-commercial&lt;span class="tag"&gt;&amp;lt;/license&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;list-price&amp;gt;&lt;/span&gt;29.95&lt;span class="tag"&gt;&amp;lt;/list-price&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;/book&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;book&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;XRX: XForms, Rest and XQuery&lt;span class="tag"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;author&amp;gt;&lt;/span&gt;Dan McCreary&lt;span class="tag"&gt;&amp;lt;/author&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;description&lt;/span&gt; &lt;span class="attribute-name"&gt;lang&lt;/span&gt;=&lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;span class="content"&gt;english&lt;/span&gt;&lt;span class="delimiter"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;This book is an overview of the key architectural and design patterns.&lt;span class="tag"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;format&amp;gt;&lt;/span&gt;Wikibook&lt;span class="tag"&gt;&amp;lt;/format&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;license&amp;gt;&lt;/span&gt;Creative Commons Sharealike 3.0 Attribution-Non-commercial&lt;span class="tag"&gt;&amp;lt;/license&amp;gt;&lt;/span&gt;
  &lt;span class="tag"&gt;&amp;lt;list-price&amp;gt;&lt;/span&gt;29.95&lt;span class="tag"&gt;&amp;lt;/list-price&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;/book&amp;gt;&lt;/span&gt;
&lt;span class="tag"&gt;&amp;lt;/library&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;br&gt;


&lt;p&gt;&lt;strong&gt;Setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can consider the XML above as our database that we will be running our queries against. The FileMaker script steps required to do a basic query are pretty simple. Here&amp;#8217;s a snippet that does most of what you might need:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;Set Variable [ $result; bBox_XPathInitializeFromText (0; DEMO::xml_source)
#
If [ $result = &amp;quot;&amp;quot; ]
   Set Variable [ $result; bBox_XPathEvaluate(DEMO::xpath_expression; DEMO::xpath_node_delimiter)
End If
#
Set Variable [ $ignore; Value:bBox_XPathFinalize ] #&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;br&gt;


&lt;p&gt;&lt;strong&gt;XPath Examples&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The XPath statements, in their simplest forms, look identical to unix style file paths. These are what you&amp;#8217;d be passing as the &lt;strong&gt;path_expression&lt;/strong&gt; above. Our first example just returns all titles from the above XML:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;/library/book/title&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;A slightly more complex form that returns all titles and their retail prices would be (&amp;#8220;//&amp;#8221; returns the following node from anywhere in the hierarchy):&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;//title | //list-price&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And here we use one of the XPath functions to get the last book in our list:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;/library/book[last()]&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;br&gt;


&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;XML does have its arcane side, so some capabilities will require some effort to learn, and may be beyond what the current implementation in bBox can handle. Also, XPath functions are fairly strict in their interpretation of XML, so any poorly formed XML is likely to be rejected by the bBox_XPathInitialize call. Use the Console utility or go directly to your system log at /var/log/system.log to check for more detailed information. The xmllint command may also be helpful here.&lt;/p&gt;

&lt;p&gt;There is quite a bit more that can be done with XPath, so don&amp;#8217;t stop looking here for examples. You can also pair up the XPath functions with the bBox&amp;#8217;s curl function to pull in remote content.&lt;/p&gt;

&lt;p&gt;Simon&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:uuid:526b954a-35a7-4567-b210-2fac79446703</id>
    <published>2012-08-03T21:07:51Z</published>
    <updated>2012-08-03T21:56:13Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/08/03/our-first-filemaker-12-certified-developers" />
    <author>
      <name>Jay G</name>
      <email>jay_g@beezwax.net</email>
    </author>
    <title type="html">Our First FileMaker 12 Certified Developers</title>
    <category term="beezwax-news" label="beezwax news" scheme="http://buzz.beezwax.net/category/beezwax-news" />
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="filemaker-news" label="filemaker news" scheme="http://buzz.beezwax.net/category/filemaker-news" />
    <content type="html">&lt;p&gt;We&amp;#8217;re pleased to announce three Beez who earned the title of &lt;a href="http://www.filemaker.com/support/training/certification/"&gt;FileMaker 12 Certified Developer&lt;/a&gt;.&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vincenzo Menanno&lt;/strong&gt;, Director of FileMaker Development&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Will Baker&lt;/strong&gt;, Senior Developer&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Brian Schick&lt;/strong&gt;, Senior Developer&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;FileMaker 12 Certification is the official credential offered by FileMaker, Inc., certifying a developer as achieving an &amp;quot;essential level of knowledge, experience and skills in developing &lt;a href="http://buzz.beezwax.net/2012/04/05/filemaker-12-exciting-new-possibilities"&gt;FileMaker 12&lt;/a&gt; solutions.&amp;quot;&lt;/p&gt;




&lt;p&gt;Vince, Will and Brian were among the first developers anywhere to receive this designation since &lt;a href="http://www.filemaker.com/company/media/press-releases/releases/2012/filemaker_12_platform_certification_testing_now_available.html"&gt;FileMaker 12 Certification was announced&lt;/a&gt;Â in July.&lt;/p&gt;


&lt;p&gt;&lt;span&gt;&lt;img src="http://buzz.beezwax.net/files/certified_12_logo_4clr_sm.png" style="padding-top:20px;" alt="FileMaker 12 Certified Developer" /&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="Apple-style-span" style="font-size: 14px; font-weight: bold; "&gt; FileMaker Certification At Beezwax&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;At Beezwax, our FileMaker Certified developers are an important resource in mentoring other developers, representing us in the FileMaker community and establishing best practices in building client solutions.&lt;/p&gt;




&lt;p&gt;We look forward to announcing other FileMaker 12 Certified Developers in coming months.&lt;/p&gt;




&lt;p&gt;Congrats, Vincenzo, Will and Brian!&lt;/p&gt;


&lt;br/&gt;


&lt;br/&gt;


&lt;br/&gt;


</content>
  </entry>
  <entry>
    <id>urn:uuid:8c0b335a-68f3-430d-8255-fb53a64a5009</id>
    <published>2012-07-24T22:41:58Z</published>
    <updated>2012-07-24T22:54:38Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/07/24/filemaker-12-sql-crafting-structural-beauty" />
    <author>
      <name>Brian</name>
      <email>brian_s@beezwax.net</email>
    </author>
    <title type="html">FileMaker 12 SQL: Crafting Structural Beauty</title>
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="filemaker-news" label="filemaker news" scheme="http://buzz.beezwax.net/category/filemaker-news" />
    <category term="filemaker-resources" label="filemaker resources" scheme="http://buzz.beezwax.net/category/filemaker-resources" />
    <category term="filemaker-tips" label="filemaker tips" scheme="http://buzz.beezwax.net/category/filemaker-tips" />
    <category term="sql" label="sql" scheme="http://buzz.beezwax.net/category/sql" />
    <category term="ExecuteSQL" scheme="http://buzz.beezwax.net/tag/executesql" />
    <category term="filemaker" scheme="http://buzz.beezwax.net/tag/filemaker" />
    <category term="sql" scheme="http://buzz.beezwax.net/tag/sql" />
    <content type="html">&lt;p&gt;
	It&amp;#39;s hard to believe it&amp;#39;s been only a few months since SQL was introduced as part of FileMaker 12.&lt;/p&gt;
&lt;p&gt;
	In the short time since, developers have quickly put this new capability to use with style and passion, publishing FileMaker SQL tutorials, demos, and development tools almost too many to number. Some early highlights include:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;
		Greg Lane created&amp;nbsp;&lt;a href="http://www.filemakeracademy.com/?p=827"&gt;an excellent webcast&lt;/a&gt;&amp;nbsp;and helpful twitter posts explaining the basics and the finer points of SQL use in FileMaker 12.&lt;/li&gt;
	&lt;li&gt;
		Kevin Frank launched&amp;nbsp;&lt;a href="http://bit.ly/NzRnnW"&gt;an insightful series of articles&lt;/a&gt;&amp;nbsp;exploring the nuances and deeper capabilities of the ExecuteSQL function. And Kevin&amp;#39;s &lt;a href="http://www.filemakerhacks.com/?p=5357"&gt;ExecuteSQL unconference session&lt;/a&gt; at FileMaker DevCon was heavily attended, giving evidence of growing community interest.&lt;/li&gt;
	&lt;li&gt;
		SeedCode released&lt;a href="http://bit.ly/NecUUT"&gt;&amp;nbsp;SQL Explorer&lt;/a&gt;, a powerful and free tool for creating well-structured SQL queries directly within FileMaker.&lt;/li&gt;
	&lt;li&gt;
		Andrew Duncan created a set of&amp;nbsp;&lt;a href="http://bit.ly/NzQxrj"&gt;SQL-based custom functions&lt;/a&gt; and explained how SQL can retrieve metadata, enabling us to query our tables and fields directly within SQL queries.&lt;/li&gt;
	&lt;li&gt;
		Beezwax &amp;nbsp;released&amp;nbsp;&lt;a href="http://www.filemaker.com/company/media/press-releases/releases/3p_2012/beezwax-announces-inspectorpro-4-for-filemaker-12.html"&gt;InspectorPro 4&lt;/a&gt;, rewritten in FileMaker 12 and taking advantage of ExecuteSQL to &lt;a href="https://twitter.com/beezwaxteam/status/227572763135729665/photo/1"&gt;go from 636 to 135 Table Occurrences&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
	With all this activity, it&amp;#39;s easy to forget that our use of SQL in FileMaker solutions is still in its early stages. We&amp;#39;re just getting our toes wet in the vast ocean of SQL. This is a very good thing: The best is still to come.&lt;/p&gt;
&lt;p&gt;
	&lt;span class="Apple-style-span" style="font-size: 18px; font-weight: bold; "&gt;Getting Our Toes Wet&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;
	Looking at our early use of FileMaker SQL, many examples in the wild use an ad hoc, left-to-right structure. Often, these queries are written as linear recipes: Start with fields to be retrieved, place them in a SELECT clause, set the matching table in the FROM clause, then tune the WHERE, and ORDER clauses until the query returns desired results. For example:&lt;/p&gt;
&lt;pre&gt;Select Title, Duration From Movie Where Duration &amp;lt; 90 Order By Title&lt;/pre&gt;
&lt;p&gt;
	This is a fine query: It&amp;#39;s simple, direct, and fast. In this kind of basic SQL, a left-to-right, ad hoc approach is natural,&amp;nbsp;and likely the way most of us get started.&amp;nbsp;We can accomplish a great deal with this form of query. Many of us have eliminated scores of TO&amp;#39;s from our FileMaker 12 solutions using basic queries just like this.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
	But this approach doesn&amp;#39;t scale well as queries become more complex.&amp;nbsp;For example,&amp;nbsp;let&amp;#39;s extend this query to ask which theaters are playing movies between 1 and 2 hours long:&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
	&lt;pre style="space {line-height: 12 px !important;"&gt;Select Movie::Title, Theater::Theater_Name, Coalesce (Showing::Showtime, &amp;#39;[Call for
Details]&amp;#39;) from Movie Join Showing on Showing::Id_Movie = Movie::Id Join Theater on
Theater::Id = Showing::Id_Theater Where Lower (Theater::Region) in (&amp;#39;Santa Barbara&amp;#39;,&lt;span class="Apple-style-span"&gt;
&amp;#39;San Francisco&amp;#39;) And Movie::Duration &amp;gt; 60 and Movie::Duration &amp;lt; 1200 Order by Movie::Title&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
	&lt;br /&gt;
	This is still a simple query, but it&amp;#39;s suddenly become very difficult to read. Are the inner joins valid? Do the columns in the select clause agree with the tables and columns in our other clauses? We&amp;#39;d need to pull this query apart to answer these basic questions. It&amp;#39;s easy to foresee that as we added more clauses, tables, fields, and conditions, a tipping point would soon be reached where this query would become incomprehensible.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
	&lt;img alt="Millau Viaduct, the tallest bridge in the world" height="280" id="lightboxImage" src="http://buzz.beezwax.net/files/Millau_Viaduct_-_5.jpg" style="cursor: default; " width="499" /&gt;&lt;/p&gt;
&lt;p&gt;
	&lt;em&gt;Millau Viaduct, world&amp;#39;s tallest bridge. source:&amp;nbsp;http://bestbridge.net/Eu_en/millau-viaduct.html&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
	The Beginning of Craft&lt;/h2&gt;
&lt;p&gt;
	Let&amp;#39;s step back a bit and reflect on our shared experience as FileMaker developers. For many of us, our initial discovery of FileMaker was exhilarating. We found that we could do amazing things with this malleable and powerful application, and we were overnight heroes! In time we took on increasingly complex projects, running into walls here and there, and parts of our solutions became unwieldy. Sooner, or perhaps (ahem)&amp;nbsp;later, we learned the importance of structure for managing complexity. We adopted naming conventions, learned the importance of structuring code, separated long ad hoc scripts into small, reusable parts, and adopted other best practices. We &amp;mdash; and our solutions &amp;mdash; are now the better for it.&lt;/p&gt;
&lt;p&gt;
	As we learned to gracefully handle complexity, we became craftspeople.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
	I&amp;#39;m privileged to know many FileMaker developers for whom crafting elegant scripts, custom functions, data structures and (of course) user interfaces is a pursuit of functional excellence and aesthetic beauty.&lt;/p&gt;
&lt;p&gt;
	I&amp;#39;m confident the same soon will be said about how we approach FileMaker SQL.&amp;nbsp;As our experience with SQL deepens in the coming months and years, we will have more opportunity to apply many of the best practices we use in FileMaker scripts and data structures to craft SQL structures of greater&amp;nbsp;beauty, clarity, and resilience.&lt;/p&gt;
&lt;h2&gt;
	Creating Structural Beauty&lt;/h2&gt;
&lt;p&gt;
	With this aspiration in mind, let&amp;#39;s take another look at this same query, but this time set in a different structure:&lt;/p&gt;
&lt;pre style="space {line-height: 12 px !important;"&gt;&lt;strong&gt;SELECT&lt;/strong&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;movie.title
&amp;nbsp;&amp;nbsp;&amp;nbsp;,&amp;nbsp;&amp;nbsp;theater.theater_name
&amp;nbsp;&amp;nbsp;&amp;nbsp;,&amp;nbsp;&amp;nbsp;COALESCE ( showing.showtime, &amp;#39;[call for details]&amp;#39; )

&lt;strong&gt;FROM&lt;/strong&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;movie
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;JOIN&amp;nbsp;showing
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ON showing.id_movie = movie.id
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;JOIN theater
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ON theater.id = showing.id_theater

&lt;strong&gt;WHERE&lt;/strong&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LOWER ( theater.region ) IN ( &amp;#39;santa barbara&amp;#39; , &amp;#39;san francisco&amp;#39; )
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AND movie.duration &amp;gt; 60 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AND movie.duration &amp;lt; 120

&lt;strong&gt;ORDER BY&lt;/strong&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;movie.title ASC&lt;/pre&gt;
&lt;p&gt;
	&lt;br /&gt;
	This example uses these simple techniques to create structural clarity:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;
		&lt;p&gt;
			Primary SQL Keywords are outdented and capitalized to emphasize essential clause structure.&amp;nbsp;&lt;/p&gt;
	&lt;/li&gt;
	&lt;li&gt;
		&lt;p&gt;
			Secondary SQL keywords are capitalized inline.&lt;/p&gt;
	&lt;/li&gt;
	&lt;li&gt;
		&lt;p&gt;
			Other elements, including data table and column names, are rendered in lowercase, again focusing attention on structural keywords.&lt;/p&gt;
	&lt;/li&gt;
	&lt;li&gt;
		&lt;p&gt;
			Native SQL dot nomenclature is used, rather than FileMaker &amp;quot;::&amp;quot; syntax.&lt;/p&gt;
	&lt;/li&gt;
	&lt;li&gt;
		&lt;p&gt;
			Individual clause elements are each placed in parallel on separate lines; for example, each field in the SELECT clause appears on a separate line.&lt;/p&gt;
	&lt;/li&gt;
	&lt;li&gt;
		&lt;p&gt;
			Required punctuation is placed prior to elements; for example, commas in the SELECT clause precede column names, making it much easier to locate missing or extra delimiters, and facilitating copying/pasting lines.&lt;/p&gt;
	&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
	&lt;img alt="The Millau Viaduct" src="http://buzz.beezwax.net/files/Millau_Viaduct_-_1.jpg" style="cursor: default; -webkit-user-select: none; " /&gt;&lt;/p&gt;
&lt;p&gt;
	&lt;em&gt;source:&amp;nbsp;http://bestbridge.net/Eu_en/millau-viaduct.html&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
	Imparting Semantic Meaning&lt;/h2&gt;
&lt;p&gt;
	Structuring a query like this may at first feel foreign and perhaps even unnecessary, particularly if we&amp;#39;ve experienced some initial success with ad hoc queries. But there&amp;#39;s a very big payoff to a structured approach: Once you&amp;#39;ve trained your eye to understand SQL structures, well-structured queries become easy to quickly scan and understand. They expose the key parts of a query directly to us.&lt;/p&gt;
&lt;p&gt;
	By contrast, the earlier ad hoc version of this same query was nearly impossible to grasp as presented. Linear form blocked meaning. The difference between these approaches becomes increasingly pronounced as queries grow in complexity.&lt;/p&gt;
&lt;p&gt;
	Well-structured queries are semantically meaningful, and help us craft SQL that is lighter, more flexible, and more powerful.&amp;nbsp;Said differently, the pursuit of well-crafted SQL isn&amp;#39;t an affectation ... but a core part of the craft of creating SQL. As Steve Jobs has it, &amp;quot;&lt;a href="http://nyti.ms/McrdGL"&gt;Design is not just what it looks like and feels like. Design is how it works&lt;/a&gt;.&amp;quot;&lt;/p&gt;
&lt;p&gt;
	One more lesson from our collective FileMaker experience also applies. As a community, we agree on the importance of crafting well-structured, consistent scripts. But we don&amp;#39;t believe there&amp;#39;s only one way to do this, and a number of structural and naming conventions are used in our FileMaker community (there is a similar range of practice in the SQL world as well).&lt;/p&gt;
&lt;p&gt;
	I suggest approaching writing structured SQL in this same spirit. Choose&amp;nbsp;a set of conventions that will help you create clear, consistent, self-documenting SQL code, and make it your own.&lt;/p&gt;
&lt;h2&gt;
	Diving into the Deep End&lt;/h2&gt;
&lt;p&gt;
	One especially thoughtful aspect of FileMaker 12&amp;#39;s new ExecuteSQL function is the way it masks so much of SQL&amp;#39;s native complexity. This dramatically lowers the bar for&amp;nbsp;FileMaker&amp;nbsp;developers getting started with SQL, letting us ignore native SQL issues like data typing, potential injection attacks, character escaping issues, and more. At the beginning &amp;mdash; and later when we want to quickly execute a simple query &amp;mdash; this is great convenience.&lt;/p&gt;
&lt;p&gt;
	But when we&amp;#39;re ready to take our SQL skills to a more advanced level, this masking of native SQL can become a hindrance. At this point, we may need to stop reyling on FileMaker to mask SQL&amp;#39;s quirks and instead take a bold plunge into the deep end of the pool. For me, this means explicitly casting FileMaker values into correct SQL types, learning and using standard SQL functions instead of FileMaker variants, and following accepted SQL conventions. My goal is for the SQL I create to be fully readable to a SQL developer who knows nothing of FileMaker.&lt;/p&gt;
&lt;p&gt;
	As before, this may raise some eyebrows. But once again, this approach offers significant payback for the effort invested.&lt;/p&gt;
&lt;p&gt;
	First, SQL written like this is immediately clear to SQL professionals who won&amp;#39;t recognize Filemaker-specific syntax, making it possible to share questions, problems, and inspirations with native SQL developers.&amp;nbsp;Second, working&amp;nbsp;in native SQL makes it much more natural to step directly into deeper features of the SQL language.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
	As a long-time FileMaker developer, I can report that &amp;mdash; when well structured &amp;mdash; native SQL queries are much less scary than I&amp;#39;d imagined. As a poor swimmer who can barely float, I can also say that the water in the SQL pool is really quite nice. Jump in!&lt;/p&gt;
&lt;p&gt;
	&lt;img alt="The Most Beautiful Bridges" src="http://buzz.beezwax.net/files/Millau_Viaduct_-_3.jpg" style="-webkit-user-select: none" /&gt;&lt;/p&gt;
&lt;p&gt;
	&lt;em&gt;source:&amp;nbsp;http://www.successupermarket.com/blog/the-most-beautiful/the-most-beautiful-bridges/&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
	Recommended Reading&lt;/h2&gt;
&lt;p&gt;
	&lt;span class="Apple-style-span" style="font-size: 12px; font-weight: normal; "&gt;&lt;a href="http://amzn.to/NRDOOM"&gt;Simply SQL&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: 12px; font-weight: normal; "&gt;&amp;nbsp;by Rudy Limeback has become my trusted companion as I explore SQL. I&amp;#39;ve found this short book&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: 12px; font-weight: normal; "&gt;&amp;nbsp;to be a friendly introduction to the syntactical details and native mindset of SQL. Coming from a FileMaker-centric background, it&amp;#39;s helped me understand both simple and more advanced SQL concepts, nicely balancing clarity, depth, and detailed examples.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;
	&amp;mdash;&amp;nbsp;Brian&lt;/p&gt;
&lt;p&gt;
	&lt;a href="http://twitter.com/brian_schick"&gt;Follow Brian on Twitter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
	&lt;style id="_clearly_component__css" type="text/css"&gt;#next_pages_container { width: 5px; hight: 5px; position: absolute; top: -100px; left: -100px; z-index: 2147483647 !important; } &lt;/style&gt;&lt;/p&gt;
&lt;p&gt;
	&lt;style id="_clearly_component__css" type="text/css"&gt;#next_pages_container { width: 5px; hight: 5px; position: absolute; top: -100px; left: -100px; z-index: 2147483647 !important; } &lt;/style&gt;&lt;/p&gt;
&lt;p&gt;
	&lt;style id="_clearly_component__css" type="text/css"&gt;#next_pages_container { width: 5px; hight: 5px; position: absolute; top: -100px; left: -100px; z-index: 2147483647 !important; } &lt;/style&gt;&lt;/p&gt;
&lt;p&gt;
	&lt;style id="_clearly_component__css" type="text/css"&gt;#next_pages_container { width: 5px; hight: 5px; position: absolute; top: -100px; left: -100px; z-index: 2147483647 !important; } &lt;/style&gt;&lt;/p&gt;
&lt;p&gt;
	&lt;style id="_clearly_component__css" type="text/css"&gt;#next_pages_container { width: 5px; hight: 5px; position: absolute; top: -100px; left: -100px; z-index: 2147483647 !important; } &lt;/style&gt;&lt;/p&gt;
&lt;p&gt;
	&lt;style id="_clearly_component__css" type="text/css"&gt;#next_pages_container { width: 5px; hight: 5px; position: absolute; top: -100px; left: -100px; z-index: 2147483647 !important; } &lt;/style&gt;&lt;/p&gt;
&lt;p&gt;
	&lt;style id="_clearly_component__css" type="text/css"&gt;#next_pages_container { width: 5px; hight: 5px; position: absolute; top: -100px; left: -100px; z-index: 2147483647 !important; } &lt;/style&gt;&lt;/p&gt;
&lt;p&gt;
	&lt;style id="_clearly_component__css" type="text/css"&gt;#next_pages_container { width: 5px; hight: 5px; position: absolute; top: -100px; left: -100px; z-index: 2147483647 !important; } &lt;/style&gt;&lt;/p&gt;
&lt;p&gt;
	&lt;style id="_clearly_component__css" type="text/css"&gt;#next_pages_container { width: 5px; hight: 5px; position: absolute; top: -100px; left: -100px; z-index: 2147483647 !important; } &lt;/style&gt;&lt;/p&gt;
&lt;p&gt;
	&lt;style id="_clearly_component__css" type="text/css"&gt;#next_pages_container { width: 5px; hight: 5px; position: absolute; top: -100px; left: -100px; z-index: 2147483647 !important; } &lt;/style&gt;&lt;/p&gt;
&lt;p&gt;
	&lt;style id="_clearly_component__css" type="text/css"&gt;#next_pages_container { width: 5px; hight: 5px; position: absolute; top: -100px; left: -100px; z-index: 2147483647 !important; } &lt;/style&gt;&lt;/p&gt;

</content>
  </entry>
  <entry>
    <id>urn:uuid:32a64d09-3a5f-42a5-85a5-d2053a640dac</id>
    <published>2012-07-19T13:31:43Z</published>
    <updated>2012-07-19T14:26:24Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/07/16/inspectorpro4-for-filemaker-12" />
    <author>
      <name>Jay G</name>
      <email>jay_g@beezwax.net</email>
    </author>
    <title type="html">[news release] InspectorPro 4 for FileMaker 12</title>
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="filemaker-add-ons" label="filemaker add-ons" scheme="http://buzz.beezwax.net/category/filemaker-add-ons" />
    <category term="filemaker-news" label="filemaker news" scheme="http://buzz.beezwax.net/category/filemaker-news" />
    <category term="filemaker-resources" label="filemaker resources" scheme="http://buzz.beezwax.net/category/filemaker-resources" />
    <category term="filemaker-tips" label="filemaker tips" scheme="http://buzz.beezwax.net/category/filemaker-tips" />
    <category term="filemaker-utilities" label="filemaker utilities" scheme="http://buzz.beezwax.net/category/filemaker-utilities" />
    <content type="html">&lt;p&gt;&lt;em&gt;[news release]&lt;/em&gt;&lt;/p&gt;


&lt;p&gt;&lt;/p&gt;


&lt;h3&gt;Beezwax Releases InspectorPro 4 for FileMaker 12&lt;/h3&gt;


&lt;p&gt;&lt;b&gt;Leading Developer Tool Now Up To 10x Faster, Provides Deeper Analysis for FileMaker 12 Databases&lt;/b&gt;&lt;/p&gt;


&lt;p&gt;
    &lt;em&gt;Mac version available now. Windows version coming soon.&lt;/em&gt;&lt;/p&gt;


&lt;p&gt;
    &lt;b&gt;MIAMI, Fla. â€“ FileMaker DevCon&lt;/b&gt; - July 16, 2012 - Beezwax Datatools, Inc. released &lt;a href="http://www.beezwax.net/products/inspectorpro"&gt;InspectorPro 4&lt;/a&gt;, a major new version of the leading developer tool for FileMaker 12 database analysis. Rewritten from the ground up to take advantage of FileMaker 12&amp;#8217;s new architecture, InspectorPro 4 is up to 10 times faster than previous versions at processing FileMaker Database Design Reports.&lt;/p&gt;




&lt;p&gt;
New features provide deeper analysis of database elements, a central dashboard, localized UI options, and powerful data visualizations - enabling FileMaker developers to discover more about their databases than ever before.&lt;/p&gt;


&lt;p&gt;
    &amp;#8220;InspectorPro 4 is blazing fast. We took advantage of many new features in FileMaker 12, such as ExecuteSQL to rewrite the product from the ground up,&amp;#8221; said Vincenzo Menanno, creator of InspectorPro and Director of FileMaker Development for Beezwax. &amp;#8220;A new centralized dashboard, sophisticated in-depth reports plus InspectorPro&amp;#8217;s unique data visualization capabilities, all enable deeper discovery of critical database information that FileMaker developers need to manage during the development process.&amp;#8221;Â &lt;/p&gt;


&lt;p&gt;
    InspectorPro 4 introduces the following features for FileMaker database analysis:&lt;/p&gt;


&lt;ul&gt;
    &lt;li&gt;
        &lt;b&gt;Central&lt;/b&gt; &lt;b&gt;Dashboard&lt;/b&gt; - InspectorPro 4 consolidates critical information about database elements into a central UI.&lt;/li&gt;
    &lt;li&gt;
        &lt;b&gt;Deeper Analysis&lt;/b&gt; - Comparison, dependency and other analysis reports offer expanded information about database elements, as well as deeper levels of information.&lt;/li&gt;
    &lt;li&gt;
        &lt;b&gt;Localized UI&lt;/b&gt; - InspectorPro 4 will be available with interfaces in English, French, German, Japanese and several other languages.&lt;/li&gt;
    &lt;li&gt;
        &lt;b&gt;Data Visualization&lt;/b&gt; - Script Universe and Security Perspective visualizations have been updated for FileMaker 12 development.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;
    Beezwax is demonstrating the new InspectorPro 4 at the 2012 &lt;a href="http://www.filemaker.com/developers/devcon/"&gt;FileMaker Developers Conference&lt;/a&gt; in Miami, Fla, July 16-19, 2012.Â &lt;/p&gt;


&lt;p&gt;&lt;em&gt;FileMaker DevCon Special Pricing is available through July 31, 2012: click &amp;#8220;Buy Now&amp;#8221; on the &lt;a href="http://www.beezwax.net/inspector"&gt;InspectorPro product page&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;


&lt;p&gt;
    More information about InspectorPro 4 is available at &lt;a href="http://www.beezwax.net/products/inspectorpro"&gt;www.beezwax.net/products/inspectorpro&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;b&gt;About InspectorPro&lt;/b&gt;&lt;/p&gt;


&lt;p&gt;InspectorPro is the leading tool for diagnosing, debugging and documenting FileMaker databases. InspectorPro works quickly to identify hard-to-find issues, compare database versions for changes, and identify all dependencies, unreferenced items and uses of any element in a solution. InspectorPro works by using a FileMaker Database Design Report (DDR) to generate a list of database problems that need addressing. InspectorPro proactively provides suggestions for developers to fix the generated list of database issues, and unique data visualization enable developers to discover more about their FileMaker solutions.&lt;/p&gt;




&lt;p&gt;&lt;b&gt;Compatibility &amp; Availability&lt;/b&gt;&lt;/p&gt;


&lt;p&gt;
    InspectorPro 4 works with FileMaker 12 databases and is available now for Mac OS X 10.6 Snow Leopard and OS X 10.7 Lion. A version for Windows is scheduled for release in Fall 2012.&lt;/p&gt;


&lt;p&gt;
    FileMaker Pro 12 Advanced is required for a developer to generate the DDR (Database Design Report) to be used for analysis. The previous product version, Inspector Pro 3, is available for purchase for use with FileMaker Pro versions 8 through 11.&lt;/p&gt;


&lt;p&gt;
    InspectorPro 4 is priced at US$495 for new customers, and is available for purchase and immediate download at www.beezwax.net. A Team License (for up to 5 users) is $1,295. A full-feature trial download is available. Upgrade pricing, and options for Educational and Non-profit pricing are available via Beezwax.&lt;/p&gt;




&lt;p&gt;&lt;b&gt;About Beezwax Datatools, Inc.&lt;/b&gt;&lt;/p&gt;


&lt;p&gt; A recognized industry leader in FileMaker Pro development, Beezwax has completed more than 1,000 successful custom database and web projects for over 400 satisfied clients.Â Headquartered in Oakland, CA, BeezwaxÂ distributes widely-used products and tools for leading developers, and is a Platinum-level member of the FileMaker Business Alliance. More info is at www.beezwax.net.&lt;/p&gt;


&lt;p&gt;
    &lt;b&gt;Media contact:&lt;/b&gt;&lt;br/&gt;
    Jay Gonzales&lt;br/&gt;
    510-835-4483&lt;br/&gt;
    info@beezwax.net&lt;br/&gt;
    www.beezwax.net&lt;br/&gt;
&lt;/p&gt;


&lt;p&gt;
    Â &lt;/p&gt;


&lt;p&gt;
    FileMaker is a trademark of FileMaker, Inc., registered in the U.S. and other countries.&lt;/p&gt;


&lt;p&gt;
    Copyright (c) 2012, Beezwax Datatools, Inc.&lt;/p&gt;


&lt;br/&gt;&lt;br/&gt;


&lt;br/&gt;


</content>
  </entry>
  <entry>
    <id>urn:uuid:2f21c174-d0f8-46a3-ac18-7623f05aff0a</id>
    <published>2012-07-07T04:59:50Z</published>
    <updated>2012-07-07T16:40:01Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/07/07/bbox-0-53-now-available" />
    <author>
      <name>simon</name>
      <email>simon_b@beezwax.net</email>
    </author>
    <title type="html">bBox 0.53 Now Available</title>
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="filemaker-add-ons" label="filemaker add-ons" scheme="http://buzz.beezwax.net/category/filemaker-add-ons" />
    <category term="filemaker-utilities" label="filemaker utilities" scheme="http://buzz.beezwax.net/category/filemaker-utilities" />
    <content type="html">&lt;p&gt;&lt;a href="http://www.beezwax.net/bbox/"&gt;Version 0.53&lt;/a&gt; adds the usual mix of some new functions plus a few fixes for previous issues.&lt;/p&gt;

&lt;p&gt;The new functions are:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;bBox_GetCharacterStyle - get typeface and color information for a given character&lt;/li&gt;
    &lt;li&gt;bBox_Base64Decode - takes Base64 encoded data and returns the result as either a container or text object&lt;/li&gt;
    &lt;li&gt;bBox_Base64Encode - pass text or a container reference to get a Base64 encoded version&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;There were also some tweaks to the Python GetVar &amp;amp; SetVar functions, and a fix for an ExecuteSQL issue on FMP 11 &amp;amp; 12.  This version was tested against a pre-release version of Mac OS 10.8 (Mountain Lion), and no issues were found.&lt;/p&gt;

&lt;p&gt;The Base64 encoding function is admittedly incomplete. Hopefully the next release will have some improvements to this function.&lt;/p&gt;

&lt;p&gt;Simon&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:uuid:447d11ac-0df3-4eb8-b0e7-da23bca0357c</id>
    <published>2012-06-08T16:44:31Z</published>
    <updated>2012-06-12T23:51:47Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/06/12/go-javascript-go" />
    <author>
      <name>Brian</name>
      <email>brian_s@beezwax.net</email>
    </author>
    <title type="html">Go, JavaScript Go!</title>
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="filemaker-add-ons" label="filemaker add-ons" scheme="http://buzz.beezwax.net/category/filemaker-add-ons" />
    <category term="filemaker-resources" label="filemaker resources" scheme="http://buzz.beezwax.net/category/filemaker-resources" />
    <category term="filemaker-tips" label="filemaker tips" scheme="http://buzz.beezwax.net/category/filemaker-tips" />
    <category term="ios" label="iOS" scheme="http://buzz.beezwax.net/category/ios" />
    <category term="ipad" label="iPad" scheme="http://buzz.beezwax.net/category/ipad" />
    <category term="iphone" label="iPhone" scheme="http://buzz.beezwax.net/category/iphone" />
    <category term="web-2-0" label="web 2.0" scheme="http://buzz.beezwax.net/category/web-2-0" />
    <category term="Go" scheme="http://buzz.beezwax.net/tag/go" />
    <category term="JavaScript" scheme="http://buzz.beezwax.net/tag/javascript" />
    <category term="database" scheme="http://buzz.beezwax.net/tag/database" />
    <category term="filemaker" scheme="http://buzz.beezwax.net/tag/filemaker" />
    <category term="iPad" scheme="http://buzz.beezwax.net/tag/ipad" />
    <category term="ins" scheme="http://buzz.beezwax.net/tag/ins" />
    <category term="plug" scheme="http://buzz.beezwax.net/tag/plug" />
    <content type="html">&lt;h2 id="introduction"&gt;
	Introduction&lt;/h2&gt;
&lt;p&gt;
	You gotta love FileMaker Go. Go&amp;rsquo;s ability to effortlessly create data-driven mobile apps and extend existing desktop data applications to mobile users is transformative. But sooner or later, almost all of us run up against one of Go&amp;rsquo;s core limitations: Its lack of native plugins.&lt;/p&gt;
&lt;p&gt;
	Most of us understand this isn&amp;rsquo;t an oversight, but rather a basic constraint imposed by the architecture of Apple&amp;rsquo;s iOS. Still, the inability to extend Go&amp;rsquo;s native toolbox through plugins often limits the capabilities and expressiveness of Go solutions. Many developers and users have probably daydreamed of how much better their mobile solutions might be if only they could find some way of extending Go with plugin functionality. If only&amp;hellip; if only&amp;hellip;&lt;/p&gt;
&lt;p&gt;
	In FileMaker Go 12, we can now do exactly this.&lt;/p&gt;
&lt;h2 id="introduction"&gt;
	Giving New Life To Your Mobile Database&lt;/h2&gt;
&lt;p&gt;
	This article describes how you can create virtual plugins for FileMaker Go 12 using JavaScript and FileMaker 12&amp;rsquo;s new &lt;em&gt;fmp:// &lt;/em&gt;protocol in your Go solutions &amp;mdash; a technique we&amp;rsquo;ll call &amp;ldquo;&lt;strong&gt;JavaScript Go&lt;/strong&gt;&amp;rdquo;. Using this new technique, you&amp;rsquo;ll be able to leverage the vast power of JavaScript &amp;mdash; as well as popular JavaScript libraries like &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;, &lt;a href="http://zeptojs.com/"&gt;zepto.js&lt;/a&gt;, and &lt;a href="http://underscorejs.org/"&gt;underscore.js&lt;/a&gt; &amp;mdash; to add power, functionality, and excitement to your mobile solutions.&lt;/p&gt;
&lt;p&gt;
	As usual, a complete demo file is available at the end of this post. Thanks to &lt;a href="http://worldcloud.com/"&gt;WorldCloud&lt;/a&gt;&amp;nbsp;for use of their FileMaker hosting services, we&amp;#39;re able to offer a live, hosted demo version of this database at: &lt;a href="fmp://shared-hosting-2.filemaker12.com/javascriptGO"&gt;fmp://shared-hosting&amp;ndash;2.filemaker12.com/javascriptGO&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
	OK. Let&amp;rsquo;s get started&amp;hellip;&lt;/p&gt;
&lt;h2 id="aquickreview.orhowtocreateyourveryownmonsterin4easysteps"&gt;
	A Quick Review. Or, &amp;quot;How To Create Your Very Own Monster in 4 Easy Steps&amp;quot;&lt;/h2&gt;
&lt;p&gt;
	The underlying techniques we&amp;rsquo;ll be using here repurpose several steps described in my recent blog post &lt;a href="http://buzz.beezwax.net/2012/04/21/native-web-2-0-controls-in-filemaker-12-layouts"&gt;Native Web 2.0 Controls in FileMaker 12 Layouts&lt;/a&gt;. I explained how FileMaker 12&amp;rsquo;s new &lt;em&gt;fmp://&lt;/em&gt; protocol lets us integrate native web controls and design patterns as full citizens of our Pro and Go visual interfaces. In our current post, we&amp;rsquo;ll flip this technology on its head. This time, we&amp;#39;ll use the same &lt;em&gt;fmp:// &lt;/em&gt;protocol&amp;nbsp;to create JavaScript engines that silently spring to life to add plugin-like power and capabilities to our hosted or stand-alone Go solutions any time we want. (Note that although we&amp;rsquo;ll focus almost exclusively on FileMaker Go, this technique works equally well on any hosted or shared Pro 12 solution).&lt;/p&gt;
&lt;p&gt;
	Let&amp;rsquo;s quickly recap the steps explained previously, this time following in the footsteps of that immortal classic, &amp;ldquo;&lt;a href="http://www.rottentomatoes.com/m/young_frankenstein/"&gt;Young Frankenstein&lt;/a&gt;&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;
	&lt;img src="http://buzz.beezwax.net/files/javascriptGO3.png" style="-webkit-user-select: none" /&gt;&lt;/p&gt;
&lt;h3 id="step1:findabody"&gt;
	Step 1: Find a Body&lt;/h3&gt;
&lt;p&gt;
	As the movies teach us, a budding mad scientist building a creature from scratch must start with a body. When the young Dr. Frankenstein needed a body for his creature, he was forced to unearth a cold, hulking corpse in the dead of night. We FileMaker Go developers have it much easier: We&amp;rsquo;ll just place a named Web Viewer on our Go layouts, staying nice and cozy as we do so.&lt;/p&gt;
&lt;h3 id="step2:selectabrainandmakeitagoodone"&gt;
	Step 2: Select a Brain (and Make it a Good One)&lt;/h3&gt;
&lt;p&gt;
	The movies also make clear that once we have our body, we must find it a brain. This step trips up so many mad scientists; time and again their well-meaning sidekicks bring back the worst specimen in the entire Brain Repository. We won&amp;rsquo;t make that mistake: We&amp;rsquo;ll return from our lab with speedy, lean, industry-standard JavaScript, ready to insert that into our Web Viewer.&lt;/p&gt;
&lt;h3 id="step3:giveyourcreaturelife"&gt;
	Step 3: Give Your Creature Life&lt;/h3&gt;
&lt;p&gt;
	Once we have a Body and have inserted our Brain into it, we face the age-old question of how to bring them both to life. To animate his new creation, Young Frankenstein had to risk life and limb, high atop a questionably designed gothic castle on a dark and stormy night. We&amp;rsquo;ll be able to bring our JavaScript virtual plugin to life simply by injecting custom JavaScript and live FileMaker parameters into our Web Viewer whenever we want it to live. If only Dr. Frederick Frankenstein had known of FileMaker 12&amp;hellip;&lt;/p&gt;
&lt;h3 id="step4:teachyourcreaturetospeak"&gt;
	Step 4: Teach Your Creature to Speak&lt;/h3&gt;
&lt;p&gt;
	Finally, our now-living creature must be able to communicate to us. Here&amp;rsquo;s where FileMaker 12&amp;rsquo;s new &lt;em&gt;fmp:// &lt;/em&gt;protocol really helps us out: In earlier versions of Go, Web Viewers trying to converse with native FileMaker scripts made awkward grunting noises, just like so many matinee creatures. Igor, Frau BlÃ¼cher and company needed an entire movie to resolve this tricky conundrum, ultimately resorting to a dangerous brain transference procedure to enable their monster to communicate clearly. In our case, FileMaker 12&amp;rsquo;s new &lt;em&gt;fmp://&lt;/em&gt; protocol makes it easy: Our Web Viewers will speak directly and eloquently to our native FileMaker scripts right out of the box, with no need for expensive brain surgeries our HMO&amp;rsquo;s likely won&amp;rsquo;t cover. Huzzah!&lt;/p&gt;
&lt;p&gt;
	&lt;img src="http://buzz.beezwax.net/files/javascriptGO2.png" style="-webkit-user-select: none" /&gt;&lt;/p&gt;
&lt;h2 id="javascriptgounderthehood"&gt;
	And Now to the Laboratory&amp;hellip;&lt;/h2&gt;
&lt;p&gt;
	Let&amp;rsquo;s roll up our sleeves and look at the details of how we can build a JavaScript Go creature of our own:&lt;/p&gt;
&lt;h3 id="jsgowebviewer"&gt;
	jsGO Web Viewer&lt;/h3&gt;
&lt;p&gt;
	We&amp;rsquo;ll start by simply placing a Web Viewer on our layout, which will act as the &amp;ldquo;body&amp;rdquo; for our JavaScript &amp;ldquo;brains&amp;rdquo;. Let&amp;rsquo;s call it &amp;ldquo;jsGO.view&amp;rdquo;. I&amp;rsquo;ve found a couple of gotchas &amp;mdash; the Web Viewer can&amp;rsquo;t be hidden on an inactive tab or beyond the visible area of a layout, and Go performance is best if each layout gets its own copy of &amp;ldquo;jsGO.view&amp;rdquo;.&lt;/p&gt;
&lt;h3 id="jsgocustomfunctions"&gt;
	jsGO Custom Functions&lt;/h3&gt;
&lt;p&gt;
	JavaScript Go uses a small set of lightweight custom functions: &amp;ldquo;jsGO.fmpWrap&amp;rdquo; provides a context-aware wrapper for the new fmp:// protocol, so whether we&amp;rsquo;re running a local or hosted Go solution, or a hosted or shared Pro solution, our JavaScript will be able to communicate with our FileMaker scripts. The custom functions &amp;ldquo;jsGO.scriptWrap&amp;rdquo; and &amp;ldquo;jsGO.webWrap&amp;rdquo; help us easily wrap JavaScript snippets in valid script and HTML5 wrappers; Last, a set of hash custom functions allow us to pass named parameters to our core scripts (see the next section for more info). All of these custom functions are fully generalized, so we can just paste them into any solution then get on with our work.&lt;/p&gt;
&lt;h3 id="jsgoscripts"&gt;
	jsGO Scripts&lt;/h3&gt;
&lt;p&gt;
	Our technique uses 2 scripts: The first, &amp;ldquo;jsGO.listener&amp;rdquo; will simply listen for results our JavaScript returns to our solution via the&amp;nbsp;&lt;em&gt;fmp:// &lt;/em&gt;protocol, then place these results in a global variable, $$jsGO.results.&lt;/p&gt;
&lt;p&gt;
	Our second script, &amp;ldquo;jsGO&amp;rdquo; is the script that will do the heavy lifting, and the script that will be the public face of javascriptGO. We&amp;rsquo;ll invoke our jsGO script whenever we call our virtual plugin, much as we&amp;rsquo;d normally call a standard plugin in Pro. &amp;nbsp;Let&amp;rsquo;s take a closer look at how it works:&lt;/p&gt;
&lt;p&gt;
	Our jsGO script will need to be able to accept many types of data, and varying numbers of parameters, depending on the JavaScript functionality desired. To handle this gracefully, we&amp;rsquo;ll choose the widely-used method of &lt;a href="http://sixfriedrice.com/wp/passing-multiple-parameters-to-scripts-advanced/"&gt;passing named parameters in a hash format&lt;/a&gt;. We&amp;rsquo;ll require each call to jsGO to pass a &amp;ldquo;function&amp;rdquo; parameter telling our script what we&amp;rsquo;re asking of it; beyond this, we&amp;rsquo;ll accept any number of additional parameters needed. This will let our script accept variable types and numbers of parameters, then parse each parameter passed to local variables we can integrate into our JavaScript.&lt;/p&gt;
&lt;p&gt;
	After we&amp;rsquo;ve parsed our parameters, we&amp;rsquo;ll use a simple if / elseif structure to locate the function requested. If a null or unknown function is encountered, we&amp;rsquo;ll return an error (via $$_jsGO.error) and exit. Within our if / elseif structure, once&amp;nbsp;we&amp;rsquo;ve located the desired function, we&amp;rsquo;ll define the custom JavaScript that will perform that task. In the simplest cases (like requesting time in milliseconds, getting random numbers, etc.) we&amp;rsquo;ll only need static JavaScript. More typically, we&amp;rsquo;ll inject live FileMaker data passed via our parameters directly into our JavaScript, so that our virtual plugin will be able to act on live solution data. Whatever task we&amp;rsquo;re performing, our JavaScript will include a return function enabling it to speak to our listener script with its calculated results.&lt;/p&gt;
&lt;p&gt;
	Now comes the fun part: We&amp;rsquo;ll wrap our JavaScript snippets inside script and HTML5 wrappers and insert this into the &amp;ldquo;jsGO.view&amp;rdquo; Web Viewer on our active layout,&amp;nbsp;bringing our creation to life. Once we&amp;rsquo;ve done this, we&amp;rsquo;ll pause and wait briefly for our Web Viewer to do its work and communicate its results back to our jsGO.listener script. As soon as we have these results, our script will resume.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
	Last, we may perform optional cleanup if, for example, our $$jsGO.results need to be reformatted a bit or have characters un/escaped. And then, jsGo exits, allowing the calling script or object to process our JavaScript Go results and continue its work.&amp;nbsp;Here&amp;rsquo;s the main body of our &amp;quot;jsGO&amp;quot; script:&lt;/p&gt;
&lt;div style="font: 12px/1 Courier,monospace; color:#666; border-left: 3px solid #92b031; padding-left: 5px;"&gt;
	&lt;p style="color:black;margin:0;"&gt;
		&lt;strong&gt;# Parse Parameters&lt;/strong&gt;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		Set Variable [ $_value; Value:#P ( &amp;quot;value&amp;quot; ) ]&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		Set Variable [ $_regex; Value:#P ( &amp;quot;regex&amp;quot; ) ]&lt;/p&gt;
	&lt;p style="margin:0"&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="color: rgb(146, 176, 49); margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;
		&lt;em&gt;&lt;strong&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; . . . (omitting similar steps for brevity) . . .&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
	&lt;div&gt;
		&lt;em&gt;&lt;strong&gt;&lt;br /&gt;
		&lt;/strong&gt;&lt;/em&gt;&lt;/div&gt;
	&lt;p style="margin:0"&gt;
		&lt;strong&gt;# &amp;nbsp; &amp;nbsp; â–¼ Single-Pass Loop â–¼&lt;/strong&gt;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		Loop&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="color:black;margin:0;"&gt;
		&lt;strong&gt;# Set Custom JavaScript by Function&lt;/strong&gt;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		If [ IsEmpty ( $_function ) ]&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		Set Variable [ $_error; Value:10 ]&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		Set Variable [ $_error_message; Value:&amp;quot;Required parameter &amp;#39;function&amp;#39; not received.&amp;quot; ]&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		Exit Loop If [ True ]&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		Else If [ $_function = &amp;quot;number.toHex&amp;quot; ]&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		Set Variable [ $_javascript; Value:Let ( the_script = &amp;quot;&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		var num = &amp;quot; &amp;amp; Int ( $_param_1 ) &amp;amp; &amp;quot; ;&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		var result = num.toString(16);&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		self.location = &amp;quot; &amp;amp; sQuote ( jsGO.fmpWrap ( &amp;quot;jsGO.listener&amp;quot; ; &amp;quot;&amp;quot; &amp;amp; &amp;quot;&amp;quot; ) ) &amp;amp; &amp;quot;+result; &amp;quot;;&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		jsGo.scriptWrap ( the_script ) )]&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="color:#92b031;margin:0;"&gt;
		&lt;em&gt;&lt;strong&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; . . . (omitting additional function definitions for brevity) . . .&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		Else If [ $_function = &amp;quot;regex.strip&amp;quot; ]&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		Set Variable [ $_javascript; Value:Let ( [&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;; "&gt;
		text=Substitute($_param_1; [&amp;quot;&amp;#39;&amp;quot;;&amp;quot;\&amp;#39;&amp;quot;];[&amp;quot;\&amp;quot;&amp;quot;;&amp;quot;\\\&amp;quot;&amp;quot;];[&amp;quot;&amp;para;&amp;quot;;&amp;quot;\n&amp;quot;];[&amp;quot;=&amp;quot;;&amp;quot;&amp;ndash;&amp;quot;]); pattern = $_param_2 ;&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;; "&gt;
		the_script = &amp;quot;&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;; "&gt;
		var str=&amp;quot; &amp;amp; sQuote ( text ) &amp;amp; &amp;quot; ;&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;; "&gt;
		var patt = &amp;quot; &amp;amp; pattern &amp;amp; &amp;quot; ;&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;; "&gt;
		var resultStr = str.replace(patt,&amp;#39;&amp;#39;);&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;; "&gt;
		self.location = &amp;quot; &amp;amp; sQuote ( jsGO.fmpWrap ( &amp;quot;jsGO.listener&amp;quot; ; &amp;quot;&amp;quot; &amp;amp; &amp;quot;&amp;quot; ) ) &amp;amp; &amp;quot; + resultStr ; &amp;quot;&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;; "&gt;
		];&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		jsGo.scriptWrap ( the_script ) )]&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		Else&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		Set Variable [ $_error; Value:10 ]&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		Set Variable [ $_error_message; Value:&amp;quot;Unknown &amp;#39;function&amp;#39; parameter received.&amp;quot; ] Exit Loop If [ True ]&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		End If&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="color:black;margin:0;"&gt;
		&lt;strong&gt;# Set web viewer and wait for response&lt;/strong&gt;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		Set Variable [ $_start_timestamp; Value:Get ( CurrentTimeStamp ) ]&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		Set Web Viewer [ Object Name: &amp;quot;jsGO.view&amp;quot;; URL: &amp;quot;data:text/html,&amp;quot; &amp;amp; jsGo.webWrap ( $_javascript ) ]&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		Loop&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		Exit Loop If [ $$_jsGO.results &amp;ne; &amp;quot;&amp;quot; or&amp;nbsp;Get ( CurrentTimeStamp ) &amp;ge; $_start_timestamp + $_timeout_seconds ]&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		Pause/Resume Script [ Duration (seconds): $_loop_interval ]&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		End Loop&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		&lt;span class="Apple-style-span" style="color: rgb(0, 0, 0); "&gt;&lt;strong&gt;# Reset web viewer and handle any errors&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		Set Web Viewer [ Object Name: &amp;quot;jsGO.view&amp;quot;; URL: &amp;quot;data:text/html,&amp;quot; &amp;amp; jsGo.webWrap ( &amp;quot;&amp;quot; ) ]&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		If [ IsEmpty ( $$_jsGO.results ) ]&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		Set Variable [ $_error; Value:20 ]&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		Set Variable [ $_error_message; Value:&amp;quot;No results were returned from the web viewer.&amp;quot; ]&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		Exit Loop If [ True ]&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		End If&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="color:black;margin:0"&gt;
		&lt;strong&gt;# Do any Cleanup if needed&lt;/strong&gt;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		If [ $_function = &amp;quot;&amp;quot; ]&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		Else If [ $_function = &amp;quot;values.unique&amp;quot; ]&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		Set Variable [ $$_jsGO.results; Value:Substitute ( $$_jsGO.results ; &amp;quot;,&amp;quot; ; &amp;para; ) ]&lt;/p&gt;
	&lt;p style="color: rgb(146, 176, 49); margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="color: rgb(146, 176, 49); margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;
		&lt;em&gt;&lt;strong&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; . . . (omitting similar steps for brevity) . . .&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
	&lt;p style="color: rgb(146, 176, 49); margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		Else If [ $_function = &amp;quot;number.toHex&amp;quot; ]&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		Set Variable [ $$_jsGO.results; Value:Upper ( $$_jsGO.results ) ]&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		End If&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		&amp;nbsp;&lt;/p&gt;
	&lt;p style="margin:0;"&gt;
		Exit Loop If [ True ] End Loop&lt;/p&gt;
	&lt;p style="margin:0"&gt;
		# &amp;nbsp; &amp;nbsp; &amp;nbsp; â–² &lt;strong&gt;Single-Pass Loop&lt;/strong&gt; â–²&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="kissorkeepitsimple"&gt;
	Is It Friendly?&lt;/h2&gt;
&lt;p&gt;
	Any useful plugin must be easy to integrate into our solutions and simple to use. We understand that any FileMaker plugin will be complex under the hood, but we also expect this complexity to be hidden within the plugin. Our technique meets this test nicely.&lt;/p&gt;
&lt;p&gt;
	Adding JavaScript Go to any solution is very simple, because it&amp;rsquo;s designed to be quickly bolted in to any solution: We simply add jsGO Web Viewers to the solution&amp;rsquo;s layouts, paste in our custom functions, paste in our scripts, and&amp;hellip; that&amp;rsquo;s it. Just that easily, we can now call a JavaScript Go function from any script or layout object in this solution as simply as we&amp;rsquo;d call a normal FileMaker plugin. The most noticeable difference is that instead of making a true function call (as with a true plugin), we instead run our jsGO script. Otherwise, the concepts &amp;mdash; and the simplicity &amp;mdash; are virtually identical. For example, here&amp;rsquo;s a sample call to jsGO:&lt;/p&gt;
&lt;div style="font: 12px/1 Courier,monospace; color:#666; border-left: 3px solid #92b031; padding-left: 5px;"&gt;
	&lt;p style="margin:0"&gt;
		Perform Script [&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		&amp;ldquo;jsGO&amp;rdquo;; Parameter: List (&lt;/p&gt;
	&lt;p style="margin:0 0 0 80px;"&gt;
		# ( &amp;quot;function&amp;quot; ; &amp;quot;regex.match&amp;quot; ) ;&lt;/p&gt;
	&lt;p style="margin:0 0 0 80px;"&gt;
		# ( &amp;quot;value&amp;quot; ; [filemaker_value] ) ;&lt;/p&gt;
	&lt;p style="margin:0 0 0 80px;"&gt;
		# ( &amp;quot;regex&amp;quot; ; [regex_pattern] )&lt;/p&gt;
	&lt;p style="margin:0 0 0 80px;"&gt;
		)&lt;/p&gt;
	&lt;p style="margin:0 0 0 40px;"&gt;
		]&lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;
	Putting On The Ritz&lt;/h2&gt;
&lt;p&gt;
	We&amp;#39;re finished in our laboratory. But the movies make clear&amp;nbsp;we&amp;#39;re not truly finished&amp;nbsp;until we&amp;#39;ve displayed our creation before a community of skeptical scientists. So let&amp;rsquo;s bring JavaScript Go out onto the stage, cue the band, and see what he can actually do for us:&lt;/p&gt;
&lt;p&gt;
	&lt;img src="http://buzz.beezwax.net/files/javascriptGO4.png" style="-webkit-user-select: none" /&gt;&lt;/p&gt;
&lt;p&gt;
	Out of the box, JavaScript Go knows some nifty steps. JavaScript string and array operations offer us a great deal of power, and number, date, and time methods bring some nice extensions to our native FileMaker toolbox. These native JavaScript functions give us new capabilities, and in some cases offer more precision (getting time in milliseconds, more accurate random numbers, etc). Not a bad start&amp;hellip;&lt;/p&gt;
&lt;p&gt;
	The band takes the tune up a half step, and JavaScript Go kicks it up a notch, showing off it&amp;rsquo;s ability to do RegEx &amp;mdash; the powerful pattern matching tool used by many modern programming environments, including JavaScript. Want to find all phone numbers &amp;mdash; regardless of formatting &amp;mdash; anywhere in a string? Or all html or xml tags &amp;mdash; even unexpected ones? Or maybe you&amp;rsquo;d like to find all zip codes in your text, but only if they&amp;rsquo;re followed by a 4 number suffix? And then you&amp;rsquo;d like to replace ones meeting certain criteria with other strings of your choosing? We can do any of these complex operations in only a single call to our virtual plugin.&lt;/p&gt;
&lt;p&gt;
	&lt;span class="Apple-style-span"&gt;As the band notches it up another half step, JavaScript Go now shows off a bit of what it can do using&amp;nbsp;&lt;/span&gt;JavaScript libraries like&lt;span class="Apple-style-span"&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;,&amp;nbsp;&lt;a href="http://zeptojs.com/"&gt;zepto.js&lt;/a&gt;, and&amp;nbsp;&lt;a href="http://underscorejs.org/"&gt;underscore.js&lt;/a&gt;&lt;span class="Apple-style-span"&gt;. We can store these directly within our mobile solutions, maximizing performance and ensuring these libraries will work offline if needed. Using these powerful libraries, we can extend JavaScript&amp;rsquo;s native toolset even further to let us do things like industry-standard RSA encryption (locally on the device, without any round trips to a server), AJAX operations, and much more heavy lifting than we can review in the current post. (But&amp;hellip; shameless teaser&amp;hellip; stay tuned for future posts).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;
	So far, everything&amp;rsquo;s going great. But what&amp;rsquo;s this? Someone from the audience runs up and pulls the plug on our internet connection, setting our iOS device to Airplane Mode and leaving JavaScript Go without a network connection of any kind. The crowd gasps! Now the band unexpectedly takes it up a full step and a half &amp;mdash; to D# minor! &amp;mdash; just as a klieg light shatters, causing a small fire to break out onstage. Smelling imminent failure, the previously friendly crowd of scientists reaches in unison for a hidden supply of tomatoes (apparently stored beneath their seats). Will our JavaScript creature degenerate into an incoherent lump of technology, perhaps grabbing Fay Wray and making an ill-advised attempt to scale the Empire State Building in the process?&lt;/p&gt;
&lt;p&gt;
	Not at all. JavaScript Go smiles to itself, then does the seemingly impossible, continuing to perform flawlessly without missing a beat &amp;mdash; even without a network connection! Except for functions explicitly built to query live data sources, everything still works perfectly, including our extended libraries, because we&amp;rsquo;ve cached them locally in our solution. Our solutions hum along seamlessly, our potential crisis is averted, and those rotten tomatoes disappear into non-existence as our audience sees how robust and versatile our virtual plugin is. The ghost of Fay Wray (who never belonged in our movie anyway) breathes a sigh of relief from its final resting place.&lt;/p&gt;
&lt;p&gt;
	&lt;img src="http://buzz.beezwax.net/files/javascriptGO1.png" style="-webkit-user-select: none" /&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;
	Conclusion&lt;/h2&gt;
&lt;p&gt;
	JavaScript Go offers FileMaker Go 12 developers the opportunity to move beyond the box of Go&amp;rsquo;s stock functionality. We can now&amp;nbsp;create mobile solutions that are richer, more powerful, and more full-featured than previously possible. At the same time, we gain access to JavaScript&amp;rsquo;s world-wide development community, and a vast library of JavaScript functions and libraries. And as with many of the most powerful FileMaker Pro plugins, JavaScript Go is endlessly extensible, ultimately being limited only by our imaginations. It will be exciting to see how our development community puts these exciting new capabilities of FileMaker Go 12 to use.&lt;/p&gt;
&lt;p&gt;
	Enjoy!&lt;br /&gt;
	&lt;em&gt;-Brian&lt;/em&gt;&lt;br /&gt;
	&lt;br /&gt;
	&lt;a href="http://twitter.com/brian_schick"&gt;Follow Brian on Twitter&lt;/a&gt;&lt;/p&gt;
&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 15.0px 'Lucida Grande'"&gt;
	. &amp;nbsp;. &amp;nbsp;. &amp;nbsp;. &amp;nbsp;. &amp;nbsp;. &amp;nbsp;. &amp;nbsp;. &amp;nbsp;. &amp;nbsp;. &amp;nbsp;. &amp;nbsp;. &amp;nbsp;.&lt;/p&gt;
&lt;h2&gt;
	Demo File&lt;/h2&gt;
&lt;p&gt;
	Our demo file now comes in 2 flavors: You can access a&amp;nbsp;hosted version of &amp;nbsp;file at:&amp;nbsp;&lt;a href="fmp://shared-hosting-2.filemaker12.com/javascriptGO"&gt;fmp://shared-hosting&amp;ndash;2.filemaker12.com/javascriptGO&lt;/a&gt;.&amp;nbsp;Note, however, that this hosted file doesn&amp;#39;t offer admin access to scripts and custom functions. If you&amp;#39;d like to tinker under the hood or load this file locally, you can download an unlocked copy of the demo file:&amp;nbsp;&lt;a href="http://buzz.beezwax.net/files/javascriptGO.fmp12"&gt;javascriptGO.fmp12&lt;/a&gt;&lt;/p&gt;


</content>
  </entry>
  <entry>
    <id>urn:uuid:fd05b4e5-b139-41ac-aa2f-f54420d9caa6</id>
    <published>2012-05-26T21:21:13Z</published>
    <updated>2012-06-12T22:22:15Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/06/12/benefits-of-automated-testing" />
    <author>
      <name>Bee</name>
      <email>info@beezwax.net</email>
    </author>
    <title type="html">The Benefits of Automated Testing</title>
    <category term="custom-functions" label="custom functions" scheme="http://buzz.beezwax.net/category/custom-functions" />
    <category term="rails" label="rails" scheme="http://buzz.beezwax.net/category/rails" />
    <category term="ruby" label="ruby" scheme="http://buzz.beezwax.net/category/ruby" />
    <category term="testing" label="testing" scheme="http://buzz.beezwax.net/category/testing" />
    <category term="web-2-0" label="web 2.0" scheme="http://buzz.beezwax.net/category/web-2-0" />
    <category term="TDD" scheme="http://buzz.beezwax.net/tag/tdd" />
    <category term="automated" scheme="http://buzz.beezwax.net/tag/automated" />
    <category term="development" scheme="http://buzz.beezwax.net/tag/development" />
    <category term="programming" scheme="http://buzz.beezwax.net/tag/programming" />
    <category term="software" scheme="http://buzz.beezwax.net/tag/software" />
    <category term="testing" scheme="http://buzz.beezwax.net/tag/testing" />
    <content type="html">&lt;p&gt;Software changes over time. Your companyâ€™s web site this year does
   things you had no idea you needed two years ago. How can we keep the
   cost of change manageable?
&lt;/p&gt;


&lt;p&gt;Automated testing is one way.
   Especially for large software projects,
   the practice of &lt;strong&gt;automated testing can
dramatically reduce the cost&lt;/strong&gt; of adapting software to new
   business necessities.
&lt;/p&gt;


&lt;p&gt;As a developer, when I upgrade
   to a new version of software or add a new feature, automated tests
   tell me right away when Iâ€™ve broken a working feature.
   Automated tests find bugs instantly. Manual testing can also find bugs, but itâ€™s slower and
   more expensive. So professional software 
   development teams
   use automated tests extensively.
&lt;/p&gt;


&lt;p&gt;Sometimes we can get to a deadline sooner by
   leaving out automated tests,
   but it increases the cost of development
   from then on,
   at least
   until we take the time to write the automated tests. We call
   shortcuts like going without tests &amp;quot;&lt;strong&gt;technical
debt&lt;/strong&gt;&amp;quot; &amp;#8212; taking those shortcuts in development can speed you up in the short
   term, but then youâ€™re stuck â€œpaying the interestâ€ on the debt
   in the form of extra time and cost. 
&lt;/p&gt;


&lt;h2&gt;Predicting and Avoiding Unpredictability&lt;/h2&gt;


&lt;p&gt;One of the most difficult issues in software project management is the
   &lt;strong&gt;inherent unpredictability of software project schedules&lt;/strong&gt;.
   The only predictable task, in any field, is one youâ€™ve already done before. But in software,
   if youâ€™re writing code thatâ€™s been written before, youâ€™re
   doing it wrong â€” you should just copy the 
   existing files
   into the new project!
&lt;/p&gt;


&lt;p&gt;As &lt;a href="http://www.joelonsoftware.com/news/fog0000000337.html"&gt;Joel Spolsky said in 2001&lt;/a&gt;:
&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;This means that almost everything we do as software developers is
   something that has &lt;em&gt;never been done before&lt;/em&gt;. Herman the Handyman,
   who just installed a tile floor for me, has probably installed
   hundreds of tile floors. He has to keep installing tile floors again
   and again as long as new tile floors are needed. We in the software
   industry would have long since written a Tile Floor Template Library
   (TFTL) and generating new tile floors would be trivial.
   &amp;#8230; Everything you do is on the cutting edge by definition. So by
   definition it is unpredictable.
&lt;/p&gt;
&lt;/blockquote&gt;


&lt;br/&gt;


&lt;p&gt;In the face of this &lt;em&gt;inherent&lt;/em&gt; unpredictability, we can at least
   remove much of the &lt;em&gt;avoidable&lt;/em&gt; unpredictability. One of the biggest
   causes of avoidable unpredictability is tracking down bugs.
   An unexpected nasty bug can blow
   your development budget &lt;em&gt;and&lt;/em&gt; your schedule.
   Because automated tests let you find bugs quickly, &lt;strong&gt;tests reduce the
risks of software
project budgets&lt;/strong&gt;.
&lt;/p&gt;




&lt;h2&gt;What Programmers Do, and Why Catching Bugs Faster is Such a Big Deal&lt;/h2&gt;


&lt;p&gt;A lot of people think that software development consists mostly of
   typing code into a computer, with the occasional error that needs to
   be fixed. A little arithmetic will show how wrong that is.
&lt;/p&gt;


&lt;p&gt;Nearly all
   programmers are adept typists, capable of speeding along at 
   90 words per minute. A line of code is typically about five words
   worth, so if a programmer is just typing in code from
   a printout, he or she can
   type about 18 lines of code per minute, or 1080 lines per hour, or
   8640 lines per day.&lt;br /&gt;

&lt;/p&gt;


&lt;p&gt;But, on real-life software projects, programmers
   might produce between 3 and 30 lines of code per day,
   or up to 100 lines
   in extreme circumstances on small projects. So theyâ€™re spending at
   least 99% of their time doing things other than typing in production code.
&lt;/p&gt;


&lt;p&gt;Where does that 99% of the time go?  Itâ€™s spent on understanding what
   the existing code does (this alone is about 50%), on figuring out what
   the new code needs to do, on organizing the code, on testing to see
   what the code does, and on hunting down bugs in the code to make it
   work right. In particular, people
   often underestimate the enormous amount of time even the best
   programmers have to spend ferreting out their own mistakes.
&lt;/p&gt;




&lt;h2&gt;How Automated Testing Works&lt;/h2&gt;


&lt;p&gt;I have a bug to fix. I load up the test
   runner and push the Run button, and a green progress bar showing the
   progress of the run of its test suite appears. A few seconds or
   minutes later, the test run is complete, and I see that
   the bar is still green, so
   the system is in working order on my workstation.
   I add a new test, which consists of writing a few lines of code
   that demonstrate the bug Iâ€™m going to fix;
   I hit Save; and I hit Run again. This time, the bar turns red, and shows him that the 
   test Iâ€™ve just written is failing. I fix the bug, push Run
   again, and the tests go green again â€” telling me not only that my
   fix worked, but also that I didnâ€™t break anything else in the system
   in the process.
&lt;/p&gt;


&lt;p&gt;There are some things about this scenario that are crucial to getting
   the benefits of automated testing:
&lt;/p&gt;


&lt;ul&gt;
 &lt;li&gt;&lt;p&gt;First, I &lt;strong&gt;didnâ€™t have to wait long&lt;/strong&gt; to get the results of the
     automated test run. If it took ten minutes, or an hour, or
     overnight, to get the results, I wouldnâ€™t run the test suite before
     I started developing, and thereâ€™s a possibility that the code or
     the test suite would already be buggy. When I finally ran the test
     suite, and the tests went red, Iâ€™d think I had introduced a bug in
     an unrelated part of the system, and Iâ€™d waste time trying to
     figure out how I could possibly have broken it. For some projects,
     itâ€™s worthwhile having a separate suite of â€œslow testsâ€, which can
     be run less frequently, but itâ€™s crucial to keep the normal test run
     snappy in order to make it useful.
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;p&gt;Second, I &lt;strong&gt;didnâ€™t have to inspect the output&lt;/strong&gt; of the test run in
     order to figure out whether the tests passed or failed. The test
     suite contains not just the script to exercise the system, but also
     the expected output, and I get a simple red/green indicator that
     everything is okay, out of a suite that may be thousands or tens of
     thousands of individual tests.
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;p&gt;Third, I &lt;strong&gt;didnâ€™t have to wait for a separate Testing Team&lt;/strong&gt; to
     write the test. QA teams are very useful for many software
     projects, but some cases, itâ€™s efficient for
     the developer to write the test, even if the QA team found the bug
     originally.
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;p&gt;Fourth, I &lt;strong&gt;tested the test&lt;/strong&gt; â€” I verified that if the bug was
     present, the test failed.
&lt;/p&gt;

 &lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;In this case, Iâ€™m testing the test by writing the test before the
   code thatâ€™s supposed to make it pass. This approach is called
   &lt;strong&gt;Test-Driven Development&lt;/strong&gt; (TDD) or &lt;strong&gt;Behavior-Driven Development&lt;/strong&gt;, 
   and itâ€™s widely believed to improve code quality and speed up
   development, for a variety of reasons that Iâ€™m saving for another blog
   post.
   But, while TDD is more convenient in many cases, I still get a lot of 
   benefit from automated tests written after the fact.
&lt;/p&gt;


&lt;p&gt;Of course, itâ€™s still possible that I could introduce a bug that the
   existing test suite wonâ€™t catch.  I still have to be careful and think
   about what Iâ€™m doing.  But a good test suite will catch almost all of
   my slip-ups.
&lt;/p&gt;




&lt;h2&gt;Conclusions&lt;/h2&gt;


&lt;p&gt;There are &lt;strong&gt;other benefits of automated tests&lt;/strong&gt; besides just reducing the
   number of bugs.  A kind of automated test called an â€œacceptance testâ€
   serves not only to catch bugs, but also to &lt;strong&gt;document customer
requirements&lt;/strong&gt;.  There are special tools for maintaining automatic
   acceptance tests in a form thatâ€™s understandable and even editable by
   non-technical customers: 
   &lt;a href="http://fitnesse.org/"&gt;FitNesse&lt;/a&gt; and &lt;a href="http://cukes.info/"&gt;Cucumber&lt;/a&gt; are two of the most popular.
&lt;/p&gt;


&lt;p&gt;Automated â€œunit testsâ€ also provide a 
   similar value for reusable modules of code, documenting what those 
   modules do, and donâ€™t do, to future programmers &amp;#8212; 
   as well as documenting how to use them &amp;#8212; &lt;strong&gt;enhancing the 
practical reusability of those modules&lt;/strong&gt;, reducing
   future development effort.
   And test-driven development is widely
   believed to &lt;strong&gt;improve the internal design&lt;/strong&gt; of software â€” something thatâ€™s
   invisible to users, but reduces the cost of later changes.&lt;/p&gt;


&lt;p&gt;Automating the tests that &lt;em&gt;can&lt;/em&gt; be automated means
   that &lt;strong&gt;human QA testers can focus their effort on finding trickier bugs&lt;/strong&gt;,
   including problems with usability, which gives customers much more
   value per QA hour spent. Many consider these benefits more important than merely catching bugs.
&lt;/p&gt;


&lt;p&gt;Finally, itâ€™s not enough to know that automated tests are a good idea;
   how do you decide what to test, and how much testing is too much?
   Hold that thought; weâ€™ll discuss these topics in
   later blog posts.
&lt;/p&gt;


</content>
  </entry>
  <entry>
    <id>urn:uuid:54f4d2f4-8562-4d45-b6b2-85bd0206d993</id>
    <published>2012-06-15T17:18:50Z</published>
    <updated>2012-06-28T18:19:55Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/06/11/list-cron-entries-for-all-users-on-mac-os-x" />
    <author>
      <name>simon</name>
      <email>simon_b@beezwax.net</email>
    </author>
    <title type="html">List cron entries for all users on Mac OS X</title>
    <content type="html">&lt;p&gt;I needed to investigate why a script was being run, and I was pretty sure cron was launching it. The problem was, little useful information was being logged, and no one was sure how it had been set up or what user it was under. Although launchd is now the preferred mechanism on Mac OS for these kinds of things, you&amp;#8217;ll still see many systems where cron is being used.&lt;/p&gt;

&lt;p&gt;First, you want to become the root user. The following Terminal command is one way to accomplish this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;sudo -s&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;br&gt;


&lt;p&gt;From here, one option is dump the contents of all files in /usr/lib/cron/tabs:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;cat /usr/lib/cron/tabs/*&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;br&gt;


&lt;p&gt;This might be a bit messy, and doesn&amp;#8217;t show which user the entries belong to without tracing back to the original file. A cleaner way to do this is in bash is:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;for user in $(dscl . list /Users); do echo $user; crontab -u $user -l; echo; done&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;br&gt;


&lt;p&gt;Don&amp;#8217;t forget to also check in /etc/periodic and use the atq command for other places that cron like jobs could be configured.&lt;/p&gt;

&lt;p&gt;Finally, I have had issues on Linux systems where a phantom cron entry persists, even after it has been removed using the crontab command. For this, I had to restart the crond process to clear out the old entry.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:uuid:217dc386-17ab-438c-91c6-4309f129f282</id>
    <published>2011-10-07T22:30:13Z</published>
    <updated>2012-06-02T03:30:09Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/06/02/version-0-50-of-bbox-now-available" />
    <author>
      <name>Jay G</name>
      <email>jay_g@beezwax.net</email>
    </author>
    <title type="html">bBox 0.52 Now Available</title>
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="filemaker-utilities" label="filemaker utilities" scheme="http://buzz.beezwax.net/category/filemaker-utilities" />
    <category term="applescript" scheme="http://buzz.beezwax.net/tag/applescript" />
    <category term="bbox" scheme="http://buzz.beezwax.net/tag/bbox" />
    <category term="filemaker" scheme="http://buzz.beezwax.net/tag/filemaker" />
    <category term="in" scheme="http://buzz.beezwax.net/tag/in" />
    <category term="mac" scheme="http://buzz.beezwax.net/tag/mac" />
    <category term="macOS" scheme="http://buzz.beezwax.net/tag/macos" />
    <category term="plug" scheme="http://buzz.beezwax.net/tag/plug" />
    <category term="python" scheme="http://buzz.beezwax.net/tag/python" />
    <category term="ruby" scheme="http://buzz.beezwax.net/tag/ruby" />
    <category term="scripting" scheme="http://buzz.beezwax.net/tag/scripting" />
    <category term="shell" scheme="http://buzz.beezwax.net/tag/shell" />
    <content type="html">&lt;p&gt;
	A new version of our &lt;a href="http://www.beezwax.net/bbox"&gt;free bBox FileMaker plug-in&lt;/a&gt; is now available.&lt;/p&gt;
&lt;p&gt;
One change in this release is a new option for the bbox_EvaluateList function that allows treating a string as an array of chars. Here's an example of what this expression and its result might look like:
&lt;pre&gt;bBox_EvaluateList (&amp;quot;abc&amp;quot;; "$i &amp; \": \" &amp; $v&amp;quot;; "")&lt;/pre&gt;
&lt;pre&gt;	1: a
	2: b
	3: c&lt;/pre&gt;
&lt;p&gt;
&lt;p&gt;
	This release also includes a new "intel" version of the plug-in. The primary reason for adding this is to provide access to a newer version of the Python API's. The standard "universal" version is linked against Python 2.5, whereas the intel version is linked to Python 2.6. This change does not affect the Ruby interface and has very little effect on any of the other bBox functions.&lt;/p&gt;
&lt;p&gt;
	You can download the latest version of bBox at &lt;a href="http://www.beezwax.net/download/bbox"&gt;http://www.beezwax.net/download/bbox&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;
	Learn more about the bBox plug-in a &lt;a href="http://beezwax.net/bbox"&gt;http://beezwax.net/bbox&lt;/a&gt; and &lt;a href="http://bbox.beezwax.net/"&gt;http://bbox.beezwax.net/&lt;/a&gt; .&lt;/p&gt;


</content>
  </entry>
  <entry>
    <id>urn:uuid:5db06c79-c53d-4a2f-a24b-3d376cf62955</id>
    <published>2012-05-15T21:04:35Z</published>
    <updated>2012-05-15T21:36:29Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/05/15/getting-a-filemaker-labels-text-in-a-conditional-formula" />
    <author>
      <name>simon</name>
      <email>simon_b@beezwax.net</email>
    </author>
    <title type="html">Getting a FileMaker label's text in a conditional formula</title>
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <category term="filemaker-tips" label="filemaker tips" scheme="http://buzz.beezwax.net/category/filemaker-tips" />
    <content type="html">&lt;p&gt;&lt;p&gt;I wanted to do some conditional formatting, such that when a global field had a certain value the label would change its appearance. For example, if my sort column was &amp;#8220;address&amp;#8221;, then I wanted the column header containing the text &amp;#8220;Address&amp;#8221; to highlight.&lt;/p&gt;

&lt;p&gt;&lt;p&gt;I had a hunch that the Self function could help. I tested this by attaching a conditional formula to a label:
&lt;pre&gt;
Let (
   $$n = Self;
   0
)
&lt;/pre&gt;
&lt;p&gt;
&lt;p&gt;Using the Data Viewer in FileMaker Advanced I could see that the label&amp;#8217;s name was then getting &amp;#8220;leaked out&amp;#8221; to the global variable $$n in the conditional statement. So, for my use case above, I could simply write the following:
&lt;pre&gt;
TABLENAME::globalField = Self;
&lt;/pre&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:uuid:87634ae3-d119-4ed9-a1eb-89f1db5e1d30</id>
    <published>2012-05-13T05:41:47Z</published>
    <updated>2012-05-21T20:21:08Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/05/13/using-cocoas-pdfdocument-class-from-filemaker" />
    <author>
      <name>simon</name>
      <email>simon_b@beezwax.net</email>
    </author>
    <title type="html">Using Cocoa's PDFDocument class from FileMaker</title>
    <category term="filemaker" label="filemaker" scheme="http://buzz.beezwax.net/category/filemaker" />
    <content type="html">&lt;p&gt;&lt;p&gt;I&amp;#8217;ve been looking for a way to interface with some Cocoa classes in the Mac OS X API from FileMaker for a while. My initial target was PDFDocument, part of the PDF Kit suite of classes. For more information on Cocoa&amp;#8217;s PDF Kit see here: &lt;a href="https://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/PDFKitGuide/PDFKit_Prog_Intro/PDFKit_Prog_Intro.html"&gt;Introduction to PDF Kit Programming Guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;p&gt;I&amp;#8217;ve had a couple versions of this working for some time, but I could never get anything that worked consistently across the various OS and Python combinations (Python is my default tool of choice for these kinds of things). Changes to both the Cocoa interfaces in Python and the OS architecture kept getting in the way. But I may of finally hit it.&lt;/p&gt;

&lt;p&gt;&lt;p&gt;Below is a Python script I&amp;#8217;m using to test this out. It uses the PyObjC module, which is the more recent method of interfacing Python with Cocoa classes. To make interfacing between Python and FileMaker easier, I&amp;#8217;m also using bBox, a free FileMaker plug-in I wrote that allows integration between FileMaker and Python.&lt;/p&gt;

&lt;p&gt;&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; &lt;span class="include"&gt;sys&lt;/span&gt;, &lt;span class="include"&gt;os&lt;/span&gt;
&lt;span class="keyword"&gt;import&lt;/span&gt; &lt;span class="include"&gt;getopt&lt;/span&gt;
&lt;span class="keyword"&gt;from&lt;/span&gt; &lt;span class="include"&gt;pprint&lt;/span&gt; &lt;span class="keyword"&gt;import&lt;/span&gt; &lt;span class="include"&gt;pprint&lt;/span&gt;
&lt;span class="comment"&gt;#&lt;/span&gt;
&lt;span class="comment"&gt;# For some OS versions we must explicity add the PyObjC path.&lt;/span&gt;
sys.path.append (&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC/&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;)
&lt;span class="comment"&gt;#&lt;/span&gt;
&lt;span class="keyword"&gt;from&lt;/span&gt; &lt;span class="include"&gt;Foundation&lt;/span&gt; &lt;span class="keyword"&gt;import&lt;/span&gt; &lt;span class="include"&gt;&lt;em&gt;&lt;/span&gt;
&lt;span class="keyword"&gt;from&lt;/span&gt; &lt;span class="include"&gt;Quartz&lt;/span&gt; &lt;span class="keyword"&gt;import&lt;/span&gt; &lt;span class="include"&gt;&lt;/em&gt;&lt;/span&gt;
&lt;span class="comment"&gt;#&lt;/span&gt;
&lt;span class="comment"&gt;# Set by the calling FMP script. Path of PDF that we will examine.&lt;/span&gt;
&lt;span class="comment"&gt;# sourcePath&lt;/span&gt;
&lt;span class="comment"&gt;#&lt;/span&gt;
&lt;span class="comment"&gt;# Set by the calling FMP script. Path to store the modified version of PDF.&lt;/span&gt;
&lt;span class="comment"&gt;# destPath&lt;/span&gt;
&lt;span class="comment"&gt;#&lt;/span&gt;
&lt;span class="comment"&gt;# Subroutine that does all the work.&lt;/span&gt;
&lt;span class="comment"&gt;#&lt;/span&gt;
&lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;addAttributes&lt;/span&gt;(filepath,destPath):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;url = NSURL.fileURLWithPath_(filepath)
pdfdoc = PDFDocument.alloc().initWithURL_(url)

attrs = NSMutableDictionary.alloc().initWithDictionary_(pdfdoc.documentAttributes())

&amp;lt;span class="keyword"&amp;gt;print&amp;lt;/span&amp;gt; attrs

attrs[PDFDocumentTitleAttribute] = &amp;lt;span class="string"&amp;gt;&amp;lt;span class="delimiter"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="content"&amp;gt;PDF TITLE&amp;lt;/span&amp;gt;&amp;lt;span class="delimiter"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
attrs[PDFDocumentAuthorAttribute] = &amp;lt;span class="string"&amp;gt;&amp;lt;span class="delimiter"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="content"&amp;gt;A. Author and B. Author&amp;lt;/span&amp;gt;&amp;lt;span class="delimiter"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;

pdfdoc.setDocumentAttributes_(attrs)
pdfdoc.writeToFile_(destPath)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;span class="comment"&gt;#&lt;/span&gt;
&lt;span class="comment"&gt;# Execute the subroutine with the given paths.&lt;/span&gt;
addAttributes (sourcePath, destPath)&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;p&gt;The above script is stored in a FileMaker field. Here&amp;#8217;s the script used in FileMaker to call the Python script:
&lt;pre&gt;
Set Variable [ $py&lt;em&gt;sourcePath; Value:"/Applications/Safari.app/Contents/Resources/SearchMagGlassTemplate~snowleopard.pdf" ] Set Variable [ $py&lt;/em&gt;destPath; Value:"/Users/Shared/bbox&lt;em&gt;version.pdf" ]
Set Variable [ $py&lt;/em&gt;script; Value:bbox pyobjc::pdf&lt;em&gt;attributes&lt;/em&gt;script ]
 #
 # Compile the script &amp;amp; setup context.
Set Variable [ $compile&lt;em&gt;result; Value:bBox&lt;/em&gt;PythonCompile(0; $py&lt;em&gt;script) ] If [ $compile&lt;/em&gt;result â‰  "" ]
Exit Script [ ] End If
 #
Set Variable [ $ignore; Value:bBox&lt;em&gt;PythonSetVar("sourcePath"; "/Applications/Mail.app/Contents/Resources/ActionTemplate.pdf";"s") ] Set Variable [ $ignore; Value:bBox&lt;/em&gt;PythonSetVar("destPath"; "/Users/Shared/bbox&lt;em&gt;version of&lt;/em&gt;pdf&lt;em&gt;file.pdf"; "s") ]
 #
Set Variable [ $execute&lt;/em&gt;result; Value:bBox&lt;em&gt;PythonExecute(0) ]
 #
 # For unknown reasons, should NOT call finalize here in bBox 0.52 and possibly earlier versions, so currently disabled.
// Set Variable [ $ignore; Value:bBox&lt;/em&gt;PythonFinalize ]
 #
Show Custom Dialog [ Title: "Python Result"; Message: $execute_result; Buttons: â€œOKâ€ ]
&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;&lt;p&gt;The key change was adding in the path for PyObjC. This may only be necessary because bBox interfaces with Python using its C based API, so it probably wouldn&amp;#8217;t be necessary in a &amp;#8220;normal&amp;#8221; Python script. Having systems that have Python.org&amp;#8217;s version of Python could also account for the differences I&amp;#8217;ve seen, but bBox is only linked to Apple&amp;#8217;s version of the Python framework so that would be surprising cause for the difference.&lt;/p&gt;

&lt;p&gt;&lt;p&gt;Since I am working on getting a new version of bBox out I&amp;#8217;ll hopefully get a bit more clarity on this issue and maybe a few more examples as I test out the new version.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:uuid:d1ac851b-1705-4b92-add8-2a956640c695</id>
    <published>2012-05-08T23:25:26Z</published>
    <updated>2012-05-09T20:56:55Z</updated>
    <link rel="alternate" type="text/html" href="http://buzz.beezwax.net/2012/05/09/getting-a-file-path-easily-in-os-x" />
    <author>
      <name>simon</name>
      <email>simon_b@beezwax.net</email>
    </author>
    <title type="html">Getting a File Path easily in OS X</title>
    <content type="html">&lt;p&gt;It comes up fairly frequently for me that I need the path to a file I have selected in the Finder. With some futzing, you can already do this. Some techniques are&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;drag file to Terminal window&lt;/li&gt;
    &lt;li&gt;copy path from Get Info dialog&lt;/li&gt;
    &lt;li&gt;drag file to TextEdit window&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;But I was hoping for something a little better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Applet in Toolbar&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first choice is a revised version of a simple AppleScript applet I wrote quite a while ago. You can download the applet here: &lt;a href="http://buzz.beezwax.net/files/Copy_Path.app.zip"&gt;Copy Path.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unzip if needed, and save the applet somewhere safe. Then drag it into a Finder window&amp;#8217;s Toolbar, so that the applet icon is now on all your Finder windows:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://buzz.beezwax.net/files/Copy_Path_Toolbar.png" alt="Screen shot showing applet in Finder window" /&gt;&lt;/p&gt;

&lt;p&gt;To use, select one or more files in the Finder, then click on the applet icon in any Finder window (hold the Shift key if you&amp;#8217;d like AppleScript/OS 9 style file paths). You can now paste the path text wherever it&amp;#8217;s needed.&lt;/p&gt;

&lt;p&gt;One interesting side note about the AppleScript used here. It turns out to be difficult to impossible to get the state of the modifier keys using just AppleScript. Creating a small command in C was required, which I then call with AppleScript&amp;#8217;s &lt;strong&gt;do shell script&lt;/strong&gt; command. I probably could&amp;#8217;ve also built the applet using Xcode and AppleScriptObjC, but compiling the command seemed more straightforward, at least until I learn more about AppleScriptObjC.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service Method&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another approach, and the one I think I like slightly better when using Lion (10.7), was to create a Service in Automator. This was dead simple, but I have a ready version for you here: &lt;a href="http://buzz.beezwax.net/files/Copy_Path.workflow.zip"&gt;Copy Path.workflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To use, first copy the .workflow file into your Library/Services folder, and then double-click to open. You can immediately close it. Select one or more files or folders in the Finder, then choose &lt;strong&gt;Finder-&gt;Services-&gt;Copy Path&lt;/strong&gt;.  Here&amp;#8217;s an example of it being used:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://buzz.beezwax.net/files/Copy_Path_Service.png" alt="Using the Copy Path service" /&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, in Snow Leopard (10.6) this does not work as well. You can only get the path to a file (not a folder), and it uses the older AppleScript/OS 9 convention for path strings.&lt;/p&gt;</content>
  </entry>
</feed>
