<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>JavaScript Archives - rweber.net</title>
	<atom:link href="https://www.rweber.net/category/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.rweber.net/category/javascript/</link>
	<description>trying to be a mile wide AND a mile deep</description>
	<lastBuildDate>Wed, 19 Sep 2018 11:30:24 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
<site xmlns="com-wordpress:feed-additions:1">37896774</site>	<item>
		<title>Coding a Social Share Widget</title>
		<link>https://www.rweber.net/javascript/coding-a-social-share-widget/</link>
					<comments>https://www.rweber.net/javascript/coding-a-social-share-widget/#respond</comments>
		
		<dc:creator><![CDATA[Rebecca]]></dc:creator>
		<pubDate>Mon, 17 Sep 2018 12:00:11 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[cross-site interaction]]></category>
		<guid isPermaLink="false">https://www.rweber.net/?p=40550</guid>

					<description><![CDATA[<div><img width="290" height="300" src="https://www.rweber.net/wp-content/uploads/2018/09/root-beer-float-290x300.jpg" class="attachment-medium size-medium wp-post-image" alt="Root Beer Float image by Darin House via Wikimedia Commons" style="float:left; margin-right:16px; margin-bottom:16px;" decoding="async" fetchpriority="high" srcset="https://www.rweber.net/wp-content/uploads/2018/09/root-beer-float-290x300.jpg 290w, https://www.rweber.net/wp-content/uploads/2018/09/root-beer-float-768x794.jpg 768w, https://www.rweber.net/wp-content/uploads/2018/09/root-beer-float.jpg 991w, https://www.rweber.net/wp-content/uploads/2018/09/root-beer-float-145x150.jpg 145w" sizes="(max-width: 290px) 100vw, 290px" /></div>
<p>Syntax and tips for cooking up your own widget for sharing by email, Twitter, Facebook, or Pinterest.</p>
<p>The post <a href="https://www.rweber.net/javascript/coding-a-social-share-widget/">Coding a Social Share Widget</a> appeared first on <a href="https://www.rweber.net">rweber.net</a>.</p>
]]></description>
										<content:encoded><![CDATA[<div><img width="290" height="300" src="https://www.rweber.net/wp-content/uploads/2018/09/root-beer-float-290x300.jpg" class="attachment-medium size-medium wp-post-image" alt="Root Beer Float image by Darin House via Wikimedia Commons" style="float:left; margin-right:16px; margin-bottom:16px;" decoding="async" srcset="https://www.rweber.net/wp-content/uploads/2018/09/root-beer-float-290x300.jpg 290w, https://www.rweber.net/wp-content/uploads/2018/09/root-beer-float-768x794.jpg 768w, https://www.rweber.net/wp-content/uploads/2018/09/root-beer-float.jpg 991w, https://www.rweber.net/wp-content/uploads/2018/09/root-beer-float-145x150.jpg 145w" sizes="(max-width: 290px) 100vw, 290px" /></div><p>Suppose you want a homegrown share widget: perhaps for page load speed, perhaps for styling control, perhaps to avoid adding a vendor&#8217;s tracking code to your site. As it turns out, this is straightforward to do for a lot of social networks with a little JavaScript: add an <code>onclick</code> attribute opening a window at the appropriate URL, and you&#8217;re done.</p>
<p>Email is even simpler &#8211; no JavaScript required. <code>Mailto:</code> links have been around since the early days of the web. (Not that everyone&#8217;s browser is configured correctly to use their preferred mail client.) For a share button the destination is omitted but the subject and body are set via parameters.</p>
<p><code>href="mailto:?subject=[encoded string]&body=[encoded string]"</code></p>
<p>I found just one complication: if you encode the ampersand between subject and body in the mailto link, as most places instruct, the body will be cut off in many circumstances. One of the problematic setups is Outlook on Windows, yet even MSDN says to encode the ampersand!</p>
<p>Twitter, Facebook, and Pinterest sharing buttons follow. For each of them, you will be opening a window at a specific address. The links get the following attribute:<br />
<code>onclick="window.open('[network-specific link]', 'window', 'menubar=no, toolbar=no, resizable=yes, scrollbars=yes, height=600, width=600')"</code></p>
<p>Twitter is the second-simplest to set up. Its network-specific link is<br />
<code>https://twitter.com/intent/tweet?text=[encoded string]</code></p>
<p>Facebook&#8217;s complication is that you need an app ID. This ID will be exposed, so do not use an app that Facebook users sign up for. A special app that is used for nothing but this widget is best. Incidentally, if someone clicks the Facebook share button when they are not logged in, they will see the name of the app (a la &#8220;Sign in to Facebook to use XYZ&#8221;), so you may want to give it a name that will make sense to the user.</p>
<p>Facebook makes its own decisions about what to show for a shared page, so you only provide it the URL:<br />
<code>https://www.facebook.com/dialog/share?app_id=[app ID]&href=[encoded page URL]</code></p>
<p>The minimalist network-specific link for Pinterest is almost as simple as Twitter&#8217;s:<br />
<code>https://www.pinterest.com/pin/create/button/?url=[encoded page URL]&description=[encoded text]</code></p>
<p>That will open a window that allows you to choose an image from the page to pin, as though you&#8217;d pinned by URL from within Pinterest itself. It&#8217;s great &hellip; provided you&#8217;re not trying to manage which images are pinnable.</p>
<p>Once upon a time, to exclude an individual image from being pinned, you gave it the attribute <code>nopin="nopin"</code>. That&#8217;s not valid HTML5, though, so now there is also the attribute <code>data-pin-nopin="true"</code>. If you are using, say, the Pinterest browser extension, adding the data-attribute to exclude images works great and allows your page to validate. However, in the context of choosing an image to pin after inputting a URL to Pinterest, <code>nopin="nopin"</code> is still current. Imagine my joy upon discovering my sitewide update from nopin to data-pin-nopin attributes was not as much of an update as I thought!</p>
<p>Fortunately, it isn&#8217;t too complicated to build an image selection overlay which excludes disallowed images regardless of syntax. Mine also kicks out any images that are too small (using size as displayed) or too landscape-oriented, but pulls in anything that appears to have special Pinterest markup &#8211; whether that be from a <code>data-pin-media</code> attribute or based on a CSS class name. And then why not take it a step further &#8211; if there is only a single pinnable image, go straight to a Pinterest window to pin that image.</p>
<p>Here&#8217;s a pseudocode skeleton for a pinnable image gate:</p>
<pre>showPinnableImages:
  A. grab all images with neither data-pin-nopin="true" nor nopin="nopin" attribute; set a counter to 0.
  B. for each image, check
    1. does it have a data-pin-media attribute or a class including "pinterest"?
      > if so, push the data-pin-media value (falling back to src and then to srcset) into a media array, and the alt text (falling back to title + metadescription) into a description array; increment the counter.
    2. if not, is it at least 236px wide with a height at least 2/3 of its width?
      > if so, push the src (falling back to srcset) into the media array, and the alt text (falling back to title + metadescription) into the description array; increment the counter.
  C. if there is more than one image, build HTML of an overlay displaying the images with their description value as alt text.
  D. if there is only one image, open a Pinterest window to pin that image.
  E. set a click handler for the overlay and its contents, to close or pin as desired.</pre>
<p>Once you&#8217;ve chosen an image, the network-specific link for Pinterest for the window.open command looks like this:<br />
<code>https://www.pinterest.com/pin/create/button/?url=[encoded page URL]&description=[encoded text]&media=[encoded image URL]</code></p>
<p>The one major limitation to the home-grown share button is that if the Pinterest gate finds zero pinnable images, it will simply do nothing. There does exist open source code to generate a &#8220;text on solid color&#8221; image, but if that is overkill you can add another &#8220;if&#8221; to the block about number of pinnable images and pop up a pin window with a default image.</p>
<p>Other than the six-week period where Facebook was rate-limiting apps severely (and contrary to its documentation), these have worked quite well, eliminating problems with slow and obvious loading. I was really pleased with them!</p>
<hr>
<p><small>Root beer float original by <a href="https://commons.wikimedia.org/wiki/File:DPS_Assignment_-_Sweet_Tooth_-_Root_Beer_Float.jpg">Darin House via Wikimedia Commons</a>.</small></p>
<p>The post <a href="https://www.rweber.net/javascript/coding-a-social-share-widget/">Coding a Social Share Widget</a> appeared first on <a href="https://www.rweber.net">rweber.net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.rweber.net/javascript/coding-a-social-share-widget/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">40550</post-id>	</item>
		<item>
		<title>Bookmarkable Ajax-Driven Pages</title>
		<link>https://www.rweber.net/javascript/bookmarkable-ajax-driven-pages/</link>
					<comments>https://www.rweber.net/javascript/bookmarkable-ajax-driven-pages/#respond</comments>
		
		<dc:creator><![CDATA[Rebecca]]></dc:creator>
		<pubDate>Mon, 09 Jul 2018 12:00:56 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[regex]]></category>
		<category><![CDATA[UX]]></category>
		<guid isPermaLink="false">http://www.rweber.net/?p=40496</guid>

					<description><![CDATA[<div><img width="212" height="300" src="https://www.rweber.net/wp-content/uploads/2018/07/Kate-Greenaway-illustrations-212x300.jpg" class="attachment-medium size-medium wp-post-image" alt="Kate Greenaway illustrations as bookmarks via Emmie_Norfolk on Pixabay" style="float:left; margin-right:16px; margin-bottom:16px;" decoding="async" srcset="https://www.rweber.net/wp-content/uploads/2018/07/Kate-Greenaway-illustrations-212x300.jpg 212w, https://www.rweber.net/wp-content/uploads/2018/07/Kate-Greenaway-illustrations-106x150.jpg 106w, https://www.rweber.net/wp-content/uploads/2018/07/Kate-Greenaway-illustrations.jpg 452w" sizes="(max-width: 212px) 100vw, 212px" /></div>
<p>Generic get/set functions for query string parameters that keep default values out of the URL and respect the existence of extra parameters.</p>
<p>The post <a href="https://www.rweber.net/javascript/bookmarkable-ajax-driven-pages/">Bookmarkable Ajax-Driven Pages</a> appeared first on <a href="https://www.rweber.net">rweber.net</a>.</p>
]]></description>
										<content:encoded><![CDATA[<div><img width="212" height="300" src="https://www.rweber.net/wp-content/uploads/2018/07/Kate-Greenaway-illustrations-212x300.jpg" class="attachment-medium size-medium wp-post-image" alt="Kate Greenaway illustrations as bookmarks via Emmie_Norfolk on Pixabay" style="float:left; margin-right:16px; margin-bottom:16px;" decoding="async" loading="lazy" srcset="https://www.rweber.net/wp-content/uploads/2018/07/Kate-Greenaway-illustrations-212x300.jpg 212w, https://www.rweber.net/wp-content/uploads/2018/07/Kate-Greenaway-illustrations-106x150.jpg 106w, https://www.rweber.net/wp-content/uploads/2018/07/Kate-Greenaway-illustrations.jpg 452w" sizes="auto, (max-width: 212px) 100vw, 212px" /></div><p>If someone might reasonably expect to bookmark or link others to content, I like that to be possible. With ajax-updated pages it doesn&#8217;t come for free, though. The newest addition to the <a href="https://github.com/ReveWeber/utilities">Utilities repository</a> is a little bit of get/set code for query strings to support bookmarkability.</p>
<p>The code consists of two functions, <code>parseQuery</code> and <code>updateQuery</code>. They should live inside a scope (perhaps a <a href="http://markdalgleish.com/2011/03/self-executing-anonymous-functions/">self-executing anonymous function</a>) with variables holding the default and current values of the parameters that determine the content of the page.</p>
<pre>
var default1 = "default1";
var param1;
</pre>
<p>Parsing queries is straightforward and can be done in multiple ways. This version uses a regular expression to grab everything between the parameter name with equals sign, and the next ampersand if any, provided that&#8217;s at least one character long.</p>
<pre>
function parseQuery() {
  var queryString = window.location.search.substr(1);
  // set all parameters to their default values
  param1 = default1;
  if (queryString.length > 0) {
    // if there's a query string, check for each param within it
    var val1 = queryString.match(/.*param1=([^&]+).*/i);
    if (val1) {
        param1 = val1[1];
    }
  }
}
</pre>
<p>To handle multiple parameters you&#8217;d repeat the blocks right after the comments: set all variables to the default, and then do a match and a length check for each of them within the single &#8220;if there&#8217;s a query string&#8221; check.</p>
<p>You can also split the query string into an array, but it&#8217;s a little more difficult to deal with exceptional cases like parameter names that lack values.</p>
<p>Updating the query is more complicated. I wanted my query string to consist of parameters with non-default values only, plus any parameters that don&#8217;t belong to this code. My original version simply rewrote the whole query string to consist exactly of all the parameters &#8211; default or not &#8211; and would not permit other parameters to persist, such as those that you might use to track (or deactivate) A/B tests. The reason to keep default parameters out of the query string was that one of those had a default value dependent on the date; if you bookmarked the &#8220;now&#8221; version of the page I wanted it to still be &#8220;now&#8221; when you came back a month later.</p>
<p>The answer was once again regular expressions (when is it not?).</p>
<pre>
function updateQuery() {
  var newUrl = window.location.href;
  // clean out valueless parameters to simplify ensuing matching
  newUrl = newUrl.replace(/(.*[?&])param1(&(.*))?$/, "$1$3");
  if (param1 !== default1) {
    if (newUrl.match(/[?&]param1=/)) {
      newUrl = newUrl.replace(/(.*[?&]param1=)[^&]*(.*)/, 
      '$1' + param1 + '$2');
    } else if (newUrl.indexOf('?') > 0) {
      newUrl = newUrl + '&amp;param1=' + param1;
    } else {
      newUrl = newUrl + '?param1=' + param1;
    }
  } else {
    newUrl = newUrl.replace(/(.*[?&])param1=[^&]*&?(.*)/, '$1$2');
  }

  // tidy up
  if (newUrl.match(/[?&]$/)) {
    newUrl = newUrl.slice(0, -1);
  }    
  window.history.pushState('', '', newUrl);
}
</pre>
<p>For each parameter in turn, clean out any valueless instance of it (meaning &#8220;without an equals sign&#8221;, really; if the browser allows valueless <strong>with</strong> an equals sign is will be handled in the if statements). Then, if the parameter has a non-default value, replace its value or add it as a new parameter to the string. If it is the default, remove it from the string. That is, the whole section between the two comments would be repeated for each parameter. All of this business might leave a trailing question mark or ampersand, so clean that away if needed and push the new URL into the browser history.</p>
<p>There&#8217;s a sample webpage in the repo as well, in which you can try this out, though you&#8217;ll need to update the internal links on the page to match its location on your localhost.</p>
<hr>
<p><small>Kate Greenaway illustrations as bookmarks via <a href="https://pixabay.com/en/kate-greenaway-vintage-bookmark-1519992/">Emmie_Norfolk on Pixabay</a>.</small></p>
<p>The post <a href="https://www.rweber.net/javascript/bookmarkable-ajax-driven-pages/">Bookmarkable Ajax-Driven Pages</a> appeared first on <a href="https://www.rweber.net">rweber.net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.rweber.net/javascript/bookmarkable-ajax-driven-pages/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">40496</post-id>	</item>
		<item>
		<title>Dipping into a Database</title>
		<link>https://www.rweber.net/php-and-mysql/dipping-into-a-database/</link>
					<comments>https://www.rweber.net/php-and-mysql/dipping-into-a-database/#respond</comments>
		
		<dc:creator><![CDATA[Rebecca]]></dc:creator>
		<pubDate>Mon, 22 Jan 2018 13:00:43 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP and MySQL]]></category>
		<category><![CDATA[game development]]></category>
		<guid isPermaLink="false">http://www.rweber.net/?p=40298</guid>

					<description><![CDATA[<div><img width="300" height="225" src="https://www.rweber.net/wp-content/uploads/2018/01/toe-in-water-772773_640-300x225.jpg" class="attachment-medium size-medium wp-post-image" alt="Toes in the water photo by Godsgirl_madi on Pixabay" style="float:left; margin-right:16px; margin-bottom:16px;" decoding="async" loading="lazy" srcset="https://www.rweber.net/wp-content/uploads/2018/01/toe-in-water-772773_640-300x225.jpg 300w, https://www.rweber.net/wp-content/uploads/2018/01/toe-in-water-772773_640-150x113.jpg 150w, https://www.rweber.net/wp-content/uploads/2018/01/toe-in-water-772773_640.jpg 640w" sizes="auto, (max-width: 300px) 100vw, 300px" /></div>
<p>A simple setup for a database-stored high score list in an otherwise JavaScript game, with PHP and MySQL troubleshooting tips.</p>
<p>The post <a href="https://www.rweber.net/php-and-mysql/dipping-into-a-database/">Dipping into a Database</a> appeared first on <a href="https://www.rweber.net">rweber.net</a>.</p>
]]></description>
			<error>
    <code>internal_server_error</code>
    <title><![CDATA[WordPress &amp;rsaquo; Error]]></title>
    <message><![CDATA[&lt;p&gt;There has been a critical error on this website.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://wordpress.org/documentation/article/faq-troubleshooting/&quot;&gt;Learn more about troubleshooting WordPress.&lt;/a&gt;&lt;/p&gt;]]></message>
    <data>
        <status>500</status>
    </data>
</error>
