CINXE.COM

Introducing Props2Js - Human Who Codes

<!DOCTYPE html> <html lang="en"> <head> <script async src="https://www.googletagmanager.com/gtag/js?id=G-DF11Y9MFRM"></script> <script>(function(){const analytics_id = "G-DF11Y9MFRM"; window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', analytics_id); })();</script> <!-- Global Metadata --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="icon" type="image/png" href="/favicon.png"> <meta name="generator" content="Astro v2.6.5"> <meta name="ttw" content="cfanq3r"> <!-- Primary Meta Tags --> <title>Introducing Props2Js - Human Who Codes</title> <meta name="title" content="Introducing Props2Js - Human Who Codes"> <meta name="description" content="The Official Web Site of Nicholas C. Zakas"> <!-- Canonical URLs --> <link rel="canonical" href="https://humanwhocodes.com/blog/2011/12/20/introducing-props2js/"> <!-- Feeds --> <link rel="alternate" type="application/rss+xml" title="Human Who Codes - Blog" href="https://humanwhocodes.com/feeds/blog.xml"> <link rel="alternate" type="application/json" title="Human Who Codes - Blog" href="https://humanwhocodes.com/feeds/blog.json"> <link rel="alternate" type="application/rss+xml" title="Human Who Codes - Snippets" href="https://humanwhocodes.com/feeds/snippets.xml"> <link rel="alternate" type="application/json" title="Human Who Codes - Snippets" href="https://humanwhocodes.com/feeds/snippets.json"> <link rel="alternate" type="application/rss+xml" title="Human Who Codes - All" href="https://humanwhocodes.com/feeds/all.xml"> <link rel="alternate" type="application/json" title="Human Who Codes - All" href="https://humanwhocodes.com/feeds/all.json"> <!-- Open Graph / Facebook --> <meta property="og:type" content="website"> <meta property="og:url" content="https://humanwhocodes.com/blog/2011/12/20/introducing-props2js/"> <meta property="og:title" content="Introducing Props2Js - Human Who Codes"> <meta property="og:description" content="The Official Web Site of Nicholas C. Zakas"> <meta property="og:image" content="https://humanwhocodes.com/favicon.png"> <!-- Twitter --> <meta property="twitter:site" content="@humanwhocodes"> <meta property="twitter:creator" content="@slicknet"> <meta property="twitter:card" content="summary_large_image"> <meta property="twitter:url" content="https://humanwhocodes.com/blog/2011/12/20/introducing-props2js/"> <meta property="twitter:title" content="Introducing Props2Js - Human Who Codes"> <meta property="twitter:description" content="The Official Web Site of Nicholas C. Zakas"> <meta property="twitter:image" content="https://humanwhocodes.com/favicon.png"> <link rel="stylesheet" href="/_astro/_...slug_.c4d39581.css" /> <link rel="stylesheet" href="/_astro/about.7a05c7cf.css" /></head> <body itemscope itemtype="http://schema.org/WebPage"> <header class="highlight-background"> <nav role="navigation" class="page-width center center-text gutters collapsible-corners"> <h1 class="no-margin"><a href="/"><img src="/_astro/logo-full-web.fbbbde18.svg" alt="Human Who Codes" height="50"></a></h1> <ul class="inline-list inline-spaced-list center-text-on-small-screens overflow-x-scroll all-caps bold"> <li class="hide-offscreen"><a href="#content">Skip to content</a></li> <li><a href="/books/" class="dark-text no-underline">Books</a></li> <li><a href="/reading/" class="dark-text no-underline">Reading</a></li> <li><a href="/coaching/" class="dark-text no-underline">Coaching</a></li> <li><a href="/newsletter/" class="dark-text no-underline">Newsletter</a></li> <!-- <li><a href="/speaking/" class="dark-text no-underline">Speaking</a></li> --> <li><a href="/donate/" class="dark-text no-underline">Donate</a></li> <li><a href="/contact/" class="dark-text no-underline">Contact</a></li> </ul> </nav> </header> <hr> <div class="content-background"> <div id="page-grid" class="page-width page-grid center"> <main id="content" role="main" class="content-width gutters"> <article itemtype="http://schema.org/Article"> <header> <h1 itemprop="headline" class="no-margin gutter-bottom headline-text">Introducing Props2Js</h1> <p itemprop="description" class="no-margin-top"></p> <div class="post-meta gutter-top smaller-font dark-dotted-border-top dark-dotted-border-bottom"> <p class="no-margin byline">Posted at <time datetime="Tue, 20 Dec 2011 00:00:00 GMT" itemprop="datePublished">December 20, 2011</time> by <span itemprop="author" itemtype="https://schema.org/Person">Nicholas C. Zakas</span></p> <p class="no-margin-top tags">Tags: <a href="/blog/tag/build" rel="tag">Build</a><span>, </span><a href="/blog/tag/javascript" rel="tag">JavaScript</a><span>, </span><a href="/blog/tag/json" rel="tag">JSON</a><span>, </span><a href="/blog/tag/jsonp" rel="tag">JSONP</a><span></span> </p> </div> </header> <section id="post-body" class="content-font"> <p>One of my principles of Maintainable JavaScript<sup><a href="http://www.slideshare.net/nzakas/maintainable-javascript-2011">1</a></sup> is to separate your configuration data from your application logic. Configuration data is hardcoded information that your JavaScript uses to work properly. This could be anything such as a URL or a UI string. For example:</p> <pre is:raw="" class="astro-code github-dark" style="background-color: #24292e; overflow-x: auto;" tabindex="0"><code><span class="line"><span style="color: #e1e4e8">function validate(value) {</span></span> <span class="line"><span style="color: #e1e4e8"> if (!value) {</span></span> <span class="line"><span style="color: #e1e4e8"> alert("Invalid value");</span></span> <span class="line"><span style="color: #e1e4e8"> location.href = "/errors/invalid.php";</span></span> <span class="line"><span style="color: #e1e4e8"> }</span></span> <span class="line"><span style="color: #e1e4e8">}</span></span> <span class="line"><span style="color: #e1e4e8"> </span></span> <span class="line"><span style="color: #e1e4e8">function toggleSelected(element) {</span></span> <span class="line"><span style="color: #e1e4e8"> if (hasClass(element, "selected")) {</span></span> <span class="line"><span style="color: #e1e4e8"> removeClass(element, "selected");</span></span> <span class="line"><span style="color: #e1e4e8"> } else {</span></span> <span class="line"><span style="color: #e1e4e8"> addClass(element, "selected");</span></span> <span class="line"><span style="color: #e1e4e8"> }</span></span> <span class="line"><span style="color: #e1e4e8">}</span></span></code></pre> <p>There are three pieces of configuration data in this code. The first is the string, “Invalid value”, which is displayed to the user. As a UI string, there’s a high chance that it will change frequently. The second is the URL “/errors/invalid.php”. URLs tend to change as development progresses due to architectural decisions. The third is the CSS class name “selected”. This class name is used three times, meaning that a class name change requires changes in three different places, increasing the likelihood that one will be missed.</p> <p>Configuration data is best extracted from the core application logic, such as:</p> <pre is:raw="" class="astro-code github-dark" style="background-color: #24292e; overflow-x: auto;" tabindex="0"><code><span class="line"><span style="color: #e1e4e8">//Configuration data externalized</span></span> <span class="line"><span style="color: #e1e4e8">var config = {</span></span> <span class="line"><span style="color: #e1e4e8"> MSG_INVALID_VALUE: "Invalid value",</span></span> <span class="line"><span style="color: #e1e4e8"> URL_INVALID: "/errors/invalid.php",</span></span> <span class="line"><span style="color: #e1e4e8"> CSS_SELECTED: "selected"</span></span> <span class="line"><span style="color: #e1e4e8">};</span></span> <span class="line"><span style="color: #e1e4e8"></span></span> <span class="line"><span style="color: #e1e4e8">function validate(value) {</span></span> <span class="line"><span style="color: #e1e4e8"> if (!value) {</span></span> <span class="line"><span style="color: #e1e4e8"> alert(config.MSG_INVALID_VALUE);</span></span> <span class="line"><span style="color: #e1e4e8"> location.href = config.URL_INVALID;</span></span> <span class="line"><span style="color: #e1e4e8"> }</span></span> <span class="line"><span style="color: #e1e4e8">}</span></span> <span class="line"><span style="color: #e1e4e8"></span></span> <span class="line"><span style="color: #e1e4e8">function toggleSelected(element) {</span></span> <span class="line"><span style="color: #e1e4e8"> if (hasClass(element, config.CSS_SELECTED)) {</span></span> <span class="line"><span style="color: #e1e4e8"> removeClass(element, config.CSS_SELECTED);</span></span> <span class="line"><span style="color: #e1e4e8"> } else {</span></span> <span class="line"><span style="color: #e1e4e8"> addClass(element, config.CSS_SELECTED);</span></span> <span class="line"><span style="color: #e1e4e8"> }</span></span> <span class="line"><span style="color: #e1e4e8">}</span></span></code></pre> <p>This example stores all of the configuration data in the <code>config</code> object. Each property of <code>config</code> holds a single piece of data, and each property name has a prefix indicating the type of data (<code>MSG</code> for a UI message, <code>URL</code> for a URL, and <code>CSS</code> for a class name). The naming convention is, of course, a matter of preference. The important part of this code is that all of the configuration data has been removed from the functions, replaced with placeholders from the <code>config</code> object.</p> <p>Externalizing the configuration data means that anyone can go in and make a change without fear of introducing an error in the application logic. It also means that the entire <code>config</code> object can be moved into its own file, so edits are made far away from the code that uses the data.</p> <p>Having an external object managing your configuration data is a good start, but I’m not a fan of storing configuration data directly in JavaScript code. Because such data changes frequently, I prefer to keep it in a simpler file format – one that’s free from worries about missing a semicolon or comma. And that’s when I turned to the Java properties file<sup><a href="http://en.wikipedia.org/wiki/.properties">2</a></sup>.</p> <p>Java properties files are incredibly simple. One name-value pair per line and comments begin with a <code>#</code>. It’s really hard to mess up this format. Here’s what the previous example’s configuration data looks like in a Java properties file:</p> <pre is:raw="" class="astro-code github-dark" style="background-color: #24292e; overflow-x: auto;" tabindex="0"><code><span class="line"><span style="color: #e1e4e8"># UI Strings</span></span> <span class="line"><span style="color: #e1e4e8">MSG_INVALID_VALUE = Invalid value</span></span> <span class="line"><span style="color: #e1e4e8"></span></span> <span class="line"><span style="color: #e1e4e8"># URLs</span></span> <span class="line"><span style="color: #e1e4e8">URL_INVALID = /errors/invalid.php</span></span> <span class="line"><span style="color: #e1e4e8"></span></span> <span class="line"><span style="color: #e1e4e8"># CSS Classes</span></span> <span class="line"><span style="color: #e1e4e8">CSS_SELECTED = selected</span></span></code></pre> <p>Even though I had my configuration data in a Java properties file, I had no easy way of making this data available to JavaScript.</p> <p>This is why I created Props2Js<sup><a href="https://github.com/nzakas/props2js/">3</a></sup>, a simple tool that does just one thing: reads a Java properties file and outputs it in a format that JavaScript can use. Actually, it’s capable of outputting the data into three formats that JavaScript can use: JSON, JSONP, and regular JavaScript.</p> <pre is:raw="" class="astro-code github-dark" style="background-color: #24292e; overflow-x: auto;" tabindex="0"><code><span class="line"><span style="color: #e1e4e8">java -jar props2js-0.1.0.jar --to jsonp --name myfunc --output result.js source.properties</span></span></code></pre> <p>The <code>--to</code> option specifies the output format, either “js”, “json”, or “jsonp”. The <code>--name</code> option specifies either the variable name (for “js”) or the function name (for “jsonp”); this option is ignored for “json”. The <code>--output</code> option specifies the file to write the data into. So this line takes the Java properties file named <code>source.properties</code> and outputs JSONP with a callback function of <code>myfunc</code> to a file named <code>result.js</code>.</p> <p>Props2Js outputs the properties file mentioned above into JSON format:</p> <pre is:raw="" class="astro-code github-dark" style="background-color: #24292e; overflow-x: auto;" tabindex="0"><code><span class="line"><span style="color: #e1e4e8">{"MSG_INVALID_VALUE":"Invalid value","URL_INVALID":"/errors/invalid.php",</span></span> <span class="line"><span style="color: #e1e4e8">"CSS_SELECTED":"selected"}</span></span></code></pre> <p>Here’s the JSONP output:</p> <pre is:raw="" class="astro-code github-dark" style="background-color: #24292e; overflow-x: auto;" tabindex="0"><code><span class="line"><span style="color: #e1e4e8">myfunc({"MSG_INVALID_VALUE":"Invalid value","URL_INVALID":"/errors/invalid.php",</span></span> <span class="line"><span style="color: #e1e4e8">"CSS_SELECTED":"selected"});</span></span></code></pre> <p>And here’s the plain JavaScript option with <code>--name config</code>:</p> <pre is:raw="" class="astro-code github-dark" style="background-color: #24292e; overflow-x: auto;" tabindex="0"><code><span class="line"><span style="color: #e1e4e8">var config={"MSG_INVALID_VALUE":"Invalid value","URL_INVALID":"/errors/invalid.php",</span></span> <span class="line"><span style="color: #e1e4e8">"CSS_SELECTED":"selected"};</span></span></code></pre> <p>Props2Js is also smart enough to know that you’re assigning to an object property if you include a dot in in the <code>--name</code> option. In that case, it omits the <code>var</code>.</p> <p>Props2Js is available under an MIT License and is hosted at GitHub<sup><a href="https://github.com/nzakas/props2js/">3</a></sup>.</p> <ol> <li><a href="http://www.slideshare.net/nzakas/maintainable-javascript-2011">Maintainable JavaScript 2011</a> by Nicholas C. Zakas</li> <li><a href="http://en.wikipedia.org/wiki/.properties">.properties</a> by Wikipedia</li> <li><a href="https://github.com/nzakas/props2js/">Props2Js</a></li> </ol> </section> </article> <div class="grid-columns round-borders content-item-border highlight-background"> <div class="gutters"> <!-- <h2 class="no-margin-top">Free E-book!</h2> --> <p><a href="https://ebooks.humanwhocodes.com/promises" target="_blank"><img src="/images/books/promises_community.png" alt="Understanding JavaScript Promises E-book Cover" height="250"></a></p> <p>Demystify JavaScript promises with the e-book that explains not just concepts, but also real-world uses of promises.</p> </div> <div class="gutters"> <h2 class="no-margin-top">Download the Free E-book!</h2> <p>The community edition of <i>Understanding JavaScript Promises</i> is a free download that arrives in minutes.</p> <form method="post" name="sideemailform" action="https://mailinglist.humanwhocodes.com/api/subscribe"> <div id="mc_embed_signup_scroll"> <div style="margin-bottom: 0.5em"> <label>First name: <input type="text" value="" style="width:100%" name="firstName"> </label> </div> <div> <label>Email address: <input type="email" value="" style="width:100%" name="email" required=""> </label> </div> <input type="hidden" name="formId" value="1580135"> <div class="center-text gutters"> <input type="submit" value="Send my E-book"> </div> </div> </form> </div> </div> </main> <div id="sidebar" class="sidebar-width sidebar-background gutters hide-on-small-screens"> <h1 class="hide-offscreen">Additional Information</h1> <script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CKYIEK3Y&placement=humanwhocodescom" id="_carbonads_js"></script> <h2 class="smaller-font">My Books</h2> <ul class="inline-list inline-image-list"> <li><a href="https://www.lulu.com/en/us/shop/nicholas-c-zakas/understanding-javascript-promises/paperback/product-2yvnqn.html"><img src="/images/books/promises.png" alt="Understanding JavaScript Promises" width="100"></a></li><li><a href="https://geni.us/hwc-es6-book"><img src="/images/books/understandinges6ns.png" alt="Understanding ECMAScript 6" width="100"></a></li><li><a href="https://geni.us/hwc-oopjs-book"><img src="/images/books/oopinjsns.png" alt="The Principles of Object-Oriented JavaScript" width="100"></a></li><li><a href="https://geni.us/hwc-mjs-book"><img src="/images/books/maintainablejs.png" alt="Maintainable JavaScript" width="100"></a></li> </ul> <h2 class="smaller-font">Recent Snippets</h2> <ul> <li><a href="/snippets/2024/03/publishing-to-jsr-release-please/">Publishing to JSR using release-please</a></li><li><a href="/snippets/2023/11/how-to-setup-known-hosts-jenkins-pipeline/">How to setup a known_hosts file for a Jenkins pipeline job</a></li><li><a href="/snippets/2023/01/mimicking-dirname-filename-nodejs-esm/">Mimicking __dirname and __filename in ESM modules in Node.js</a></li><li><a href="/snippets/2022/02/eleventy-npm-modules-client/">How to add npm packages for client-side use in Eleventy</a></li><li><a href="/snippets/2021/03/create-user-linux-ssh-key/">Creating a new user with an SSH key on Linux</a></li><li><a href="/snippets/2021/02/how-to-setup-deploy-web-application-dokku/">How to setup and deploy a web application on Dokku</a></li><li><a href="/snippets/2021/02/how-to-regain-jenkins-web-access-after-lockout/">How to regain Jenkins web access after being locked out</a></li><li><a href="/snippets/2020/10/create-typescript-declarations-from-javascript-jsdoc/">Create TypeScript declarations from JavaScript and JSDoc</a></li><li><a href="/snippets/2020/10/read-environment-variables-deno/">How to read environment variables in Deno using JavaScript</a></li><li><a href="/snippets/2020/08/validate-github-webhook-signature-nodejs/">How to validate the signature of a GitHub webhook using Node.js</a></li> </ul> <h2 class="smaller-font">Archives (20 Years)</h2> <ul> <li><a href="/blog/2024/">2024</a></li><li><a href="/blog/2023/">2023</a></li><li><a href="/blog/2022/">2022</a></li><li><a href="/blog/2021/">2021</a></li><li><a href="/blog/2020/">2020</a></li><li><a href="/blog/2019/">2019</a></li><li><a href="/blog/2018/">2018</a></li><li><a href="/blog/2016/">2016</a></li><li><a href="/blog/2015/">2015</a></li><li><a href="/blog/2014/">2014</a></li><li><a href="/blog/2013/">2013</a></li><li><a href="/blog/2012/">2012</a></li><li><a href="/blog/2011/">2011</a></li><li><a href="/blog/2010/">2010</a></li><li><a href="/blog/2009/">2009</a></li><li><a href="/blog/2008/">2008</a></li><li><a href="/blog/2007/">2007</a></li><li><a href="/blog/2006/">2006</a></li><li><a href="/blog/2005/">2005</a></li><li><a href="/blog/2004/">2004</a></li> </ul> </div> </div> </div> <hr> <footer class="inverted-colors"> <div class="page-width center"> <div class="page-grid orange-border-bottom"> <div class="margin-top content-width gutters"> <div class="collapsible-media-box"> <div class="media-box-media center-text"> <img src="/_astro/me-150x150.0969500a.jpg" alt="Photo of Nicholas C. Zakas" width="150" class="circle-image"> </div> <div> <h2 class="no-margin-top center-text-on-mobile">About the Human</h2> <p>Hi, I'm Nicholas C. Zakas, an independent software developer living in Mountain View, California. I've been a software architect at companies like Yahoo and Box, as well as an author and speaker. I created the <a href="https://eslint.org">ESLint</a> open source project and wrote several <a href="https://humanwhocodes.com/books">books</a>. At the moment, I'm <a href="https://humanwhocodes.com/blog/2014/04/02/i-have-lyme-disease/">recovering from Lyme disease</a> and haven't been able to leave my home much in the past five years. (<a href="https://medium.com/lyme-disease-warrior/progress-report-october-2018-fc38d4769e65">Health update</a>, <a rel="me" href="/about">More about me</a>)</p> </div> </div> </div> <div class="margin-top sidebar-width hide-on-small-screens"> <h2 class="no-margin-top">On the Web</h2> <ul> <li><a href="https://fosstodon.org/@nzakas" rel="me">Mastodon</a></li> <li><a href="https://www.twitter.com/slicknet/">Twitter</a></li> <li><a href="https://www.github.com/nzakas/">GitHub</a></li> <li><a href="https://www.instagram.com/humanwhocodes">Instagram</a></li> <li><a href="https://www.youtube.com/channel/UC95Pwj8oPPZN2mJCEtMqOsg">YouTube</a></li> <li><a href="https://www.linkedin.com/in/nzakas">LinkedIn</a></li> <li><a href="https://www.slideshare.net/nzakas/presentations/">Slideshare</a></li> <li><a href="https://amazon.com/author/nzakas/">Amazon</a></li> </ul> </div> </div> <p class="center-text"><a href="/policies/privacy">Privacy Policy</a> | <a href="/policies/terms">Terms of Service</a></p> <p class="center-text">Copyright &copy; 2020-2024 Human Who Codes LLC. Content licensed under a <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="nofollow noopener">Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License</a>.<br>Some links may be affiliate links. We may get paid if you buy something or take an action after clicking one of these. As an Amazon Associate we earn from qualifying purchases. <a href="/feeds/blog.xml">Blog Feed</a></p> </div> </footer> </body></html>

Pages: 1 2 3 4 5 6 7 8 9 10