<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Josh Nederveld</title>
    <description>The latest articles on DEV Community by Josh Nederveld (@jhned).</description>
    <link>https://dev.to/jhned</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F385479%2F73af698d-d8cd-4fc0-bbe1-6a9d1b91e8df.jpeg</url>
      <title>DEV Community: Josh Nederveld</title>
      <link>https://dev.to/jhned</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jhned"/>
    <language>en</language>
    <item>
      <title>Copy values in FormAssembly HTTPS Connector</title>
      <dc:creator>Josh Nederveld</dc:creator>
      <pubDate>Mon, 05 Oct 2020 13:56:06 +0000</pubDate>
      <link>https://dev.to/jhned/copy-values-in-formassembly-https-connector-lgl</link>
      <guid>https://dev.to/jhned/copy-values-in-formassembly-https-connector-lgl</guid>
      <description>&lt;p&gt;FormAssembly's HTTPS Connector is a little dopey when it comes to drop-down values-- they really need a button in here that lets you copy everything from the left column to right. But until we have that, we can use some jQuery to copy it in the Inspector.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kzQHk0qe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2aynwqukujpch3z3vcwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kzQHk0qe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2aynwqukujpch3z3vcwg.png" alt="Before: values in the left column"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use_strict&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pick-tfa_## .picklist td:first-child&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="nx"&gt;jQuery&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e-9SRMl2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hsawqr5yzn6fnb9xhtkx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e-9SRMl2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hsawqr5yzn6fnb9xhtkx.png" alt="After: values in the right column"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>formassembly</category>
      <category>forms</category>
      <category>javascript</category>
    </item>
    <item>
      <title>WordPress enqueues don't support Google Fonts with more than one font-family.</title>
      <dc:creator>Josh Nederveld</dc:creator>
      <pubDate>Fri, 22 May 2020 14:26:22 +0000</pubDate>
      <link>https://dev.to/jhned/wordpress-enqueues-don-t-support-google-fonts-with-more-than-one-font-family-36jd</link>
      <guid>https://dev.to/jhned/wordpress-enqueues-don-t-support-google-fonts-with-more-than-one-font-family-36jd</guid>
      <description>&lt;p&gt;The current Google Fonts stylesheet URLs syntax looks like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,700;1,400;1,700&amp;amp;family=Montserrat:wght@700;800&amp;amp;display=swap&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you use more than one font-family, the "family" parameter is reused. If you're using &lt;code&gt;wp_register_style&lt;/code&gt; and &lt;code&gt;wp_enqueue_style&lt;/code&gt; to add this stylesheet link to your site, you'll get this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://fonts.googleapis.com/css2?family=Montserrat:wght@700;800&amp;amp;display=swap&amp;amp;ver=5.4.1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The code that adds the version query string parameter uses &lt;a href="https://www.php.net/manual/en/function.parse-str.php"&gt;parse_str&lt;/a&gt;, which returns code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"family=Lora:ital,wght@0,400;0,700;1,400;1,700&amp;amp;family=Montserrat:wght@700;800&amp;amp;display=swap"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;parse_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'family'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;  &lt;span class="c1"&gt;// Montserrat:wght@700;800&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'display'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// swap&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I'm not sure why &lt;code&gt;add_query_arg&lt;/code&gt; &lt;em&gt;has&lt;/em&gt; to deconstruct the entire query string and rebuild it in order to add another query string parameter. In my opinion, WordPress also does a bad job of giving devs the opportunity to prevent this behavior with hooks. Consider this snippet from &lt;code&gt;do_item&lt;/code&gt; in &lt;code&gt;class.wp-styles.php&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;_css_href&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$ver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$handle&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;....&lt;/span&gt;
&lt;span class="nv"&gt;$tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;apply_filters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'style_loader_tag'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$media&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The original &lt;code&gt;$src&lt;/code&gt; variable is never accessible through hooks after being changed into &lt;code&gt;$href&lt;/code&gt;. Consider &lt;code&gt;_css_href&lt;/code&gt;, which &lt;code&gt;do_item&lt;/code&gt; calls. This is where the query string arg is added:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$ver&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;add_query_arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'ver'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$ver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$src&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;apply_filters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'style_loader_src'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$handle&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;esc_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$src&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We're given a filter, but it doesn't include the original &lt;code&gt;$src&lt;/code&gt;, because it's been overwritten by &lt;code&gt;add_query_arg&lt;/code&gt;. If the original variables were preserved and passed in these hooks, then we'd be able to prevent this behavior.&lt;/p&gt;

&lt;p&gt;Another way to do it is to change the behavior of &lt;code&gt;wp_parse_str&lt;/code&gt;. There's a &lt;a href="https://www.php.net/manual/en/function.parse-str.php#76792"&gt;good comment on php.net outlining the issue from Evan K from &lt;strong&gt;12 years ago&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It bears mentioning that the parse_str builtin does NOT process a query string in the CGI standard way, when it comes to duplicate fields.  If multiple fields of the same name exist in a query string, every other web processing language would read them into an array, but PHP silently overwrites them:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;# silently fails to handle multiple values&lt;/span&gt;
&lt;span class="nb"&gt;parse_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'foo=1&amp;amp;foo=2&amp;amp;foo=3'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;# the above produces:&lt;/span&gt;
&lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'foo'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'3'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Instead, PHP uses a non-standards compliant practice of including brackets in fieldnames to achieve the same effect.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;# bizarre php-specific behavior&lt;/span&gt;
&lt;span class="nb"&gt;parse_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'foo[]=1&amp;amp;foo[]=2&amp;amp;foo[]=3'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;# the above produces:&lt;/span&gt;
&lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'foo'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'3'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This can be confusing for anyone who's used to the CGI standard, so keep it in mind.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But of course, changing the Google Fonts URL to &lt;code&gt;https://fonts.googleapis.com/css2?family[]=Lora:ital,wght@0,400;0,700;1,400;1,700&amp;amp;family[]=Montserrat:wght@700;800&amp;amp;display=swap&lt;/code&gt; results in a 404, so there's no easy fix there.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Fix
&lt;/h2&gt;

&lt;p&gt;There are a few ways to fix this. I grabbed Evan's &lt;code&gt;proper_parse_str&lt;/code&gt; function and plugged it into &lt;code&gt;wp_parse_str&lt;/code&gt; and it worked fine for this case, but I don't know where all else &lt;code&gt;wp_parse_str&lt;/code&gt; is used, so it makes me hesitant to propose that as a solution. &lt;/p&gt;

&lt;p&gt;For the meantime, we can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set &lt;code&gt;$ver&lt;/code&gt; to &lt;code&gt;null&lt;/code&gt; when registering and/or enqueueing the stylesheet.&lt;/li&gt;
&lt;li&gt;Enqueue fonts in separate files, rather than one.&lt;/li&gt;
&lt;li&gt;Petition WordPress to change the behavior of &lt;code&gt;wp_parse_str&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>wordpress</category>
      <category>google</category>
      <category>fonts</category>
    </item>
  </channel>
</rss>
