├── .DS_Store ├── .eslintrc.js ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── README.md ├── index.html ├── jsDev.fmp12 ├── package-lock.json ├── package.json ├── scripts ├── generate-script-steps.js ├── reload-dev.js ├── start-fm-dev.js └── upload.js ├── src ├── index.js └── style.css └── widget.config.js /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/integrating-magic/js-dev-environment/6ccc20c67fd4c437e1aae4ecc2d0ed7c4742942f/.DS_Store -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | }, 6 | extends: ["eslint:recommended", "prettier"], 7 | parserOptions: { 8 | ecmaVersion: "latest", 9 | sourceType: "module", 10 | }, 11 | rules: { 12 | "no-var": "warn", 13 | "no-undef": "off", 14 | "no-unused-vars": "warn", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode 3 | dist 4 | import.log 5 | .parcel-cache 6 | .DS_Store' -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode 3 | dist 4 | import.log 5 | .parcel-cache -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "bracketSpacing": true, 4 | "endOfLine": "lf", 5 | "htmlWhitespaceSensitivity": "css", 6 | "insertPragma": false, 7 | "jsxBracketSameLine": false, 8 | "jsxSingleQuote": false, 9 | "printWidth": 80, 10 | "proseWrap": "preserve", 11 | "quoteProps": "as-needed", 12 | "requirePragma": false, 13 | "semi": true, 14 | "singleQuote": false, 15 | "tabWidth": 2, 16 | "trailingComma": "es5", 17 | "useTabs": false, 18 | "vueIndentScriptAndStyle": false, 19 | "parser": "babel" 20 | } 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JS Dev Kit for FileMaker Developers 2 | 3 | *Develop, Render, and Deploy JavaScript for a FileMaker App* 4 | 5 | # This Kit 6 | ## What it does 7 | This environment allows a FileMaker developer to start coding their widget and see the results right away in a FileMaker file. Once done developing, the can be inlined and pushed to the FileMaker file for use offline. 8 |
9 | It's a template file, so you can use to start other projects. 10 | ## Consists of 11 | - A repository template on Github 12 | - A basic html / JS set up. 13 | - package.json file for install 14 | - A FileMaker file to show the widget rendered 15 | - Scripts to build and upload the inlined code to FileMaker 16 | ## TO GET STARTED Using this file 17 | 1. `npm install` 18 | 2. `npm start` 19 | 3. Open the jsDev.fmp12 file. 20 | 4. Allow it to work in Dev mode. 21 | 22 | At this point you should see the web viewer on the layout load up with the HTML and JavaScript here. Edit the JavaScript or the HTML and you'll see the render in the web viewer update. 23 | 24 | ## Use this kit 25 | Now you're ready to use this kit to create awesome JS widgets. 26 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | JSDev 9 | 10 | 11 |

Alright. You're set.

12 |

Now build something amazing!

13 |

JS in FM is amazing

14 | 15 | 16 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /jsDev.fmp12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/integrating-magic/js-dev-environment/6ccc20c67fd4c437e1aae4ecc2d0ed7c4742942f/jsDev.fmp12 -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-dev-env", 3 | "version": "2.1.0", 4 | "author": "jeremy@integratingmagic.io", 5 | "license": "MIT", 6 | "description": "a generic development environment for developing JS in FileMaker", 7 | "scripts": { 8 | "start": "parcel index.html --no-source-maps", 9 | "reload": "node ./scripts/reload-dev", 10 | "deploy-to-fm": "npm run build && npm run upload", 11 | "build": "parcel build index.html", 12 | "upload": "node ./scripts/upload", 13 | "generate-script-steps": "node ./scripts/generate-script-steps", 14 | "clear-cache": "rm -rf .parcel-cache dist", 15 | "reset-dev": "npm run clear-cache && npm run start", 16 | "start-fm-dev": "node ./scripts/start-fm-dev", 17 | "open-dev-browser": "open http://localhost:1234" 18 | }, 19 | "browserslist": "> 0.5%, last 2 versions, not dead", 20 | "devDependencies": { 21 | "eslint": "^8.16.0", 22 | "eslint-config-prettier": "^8.5.0", 23 | "open": "^8.2.1", 24 | "parcel": "^2.8.1", 25 | "prettier": "2.6.2" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /scripts/generate-script-steps.js: -------------------------------------------------------------------------------- 1 | const { exec, spawn } = require("child_process"); 2 | 3 | function pbcopy(data) { 4 | const proc = spawn("pbcopy"); 5 | proc.stdin.write(data); 6 | proc.stdin.end(); 7 | } 8 | 9 | function convertClipboardToFM() { 10 | exec( 11 | "osascript -e 'set the clipboard to (do shell script \"pbpaste\" as «class XMSS»)'", 12 | (error) => { 13 | if (error) { 14 | console.error(`exec error: ${error}`); 15 | return; 16 | } 17 | } 18 | ); 19 | } 20 | 21 | const xml = `$callbackName$promiseID$parameterAdd your logic here to set result data to return to the webviewer.$resultChange this to your webviewer name$webviewer

`; 22 | 23 | pbcopy(xml); 24 | console.log("\x1b[34mXML copied to clipboard.\x1b[0m"); 25 | convertClipboardToFM(); 26 | console.log( 27 | "\x1b[32mConverted to script steps. Go paste it in your FM script!\x1b[0m" 28 | ); 29 | -------------------------------------------------------------------------------- /scripts/reload-dev.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const config = require("../widget.config"); 3 | 4 | const { widgetName, reloadScript, file, server } = config; 5 | 6 | const open = require("open"); 7 | const path = require("path"); 8 | 9 | const fileUrl = `fmp://${server}/${file}?script=${reloadScript}`; 10 | 11 | // const thePath = path.join(__dirname, "../", "dist", "index.html"); 12 | // const params = { widgetName, thePath }; 13 | const url = fileUrl; 14 | open(url); 15 | -------------------------------------------------------------------------------- /scripts/start-fm-dev.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const config = require("../widget.config"); 3 | 4 | const { widgetName, startDevScript, file, server } = config; 5 | 6 | const open = require("open"); 7 | const path = require("path"); 8 | 9 | const fileUrl = `fmp://${server}/${file}?script=${startDevScript}¶m=turnOn`; 10 | 11 | // const thePath = path.join(__dirname, "../", "dist", "index.html"); 12 | // const params = { widgetName, thePath }; 13 | const url = fileUrl; 14 | open(url); 15 | -------------------------------------------------------------------------------- /scripts/upload.js: -------------------------------------------------------------------------------- 1 | const config = require("../widget.config"); 2 | 3 | const { widgetName, uploadScript, file, server } = config; 4 | 5 | console.log(widgetName, uploadScript, file, server); 6 | const open = require("open"); 7 | const path = require("path"); 8 | 9 | const fileUrl = `fmp://${server}/${file}?script=${uploadScript}¶m=`; 10 | 11 | const thePath = path.join(__dirname, "../", "dist", "index.html"); 12 | const params = { widgetName, thePath }; 13 | const url = fileUrl + encodeURIComponent(JSON.stringify(params)); 14 | open(url); 15 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | //The first function. Remove this. 2 | const btn = document.querySelector("button"); 3 | console.log("Hello"); 4 | 5 | btn.onclick = function () { 6 | console.log("You ran some JavaScript"); 7 | alert("You ran some JavaScript"); 8 | }; -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | -webkit-font-smoothing: antialiased; 3 | -moz-osx-font-smoothing: grayscale; 4 | font-family: 'Arial', sans-serif; 5 | font-size: 16px; 6 | line-height: 1; 7 | color: #000; 8 | background-color: #fff; 9 | margin: 10; 10 | overflow: hidden; 11 | } 12 | 13 | p{ 14 | color:#282828; 15 | font-size: 16px; 16 | } 17 | 18 | 19 | h1 { 20 | background-color:#006690; 21 | color: #fff; 22 | font-size: 22px; 23 | font-weight: 400; 24 | line-height: 1.2; 25 | margin: 0 0 10px; 26 | } 27 | 28 | .tintedBlackLeft { 29 | background-color:#00000033; 30 | color: #fff; 31 | text-transform: uppercase; 32 | font-size: 12px; 33 | font-weight: 400; 34 | line-height: 1.2; 35 | padding:11px 11px 11px 0px; 36 | } 37 | 38 | button { 39 | padding: 5px 9px 5px 9px; 40 | border-radius: 3px; 41 | font-size: 18px; 42 | border: 1px solid #0091CE; 43 | background-color: #0091CE; 44 | color: #fff; 45 | } -------------------------------------------------------------------------------- /widget.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | widgetName: "jsDev", 3 | server: "$", 4 | file: "jsDev", 5 | uploadScript: "UploadToHTML", 6 | reloadScript: "Load Widget", 7 | startDevScript: "Set to Dev Mode", 8 | }; 9 | --------------------------------------------------------------------------------