Web-Based Tagged Container Publishing

Here are the scripts and functions that make this publishing example possible.

The left column contains the decoded scripts and functions that process the shapes in the OmniGraffle document.

The right column contains the scripts and functions embedded in the webpage.

Decoded Function for Tagging Selected Solid With Metadata

This function is designed to take an argument that is an array of input data, namely the item’s user data key value (SKU), the user data value that is a URL to the larger image file on the server, and the shapes note string.

By wrapping the script in a function with an single argument, it can be “user-approved” during its first execution prompt so that following executions of the script wil be un-prompted. See the section on Script URLs regarding security procedures.

Tag the Selected Shape


(function setMetadataForItem(args){ itemSKUStr = args[0]; itemURLStr = args[1]; itemNotes = args[2]; slds = document.windows[0].selection.solids; if (slds.length === 1){ slds[0].setUserData('SKU', itemSKUStr); slds[0].setUserData('URL', itemURLStr); slds[0].notes = itemNotes; } else { alertTitle = 'SELECTION ERROR'; alertMessage = 'Please select a single solid graphic.'; new Alert(alertTitle, alertMessage).show(); } })(argument)

Decoded Script for Importing Images Into Tagged Containers

This script reads the value of the URL user data key to derive the url to the image file on the server. It then uses the Omni Automation FetchRequest API to asynchronously download and insert the linked image file.

Import Images into Tagged Shapes


(async () => { try { cnvs = document.windows[0].selection.canvas shapez = cnvs.graphics.filter(graphk => { return graphk instanceof Shape }) if(shapez.length === 0){ throw { name: "Missing Items", message: "This canvas does not contain any shapes." } } const dataKey = 'SKU' const urlKey = 'URL' for (shape of shapez){ const shapeDataKey = shape.userData[dataKey] if(shapeDataKey){ const shapeURLStr = shape.userData[urlKey] if(shapeURLStr){ request = URL.FetchRequest.fromString(shapeURLStr) request.method = 'GET' request.cache = "no-cache" response = await request.fetch() responseCode = response.statusCode console.log(shapeDataKey, responseCode) if(responseCode >= 200 && responseCode < 300){ shape.image = addImage(response.bodyData) } else { console.error(shapeDataKey, shapeURLStr) } } } } } catch(err){ new Alert(err.name, err.message).show() } })();

Decoded Notes Placement Script

This script prompts the user for the placement of the notes extracted from the selected shape’s metadata. THe script then replicates the selected shape to the indicated postion and fills it with the note text.

Notes Placement


(async () => { try { // default settings defaultOffset = 12 defaultTextSize = 14 // prompt for placement location alertTitle = "Notes Placement" alertMessage = "Should the notes be placed to the left, right, or below the selected graphic solid?" alert = new Alert(alertTitle, alertMessage) alert.addOption("Right") alert.addOption("Left") alert.addOption("Below") buttonIndex = await alert.show() cnvs = document.windows[0].selection.canvas slds = document.windows[0].selection.solids shapez = document.windows[0].selection.solids switch(buttonIndex){ case 0: for(shape of shapez){ sName = shape.name sNotes = shape.notes cRect = shape.geometry nRect = new Rect(cRect.maxX + defaultOffset, cRect.minY, cRect.width, cRect.height) newShape = cnvs.addShape('Rectangle',nRect) newShape.text = sNotes newShape.name = sName newShape.shadowColor = null newShape.strokeType = null newShape.fillType = null newShape.autosizing = TextAutosizing.Overflow newShape.textHorizontalAlignment = HorizontalTextAlignment.Left newShape.textHorizontalPadding = 0 newShape.textVerticalPlacement = VerticalTextPlacement.Top newShape.textVerticalPadding = 0 newShape.textSize = defaultTextSize } break; case 1: for(shape of shapez){ sName = shape.name sNotes = shape.notes cRect = shape.geometry nRect = new Rect(cRect.minX - defaultOffset - cRect.width, cRect.minY, cRect.width, cRect.height) newShape = cnvs.addShape('Rectangle',nRect) newShape.text = sNotes newShape.name = sName newShape.shadowColor = null newShape.strokeType = null newShape.fillType = null newShape.autosizing = TextAutosizing.Overflow newShape.textHorizontalAlignment = HorizontalTextAlignment.Left newShape.textHorizontalPadding = 0 newShape.textVerticalPlacement = VerticalTextPlacement.Top newShape.textVerticalPadding = 0 newShape.textSize = defaultTextSize } break; case 2: for(shape of shapez){ sName = shape.name sNotes = shape.notes cRect = shape.geometry nRect = new Rect(cRect.minX, cRect.maxY + defaultOffset, cRect.width, cRect.height) aShape = cnvs.addShape('Rectangle',nRect) aShape.text = sNotes aShape.name = sName aShape.shadowColor = null aShape.strokeType = null aShape.fillType = null aShape.autosizing = TextAutosizing.Overflow aShape.textHorizontalAlignment = HorizontalTextAlignment.Left aShape.textHorizontalPadding = 0 aShape.textVerticalPlacement = VerticalTextPlacement.Top aShape.textVerticalPadding = 0 aShape.textSize = defaultTextSize } break; default: console.log("DEFAULT OPTION") } } catch(err){ new Alert(err.name, err.message).show() } })();

Scripts Embedded in Webpage

This function encodes the argument data (product SKU and Description) for the clicked or tapped product image. The argument data is embedded in the webpage with IDs that correspond the the SKU value of the item.

Encode the Function Argument


function encodeArgumentForURL(argumentData){ var encodedArgument = encodeURIComponent(argumentData); return "&arg=" + encodedArgument; }

This function appends the encoded argument data to the encoded tagging function. Then it appends the appropriate Omni Automation schema for OmniGraffle and returns the resulting Omni Automation Script URL.

Append Encoded Function with Encoded Argument


function combineScriptAndArgument(encodedArgument){ // the setMetadataForItem(args) function encoded already encodedFunction = "omnigraffle://localhost/omnijs-run?script=%28function%20setMetadataForItem%28args%29%7B%0A%09itemSKUStr%20%3D%20args%5B0%5D%3B%0A%09itemURLStr%20%3D%20args%5B1%5D%3B%0A%09itemNotes%20%3D%20args%5B2%5D%3B%0A%09slds%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Esolids%3B%0A%09if%20%28slds%2Elength%20%3D%3D%3D%201%29%7B%0A%09%09slds%5B0%5D%2EsetUserData%28%27SKU%27%2C%20itemSKUStr%29%3B%0A%09%09slds%5B0%5D%2EsetUserData%28%27URL%27%2C%20itemURLStr%29%3B%0A%09%09slds%5B0%5D%2Enotes%20%3D%20itemNotes%3B%0A%09%7D%20else%20%7B%0A%09%09alertTitle%20%3D%20%27SELECTION%20ERROR%27%3B%0A%09%09alertMessage%20%3D%20%27Please%20select%20a%20single%20solid%20graphic%2E%27%3B%0A%09%09new%20Alert%28alertTitle%2C%20alertMessage%29%2Eshow%28%29%3B%0A%09%7D%0A%7D%29%28argument%29" // append the encoded script argument (in this case and array) scriptURL = encodedFunction + encodedArgument return scriptURL }

This embedded function extracts the relevant product data from the hidden DIVs tagged with the SKU of the clicked or tapped product, creates the URL to the image on the server, encodes the function argument, appends the argument to the encoded tagging function, creates the Omni Automation Script URL targeting OmniGraffle, and then executes the script URL!

Create and Execute Omni Automation Script URL


function createExecuteScriptURL(key, keyValue){ if (confirm('Click|Tap OK to tag the selected OmniGraffle graphic with this data key and data value:\n\n\t' + key + ':' + keyValue)){ // locate the description element auxElement = document.getElementById(keyValue); // get the key name for the description element auxKeyName = auxElement.getAttribute("name"); // get the description content notesValue = auxElement.innerHTML; // construct the URL to the image file imageURL = "https://omni-automation.com/omnigraffle/tagged-import/gfx/"; imageURL = imageURL + keyValue + ".jpg"; // create the script argument array argumentData = JSON.stringify([keyValue, imageURL, notesValue]) // encode the argument encodedArgument = encodeArgumentForURL(argumentData) // combine the script and the argument scriptURL = combineScriptAndArgument(encodedArgument) // execute the Omni Automation script url window.location = scriptURL; } }

This function creates and executes the Omni Automation Script URL for importing images into all tagged shapes. It is triggered by a button on the webpage.

Import Images into All Tagged Shapes


function importToTaggedGraphics(){ if (confirm('Click|Tap OK to import images from this webpage into the tagged graphics in the front OmniGraffle document.')){ const scriptCode = '%28async%20%28%29%20%3D%3E%20%7B%0A%09try%20%7B%09%09%0A%09%09cnvs%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Ecanvas%0A%09%09shapez%20%3D%20cnvs%2Egraphics%2Efilter%28graphk%20%3D%3E%20%7B%0A%09%09%09return%20graphk%20instanceof%20Shape%0A%09%09%7D%29%0A%09%09if%28shapez%2Elength%20%3D%3D%3D%200%29%7B%0A%09%09%09throw%20%7B%0A%09%09%09%09name%3A%20%22Missing%20Items%22%2C%0A%09%09%09%09message%3A%20%22This%20canvas%20does%20not%20contain%20any%20shapes%2E%22%0A%09%09%09%7D%0A%09%09%7D%0A%09%09%0A%09%09const%20dataKey%20%3D%20%27SKU%27%0A%09%09const%20urlKey%20%3D%20%27URL%27%09%09%09%09%09%0A%09%09%0A%09%09for%20%28shape%20of%20shapez%29%7B%0A%09%09%09const%20shapeDataKey%20%3D%20shape%2EuserData%5BdataKey%5D%0A%09%09%09if%28shapeDataKey%29%7B%0A%09%09%09%09const%20shapeURLStr%20%3D%20shape%2EuserData%5BurlKey%5D%0A%09%09%09%09if%28shapeURLStr%29%7B%0A%09%09%09%09%09request%20%3D%20URL%2EFetchRequest%2EfromString%28shapeURLStr%29%0A%09%09%09%09%09request%2Emethod%20%3D%20%27GET%27%0A%09%09%09%09%09request%2Ecache%20%3D%20%22no%2Dcache%22%0A%09%09%09%09%09response%20%3D%20await%20request%2Efetch%28%29%0A%09%09%09%09%09responseCode%20%3D%20response%2EstatusCode%0A%09%09%09%09%09console%2Elog%28shapeDataKey%2C%20responseCode%29%0A%09%09%09%09%09if%28responseCode%20%3E%3D%20200%20%26%26%20responseCode%20%3C%20300%29%7B%0A%09%09%09%09%09%09shape%2Eimage%20%3D%20addImage%28response%2EbodyData%29%0A%09%09%09%09%09%7D%20else%20%7B%0A%09%09%09%09%09%09console%2Eerror%28shapeDataKey%2C%20shapeURLStr%29%0A%09%09%09%09%09%7D%0A%09%09%09%09%7D%0A%09%09%09%7D%0A%09%09%7D%0A%09%7D%0A%09catch%28err%29%7B%0A%09%09new%20Alert%28err%2Ename%2C%20err%2Emessage%29%2Eshow%28%29%0A%09%7D%0A%7D%29%28%29%3B'; const targetURL = "omnigraffle:///omnijs-run?script=" + scriptCode; window.location = targetURL; }; }

This function creates and executes the Omni Automation Script URL for importing images into only the selected tagged shapes. It is triggered by a button on the webpage.

Import Images into Selected Tagged Shapes


function importToSelectedTaggedGraphics(){ if (confirm('Click|Tap OK to import images from this webpage into the tagged graphics in the front OmniGraffle document.')){ const scriptCode = '%28async%20%28%29%20%3D%3E%20%7B%0A%09try%20%7B%09%09%0A%09%09cnvs%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Ecanvas%0A%09%09shapez%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Esolids%0A%09%09if%28shapez%2Elength%20%3D%3D%3D%200%29%7B%0A%09%09%09throw%20%7B%0A%09%09%09%09name%3A%20%22Missing%20Items%22%2C%0A%09%09%09%09message%3A%20%22Select%20the%20tagged%20shapes%20to%20import%20images%20into%2E%22%0A%09%09%09%7D%0A%09%09%7D%0A%09%09%0A%09%09const%20dataKey%20%3D%20%27SKU%27%0A%09%09const%20urlKey%20%3D%20%27URL%27%09%09%09%09%09%0A%09%09%0A%09%09for%20%28shape%20of%20shapez%29%7B%0A%09%09%09const%20shapeDataKey%20%3D%20shape%2EuserData%5BdataKey%5D%0A%09%09%09if%28shapeDataKey%29%7B%0A%09%09%09%09const%20shapeURLStr%20%3D%20shape%2EuserData%5BurlKey%5D%0A%09%09%09%09if%28shapeURLStr%29%7B%0A%09%09%09%09%09request%20%3D%20URL%2EFetchRequest%2EfromString%28shapeURLStr%29%0A%09%09%09%09%09request%2Emethod%20%3D%20%27GET%27%0A%09%09%09%09%09request%2Ecache%20%3D%20%22no%2Dcache%22%0A%09%09%09%09%09response%20%3D%20await%20request%2Efetch%28%29%0A%09%09%09%09%09responseCode%20%3D%20response%2EstatusCode%0A%09%09%09%09%09console%2Elog%28shapeDataKey%2C%20responseCode%29%0A%09%09%09%09%09if%28responseCode%20%3E%3D%20200%20%26%26%20responseCode%20%3C%20300%29%7B%0A%09%09%09%09%09%09shape%2Eimage%20%3D%20addImage%28response%2EbodyData%29%0A%09%09%09%09%09%7D%20else%20%7B%0A%09%09%09%09%09%09console%2Eerror%28shapeDataKey%2C%20shapeURLStr%29%0A%09%09%09%09%09%7D%0A%09%09%09%09%7D%0A%09%09%09%7D%0A%09%09%7D%0A%09%7D%0A%09catch%28err%29%7B%0A%09%09new%20Alert%28err%2Ename%2C%20err%2Emessage%29%2Eshow%28%29%0A%09%7D%0A%7D%29%28%29%3B'; const targetURL = "omnigraffle:///omnijs-run?script=" + scriptCode; window.location = targetURL; }; }

This function creates and executes the Omni Automation Script URL for placing the notes of only the selected tagged shapes. It is triggered by a button on the webpage.

Place the Notes


function placeNotes(){ if (confirm('Extract and place the image notes of the selected tagged OmniGraffle image?')){ const scriptCode = '%28async%20%28%29%20%3D%3E%20%7B%0A%09try%20%7B%0A%09%09%2F%2F%20default%20settings%0A%09%09defaultOffset%20%3D%2012%0A%09%09defaultTextSize%20%3D%2014%0A%09%09%0A%09%09%2F%2F%20prompt%20for%20placement%20location%0A%09%09alertTitle%20%3D%20%22Notes%20Placement%22%0A%09%09alertMessage%20%3D%20%22Should%20the%20notes%20be%20placed%20to%20the%20left%2C%20right%2C%20or%20below%20the%20selected%20graphic%20solid%3F%22%0A%09%09alert%20%3D%20new%20Alert%28alertTitle%2C%20alertMessage%29%0A%09%09alert%2EaddOption%28%22Right%22%29%0A%09%09alert%2EaddOption%28%22Left%22%29%0A%09%09alert%2EaddOption%28%22Below%22%29%0A%09%09buttonIndex%20%3D%20await%20alert%2Eshow%28%29%0A%09%09%0A%09%09cnvs%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Ecanvas%0A%09%09slds%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Esolids%0A%09%09shapez%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Esolids%0A%09%09%0A%09%09switch%28buttonIndex%29%7B%0A%09%09%09case%200%3A%0A%09%09%09%09for%28shape%20of%20shapez%29%7B%0A%09%09%09%09%09sName%20%3D%20shape%2Ename%0A%09%09%09%09%09sNotes%20%3D%20shape%2Enotes%0A%09%09%09%09%09cRect%20%3D%20shape%2Egeometry%0A%09%09%09%09%09nRect%20%3D%20new%20Rect%28cRect%2EmaxX%20%2B%20defaultOffset%2C%20cRect%2EminY%2C%20cRect%2Ewidth%2C%20cRect%2Eheight%29%0A%09%09%09%09%09newShape%20%3D%20cnvs%2EaddShape%28%27Rectangle%27%2CnRect%29%0A%09%09%09%09%09newShape%2Etext%20%3D%20sNotes%0A%09%09%09%09%09newShape%2Ename%20%3D%20sName%0A%09%09%09%09%09newShape%2EshadowColor%20%3D%20null%0A%09%09%09%09%09newShape%2EstrokeType%20%3D%20null%0A%09%09%09%09%09newShape%2EfillType%20%3D%20null%0A%09%09%09%09%09newShape%2Eautosizing%20%3D%20TextAutosizing%2EOverflow%0A%09%09%09%09%09newShape%2EtextHorizontalAlignment%20%3D%20HorizontalTextAlignment%2ELeft%0A%09%09%09%09%09newShape%2EtextHorizontalPadding%20%3D%200%0A%09%09%09%09%09newShape%2EtextVerticalPlacement%20%3D%20VerticalTextPlacement%2ETop%0A%09%09%09%09%09newShape%2EtextVerticalPadding%20%3D%200%0A%09%09%09%09%09newShape%2EtextSize%20%3D%20defaultTextSize%0A%09%09%09%09%7D%0A%09%09%09%09break%3B%0A%09%09%09case%201%3A%0A%09%09%09%09for%28shape%20of%20shapez%29%7B%0A%09%09%09%09%09sName%20%3D%20shape%2Ename%0A%09%09%09%09%09sNotes%20%3D%20shape%2Enotes%0A%09%09%09%09%09cRect%20%3D%20shape%2Egeometry%0A%09%09%09%09%09nRect%20%3D%20new%20Rect%28cRect%2EminX%20%2D%20defaultOffset%20%2D%20cRect%2Ewidth%2C%20cRect%2EminY%2C%20cRect%2Ewidth%2C%20cRect%2Eheight%29%0A%09%09%09%09%09newShape%20%3D%20cnvs%2EaddShape%28%27Rectangle%27%2CnRect%29%0A%09%09%09%09%09newShape%2Etext%20%3D%20sNotes%0A%09%09%09%09%09newShape%2Ename%20%3D%20sName%0A%09%09%09%09%09newShape%2EshadowColor%20%3D%20null%0A%09%09%09%09%09newShape%2EstrokeType%20%3D%20null%0A%09%09%09%09%09newShape%2EfillType%20%3D%20null%0A%09%09%09%09%09newShape%2Eautosizing%20%3D%20TextAutosizing%2EOverflow%0A%09%09%09%09%09newShape%2EtextHorizontalAlignment%20%3D%20HorizontalTextAlignment%2ELeft%0A%09%09%09%09%09newShape%2EtextHorizontalPadding%20%3D%200%0A%09%09%09%09%09newShape%2EtextVerticalPlacement%20%3D%20VerticalTextPlacement%2ETop%0A%09%09%09%09%09newShape%2EtextVerticalPadding%20%3D%200%0A%09%09%09%09%09newShape%2EtextSize%20%3D%20defaultTextSize%0A%09%09%09%09%7D%0A%09%09%09%09break%3B%0A%09%09%09case%202%3A%0A%09%09%09%09for%28shape%20of%20shapez%29%7B%0A%09%09%09%09%09sName%20%3D%20shape%2Ename%0A%09%09%09%09%09sNotes%20%3D%20shape%2Enotes%0A%09%09%09%09%09cRect%20%3D%20shape%2Egeometry%0A%09%09%09%09%09nRect%20%3D%20new%20Rect%28cRect%2EminX%2C%20cRect%2EmaxY%20%2B%20defaultOffset%2C%20cRect%2Ewidth%2C%20cRect%2Eheight%29%0A%09%09%09%09%09aShape%20%3D%20cnvs%2EaddShape%28%27Rectangle%27%2CnRect%29%0A%09%09%09%09%09aShape%2Etext%20%3D%20sNotes%0A%09%09%09%09%09aShape%2Ename%20%3D%20sName%0A%09%09%09%09%09aShape%2EshadowColor%20%3D%20null%0A%09%09%09%09%09aShape%2EstrokeType%20%3D%20null%0A%09%09%09%09%09aShape%2EfillType%20%3D%20null%0A%09%09%09%09%09aShape%2Eautosizing%20%3D%20TextAutosizing%2EOverflow%0A%09%09%09%09%09aShape%2EtextHorizontalAlignment%20%3D%20HorizontalTextAlignment%2ELeft%0A%09%09%09%09%09aShape%2EtextHorizontalPadding%20%3D%200%0A%09%09%09%09%09aShape%2EtextVerticalPlacement%20%3D%20VerticalTextPlacement%2ETop%0A%09%09%09%09%09aShape%2EtextVerticalPadding%20%3D%200%0A%09%09%09%09%09aShape%2EtextSize%20%3D%20defaultTextSize%0A%09%09%09%09%7D%0A%09%09%09%09break%3B%0A%09%09%09default%3A%0A%09%09%09%09console%2Elog%28%22DEFAULT%20OPTION%22%29%0A%09%09%7D%0A%09%7D%0A%09catch%28err%29%7B%0A%09%09new%20Alert%28err%2Ename%2C%20err%2Emessage%29%2Eshow%28%29%0A%09%7D%0A%7D%29%28%29%3B'; const targetURL = "omnigraffle:///omnijs-run?script=" + scriptCode; window.location = targetURL; } }

Functions for Touch Interfaces

These function ensure that taps work like clicks.

Touch Interfaces


function keyTouched(e,aKey){ e.preventDefault(); //e.target.onclick(); aKey.style.opacity = 0.5; }
Touch Interfaces


function keyUnTouched(aKey,tagName,tagValue){ aKey.style.opacity = 1.0; createExecuteScriptURL(tagName, tagValue); }