<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title></title>
  <subtitle></subtitle>
  <id>https://www.endpointdev.com/blog/tags/jquery/</id>
  <link href="https://www.endpointdev.com/blog/tags/jquery/"/>
  <link href="https://www.endpointdev.com/blog/tags/jquery/" rel="self"/>
  <updated>2016-01-26T00:00:00+00:00</updated>
  <author>
    <name>End Point Dev</name>
  </author>
  
    <entry>
      <title>Full Screen Gallery with Supersized and video slides</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2016/01/full-screen-gallery-with-supersized-and/"/>
      <id>https://www.endpointdev.com/blog/2016/01/full-screen-gallery-with-supersized-and/</id>
      <published>2016-01-26T00:00:00+00:00</published>
      <author>
        <name>Marina Lohova</name>
      </author>
      <content type="html">
        &lt;p&gt;I was recently looking to build a full screen image and video gallery for our client &lt;a href=&#34;https://mission-blue.org/&#34;&gt;Mission Blue&lt;/a&gt;. Something similar to the Google Maps interface you can see in the screenshot below:&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;    &lt;a href=&#34;/blog/2016/01/full-screen-gallery-with-supersized-and/image-0-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;       &lt;img border=&#34;0&#34; src=&#34;/blog/2016/01/full-screen-gallery-with-supersized-and/image-0.png&#34; width=&#34;600&#34;/&gt;     &lt;/a&gt;   &lt;/div&gt;
&lt;p&gt;After scouring the Internet to find a suitable jQuery plugin I finally decided on &lt;a href=&#34;https://web.archive.org/web/20170629183603/http://buildinternet.com/2009/05/supersized-20-full-screen-imagebackground-slideshow-jquery-plugin-w-transitions-and-controls/&#34;&gt;Supersized, Full screen background slideshow plugin for jQuery&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After downloading the library, include it on the page:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;link&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;href&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/wp-content/plugins/wp-supersized/theme/supersized.shutter.css?ver=4.2.2&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;supersized_theme_css-css&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;media&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;all&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;rel&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text/css&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;link&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/wp-includes/js/jquery/ui/effect.min.js?ver=1.11.4&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/wp-content/plugins/wp-supersized/js/jquery.easing.min.js?ver=1.3&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/wp-content/plugins/wp-supersized/js/jquery.easing.compatibility.js?ver=1.0&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/wp-content/plugins/wp-supersized/js/jquery.animate-enhanced.min.js?ver=0.75&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;text/javascript&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;/wp-content/plugins/wp-supersized/js/supersized.3.2.7.min.js?ver=3.2.7&amp;#39;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;basic-functionality&#34;&gt;Basic functionality&lt;/h3&gt;
&lt;p&gt;Let’s create a variable that will hold all the images in the slideshow:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; images = [];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;images.push({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  type: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;IMAGE&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  image: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;img1.jpg&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  title: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;Image 1&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  thumb: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;img1_thumb.jpg&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  url: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;https://www.endpointdev.com&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;images.push({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  type: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;YOUTUBE&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  image: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;screenshot1.jpg&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  title: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;YouTube slide&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  videoid: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;abc12345678&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  thumb: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;screenshot1_thumb.jpg&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  url: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;https://www.youtube.com/watch?v=abc12345678&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s initialize Supersized:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jQuery.supersized({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  slideshow: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  autoplay: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  min_width: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  min_height: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  vertical_center: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  horizontal_center: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fit_always: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fit_portrait: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fit_landscape: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  slide_links: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;blank&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  thumb_links: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  thumbnail_navigation: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  slides: images,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  mouse_scrub: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;customizing-the-toolbar&#34;&gt;Customizing the toolbar&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;thumb-tray&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;load-item&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;thumb-back&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;thumb-forward&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;slidecaption&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;customizing-the-screen-image-size&#34;&gt;Customizing the screen image size&lt;/h3&gt;
&lt;p&gt;I didn’t want to have the full screen image as it was a little overwhelming for the user. I wanted the black bars just like in the Google interface. Supersized allows for easy customization. This CSS did the trick:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;supersized&lt;/span&gt;, #&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;supersized&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;width&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;70&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#c00;font-weight:bold&#34;&gt;!important&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;left&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#c00;font-weight:bold&#34;&gt;!important&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;right&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#c00;font-weight:bold&#34;&gt;!important&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;top&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;px&lt;/span&gt; &lt;span style=&#34;color:#c00;font-weight:bold&#34;&gt;!important&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;margin&lt;/span&gt;:&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;auto&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;introducing-video-youtube-slides&#34;&gt;Introducing video (YouTube) slides&lt;/h3&gt;
&lt;p&gt;First, I added the Youtube API:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;https://www.youtube.com/iframe_api&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then I added a couple of CSS styles:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;supersized&lt;/span&gt; .&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;player&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;margin&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;auto&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;display&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;block&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, I went into the Supersized library source and modified it. To allow for the video slides to appear, I added the new condition and the slide type &amp;lsquo;YOUTUBE&amp;rsquo;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;base._renderSlide = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(loadPrev, options) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; linkTarget = base.options.new_window ? &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39; target=&amp;#34;_blank&amp;#34;&amp;#39;&lt;/span&gt; : &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; imageLink = (base.options.slides[loadPrev].url) ? &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;href=&amp;#39;&amp;#34;&lt;/span&gt; + base.options.slides[loadPrev].url + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;#39;&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; slidePrev = base.el + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39; li:eq(&amp;#39;&lt;/span&gt; + loadPrev + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; imgPrev = $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;img src=&amp;#34;&amp;#39;&lt;/span&gt; + base.options.slides[loadPrev].image + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;#34;/&amp;gt;&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (base.options.slides[loadPrev].type == &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;YOUTUBE&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    imgPrev.load(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; video = $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;div class=&amp;#34;player&amp;#34; id=&amp;#34;player&amp;#39;&lt;/span&gt;+ base.options.slides[loadPrev].videoid + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;#34;&amp;gt;&amp;lt;/div&amp;gt;&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      video.appendTo(slidePrev);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; player = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; YT.Player(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;player&amp;#39;&lt;/span&gt; + base.options.slides[loadPrev].videoid, {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        height: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;390&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        width: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;640&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        videoId: base.options.slides[loadPrev].videoid
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });&lt;span style=&#34;color:#888&#34;&gt;// End Load
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    imgPrev.appendTo(slidePrev).wrap(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;a &amp;#39;&lt;/span&gt; + imageLink + linkTarget + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;gt;&amp;lt;/a&amp;gt;&amp;#39;&lt;/span&gt;).parent().parent().addClass(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;image-loading &amp;#39;&lt;/span&gt; + options[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;class&amp;#39;&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    imgPrev.load(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;).data(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;origWidth&amp;#39;&lt;/span&gt;, $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;).width()).data(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;origHeight&amp;#39;&lt;/span&gt;, $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;).height());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      base.resizeNow();&lt;span style=&#34;color:#888&#34;&gt;// Resize background image
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;    });&lt;span style=&#34;color:#888&#34;&gt;// End Load
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;final-result&#34;&gt;Final Result&lt;/h3&gt;
&lt;p&gt;This is how gallery looks with the customizations:&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;  &lt;a href=&#34;/blog/2016/01/full-screen-gallery-with-supersized-and/image-1-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;     &lt;img border=&#34;0&#34; src=&#34;/blog/2016/01/full-screen-gallery-with-supersized-and/image-1.png&#34; width=&#34;600&#34;/&gt;   &lt;/a&gt; &lt;/div&gt;
&lt;p&gt;This is what a video slide looks like:&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;  &lt;a href=&#34;/blog/2016/01/full-screen-gallery-with-supersized-and/image-2-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;     &lt;img border=&#34;0&#34; src=&#34;/blog/2016/01/full-screen-gallery-with-supersized-and/image-2.png&#34;/&gt;   &lt;/a&gt; &lt;/div&gt;
&lt;p&gt;Hope you found this writeup useful!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Using jQuery Migrate plugin</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/09/using-jquery-migrate-plugin/"/>
      <id>https://www.endpointdev.com/blog/2014/09/using-jquery-migrate-plugin/</id>
      <published>2014-09-26T00:00:00+00:00</published>
      <author>
        <name>Marina Lohova</name>
      </author>
      <content type="html">
        &lt;p&gt;We all know these tricky situations, like introducing a new feature on top of old code, when it seems we’re about to step into a tedious swamp of workarounds and dirty hacks. Fortunately, &lt;a href=&#34;http://jquery.com/upgrade-guide/1.9/#jquery-migrate-plugin&#34;&gt;jQuery Migrate plugin&lt;/a&gt; is here to make these situations easier, at least in JavaScript. So for any of you who wondered about a real-life example of using jQuery Migrate plugin I have one!&lt;/p&gt;
&lt;p&gt;My task was to add an editable combomonster, oh sorry, combobox (even though editable comboboxes remind me of UX Frankenstein’s Monster, they are still requested a lot) to a rather old website built on jQuery v1.4.2.&lt;/p&gt;
&lt;p&gt;I downloaded the most recent jQuery UI (at that time it was v1.10.4) and a very neat &lt;a href=&#34;https://github.com/jquery/jquery-ui/blob/master/demos/autocomplete/combobox.html&#34;&gt;editable combobox component&lt;/a&gt; to go with it. It was expected that it wouldn’t work out of box with the rather outdated jQuery we had. It didn’t work and the page produced the following JavaScript error:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TypeError: t.cssHooks is &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;undefined&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...t(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;);f(i,&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(e,i){t.cssHooks[i]={set:&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(e,n){&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; a,o,r=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&amp;#34;&lt;/span&gt;trans...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;No problem, I grab the newer compatible jQuery v1.10.2 from the website and yield it into head in that particular page.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#2b2;background-color:#f0fff0&#34;&gt;% content_for &lt;/span&gt; &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:head&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;  javascript_include_tag &amp;#34;jquery-1.10.2.min.js&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;  javascript_include_tag &amp;#34;jquery-ui-1.10.4.min.js&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;  javascript_include_tag &amp;#34;jquery.editableselect.js&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;lt;% end %&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There’s good news and bad news. Good - the old error is gone. Bad - there’s a new one:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TypeError: jQuery.browser is undefined&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (jQuery.browser.safari &amp;amp;&amp;amp; &lt;span style=&#34;color:#038&#34;&gt;document&lt;/span&gt;.readyState != &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;complete”)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;function stretchbar(){
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;  /* the if block is for safari 4, it was disrupting the display on refresh. */
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;  if (jQuery.browser.safari &amp;amp;&amp;amp; document.readyState != &amp;#34;&lt;/span&gt;complete&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     setTimeout( arguments.callee, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We have a lot of old components on that page and they fail to work with the new jQuery. Why? All versions of jQuery after v.1.9 are stripped of certain components that are not ‘core’ ones. jQuery offers a migration technique to restore deprecated and removed functionality using &lt;a href=&#34;http://jquery.com/upgrade-guide/1.9/#jquery-migrate-plugin&#34;&gt;jQuery Migrate plugin&lt;/a&gt; so the older code could work. The plugin can be included with versions of jQuery as old as 1.6.4. However, the plugin is only required for version 1.9.0 or higher.&lt;/p&gt;
&lt;p&gt;The section &lt;a href=&#34;http://jquery.com/upgrade-guide/1.9/#jquery-browser-removed&#34;&gt;“Changes of Note in jQuery 1.9”&lt;/a&gt; explains the particular error I got. Finally, I downloaded &lt;a href=&#34;https://github.com/jquery/jquery-migrate/&#34;&gt;jQuery Migrate plugin&lt;/a&gt; v1.2.1 (the most recent at the time) and put it after the script for jQuery:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#2b2;background-color:#f0fff0&#34;&gt;% content_for &lt;/span&gt; &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:head&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;  javascript_include_tag &amp;#34;jquery-1.10.2.min.js&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;  javascript_include_tag &amp;#34;jquery-ui-1.10.4.min.js&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;  javascript_include_tag &amp;#34;jquery.editableselect.js&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;  javascript_include_tag &amp;#34;jquery-migrate-1.2.1.min.js&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;lt;% end %&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Voila! The website gets an instant design boost with this brand new, sleek grey editable combobox:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;/blog/2014/09/using-jquery-migrate-plugin/image-0-big.png&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2014/09/using-jquery-migrate-plugin/image-0.png&#34;/&gt;&lt;/a&gt;&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>jQuery Content Replacement with AJAX</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/04/jquery-content-replacement-with-ajax/"/>
      <id>https://www.endpointdev.com/blog/2014/04/jquery-content-replacement-with-ajax/</id>
      <published>2014-04-15T00:00:00+00:00</published>
      <author>
        <name>Jeff Boes</name>
      </author>
      <content type="html">
        &lt;p&gt;This is not a huge breakthrough, but it colored in some gaps in my knowledge so I thought I would share.&lt;/p&gt;
&lt;p&gt;Let’s say you have a product flypage for a widget that comes in several colors. Other than some of the descriptive text, and maybe a hidden field for use in ordering one color instead of another, all the pages look the same. So your page looks like this (extremely simplified):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;... a lot of boilerplate ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;form&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;order_item&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;name&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;sku&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;WDGT-001-RED&amp;#34;&lt;/span&gt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;form&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;... a lot more boilerplate ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Probably the page is generated into a template based on a parameter or path segment:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http://.../app/product/WDGT-001-RED&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;What we’re going to add is a quick-and-dirty way of having your page &lt;em&gt;rewrite itself&lt;/em&gt; on the fly with just the bits that change when you select a different version (or variant) of the same product. E.g.,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;select&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;name&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;sku&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;option&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;WDGT-001-RED&amp;#34;&lt;/span&gt;&amp;gt;Cinnamon Surprise&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;option&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;option&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;WDGT-002-BLK&amp;#34;&lt;/span&gt;&amp;gt;Midnight Delight&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;option&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;option&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;WDGT-003-YLW&amp;#34;&lt;/span&gt;&amp;gt;Banana Rama&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;option&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;select&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The old-school approach was something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;select[name=sku]&amp;#39;&lt;/span&gt;).change(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#038&#34;&gt;document&lt;/span&gt;.location.href = my_url + $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;).val();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; });&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I.e., we’ll just send the browser to re-display the page, but with the selected SKU in the URL instead of where we are now. Slow, clunky, and boring!&lt;/p&gt;
&lt;p&gt;Instead, let’s take advantage of the ability to grab the page from the server and only freshen the parts that change for the desired SKU (warning: this is a bit hand-wavy, as your specifics will change up the code below quite a bit):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// This is subtly wrong:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;$(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;select[name=sku]&amp;#39;&lt;/span&gt;).change(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $.ajax({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;async&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    url: my_url + $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;).val(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    complete: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(data){
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;form#order_item&amp;#39;&lt;/span&gt;).html( $(data.responseText).find(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;form#order_item&amp;#39;&lt;/span&gt;).html() );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Why wrong? Well, any event handlers you may have installed (such as the .change() on our selector!) will fail to fire after the content is replaced, because the contents of the form don’t have those handlers. You could set them up all over again, but there’s a better way:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// This is better:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;$(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;form#order_item&amp;#39;&lt;/span&gt;).on(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;change&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;select[name=sku]&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $.ajax({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;async&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    url: my_url + $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;).val(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    complete: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(data){
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; doc = $(data.responseText);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; $form = $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;form#order_item&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; $clone = $form.clone( &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      $clone.html(doc.find(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;form#order_item&amp;#39;&lt;/span&gt;).html());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      $form.replaceWith($clone);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using an “on” handler for the whole form, with a filter of just the select element we care about, works better—​because when we clone the form, we copy its handler(s), too.&lt;/p&gt;
&lt;p&gt;There’s room for improvement in this solution, because we’re still fetching the entire product display page, even the bits that we’re going to ignore, so we should look at changing the .ajax() call to reference something else—​maybe a custom version of the page that only generates the form and leaves out all the boilerplate. This solution also leaves the browser’s address showing the original product, not the one we selected, so a page refresh will be confusing. There are fixes for both of these, but that’s for another day.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>More jQuery confusion: hidden, disabled fields</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/02/more-jquery-confusion-hidden-disabled/"/>
      <id>https://www.endpointdev.com/blog/2014/02/more-jquery-confusion-hidden-disabled/</id>
      <published>2014-02-24T00:00:00+00:00</published>
      <author>
        <name>Jeff Boes</name>
      </author>
      <content type="html">
        &lt;p&gt;As you may have read in my &lt;a href=&#34;/blog/2014/01/unbalanced-html-considered-harmful-for/&#34;&gt;earlier post&lt;/a&gt;, I have a proclivity for stumbling into oddball bits of jQuery behavior. (Maybe it’s not just me.)&lt;/p&gt;
&lt;p&gt;Here’s another I discovered recently. I was debugging an odd AJAX bug in a form, one of those dynamically updating form widgets in a page:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;select&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;name&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;make&amp;#34;&lt;/span&gt;&amp;gt;...&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;select&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;select&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;name&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;model&amp;#34;&lt;/span&gt;&amp;gt;...&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;select&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;where the first selector sends off an AJAX query to retrieve data to fill the second selector, and it in turn fires off a query to get data for the next, and so on down the line.&lt;/p&gt;
&lt;p&gt;Squirreled away in the form was:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;name&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;limitation&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;disabled&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;disabled&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Supposedly, this input was filled in to restrict the query on some pages, but not all. I think the original author’s intent was to put data in here as it became available, and to toggle the field’s disabled setting when it was pertinent to limit the query. (Mostly, it was pertinent when the second or third selector was firing off its AJAX query.)&lt;/p&gt;
&lt;p&gt;However, a recent change to the code behind this AJAX query created a bug, because the “limitation” parameter was showing up where it wasn’t wanted. The AJAX call was assembling parameters “by hand” (as opposed to the .serialize() method, and that’s where the problem lies!).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;form&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;name&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;secret&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;disabled&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;disabled&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Sue Richards&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;submit&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;form&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you submit this form, the data received by the server won’t include the “secret” field. If you .serialize() it, likewise the data won’t include “secret”’s value. &lt;em&gt;But&lt;/em&gt; if you build up the parameters “by hand”, e.g.,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; data = {};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;data.secret = $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;input[name=secret]&amp;#39;&lt;/span&gt;).val();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And that’s the bug. The short answer is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;data.secret = $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;input[name=secret]&amp;#39;&lt;/span&gt;).not(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;:disabled&amp;#39;&lt;/span&gt;).val();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;because that will at least suppress the unwanted data from being transmitted.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Unbalanced HTML considered harmful for jQuery</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/01/unbalanced-html-considered-harmful-for/"/>
      <id>https://www.endpointdev.com/blog/2014/01/unbalanced-html-considered-harmful-for/</id>
      <published>2014-01-20T00:00:00+00:00</published>
      <author>
        <name>Jeff Boes</name>
      </author>
      <content type="html">
        &lt;p&gt;This isn’t earth-shattering news, but it’s one of those things that someone new to jQuery might trip over so I thought I’d share.&lt;/p&gt;
&lt;p&gt;I had a bad experience recently adding jQuery to an existing page that had less than stellar HTML construction, and I didn’t have time nor budget to clean up the HTML before starting work. Thus, I was working with something much more complex than, but equally broken as what follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;table&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;input&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The jQuery I added did something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;form input&amp;#39;&lt;/span&gt;).css(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;background-color: red&amp;#39;&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and of course, I was quite puzzled when it didn’t work. The pitfall here is that jQuery may or may not be able to handle misconstructed or unbalanced HTML, at least not as well as your average browser, which will shift things around internally until something makes sense to it. The minimal solution is to move the opening and closing “form” tags outside the table.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Using Google Maps and jQuery for Location Search</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/01/using-google-maps-and-jquery-for/"/>
      <id>https://www.endpointdev.com/blog/2014/01/using-google-maps-and-jquery-for/</id>
      <published>2014-01-16T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;margin-bottom:10px;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2014/01/using-google-maps-and-jquery-for/image-0.png&#34;/&gt;&lt;br/&gt;
Example of Google maps showing &lt;a href=&#34;http://www.paper-source.com/&#34;&gt;Paper Source&lt;/a&gt; locations.&lt;/div&gt;
&lt;p&gt;A few months ago, I built out functionality to display physical store locations within a search radius for &lt;a href=&#34;http://www.paper-source.com/&#34;&gt;Paper Source&lt;/a&gt; on an interactive map. There are a few map tools out there to help accomplish this goal, but I chose Google Maps because of my familiarity and past success using it. Here I’ll go through some of the steps to implement this functionality.&lt;/p&gt;
&lt;h3 id=&#34;google-maps-api-key&#34;&gt;Google Maps API Key&lt;/h3&gt;
&lt;p&gt;Before you start this work, you’ll want to get a Google Maps API key. Learn more &lt;a href=&#34;https://developers.google.com/maps/documentation/javascript/tutorial#api_key&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;geocoder-object&#34;&gt;Geocoder Object&lt;/h3&gt;
&lt;p&gt;At the core of our functionality is the use of the &lt;a href=&#34;https://developers.google.com/maps/documentation/javascript/geocoding&#34;&gt;google.maps.Geocoder&lt;/a&gt; object. The Geocoder converts a search point or search string to into geographic coordinates. The most basic use of the geocoder might look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; geocoder = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Geocoder();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//search is a string, input by user
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;geocoder.geocode({ &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;address&amp;#39;&lt;/span&gt; : search }, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(results, status) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(status == &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;ZERO_RESULTS&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;//Indicate to user no location has been found
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  } &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;//Do something with resulting location(s)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;rendering-a-map-from-the-results&#34;&gt;Rendering a Map from the Results&lt;/h3&gt;
&lt;p&gt;After a geocoder results set is acquired, a map and locations might be displayed. A simple and standard implementation of Google Maps can be executed, with the map center set to the geocoder results set center:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; mapOptions = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  center: results[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;].geometry.bounds.getCenter(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  zoom: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;10&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  mapTypeId: google.maps.MapTypeId.ROADMAP
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; map = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Map(&lt;span style=&#34;color:#038&#34;&gt;document&lt;/span&gt;.getElementById(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;map&amp;#34;&lt;/span&gt;), mapOptions);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;searching-within-a-radius&#34;&gt;Searching within a Radius&lt;/h3&gt;
&lt;p&gt;Next up, you may want to figure out how to display a set of locations inside the map bounds. At the time I implemented the code, I found no functionality that automagically did this, so I based my solution off of a few references I found online. The following code excerpt steps through the process:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//search center is the center of the geocoded location
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; search_center = results[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;].geometry.bounds.getCenter();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//Earth&amp;#39;s radius, used in distance calculation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; R = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;6371&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//Step through each location
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;$.each(all_locations, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, loc) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;//Calculate distance from map center
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; loc_position = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(loc.latitude, loc.longitude);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; dLat  = locations.rad(loc.latitude - search_center.lat());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; dLong = locations.rad(loc.longitude - search_center.lng());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; a = &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLat/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLat/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) +
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.cos(locations.rad(search_center.lat())) *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.cos(locations.rad(search_center.lat())) *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLong/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLong/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; c = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt; * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.atan2(&lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sqrt(a), &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sqrt(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;-a));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; d = R * c;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  loc.distance = d;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;//Add the marker to the map
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; marker = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Marker({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    map: map,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    position: loc_position,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    title: loc.store_title
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;//Convert distance to miles (readable distance) for display purposes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  loc.readable_distance = (google.maps.geometry.spherical.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    computeDistanceBetween(search_center, loc_position)*
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0.000621371&lt;/span&gt;).toFixed(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The important thing about this code is that it renders markers for all the locations, but a subset of them will be visible.&lt;/p&gt;
&lt;h3 id=&#34;figuring-out-which-locations-are-visible&#34;&gt;Figuring out which Locations are Visible&lt;/h3&gt;
&lt;p&gt;If you want to display additional information in the HTML related to current visible locations (such as in the screenshot at the top of this post), you might consider using the map.getBounds.contains() method:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; render_locations = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(map) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; included_locations = [];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;//Loop through all locations to determine which locations are contained in the map boundary
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  $.each(all_locations, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, loc) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(map.getBounds().contains(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(loc.latitude, loc.longitude))) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            _push(loc);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;// sort locations by distance if desired
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;// render included_locations
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The above code determines which locations are visible, sorts those locations by readable distance, and then those locations are rendered in the HTML.&lt;/p&gt;
&lt;h3 id=&#34;adding-listeners&#34;&gt;Adding Listeners&lt;/h3&gt;
&lt;p&gt;After you’ve got your map and location markers added, a few map listeners will add more functionality, described below:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; listener = google.maps.event.addListener(map, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  render_locations(map);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  google.maps.event.addListener(map, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;center_changed&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    render_locations(map);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  google.maps.event.addListener(map, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;zoom_changed&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    render_locations(map);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After the map has loaded (via the map “idle” event), render_locations is called to render the HTML for visible locations. This method is also triggered any time the map center or zoom level is changed, so the HTML to the left of the map is updated whenever a user modifies the map bounds.&lt;/p&gt;
&lt;h3 id=&#34;advanced-elements&#34;&gt;Advanced Elements&lt;/h3&gt;
&lt;p&gt;Two advanced pieces implemented were the use of extending the map bounds and modifying listeners in a mobile environment. When it was desired that the map explicitly contain a set of locations within the map bounds, the following code was used:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; current_bounds = results[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;].geometry.bounds;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$.each(locations_to_include, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, loc) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  current_bounds.extend(loc_position);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;map.fitBounds(current_bounds);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And in a mobile environment, it was desired to disable various map options such as draggability, zoomability, and scroll wheel use. This was done with the following conditional:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;($(&lt;span style=&#34;color:#038&#34;&gt;window&lt;/span&gt;).width() &amp;lt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;656&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  map.setOptions({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    draggable: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zoomControl: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    scrollwheel: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    scrollwheel: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    disableDoubleClickZoom: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    streetViewControl: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Of course, all the code shown above is just in snippet form. Many of the building blocks described above were combined to build a user-friendly map feature. There are a lot of additional map features – &lt;a href=&#34;https://developers.google.com/maps/documentation/webservices/&#34;&gt;check out the documentation&lt;/a&gt; to learn more.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Pagination days are over? Infinite scrolling technique</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/11/pagination-days-are-over-infinite/"/>
      <id>https://www.endpointdev.com/blog/2013/11/pagination-days-are-over-infinite/</id>
      <published>2013-11-15T00:00:00+00:00</published>
      <author>
        <name>Marina Lohova</name>
      </author>
      <content type="html">
        &lt;p&gt;Love it or hate it, but the infinite scrolling technique became a big part of UX. Google Images use it, Flickr uses it, Beyonce’s official website uses it. Twitter, Tumblr and the Facebook feed have it as well. The technique allows users to seamlessly scroll through content. When the user reaches the end of the page new content will automatically load at the bottom.&lt;/p&gt;
&lt;p&gt;In my opinion, it allows for a much more natural and immersive experience while viewing images or articles, much better than pagination or once popular image slideshow galleries. In the real life you don’t click on pagination links to get through your day, right?&lt;/p&gt;
&lt;p&gt;To create the infinite scrolling page with images we will use the &lt;a href=&#34;https://github.com/paulirish/infinite-scroll&#34;&gt;jQuery Infinite Scroll&lt;/a&gt; plugin and &lt;a href=&#34;https://masonry.desandro.com/&#34;&gt;Masonry&lt;/a&gt; to lay out the images. Here is the &lt;a href=&#34;https://infinite-scroll.com/demo/masonry/&#34;&gt;demo&lt;/a&gt; of what we are going to accomplish. The code is below.&lt;/p&gt;
&lt;p&gt;First step is to include the necessary scripts:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;script src=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/javascripts/jquery.min.js&amp;#34;&lt;/span&gt; type=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#080;background-color:#fff0ff&#34;&gt;/script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;background-color:#fff0ff&#34;&gt;&amp;lt;script src=&amp;#34;/&lt;/span&gt;javascripts/jquery.masonry.min.js&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34; type=&amp;#34;&lt;/span&gt;text/javascript&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;lt;script src=&amp;#34;&lt;/span&gt;/javascripts/jquery.infinitescroll.min.js&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34; type=&amp;#34;&lt;/span&gt;text/javascript&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add the container element. The navigation element is a very important part that triggers the loading of the subsequent page. After the second page the page number will automatically increment to fetch the subsequent pages:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;container&amp;#34;&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&amp;lt;&lt;/span&gt;% @images.each do |i| %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;item&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;img&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt;/&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&amp;lt;&lt;/span&gt;% end %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;nav&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;page-nav&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;style&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;display: none;&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;href&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/?p=2&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;nav&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Ready to init the infinite scrolling script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; container = $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#container&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    container.masonry({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       itemSelector: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;.item&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    container.infinitescroll({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      navSelector  : &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#page-nav&amp;#39;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      nextSelector : &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#page-nav a&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      itemSelector : &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;.item&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      loading: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          finishedMsg: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;No more pages to load.&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          img: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;http://i.imgur.com/6RMhx.gif&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;( newElements ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; newElems = $( newElements ).css({ opacity: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          newElems.animate({ opacity: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          container.masonry( &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;appended&amp;#39;&lt;/span&gt;, $newElems, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the user scrolls down to the bottom of the first page, the script will fetch the second page and filter out the new elements by the item selector. The controller action will look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;list&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#33b&#34;&gt;@images&lt;/span&gt; = &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Image&lt;/span&gt;.paginate(&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:page&lt;/span&gt; =&amp;gt; params[&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:p&lt;/span&gt;] || &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:per_page&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;25&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, we will add the styles to create a three-column layout and some nice animations to render the newly loaded items:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;container&lt;/span&gt; .&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;item&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;width&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;33&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;%&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;transitions-enabled&lt;/span&gt;.&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;masonry&lt;/span&gt; .&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;masonry-brick&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;transition-property&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;left&lt;/span&gt;, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;right&lt;/span&gt;, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;top&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;transitions-enabled&lt;/span&gt;.&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;masonry&lt;/span&gt;, .&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;transitions-enabled&lt;/span&gt;.&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;masonry&lt;/span&gt; .&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;masonry-brick&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;transition-duration&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0.7&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;s&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


      </content>
    </entry>
  
    <entry>
      <title>IE7 “Enhances” href Attributes of Links Added via innerHTML</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/11/ie7-href-attributes-of-links-added-via/"/>
      <id>https://www.endpointdev.com/blog/2013/11/ie7-href-attributes-of-links-added-via/</id>
      <published>2013-11-07T00:00:00+00:00</published>
      <author>
        <name>Greg Davidson</name>
      </author>
      <content type="html">
        &lt;p&gt;I ran into this issue the other day while testing a new feature for a client site. The code worked well in Chrome, Firefox, Safari and IE (8-11) but it blew up in IE7. The page was fairly straightforward—​I was using jQuery and the excellent &lt;a href=&#34;http://olado.github.io/doT/index.html&#34;&gt;doT.js templating library&lt;/a&gt; to build up some HTML and add it to the page after the DOM had loaded. This content included several links like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;href&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;#panel1&amp;#34;&lt;/span&gt;&amp;gt;More Info&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;href&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;#panel2&amp;#34;&lt;/span&gt;&amp;gt;More Info&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;href&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;#panel3&amp;#34;&lt;/span&gt;&amp;gt;More Info&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;a&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Each of the links pointed to their corresponding counterparts which had also been added to the page. The JavaScript code in question responded to clicks on the “More Info” links and used their href attribute as a jQuery selector:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;.my-links&amp;#39;&lt;/span&gt;).on(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;click&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(e) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      e.preventDefault();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; sel = $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;).attr(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;href&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;links-enhanced-by-ie7&#34;&gt;Links “Enhanced” By IE7&lt;/h3&gt;
&lt;p&gt;As I debugged in IE7, I determined that it was adding the fully qualified domain name to the links. Instead of “#panel2” the href attributes were set to “http://example.com/#panel2” which broke things—​especially my jQuery selectors. Fixing the issue was straightforward at this point:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// fix hrefs in IE7 and 6
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; ( &lt;span style=&#34;color:#080;background-color:#fff0ff&#34;&gt;/^http/&lt;/span&gt;.test(href) ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sel = sel.substr(href.indexOf(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#&amp;#39;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When the href attribute begins with http, discard everything before the hash (#).&lt;/p&gt;
&lt;h3 id=&#34;digging-deeper&#34;&gt;Digging Deeper&lt;/h3&gt;
&lt;p&gt;Although the problem had been solved, I was still curious as to why this was happening. While the .href property (e.g. myAnchor.href) of a link will return the entire domain in all browsers, getAttribute(&amp;lsquo;href&amp;rsquo;) will return only the text of the attribute. I believe the $.attr() method from jQuery is using getAttribute() behind the scenes. For modern browsers, calling $.attr() or getAttribute() worked as I was expecting.&lt;/p&gt;
&lt;p&gt;However IE 6 and 7 had different ideas about this:&lt;/p&gt;
&lt;img alt=&#34;Ie7 demo&#34; border=&#34;0&#34; height=&#34;355&#34; src=&#34;/blog/2013/11/ie7-href-attributes-of-links-added-via/image-0.png&#34; title=&#34;ie7-demo.png&#34; width=&#34;550&#34;/&gt; 
&lt;p&gt;Notice that the fully qualified domain name is prepended to the href attribute in the first example.&lt;/p&gt;
&lt;p&gt;When links are added to the page &lt;em&gt;via innerHTML&lt;/em&gt;, IE includes/prepends the full URL. However, when links are added to the page via the createElement function they remain unscathed.&lt;/p&gt;
&lt;p&gt;The following screenshot demonstrates how Chrome and other modern browsers handle the same code:&lt;/p&gt;
&lt;img alt=&#34;Chrome demo&#34; border=&#34;0&#34; height=&#34;385&#34; src=&#34;/blog/2013/11/ie7-href-attributes-of-links-added-via/image-1.png&#34; title=&#34;chrome-demo.png&#34; width=&#34;550&#34;/&gt;
&lt;p&gt;These browsers happily leave the href attributes alone :)&lt;/p&gt;
&lt;p&gt;You learn something new every day!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>jQuery contents() method</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/11/jquery-contents-method/"/>
      <id>https://www.endpointdev.com/blog/2013/11/jquery-contents-method/</id>
      <published>2013-11-04T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;p&gt;I had an interesting JavaScript challenge recently and came across a jQuery method that I hadn’t heard of before, so I wanted to share my experience. Given the following markup, I needed a way to hide all the text not inside span.highlighted elements:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;Here is some text. 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlighted&amp;#34;&lt;/span&gt;&amp;gt;Here is more text! &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Here is even more text! Here is some more un-wrapped text. 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlighted&amp;#34;&lt;/span&gt;&amp;gt;Here is another wrapped span.&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With standard CSS rules like visibility, display, and opacity, there’s not an easy way to hide only the unhighlighted text without additional HTML modifications. So, I set out to wrap the unhighlighted text in additional HTML elements dynamically, to produce the following markup from our example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;unhighlighted&amp;#34;&lt;/span&gt;&amp;gt;Here is some text. &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlighted&amp;#34;&lt;/span&gt;&amp;gt;Here is more text! &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;unhighlighted&amp;#34;&lt;/span&gt;&amp;gt;Here is even more text! Here is some more un-wrapped text. &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlighted&amp;#34;&lt;/span&gt;&amp;gt;Here is another wrapped span.&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With the markup above, the CSS rules to hide the desired spans would look something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;.&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;unhighlighted&lt;/span&gt; { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;display&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;none&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;.&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;highlighted&lt;/span&gt; { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;display&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;inline-block&lt;/span&gt;; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The challenge was how to wrap the unwrapped text inside the paragraph without having any DOM elements to select? My first clumsy attempt was using regular expressions, which looked something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; matches = $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;p&amp;#39;&lt;/span&gt;).html().match(&lt;span style=&#34;color:#080;background-color:#fff0ff&#34;&gt;/&amp;lt;span class=&amp;#34;highlighted.*?&amp;#34;&amp;lt;.*?&amp;lt;\/span&amp;gt;/g&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; non_matches = $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;p&amp;#39;&lt;/span&gt;).html().split(&lt;span style=&#34;color:#080;background-color:#fff0ff&#34;&gt;/&amp;lt;span class=&amp;#34;highlighted.*?&amp;#34;&amp;gt;.*?&amp;lt;\/span&amp;gt;/&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; b = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt;(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; _i=&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;; _i&amp;lt;non_matches.length; _i++) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(non_matches[i] != &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    b += &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;span class=&amp;#34;unhighlighted&amp;#34;&amp;gt;&amp;#39;&lt;/span&gt; + non_matches[i] + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;/span&amp;gt;&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(matches[i] !== &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;undefined&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    b += matches[i];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;p&amp;#39;&lt;/span&gt;).html(b);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the code above, I create two arrays—​one that includes the unhighlighted text and one that includes the highlighted spans and their content with a non-greedy regular expression. I incremented through these arrays and built HTML with alternating newly wrapped unhighlighted content and existing highlighted spans. At the end of the loop, the paragraph HTML is updated with the new HTML. Now, there are quite a few edge cases with this method which needed to be addressed &lt;strong&gt;and&lt;/strong&gt; the bigger issue I came across was that the highlighted spans were being rewritten, so any important data tied to the overwritten highlighted spans was lost with the HTML update. I felt that this implementation was overcomplicated and went in search of something more simple.&lt;/p&gt;
&lt;h3 id=&#34;jquery-contents&#34;&gt;jQuery contents()&lt;/h3&gt;
&lt;p&gt;Enter the &lt;a href=&#34;https://api.jquery.com/contents/&#34;&gt;jQuery.contents()&lt;/a&gt; method. This method returns the children nodes of an element (or elements) in an array form, including(!) text and comment nodes. The console output of the contents() method for our example paragraph might look like:&lt;/p&gt;
&lt;img src=&#34;/blog/2013/11/jquery-contents-method/image-0.png&#34; style=&#34;border:1px solid #000;&#34;/&gt;
&lt;p&gt;Example output from the contents() method.&lt;/p&gt;
&lt;p&gt;This was just the tool I was looking for: I wanted a simple way to iterate through text and span elements from my existing paragraph, without replacing exising span elements. The following JavaScript shows incremental through the contents() array and wrapping text elements with the new markup:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; contents = $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;p&amp;#39;&lt;/span&gt;).contents();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt;(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; _i = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;; _i &amp;lt; contents.length; _i++) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(contents[_i].nodeType == &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;) { &lt;span style=&#34;color:#888&#34;&gt;//conditional indicates match on TextNode
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; updated = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;span class=&amp;#34;unhighlighted&amp;#34;&amp;gt;&amp;#39;&lt;/span&gt; + $(contents[_i]).text() + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;/span&amp;gt;&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $(contents[_i]).replaceWith(updated); 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I then have the ability to toggle the visibility of both the highlighted and unhighlighted spans for the desired functionality. I’ve been working with jQuery for a long time and was happy to browse through the documentation to find this little gem!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Fixed Navigation Bar: HTML, CSS, and JavaScript Breakdown</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/09/fixed-navigation-bar-html-css-and/"/>
      <id>https://www.endpointdev.com/blog/2013/09/fixed-navigation-bar-html-css-and/</id>
      <published>2013-09-02T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;p&gt;Something that I’ve seen frequently these days on content rich sites are fixed navigation bars, or small abbreviated header in the form of a horizontal bar at the top of the screen that shows after a user has scrolled below the header. Here’s an example:&lt;/p&gt;
&lt;p&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2013/09/fixed-navigation-bar-html-css-and/image-0.png&#34; width=&#34;740px;&#34;/&gt;&lt;br&gt;
A live example of an abbreviated fixed navigation bar at the top of the articles at &lt;a href=&#34;http://abcnews.go.com/&#34;&gt;ABCNews.com&lt;/a&gt;. The background has a grey opaque layer for demonstration purposes only.&lt;/p&gt;
&lt;p&gt;I recently implemented this functionality for &lt;a href=&#34;http://cyber.law.harvard.edu/research/h2o&#34;&gt;H2O&lt;/a&gt;, and I’ll go through the tools needed to do this.&lt;/p&gt;
&lt;h3 id=&#34;html-markup&#34;&gt;HTML Markup&lt;/h3&gt;
&lt;p&gt;First thing’s first, you need the HTML markup for this. The only tricky thing here is that the horizontal bar must be outside of any wrapping dividers on the page that are confining the content to a set width. For example, if your content is limited to 900 pixels in width, the horizontal bar markup must be outside that constraint. Here’s what the HTML might look like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;fixed_bar&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;wrapper&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Links &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&amp;amp;&lt;/span&gt; content here.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that in the above HTML, the “wrapper” div may be constraining the content width to match the remaining content, such as in the example above. This HTML may go at the beginning or end of the page HTML. I prefer to see it at the top of the page HTML. Another note is that other HTML elements may be used in place of the div, but I chose the div above because it defaults to a block element (an element where the CSS display default value is block).Finally, one more note here is that HTML5 elements can be used in place of the div as well (section or nav might make sense) if the site is HTML5 compliant.&lt;/p&gt;
&lt;h3 id=&#34;css-settings&#34;&gt;CSS Settings&lt;/h3&gt;
&lt;p&gt;The secret to this interactive feature lies in the CSS settings. Here’s what the CSS for my example code above might look like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;body&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;margin&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;padding&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;fixed_bar&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;width&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;%&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;position&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;fixed&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;z-index&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt;; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;//exceed&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;z-index&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;of&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;other&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;elements&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;on&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;the&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;page&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;display&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;none&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;background&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;transparent&lt;/span&gt; &lt;span style=&#34;color:#038&#34;&gt;url&lt;/span&gt;(&lt;span style=&#34;color:#2b2;background-color:#f0fff0&#34;&gt;/images/fixed_bar.png&lt;/span&gt;) &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;bottom&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;repeat-x&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;top&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;wrapper&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;width&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;900&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;margin&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;px&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;auto&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here are the important bits of the CSS above:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The fixed positioning setting is what keeps the bar in one place as the user scrolls up and down (line 7).&lt;/li&gt;
&lt;li&gt;The body must have margin and padding settings at 0px to ensure that the fixed bar is flush against the top of the screen (line 2 &amp;amp; 3).&lt;/li&gt;
&lt;li&gt;The fixed bar spans the width of the browser, but in this case, the .wrapper element is constrained to 900 pixels wide (line 14).&lt;/li&gt;
&lt;li&gt;The default state of the #fixed_bar element is none, which is hidden upon page load (line 9).&lt;/li&gt;
&lt;li&gt;The background of the #fixed_bar can be a small image with a gradient to transparency, such as in the example above (line 10).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;scroll-event-listener&#34;&gt;Scroll Event Listener&lt;/h3&gt;
&lt;p&gt;Finally, after the HTML and CSS markup is good to go, here’s what the interactive JavaScript (via jQuery) might look like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; offset = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt;; &lt;span style=&#34;color:#888&#34;&gt;// some offset value for which when the header becomes hidden
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;jQuery(&lt;span style=&#34;color:#038&#34;&gt;window&lt;/span&gt;).scroll(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() { &lt;span style=&#34;color:#888&#34;&gt;//also an option: jQuery .on(&amp;#39;scroll&amp;#39;) method
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(jQuery(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#fixed_bar&amp;#39;&lt;/span&gt;).is(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;:visible&amp;#39;&lt;/span&gt;) &amp;amp;&amp;amp; jQuery(&lt;span style=&#34;color:#038&#34;&gt;window&lt;/span&gt;).scrollTop() &amp;lt; offset) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    jQuery(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#fixed_bar&amp;#39;&lt;/span&gt;).fadeOut(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;200&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(!jQuery(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#fixed_bar&amp;#39;&lt;/span&gt;).is(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;:visible&amp;#39;&lt;/span&gt;) &amp;amp;&amp;amp; jQuery(&lt;span style=&#34;color:#038&#34;&gt;window&lt;/span&gt;).scrollTop() &amp;gt; offset) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    jQuery(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#fixed_bar&amp;#39;&lt;/span&gt;).fadeIn(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;200&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The jQuery above checks for two scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a) If the #fixed_bar div is visible and the scroll position is less than the offset, fade the #fixed_bar div to a hidden state.&lt;/li&gt;
&lt;li&gt;b) If the #fixed_bar div is not visible and the scroll position is greater than the offset, fade the #fixed_bar div to a visible state.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These two use cases will toggle the visibility of the fixed bar to a hidden and visible state. With these combined elements of HTML, CSS, and jQuery &amp;amp; JavaScript, a nice user interactivity feature adds to the usability of the site by providing valuable links and content as the user scrolls down the page.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Paper Source Case Study with Google Maps API</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/03/paper-source-case-study-with-google/"/>
      <id>https://www.endpointdev.com/blog/2013/03/paper-source-case-study-with-google/</id>
      <published>2013-03-29T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;img alt=&#34;Basic Google map with location markers&#34; border=&#34;0&#34; src=&#34;/blog/2013/03/paper-source-case-study-with-google/image-0.png&#34;/&gt;
&lt;p&gt;Recently, I’ve been working with the &lt;a href=&#34;https://developers.google.com/maps/&#34;&gt;Google Maps API&lt;/a&gt; for Paper Source, one of our large &lt;a href=&#34;/expertise/perl-interchange/&#34;&gt;Interchange&lt;/a&gt; clients with over 40 physical stores throughout the US.&lt;/p&gt;
&lt;p&gt;On their website, they had previously been managing static HTML pages for these 40 physical stores to share store information, location, and hours. They wanted to move in the direction of something more dynamic with interactive maps. After doing a bit of research on search options out there, I decided to go with the Google Maps API. This article discusses basic implementation of map rendering, search functionality, as well as interesting edge case behavior.&lt;/p&gt;
&lt;h3 id=&#34;basic-map-implementation&#34;&gt;Basic Map Implementation&lt;/h3&gt;
&lt;p&gt;In its most simple form, the markup required for adding a basic map with markers is the shown below. Read more at &lt;a href=&#34;https://developers.google.com/maps/&#34;&gt;Google Maps Documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h5 id=&#34;html&#34;&gt;HTML&lt;/h5&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;map&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h5 id=&#34;css&#34;&gt;CSS&lt;/h5&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#map {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  height: 500px;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  width: 500px;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h5 id=&#34;javascript&#34;&gt;JavaScript&lt;/h5&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//mapOptions defined here
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; mapOptions = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  center: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;40&lt;/span&gt;, -&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;98&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  zoom: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  mapTypeId: google.maps.MapTypeId.ROADMAP
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//map is the HTML DOM element ID where it will be rendered
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; map = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Map(&lt;span style=&#34;color:#038&#34;&gt;document&lt;/span&gt;.getElementById(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;map&amp;#34;&lt;/span&gt;), mapOptions);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//all locations is a JSON object representing locations,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//where each location has a latitude and longitude
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;$.each(all_locations, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, loc) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; marker = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Marker({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    map: map,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    position: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(loc.latitude, loc.longitude)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;building-search-functionality&#34;&gt;Building Search Functionality&lt;/h3&gt;
&lt;img alt=&#34;Search interface: search results are listed on the left, and map with markers is shown on the right&#34; border=&#34;0&#34; src=&#34;/blog/2013/03/paper-source-case-study-with-google/image-1.png&#34; width=&#34;700&#34;/&gt;
&lt;p&gt;Next up, I needed to build out search functionality. Google has its own geocoder to allow address searches. Here is the basic markup for running a search:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; geocoder = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Geocoder();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//search is a variable representing the user search, such as a zip code, city name, or state name
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;geocoder.geocode({ &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;address&amp;#39;&lt;/span&gt; : search }, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(results, status) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; search_center = results[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;].geometry.bounds.getCenter();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; mapOptions = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    center: search_center,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zoom: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;10&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mapTypeId: google.maps.MapTypeId.ROADMAP
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; map = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Map(&lt;span style=&#34;color:#038&#34;&gt;document&lt;/span&gt;.getElementById(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;map&amp;#34;&lt;/span&gt;), mapOptions);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $.each(all_locations, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, loc) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; marker = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Marker({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      map: map,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      position: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(loc.latitude, loc.longitude)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above code, the search term is passed into the Geocoder object and a map with all locations marked is rendered. To determine which markers are in the visible map boundaries, the following map.getBounds().contains() method would be leveraged:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; visible_locations = [];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$.each(all_locations, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, loc) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(map.getBounds().contains(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(loc.latitude, loc.longitude))) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    visible_locations.push(loc);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;//render visible locations to the left of the map
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;One final step here is to add a listener to the map, so that visible locations are updated when the user zooms in and out. This is accomplished with the following listener:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;google.maps.event.addListener(map, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;zoom_changed&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;//call method to rerender visible locations
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;handling-zero-results&#34;&gt;Handling Zero Results&lt;/h3&gt;
&lt;p&gt;What happens if your Geocoder object can’t find the address? A simple conditional can be used:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;geocoder.geocode({ &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;address&amp;#39;&lt;/span&gt; : search }, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(results, status) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(status == &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;ZERO_RESULTS&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;//notify customer that no results have been found
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  } &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;//got results, render location
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;calculate-and-sort-by-distance&#34;&gt;Calculate and Sort by Distance&lt;/h3&gt;
&lt;p&gt;The next layer of logic I needed to add was the ability to determine the distance between the search address and sort the results by distance. To calculate distance, I did some research and settled on the following code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; R = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;6371&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$.each(all_locations, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, loc) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; loc_position = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(loc.latitude, loc.longitude);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; dLat  = locations.rad(loc.latitude - search_center.lat());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; dLong = locations.rad(loc.longitude - search_center.lng());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;//calculate spherical distance between search position and location
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; a = &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLat/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLat/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) +
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.cos(locations.rad(search_center.lat())) *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.cos(locations.rad(search_center.lat())) *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLong/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLong/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; c = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt; * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.atan2(&lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sqrt(a), &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sqrt(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;-a));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; d = R * c;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  loc.distance = d;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;//convert distance to miles
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  loc.readable_distance =
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (google.maps.geometry.spherical.computeDistanceBetween(search_center, loc_position) *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0.000621371&lt;/span&gt;).toFixed(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To sort the locations by distance, I leverage jQuery sort:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; sort_by_distance = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(obj) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; obj.sort(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(a, b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(a.distance &amp;gt; b.distance) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; -&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; sorted_locations = sort_by_distance(all_locations);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;adjust-map-boundaries-to-include-specific-markers&#34;&gt;Adjust Map Boundaries to Include Specific Markers&lt;/h3&gt;
&lt;p&gt;Another interesting use case I needed to handle was forcing the map to zoom out to include stores within 100 miles if there was nothing in the initial map boundaries, e.g.:&lt;/p&gt;
&lt;img border=&#34;0&#34; src=&#34;/blog/2013/03/paper-source-case-study-with-google/image-2.png&#34; width=&#34;700&#34;/&gt;
&lt;p&gt;The search for &amp;ldquo;27103&amp;rdquo; doesn’t return any nearby stores, so the map is extended to include stores within 100 miles.&lt;/p&gt;
&lt;p&gt;To accomplish this functionality, I added a bit of code to extend the map boundaries:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;geocoder.geocode({ &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;address&amp;#39;&lt;/span&gt; : search }, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(results, status) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; search_center = results[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;].geometry.bounds.getCenter();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; mapOptions = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    center: search_center,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zoom: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;10&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mapTypeId: google.maps.MapTypeId.ROADMAP
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; map = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Map(&lt;span style=&#34;color:#038&#34;&gt;document&lt;/span&gt;.getElementById(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;map&amp;#34;&lt;/span&gt;), mapOptions);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; current_bounds = results[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;].geometry.bounds;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $.each(all_locations, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, loc) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; loc_position = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(loc.latitude, loc.longitude);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; dLat  = locations.rad(loc.latitude - search_center.lat());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; dLong = locations.rad(loc.longitude - search_center.lng());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;//calculate spherical distance between search position and location
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; a = &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLat/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLat/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) +
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.cos(locations.rad(search_center.lat())) *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.cos(locations.rad(search_center.lat())) *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLong/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;) * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sin(dLong/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; c = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt; * &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.atan2(&lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sqrt(a), &lt;span style=&#34;color:#038&#34;&gt;Math&lt;/span&gt;.sqrt(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;-a));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; d = R * c;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    loc.distance = d;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;//convert distance to miles
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;    loc.readable_distance =
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (google.maps.geometry.spherical.computeDistanceBetween(search_center, loc_position) *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0.000621371&lt;/span&gt;).toFixed(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; marker = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.Marker({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      map: map,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      position: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; google.maps.LatLng(loc.latitude, loc.longitude)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(loc.readable_distance &amp;lt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      current_bounds.extend(loc_position);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;//Google map method to fit map boundaries to desired boundaries
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  map.fitBounds(current_bounds);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;disable-scroll-and-zoom-on-mobile-sized-devices&#34;&gt;Disable Scroll and Zoom on Mobile-Sized Devices&lt;/h3&gt;
&lt;p&gt;One final behavior needed was to disable map zooming and scrolling on mobile devices, to improve the usability on mobile/touch interfaces. Here’s how this was accomplished:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; options_listener = google.maps.event.addListener(map, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;($(&lt;span style=&#34;color:#038&#34;&gt;window&lt;/span&gt;).width() &amp;lt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;656&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    map.setOptions({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      draggable: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      zoomControl: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      scrollwheel: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      disableDoubleClickZoom: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      streetViewControl: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  google.maps.event.removeListener(options_listener);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;With all this code, the final location search functionality includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Basic United States map rendering to display all physical store locations.&lt;/li&gt;
&lt;li&gt;Search by location which shows stores within 100 miles, and allows users to zoom in and out to adjust their search. Search lists results sorted by distance.&lt;/li&gt;
&lt;li&gt;“Saved” or “Quick” searches by states, which displays all physical stores by state.&lt;/li&gt;
&lt;li&gt;Adjustment of mobile display map options.&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
  
    <entry>
      <title>Data binding in web applications</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/03/data-binding-in-web-applications/"/>
      <id>https://www.endpointdev.com/blog/2013/03/data-binding-in-web-applications/</id>
      <published>2013-03-06T00:00:00+00:00</published>
      <author>
        <name>Kamil Ciemniewski</name>
      </author>
      <content type="html">
        &lt;p&gt;Ever since JavaScript was introduced the world of web programming has constantly been visited by creative minds, ready to solve burning problems web developers were experiencing.&lt;/p&gt;
&lt;p&gt;Navigating through some of the oldest web-dev articles, we still can feel the pain of manipulating the DOM, the-vanilla-way and creating ever so clever hacks to make the code work on all of the web browsers.&lt;/p&gt;
&lt;p&gt;Then, the JS-frameworks epidemy started to disseminate. As web developers—​we started to have some powerful tools. The productivity of average nerdy Joe raised immediately as he started using Prototype.js, Mootools or jQuery.&lt;/p&gt;
&lt;h3 id=&#34;evolution-of-ui-programming-for-browsers&#34;&gt;Evolution of UI programming for browsers&lt;/h3&gt;
&lt;p&gt;And so was the start of our global evolution, towards making the Web—​our main means of interacting with &lt;em&gt;users&lt;/em&gt;. Few with big enough imagination were already seeing HTML, CSS &amp;amp; JS as the future standard of creating user interfaces for data-rich applications. Of course, there were toolkits like ExtJS which aimed at nothing but this—​but who would have known back then, that we will be able to build apps for &lt;strong&gt;smartphones&lt;/strong&gt; the way we are building ones for the web?&lt;/p&gt;
&lt;p&gt;I have my little observation in life — all &lt;em&gt;hot stuff&lt;/em&gt; in the world of technology, has their &lt;em&gt;phases&lt;/em&gt;. That is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;they don’t exist, but the problems they solve do and they are &lt;strong&gt;painful&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;they show up, and there is massive excitement&lt;/li&gt;
&lt;li&gt;people discover new pains brought on by these solutions&lt;/li&gt;
&lt;li&gt;next pain and the beginning of the “next big thing”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At the beginning it was painful to write all the &lt;em&gt;vanilla&lt;/em&gt; JS code without shooting yourself in your own foot (well let’s just say it—​JS is Pandora’s Box of pain). Then you realize you’ve got your sweet &amp;amp; cool jQuery with which you can rapidly impress your boss/clients/friends.&lt;/p&gt;
&lt;p&gt;Your next surprise is that jQuery isn’t enough—​ever wondered why frameworks like Backbone.js were created?&lt;/p&gt;
&lt;h3 id=&#34;data-binding&#34;&gt;Data binding&lt;/h3&gt;
&lt;p&gt;Here is the challenge for you: write GMail web interface clone using &lt;strong&gt;just&lt;/strong&gt; jQuery. Here is the spoiler: you’d get lost in managing your app’s &lt;em&gt;state&lt;/em&gt;—​and syncing UI to reflect it. In fact—​even small &lt;em&gt;todo&lt;/em&gt; app in vanilla jQuery could end up being quite complicated. That’s just not the way other folks are dealing with UI programming. A long time ago they were—​but they got smarter. We can learn from their mistakes.&lt;/p&gt;
&lt;p&gt;When I was beginning my journey into the world of professional programming, I was given a job of creating small business app with C# and Windows Forms. Despite the fact that in the world of desktop apps you have to be mindful of much more things than in the web/browsers world (like updating your UI only on the main thread), the whole experience was pretty much the same as with vanilla jQuery:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;create inputs&lt;/li&gt;
&lt;li&gt;subscribe to its events&lt;/li&gt;
&lt;li&gt;write the code that updates inner state based on the state of those inputs/controls&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This quickly gets very cumbersome as the needs grows. You could have a requirement that one set of inputs is dependent on another, which results in hours of coding and more hours in debugging.&lt;/p&gt;
&lt;p&gt;The way &lt;em&gt;smart devs&lt;/em&gt; are tackling this issue is called &lt;em&gt;data binding&lt;/em&gt;. This simply means that you &lt;em&gt;tell&lt;/em&gt; specific portion of UI to be &lt;em&gt;bound&lt;/em&gt; to some value from your business layer.&lt;/p&gt;
&lt;p&gt;One nice example of the framework that employs data binding is Apple’s Cocoa. The XCode even has nice visual tools to bind controls values with the data model. Another example of the framework that uses data binding extensively is WPF (Windows Presentation Foundation). The concept widely used there is the MVVM pattern (Model-View-ViewModel). Which basically says that you have your &lt;em&gt;view model&lt;/em&gt; object and UI which is bound to the view model and all you have to do is to manage the view model.&lt;/p&gt;
&lt;p&gt;That’s the core concept here: &lt;strong&gt;managing objects is much easier than managing UI&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;data-binding-on-web&#34;&gt;Data binding on web&lt;/h3&gt;
&lt;p&gt;As the need came with more and more amazing web apps—​we now have quite a nice choice when it comes to employing data binding:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://angularjs.org/&#34;&gt;Angular.js&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Angular.js is one of the most impressive front-end JS frameworks there are. It has view templates mechanism allowing you to specify your binding statements directly there.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://emberjs.com/&#34;&gt;Ember.js&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ember.js gains popularity every day. Just like Angular.js, it has its own nice templating language (handlebars) which allows you to have your binding statements in the markup too.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://knockoutjs.com/&#34;&gt;Knockout.js&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you don’t want to use any of those frameworks, that’s a great library that implements &lt;strong&gt;just&lt;/strong&gt; the data binding part.&lt;/p&gt;
&lt;p&gt;It uses the concept I described before: the MVVM pattern. You are simply defining your view model and telling your UI where it has to get values from and that’s it.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://backbonejs.org/&#34;&gt;Backbone.js&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But what if you’d like to use Backbone.js? It’s true that it’s amazing and is one neat piece of technology you can use to build your next ‘cool app’. There is one caveat though: you have to set up all the niceties that comes along with Angular.js or Ember.js yourself, including all the sweetness of data binding.&lt;/p&gt;
&lt;h3 id=&#34;backbonejs--knockoutjs&#34;&gt;Backbone.js + Knockout.js&lt;/h3&gt;
&lt;p&gt;Here is a simple way of using Knockout.js with Backbone.js:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;for every Backbone.js view, define complementary view model&lt;/li&gt;
&lt;li&gt;put ‘ko.applyBindings’ at the end of your ‘render’ method&lt;/li&gt;
&lt;li&gt;do not use any logic in your view templates—​rely solely on data binding&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So for example:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;# app/views/photos.coffee&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;module.exports = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;PhotosView&lt;/span&gt; extends Backbone.View
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   template: require &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;./templates/photos/index&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   initialize: () -&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#555&#34;&gt;@view&lt;/span&gt; = new PhotosViewModel()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#555&#34;&gt;@render&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   render: () -&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;$&lt;/span&gt;(&lt;span style=&#34;color:#555&#34;&gt;@el&lt;/span&gt;).html(&lt;span style=&#34;color:#555&#34;&gt;@template&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       ko.applyBindings(&lt;span style=&#34;color:#555&#34;&gt;@view&lt;/span&gt;, &lt;span style=&#34;color:#555&#34;&gt;@el&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   setData: (photos) =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#555&#34;&gt;@view.photos&lt;/span&gt;(photos)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;PhotosViewModel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   constructor: -&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#555&#34;&gt;@photos&lt;/span&gt; = ko.observableArray []&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;# app/views/templates/photos/index.eco&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;ul&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;data-bind&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;foreach: photos&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;img&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;data-bind&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;attr: {src: $data.get(&amp;#39;url&amp;#39;)}&amp;#34;&lt;/span&gt;/&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;ul&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now—​with this, you can manipulate the photos array however you like, and the UI will get auto-updated on its own. But this idea shines the most when it comes to implementing forms with it. Take a look at the following example:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;# app/views/company.coffee&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;module.exports = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;EditCompanyView&lt;/span&gt; extends Backbone.View
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   template: require &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;./templates/companies/edit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   initialize: () -&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#555&#34;&gt;@view&lt;/span&gt; = new EditCompanyViewModel()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#555&#34;&gt;@render&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   render: () -&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;$&lt;/span&gt;(&lt;span style=&#34;color:#555&#34;&gt;@el&lt;/span&gt;).html(&lt;span style=&#34;color:#555&#34;&gt;@template&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       ko.applyBindings(&lt;span style=&#34;color:#555&#34;&gt;@view&lt;/span&gt;, &lt;span style=&#34;color:#555&#34;&gt;@el&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   setData: (company) =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#555&#34;&gt;@view.company&lt;/span&gt;(company)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;EditCompanyViewModel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   constructor: -&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#888&#34;&gt;# let’s instantiate it with default company for bindings to work&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#555&#34;&gt;@company&lt;/span&gt; = ko.observable(new Company())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#555&#34;&gt;@companyName&lt;/span&gt; = ko.computed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           read: =&amp;gt; &lt;span style=&#34;color:#555&#34;&gt;@company.get&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           write: (value) =&amp;gt; &lt;span style=&#34;color:#555&#34;&gt;@company.set&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;: value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#555&#34;&gt;@companyState&lt;/span&gt; = ko.computed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           read: =&amp;gt; &lt;span style=&#34;color:#555&#34;&gt;@company.get&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;state&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           write: (value) =&amp;gt; &lt;span style=&#34;color:#555&#34;&gt;@company.set&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;state&amp;#39;&lt;/span&gt;: value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#555&#34;&gt;@companyWebsite&lt;/span&gt; = ko.computed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           read: =&amp;gt; &lt;span style=&#34;color:#555&#34;&gt;@company.get&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;url&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           write: (value) =&amp;gt; &lt;span style=&#34;color:#555&#34;&gt;@company.set&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;url&amp;#39;&lt;/span&gt;: value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#555&#34;&gt;@saveCompany&lt;/span&gt; = () =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#555&#34;&gt;@company.save&lt;/span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;# app/views/templates/companies/edit.eco&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;form&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;data-bind&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;submit: saveCompany&amp;#34;&lt;/span&gt;&amp;gt;Name:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;data-bind&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;value: companyName&amp;#34;&lt;/span&gt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   State:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;data-bind&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;value: companyState&amp;#34;&lt;/span&gt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Website:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;data-bind&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;value: companyWebsite&amp;#34;&lt;/span&gt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;button&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;submit&amp;#34;&lt;/span&gt;&amp;gt;Submit&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;button&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;form&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;other-solutions&#34;&gt;Other solutions&lt;/h3&gt;
&lt;p&gt;These are quite contrived examples to give you an idea of how it can be done. The beauty of Backbone is that it allows you to structure your code however you’d like. And there are plenty of other solutions for this. Most notable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://kmalakoff.github.com/knockback/&#34;&gt;http://kmalakoff.github.com/knockback/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://rivetsjs.com/&#34;&gt;http://rivetsjs.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/DreamTheater/Backbone.DataBinding&#34;&gt;https://github.com/DreamTheater/Backbone.DataBinding&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
  
    <entry>
      <title>Ghost Table Cells in IE9</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/02/ghost-table-cells-in-ie9/"/>
      <id>https://www.endpointdev.com/blog/2013/02/ghost-table-cells-in-ie9/</id>
      <published>2013-02-08T00:00:00+00:00</published>
      <author>
        <name>Greg Davidson</name>
      </author>
      <content type="html">
        &lt;h3 id=&#34;whats-this-about-ghosts&#34;&gt;What’s this about ghosts?&lt;/h3&gt;
&lt;p&gt;I recently came across an arcane layout issue in my work on a redesigned client site. The problem was specific to Internet Explorer 9 (IE9). The related CSS styles had been well tested and rendered consistently across a variety of browsers including IE7 and 8. Everything was fine and dandy until some new content was introduced into the page for a &amp;ldquo;Quickview&amp;rdquo; feature. While all of the other browsers continued to behave and render the page correctly, the layout would break in random and confusing ways in IE9.&lt;/p&gt;
&lt;p&gt;The following screenshots compare the correct layout with an example of the broken layout in IE9.&lt;/p&gt;
&lt;h3 id=&#34;correct-grid-layout&#34;&gt;Correct grid layout:&lt;/h3&gt;
&lt;img alt=&#34;Correct grid&#34; border=&#34;0&#34; height=&#34;323&#34; src=&#34;/blog/2013/02/ghost-table-cells-in-ie9/image-0.png&#34; title=&#34;correct-grid.png&#34; /&gt;
&lt;h3 id=&#34;broken-layout-in-ie9&#34;&gt;Broken layout in IE9:&lt;/h3&gt;
&lt;img alt=&#34;IE9 ghost cells&#34; border=&#34;0&#34; height=&#34;325&#34; src=&#34;/blog/2013/02/ghost-table-cells-in-ie9/image-1.png&#34; title=&#34;IE9-ghost-cells.png&#34; /&gt;
&lt;h3 id=&#34;the-stage&#34;&gt;The Stage&lt;/h3&gt;
&lt;p&gt;The following is a list of the factors at work on the page in question:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Internet Explorer 9&lt;/li&gt;
&lt;li&gt;Browser mode: IE9, Document mode: IE9 standards&lt;/li&gt;
&lt;li&gt;Some content manipulation performed via JavaScript (and jQuery in this case)&lt;/li&gt;
&lt;li&gt;Lots of table cells&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;debugging&#34;&gt;Debugging&lt;/h3&gt;
&lt;p&gt;The page included a list of products. The first “page” of twelve results was shown initially while JavaScript split the rest of the list into several additional pages. Once this JavaScript pagination function was complete, users could cycle through products in bite-sized pieces.&lt;/p&gt;
&lt;p&gt;My first thought was that the issue may be related to CSS or JavaScript. I tested and debugged the styles thoroughly, tweaked styles and edited the underlying HTML structure to see if that might resolve the problem. I also tested the JavaScript and compared the original HTML with the parts which had been paginated via JavaScript. No dice.&lt;/p&gt;
&lt;p&gt;When changes improved the paginated HTML, the bug appeared in the initial HTML. Other changes resolved the issue in the original HTML but it appeared in the paginated HTML.&lt;/p&gt;
&lt;p&gt;I inspected the table with the Chrome Developer Tools console and also with the Developer Tools in IE9. There did not appear to be any differences between the rows which rendered properly and those which were skewed.&lt;/p&gt;
&lt;h3 id=&#34;bugging-out&#34;&gt;Bugging Out&lt;/h3&gt;
&lt;p&gt;At this point I began to research the issue and discovered it was a bug in the IE9 browser. A Microsoft forum post described the issue and included responses from Microsoft stating that it will not be fixed. It also included a sample application which demonstrated the issue. I tested and verified that the problem has been addressed and fixed in Internet Explorer 10, thankfully.&lt;/p&gt;
&lt;p&gt;This explained the many, seemingly random ways I had seen the grid break. At times the cells were squished and pushed to the left. This was because the ghost cell had been added at the end of a row. Other times the cells were shifted to the right (as seen in the screenshot above). In this case, the ghost cell had been added to the middle of a row.&lt;/p&gt;
&lt;h3 id=&#34;the-fix&#34;&gt;The Fix&lt;/h3&gt;
&lt;p&gt;Further digging revealed the the issue was related to whitespace between table cells. The solution was fairly simple: use a regular expression to remove all whitespace between the table elements:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#problem-table&amp;#39;&lt;/span&gt;).html(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, el) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; el.replace(&lt;span style=&#34;color:#080;background-color:#fff0ff&#34;&gt;/&amp;gt;\s+&amp;lt;/g&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;gt;&amp;lt;&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With all of the whitespace removed from the affected &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt;, IE9 rendered the page correctly.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>jQuery Performance Tips: Slice, Filter, parentsUntil</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/02/jquery-performance-tips-slice-filter/"/>
      <id>https://www.endpointdev.com/blog/2013/02/jquery-performance-tips-slice-filter/</id>
      <published>2013-02-04T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;p&gt;I recently wrote about working with an &lt;a href=&#34;/blog/2013/01/javascript-driven-interactive/&#34;&gt;intensive jQuery UI interface to emulate highlighting text&lt;/a&gt;. During this work, I experimented with and worked with jQuery optimization quite a bit. In the previous blog article, I mentioned that in some cases, the number of DOM elements that I was traversing at times exceeded 44,000, which caused significant performance issues in all browsers. Here are a few things I was reminded of, or learned throughout the project.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;console.profile, console.time, and the Chrome timeline are all tools that I used during the project to some extent. I typically used console.time the most to identify which methods were taking the most time.&lt;/li&gt;
&lt;li&gt;Caching elements is a valuable performance tool, as it’s typically faster to run jQuery calls on a cached jQuery selector rather than reselecting the elements. Here’s an example:&lt;/li&gt;
&lt;/ul&gt;
&lt;table cellpadding=&#34;0&#34; cellspacing=&#34;0&#34; width=&#34;100%&#34;&gt;&lt;tbody&gt;&lt;tr&gt; &lt;th align=&#34;center&#34; width=&#34;50%&#34;&gt;Slower&lt;/th&gt; &lt;th align=&#34;center&#34; width=&#34;50%&#34;&gt;Faster&lt;/th&gt; &lt;/tr&gt;
&lt;tr&gt; &lt;td valign=&#34;top&#34; width=&#34;50%&#34;&gt;&lt;pre class=&#34;brush:javascript&#34;&gt;//Later in the code
$(&#39;.items&#39;).do_something();
&lt;/pre&gt;&lt;/td&gt; &lt;td valign=&#34;top&#34; width=&#34;50%&#34;&gt;&lt;pre class=&#34;brush:javascript&#34;&gt;//On page load
var cached_items = $(&#39;.items&#39;);
//Later in the code
cached_items.do_something();
&lt;/pre&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&#34;https://api.jquery.com/filter/&#34;&gt;jQuery .filter operator&lt;/a&gt; came in handy, and gave a bit of a performance bump in some cases.&lt;/li&gt;
&lt;/ul&gt;
&lt;table cellpadding=&#34;0&#34; cellspacing=&#34;0&#34; width=&#34;100%&#34;&gt;&lt;tbody&gt;&lt;tr&gt; &lt;th align=&#34;center&#34; width=&#34;50%&#34;&gt;Slower&lt;/th&gt; &lt;th align=&#34;center&#34; width=&#34;50%&#34;&gt;Faster&lt;/th&gt; &lt;/tr&gt;
&lt;tr&gt; &lt;td valign=&#34;top&#34; width=&#34;50%&#34;&gt;&lt;pre class=&#34;brush:javascript&#34;&gt;$(&#39;.highlighted&#39;);
&lt;/pre&gt;&lt;/td&gt; &lt;td valign=&#34;top&#34; width=&#34;50%&#34;&gt;&lt;pre class=&#34;brush:javascript&#34;&gt;cached_items.filter(&#39;.highlighted&#39;);
&lt;/pre&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://api.jquery.com/slice/&#34;&gt;jQuery slicing&lt;/a&gt; from a cached selection was typically much faster than reselecting or selecting those elements by class. If retrieving slice boundaries is inexpensive and there are a lot of elements, slice was extremely valuable.&lt;/li&gt;
&lt;/ul&gt;
&lt;table cellpadding=&#34;0&#34; cellspacing=&#34;0&#34; width=&#34;100%&#34;&gt;&lt;tbody&gt;&lt;tr&gt; &lt;th align=&#34;center&#34; width=&#34;50%&#34;&gt;Slower&lt;/th&gt; &lt;th align=&#34;center&#34; width=&#34;50%&#34;&gt;Faster&lt;/th&gt; &lt;/tr&gt;
&lt;tr&gt; &lt;td valign=&#34;top&#34; width=&#34;50%&#34;&gt;&lt;pre class=&#34;brush:javascript&#34;&gt;cached_items.filter(&#39;.highlighted&#39;);
&lt;/pre&gt;&lt;/td&gt; &lt;td valign=&#34;top&#34; width=&#34;50%&#34;&gt;&lt;pre class=&#34;brush:javascript&#34;&gt;cached_items.slice(10, 100);
&lt;/pre&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://api.jquery.com/jQuery.data/&#34;&gt;Storing data&lt;/a&gt; on elements was typically a faster alternative than parsing the id from the HTML markup (class or id). If it’s inexpensive to add data values to the HTML markup, this was a valuable performance tool. Note that it’s important to test if the jQuery version in use automatically parses the data value to an integer.&lt;/li&gt;
&lt;/ul&gt;
&lt;table cellpadding=&#34;0&#34; cellspacing=&#34;0&#34; width=&#34;100%&#34;&gt;&lt;tbody&gt;&lt;tr&gt; &lt;th align=&#34;center&#34; width=&#34;50%&#34;&gt;Slower&lt;/th&gt; &lt;th align=&#34;center&#34; width=&#34;50%&#34;&gt;Faster&lt;/th&gt; &lt;/tr&gt;
&lt;tr&gt; &lt;td valign=&#34;top&#34; width=&#34;50%&#34;&gt;&lt;pre class=&#34;brush:javascript&#34;&gt;//given &lt;tt data-id=&#34;123&#34; id=&#34;r123&#34;&gt;&lt;/tt&gt;
var slice_start = parseInt($(&#39;tt#r123&#39;)
                    .attr(&#39;id&#39;)
                    .replace(/^r/, &#39;&#39;));
&lt;/pre&gt;&lt;/td&gt; &lt;td valign=&#34;top&#34; width=&#34;50%&#34;&gt;&lt;pre class=&#34;brush:javascript&#34;&gt;//given &lt;tt data-id=&#34;123&#34; id=&#34;r123&#34;&gt;&lt;/tt&gt;
var slice_start = $(&#39;tt#r123&#39;)
                    .data(&#39;id&#39;);
&lt;/pre&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.w3schools.com/jquery/jquery_ref_selectors.asp&#34;&gt;Advanced jQuery selectors&lt;/a&gt; offered performance gain as opposed to jQuery iterators. In the example below, it’s faster to use selectors :has and :not combined rather than iterating through each parent.&lt;/li&gt;
&lt;/ul&gt;
&lt;table cellpadding=&#34;0&#34; cellspacing=&#34;0&#34; width=&#34;100%&#34;&gt;&lt;tbody&gt;&lt;tr&gt; &lt;th align=&#34;center&#34; width=&#34;50%&#34;&gt;Slower&lt;/th&gt; &lt;th align=&#34;center&#34; width=&#34;50%&#34;&gt;Faster&lt;/th&gt; &lt;/tr&gt;
&lt;tr&gt; &lt;td valign=&#34;top&#34; width=&#34;50%&#34;&gt;&lt;pre class=&#34;brush:javascript&#34;&gt;$.each($(&#39;p.parent&#39;), function(i, el) {
  //if el does not have any visible spans
  //  do_something()
});
&lt;/pre&gt;&lt;/td&gt; &lt;td valign=&#34;top&#34; width=&#34;50%&#34;&gt;&lt;pre class=&#34;brush:javascript&#34;&gt;$(&#39;p.parent:not(:has(span:visible))&#39;)
  .do_something();
&lt;/pre&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&#34;https://api.jquery.com/parentsUntil/&#34;&gt;jQuery method parentsUntil&lt;/a&gt; was a valuable tool instead of looking at the entire document or a large set of elements. In the cases where the children were already defined in a subset selection, I  used the parentsUntil method to select all parents until a specific DOM element.&lt;/li&gt;
&lt;/ul&gt;
&lt;table cellpadding=&#34;0&#34; cellspacing=&#34;0&#34; width=&#34;100%&#34;&gt;&lt;tbody&gt;&lt;tr&gt; &lt;th align=&#34;center&#34; width=&#34;50%&#34;&gt;Slower&lt;/th&gt; &lt;th align=&#34;center&#34; width=&#34;50%&#34;&gt;Faster&lt;/th&gt; &lt;/tr&gt;
&lt;tr&gt; &lt;td valign=&#34;top&#34; width=&#34;50%&#34;&gt;&lt;pre class=&#34;brush:javascript&#34;&gt;$(&#39;#some_div p.parent:not(:has(span:visible))&#39;)
  .do_something();
&lt;/pre&gt;&lt;/td&gt; &lt;td valign=&#34;top&#34; width=&#34;50%&#34;&gt;&lt;pre class=&#34;brush:javascript&#34;&gt;subset_of_items
  .parentsUntil(&#39;#some_div&#39;)
  .filter(&#39;:not(:has(span:visible))&#39;)
  .do_something();
&lt;/pre&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The best takeaway I can offer here is that it was almost always more efficient to work with as precise set of selected elements as possible, rather than reselecting from the whole document. The various methods such as filter, slice, and parentsUntil helped define the precise set of elements.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>JavaScript-driven Interactive Highlighting</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/01/javascript-driven-interactive/"/>
      <id>https://www.endpointdev.com/blog/2013/01/javascript-driven-interactive/</id>
      <published>2013-01-25T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2013/01/javascript-driven-interactive/image-0.jpeg&#34; /&gt;&lt;br&gt;
An example of highlighted text, by &lt;a href=&#34;https://www.flickr.com/photos/srgblog/7366596592/&#34;&gt;sergis on Flickr&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;One project I’ve been involved in for almost two years here at End Point is the &lt;a href=&#34;https://cyber.law.harvard.edu/research/h2o&#34;&gt;H2O project&lt;/a&gt;. The Ruby on Rails web application behind H2O serves as a platform for creating, editing, organizing, consuming and sharing course materials that is used by professors and their students.&lt;/p&gt;
&lt;p&gt;One of the most interesting UI elements of this project is the requirement to allow highlighting and annotating text interactively. For example, when one reads a physical textbook for a college course, they may highlight and mark it up in various ways with different colors and add annotated text. They may also highlight a section that is particularly important for an upcoming exam, or they may highlight another section with a different color and notes that may be needed for a paper.&lt;/p&gt;
&lt;p&gt;The H2O project has required support for digitizing interactive highlighting and annotating. Since individual text is not selectable as a DOM element, each word is wrapped into an individual DOM element that is selectable, hoverable, and has DOM properties that we can assign it. For example, we have the following text:&lt;/p&gt;
&lt;p&gt;The cow jumped over the moon.&lt;/p&gt;
&lt;p&gt;Which is manipulated to create individual DOM elements by word:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;The &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;cow &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;jumped &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;over &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;the &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;moon.&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And an id is assigned to each element:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e1&amp;#34;&lt;/span&gt;&amp;gt;The &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e2&amp;#34;&lt;/span&gt;&amp;gt;cow &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e3&amp;#34;&lt;/span&gt;&amp;gt;jumped &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e4&amp;#34;&lt;/span&gt;&amp;gt;over &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e5&amp;#34;&lt;/span&gt;&amp;gt;the &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e6&amp;#34;&lt;/span&gt;&amp;gt;moon.&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This markup is the foundation of digitizing highlighting behavior: it allows the starting and ending boundaries of a highlighted section to be selected. It also allows additional highlighting boundary elements to be created before and after highlighted text, as well as provide the ability to interactively toggle highlighting. Without this, we can’t easily parse or identify starting and ending points other than trying to determine it by other methods such as substring-ing text or using positioning details to identify the current word.&lt;/p&gt;
&lt;h3 id=&#34;how-do-we-highlight&#34;&gt;How do we Highlight?&lt;/h3&gt;
&lt;p&gt;With our example, I’ll describe the history of highlighting functionality that I’ve been involved in on the project. For this post, let’s say our desired emulated highlighted behavior is the following, where “cow jumped over” is highlighted in pink, and “over the” is highlighted in blue:&lt;/p&gt;
&lt;p&gt;The cow jumped over the moon.&lt;/p&gt;
&lt;p&gt;And our HTML markup may look like this to indicate the highlighted layers:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e1&amp;#34;&lt;/span&gt;&amp;gt;The &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e2&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;pink&amp;#34;&lt;/span&gt;&amp;gt;cow &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e3&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;pink&amp;#34;&lt;/span&gt;&amp;gt;jumped &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e4&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;pink blue&amp;#34;&lt;/span&gt;&amp;gt;over &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e5&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;blue&amp;#34;&lt;/span&gt;&amp;gt;the &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e6&amp;#34;&lt;/span&gt;&amp;gt;moon.&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;highlighting-iteration-1&#34;&gt;Highlighting Iteration 1&lt;/h3&gt;
&lt;p&gt;One of the challenges with emulating highlighting is that a DOM element can only have one background color. We can’t easily layer pink and blue highlights over a specific word to give a layered highlighted effect. So in our example, the pink and blue highlighted words will show up fine, but no color combinations will show up because a node cannot have multiple background colors. During my first iteration on this functionality, I implemented behavior to track the history of our highlights per textual node. The following steps are an example of a use case that demonstrates the highlight overlap:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Starting from unhighlighted text, first a user highlights pink:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;span style=&#34;background-color: pink&#34;&gt;cow jumped over&lt;/span&gt; the moon.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Next, a user highlights blue:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;span style=&#34;background-color: pink&#34;&gt;cow jumped&lt;/span&gt; &lt;span style=&#34;background-color: lightblue&#34;&gt;over the&lt;/span&gt; moon.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Next, a user unhighlights blue:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;span style=&#34;background-color: pink&#34;&gt;cow jumped over&lt;/span&gt; the moon.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Finally, a user unhighlights pink:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The cow jumped over the moon.&lt;/p&gt;
&lt;p&gt;Or another simple use case:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Starting from unhighlighted text, first a user highlights pink:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;span style=&#34;background-color: pink&#34;&gt;cow jumped over&lt;/span&gt; the moon.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Next, a user highlights blue:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;span style=&#34;background-color: pink&#34;&gt;cow jumped&lt;/span&gt; &lt;span style=&#34;background-color: lightblue&#34;&gt;over the&lt;/span&gt; moon.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Next, a user unhighlights pink:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The cow jumped &lt;span style=&#34;background-color: lightblue&#34;&gt;over the&lt;/span&gt; moon.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Finally, a user unhighlights pink:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The cow jumped over the moon.&lt;/p&gt;
&lt;p&gt;Programmatically, this method required that a history of highlights be stored to each text node in the form of an array. When something was highlighted or unhighlighted, the array was manipulated to remove or add highlights and the last highlight applied to the text node. While this method was fairly simply to implement, it did not allow users to visualize the overlapping highlighted sections. This iteration was in place for over a year, but ultimately it did not appropriately demonstrate overlapped highlights.&lt;/p&gt;
&lt;h3 id=&#34;highlighting-iteration-2&#34;&gt;Highlighting Iteration 2&lt;/h3&gt;
&lt;p&gt;In the next iteration, I attempted to implement a method that added opaque, absolute and fixed positioned elements underneath the text, similar to how one might see layers in Photoshop:&lt;/p&gt;
&lt;img border=&#34;0&#34; src=&#34;/blog/2013/01/javascript-driven-interactive/image-1.jpeg&#34;/&gt;
&lt;p&gt;In the second iteration, additional colored &amp;amp; opaque nodes were created under the text to provide a layered highlighting effect.&lt;/p&gt;
&lt;p&gt;Unhighlighted markup looked like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e1&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlights&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    The 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e2&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;pink&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlights&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cow 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e3&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;pink&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlights&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    jumped
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e4&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;pink blue&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlights&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    over
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e5&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;blue&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlights&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    the
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e6&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlights&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    moon.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And highlighted markup looked like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e1&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlights&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    The 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e2&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;pink&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlights&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlight_pink&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cow 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e3&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;pink&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlights&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlight_pink&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    jumped 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e4&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;pink blue&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlights&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlight_pink&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlight_blue&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    over 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e5&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;blue&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlights&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlight_blue&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    the 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e6&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;highlights&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    moon.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above markup, the following should be noted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each &lt;code&gt;span.highlights&lt;/code&gt; node is absolutely positioned with a width and height matching the text node.&lt;/li&gt;
&lt;li&gt;Each &lt;code&gt;span.highlights&lt;/code&gt; span node (e.g. a node with the &lt;code&gt;highlight_pink&lt;/code&gt; class) has a width and height of 100%, a background color defined in CSS, and an opacity that is scaled based on the number of highlights.&lt;/li&gt;
&lt;li&gt;Whenever highlights are toggled in the text, the children nodes of span.highlights are manipulated (added or removed), as well as the opacity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While this functionality provides a nice highlighted layering effect, absolute positioning is probably my least favorite thing to work with in cross browser development, and it did not always behave as expected. Specifically, IE and Chrome behaved somewhat as expected, but Firefox did not. This absolute positioning also caused problems with other absolutely positioned elements on the page.&lt;/p&gt;
&lt;p&gt;Additionally, this markup was subject to cause significant performance issues. In one case, content with 44,000 words (and text nodes) alone caused performance implications, but additional highlighting layering caused extreme performance pain, to the point that Chrome would not load the content and the content would take more than 30 seconds to load in Firefox, so I went searching for a better solution.&lt;/p&gt;
&lt;h3 id=&#34;highlighting-iteration-3&#34;&gt;Highlighting Iteration 3&lt;/h3&gt;
&lt;p&gt;Finally, in the most recent iteration, after identifying that Iteration 2 produced significant performance issues, after more research, I came across the jQuery &lt;a href=&#34;https://github.com/infusion/jQuery-xcolor&#34;&gt;xColor&lt;/a&gt; plugin. This plugin allows you to do mathematical operations on colors, such as combining colors. While the plugin itself only lets you combine 2 colors at one time, I created a method to combine multiple opaque layers:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$.each($(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;span.&amp;#39;&lt;/span&gt; + highlighted_class), &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, el) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; current = $(el);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; highlight_colors = current.data(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;highlight_colors&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt;(highlight_colors) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      highlight_colors.push(hex);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       highlight_colors = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#038&#34;&gt;Array&lt;/span&gt;(hex);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; current_hex = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#FFFFFF&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; opacity = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0.4&lt;/span&gt; / highlight_colors.length;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $.each(highlight_colors, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(i, color) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; new_color = $.xcolor.opacity(current_hex, color, opacity);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        current_hex = new_color.getHex();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     current.css(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;background&amp;#39;&lt;/span&gt;, current_hex);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     current.data(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;highlight_colors&amp;#39;&lt;/span&gt;, highlight_colors);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Step by step, the above code does, for each span node with a specific highlight:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Retrieve the array of highlights applied to that node, or create a new array with the new highlight color.&lt;/li&gt;
&lt;li&gt;For each highlight, layer an opaque version of that highlight on top of the summation of colors.&lt;/li&gt;
&lt;li&gt;Set the background to the final combination of layered highlights.&lt;/li&gt;
&lt;li&gt;Store the new array of highlights applied to that node.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The markup is back to the original markup with no additional children elements per text node. Each highlighting interaction triggers a recalculation of the background color per text node based on the data stored to that node.&lt;/p&gt;
&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Significant limitations during this work have included the described performance limitations, as well as the inability to set multiple background images on a DOM element. Absolutely positioning, while valuable at times, proved to be quite challenging because of other absolute and fixed positioned elements on the page. In addition to emulating this highlighting behavior, there are additional interactive requirements included with the interactive highlighting.&lt;/p&gt;
&lt;img border=&#34;0&#34; src=&#34;/blog/2013/01/javascript-driven-interactive/image-2.png&#34; width=&#34;740&#34;/&gt;
&lt;p&gt;Example of additional features needed in interactive highlighting tool.&lt;/p&gt;
&lt;p&gt;Additional UI functional requirements include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Functionality to show paragraph numbers, and hide all paragraph numbers when they have no visible children (Hint: advanced jQuery selectors are used here).&lt;/li&gt;
&lt;li&gt;Ability to toggle display of unhighlighted text. The […] in the above image trigger the unhighlighted text in that section to display, while the left and right arrows trigger the unhighlighted text in that section to be hidden.&lt;/li&gt;
&lt;li&gt;Ability to toggle display of highlighted text, similar to the toggle of unhighlighted text.&lt;/li&gt;
&lt;li&gt;Ability to toggle between a “read” and “edit” mode for owners of the text, which allows for these users to interactively add additional highlights and dynamically modify the markup. In the edit mode, additional markup is added to identify these highlighted layers.&lt;/li&gt;
&lt;li&gt;Ability to toggle display of the annotation. In the above image, clicking on the green asterisk toggles this display. No asterisk is shown if there is no annotation.&lt;/li&gt;
&lt;li&gt;Ability for highlights to encompass HTML nodes that are not individual span elements. For example, highlighted sections may encompass multiple paragraphs and headers of &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; nodes, which is why simply adding a wrapping element to highlights will not work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One might suggest we go to a better tool to manage content markup, but ultimately these types of markup tools do not provide the interactivity we seek, and they require that the end user have knowledge of HTML markup, which is not always the case.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Lazy AJAX</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/12/lazy-ajax/"/>
      <id>https://www.endpointdev.com/blog/2012/12/lazy-ajax/</id>
      <published>2012-12-18T00:00:00+00:00</published>
      <author>
        <name>Jeff Boes</name>
      </author>
      <content type="html">
        &lt;p&gt;Don&amp;rsquo;t do this, at least not without a good reason. It&amp;rsquo;s not the way to design AJAX interfaces from scratch, but it serves well in a pinch, where you have an existing CGI-based page and you don&amp;rsquo;t want to spend a lot of time rewriting it.&lt;/p&gt;
&lt;p&gt;I was in a hurry, and the page involved was a seldom-used administration page. I was attempting to convert it into an AJAX-enabled setup, wherein the page would stand still, but various parts of it could be updated with form controls, each of which would fire off an AJAX request, and use the data returned to update the page.&lt;/p&gt;
&lt;p&gt;However, one part of it just wasn&amp;rsquo;t amenable to this approach, or at least not quick-and-dirty. This part had a relatively large amount of inline interpolated (Interchange) data (if you don&amp;rsquo;t know what Interchange is, you can substitute &amp;ldquo;PHP&amp;rdquo; in that last sentence and you&amp;rsquo;ll be close enough.) I wanted to run the page back through the server-side processing, but only cared about (and would discard all but) one element of the page.&lt;/p&gt;
&lt;p&gt;My lazy-programmer&amp;rsquo;s approach was to &lt;em&gt;submit the page itself as an AJAX request&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$.ajax({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    url: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;/@_MV_PAGE_@&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    data: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;order_date&amp;#39;&lt;/span&gt;: order_date,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;shipmode&amp;#39;&lt;/span&gt; : shipmode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    method: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;GET&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;async&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    success: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(data, status){
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;table#attraction_booklet_order&amp;#39;&lt;/span&gt;).replaceWith(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            $(data).find(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#attraction_booklet_order&amp;#39;&lt;/span&gt;).get(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;table#attraction_booklet_order&amp;#39;&lt;/span&gt;).show();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}); 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this excerpt, &amp;ldquo;MV_PAGE&amp;rdquo; is a server-side macro that evaluates to the current page&amp;rsquo;s path. The element I care about is a rather complex HTML table containing all sorts of interpolated data. So I&amp;rsquo;m basically reloading the page, or at least that restricted piece of it. The tricky bit, unfamiliar to jQuery newcomers, lets you parse out something from the returned document much as you would from your current document.&lt;/p&gt;
&lt;p&gt;Again, don&amp;rsquo;t do this without a reason. When I have more time, I&amp;rsquo;ll revisit this and improve it, but for now it&amp;rsquo;s good enough for the current needs.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Interactive Piggybak Demo Tour</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/12/interactive-piggybak-demo-tour/"/>
      <id>https://www.endpointdev.com/blog/2012/12/interactive-piggybak-demo-tour/</id>
      <published>2012-12-06T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;p&gt;A new interactive tour of Piggybak and the Piggybak demo has been released at piggybak.org. &lt;a href=&#34;https://github.com/piggybak/piggybak&#34;&gt;Piggybak&lt;/a&gt; is an open source Ruby on Rails ecommerce framework built as a Rails 3 engine and intended to be mounted on existing Rails applications.&lt;/p&gt;
&lt;p&gt;The tour leverages &lt;a href=&#34;http://codecanyon.net/item/jtour-website-tour-engine/409593&#34;&gt;jTour&lt;/a&gt; (a jQuery plugin) and guides you through the homepage, navigation page, product page, cart and checkout pages, gift certificate page, advanced product option page, and WYSIWYG driven page. The tour also highlights several of the Piggybak plugins available and installed into the demo such as plugins that introduce advanced product navigation, advanced product optioning, and gift certificate functionality. Below are a few screenshots from the demo.&lt;/p&gt;
&lt;p&gt;An interesting side note of developing this tour is that while I found many nice jQuery-driven tour plugins available for free or at a small cost, this jQuery plugin was the only plugin offering decent multi-page tour functionality.&lt;/p&gt;
&lt;table cellpadding=&#34;5&#34; cellspacing=&#34;0&#34; width=&#34;100%&#34;&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td align=&#34;center&#34; valign=&#34;top&#34;&gt;&lt;a href=&#34;/blog/2012/12/interactive-piggybak-demo-tour/image-0-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left:1em; margin-right:1em&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2012/12/interactive-piggybak-demo-tour/image-0.png&#34; width=&#34;350&#34;/&gt;&lt;/a&gt;&lt;br/&gt;Here is the starting point of Piggybak tour.&lt;/td&gt;
&lt;td align=&#34;center&#34; valign=&#34;top&#34;&gt;&lt;a href=&#34;/blog/2012/12/interactive-piggybak-demo-tour/image-1-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left:1em; margin-right:1em&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2012/12/interactive-piggybak-demo-tour/image-1.png&#34; width=&#34;350&#34;/&gt;&lt;/a&gt;&lt;br/&gt;The Piggybak tour adds an item to the cart during the tour.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;center&#34; valign=&#34;top&#34;&gt;&lt;a href=&#34;/blog/2012/12/interactive-piggybak-demo-tour/image-2-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left:1em; margin-right:1em&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2012/12/interactive-piggybak-demo-tour/image-2.png&#34; width=&#34;350&#34;/&gt;&lt;/a&gt;&lt;br/&gt;The Piggybak tour highlights advanced product navigation&lt;br/&gt;in the demo.&lt;/td&gt;
&lt;td align=&#34;center&#34; valign=&#34;top&#34;&gt;&lt;a href=&#34;/blog/2012/12/interactive-piggybak-demo-tour/image-3-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left:1em; margin-right:1em&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2012/12/interactive-piggybak-demo-tour/image-3.png&#34; width=&#34;350&#34;/&gt;&lt;/a&gt;&lt;br/&gt;The Piggybak tour highlights features and functionality&lt;br/&gt;on the one-page checkout.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;You can check out the interactive tour with your own &lt;a href=&#34;https://github.com/piggybak/demo&#34;&gt;Piggybak demo&lt;/a&gt;.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>AJAX Queuing in Piggybak</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/09/ajax-queuing-in-piggybak/"/>
      <id>https://www.endpointdev.com/blog/2012/09/ajax-queuing-in-piggybak/</id>
      <published>2012-09-18T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;p&gt;AJAX is inherently asynchronous; for the most part, this works fine in web development, but sometimes it can cause problem if you have multiple related AJAX calls that are asynchronous to eachother, such as the use case described in this article.&lt;/p&gt;
&lt;p&gt;In &lt;a href=&#34;https://github.com/piggybak/piggybak&#34;&gt;Piggybak&lt;/a&gt;, a Ruby on Rails open source shopping cart module developed and maintained by End Point, the one page checkout uses AJAX to generate shipping options. Whenever state and zip options change, the shipping address information is sent via AJAX and valid shipping methods are returned and rendered in a select dropdown.&lt;/p&gt;
&lt;img border=&#34;0&#34; src=&#34;/blog/2012/09/ajax-queuing-in-piggybak/image-0.png&#34; width=&#34;750&#34;/&gt;
&lt;p&gt;Event listeners on the state and zip code inputs trigger to generate shipping options via AJAX.&lt;/p&gt;
&lt;p&gt;While working on development for a client using Piggybak, I came across a scenario where AJAX asynchronous-ity was problematic. Here&amp;rsquo;s how the problematic behavior looked on a timeline, picking up as the user enters their shipping address:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0 seconds: User changes state, triggers AJAX shipping lookup with state value, but no zip code entered (Let&amp;rsquo;s refer to this as AJAX REQUEST 1).&lt;/li&gt;
&lt;li&gt;1 second: User changes zip code, triggers AJAX shipping lookup with state and zip value present (Let&amp;rsquo;s refer to this as AJAX REQUEST 2).&lt;/li&gt;
&lt;li&gt;2 seconds: AJAX REQUEST 2 returns valid shipping options.&lt;/li&gt;
&lt;li&gt;3 seconds: AJAX REQUEST 1 returns invalid shipping options, because no zip code provided in this data set, and overwrites shipping options returned by AJAX REQUEST 2.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The result is that the user has finished entering a valid shipping address, but sees that no valid shipping options can be chosen:&lt;img border=&#34;0&#34; src=&#34;/blog/2012/09/ajax-queuing-in-piggybak/image-1.png&#34; width=&#34;750&#34;/&gt;&lt;/p&gt;
&lt;p&gt;To address this issue, I researched AJAX queuing, with the requirement that AJAX requests should be performed synchronously and existing AJAX requests could be aborted if needed. After experimenting with a few different plugins, I found the most success with the &lt;a href=&#34;http://code.google.com/p/jquery-ajaxq/&#34;&gt;jQuery-ajaxq&lt;/a&gt; plugin. It&amp;rsquo;s simple to use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;To append a new AJAX call on to a queue, you call $.ajaxq(queue_name, options), where options includes the standard AJAX arguments.&lt;/li&gt;
&lt;li&gt;To cancel or abort AJAX calls currently running in a queue, you call $.ajaxq(queue_name).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The event listener on state and zip changes now looks like the code shown below, in simplified form. The piggybak.update_shipping_options cancels AJAX requests on the shipping_options queue and then adds a new request to the queue which will execute immediately. This does not affect other asynchronous AJAX requests on the page.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; piggybak = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    update_shipping_options: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        $.ajaxq(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;shipping_options&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        $.ajaxq(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;shipping_options&amp;#34;&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            url: ...,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            cached: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            data: ...,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dataType: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;JSON&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            beforeSend: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            success: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(data) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here&amp;rsquo;s how this looks on a timeline:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0 seconds: User changes state, triggers AJAX shipping lookup with state value, but no zip code entered (Let&amp;rsquo;s refer to this as AJAX REQUEST 1).&lt;/li&gt;
&lt;li&gt;1 second: User changes zip code, triggers AJAX shipping lookup with state and zip value present (Let&amp;rsquo;s refer to this as AJAX REQUEST 2). This signals to abort all current AJAX requeusts on the shipping_options queue.&lt;/li&gt;
&lt;li&gt;2 seconds: AJAX REQUEST 2 returns valid shipping options.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This was an interesting technical problem to solve, but the needs were not surprising. The &lt;a href=&#34;http://code.google.com/p/jquery-ajaxq/&#34;&gt;jQuery-ajaxq plugin&lt;/a&gt; offers a simple, elegant solution for handling AJAX queing in jQuery.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Three Things: Times Two</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/09/three-things-times-two/"/>
      <id>https://www.endpointdev.com/blog/2012/09/three-things-times-two/</id>
      <published>2012-09-10T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;p&gt;It’s been a while since I’ve written up a “Three Things” article where I share a few featured web development tidbits picked up recently. So I made this a double episode!&lt;/p&gt;
&lt;h3 id=&#34;1-eventstoppropagation-and-eventstopimmediatepropagation&#34;&gt;1. event.stopPropagation() and event.stopImmediatePropagation()&lt;/h3&gt;
&lt;p&gt;I recently came across these two methods in jQuery, described &lt;a href=&#34;http://api.jquery.com/event.stopPropagation/&#34;&gt;here&lt;/a&gt; and &lt;a href=&#34;http://api.jquery.com/event.stopImmediatePropagation/&#34;&gt;here&lt;/a&gt;. Both of these methods [prevent the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event]. In my web application, my $(&amp;lsquo;html&amp;rsquo;) element had a listener on it, but I added specific listeners to children elements that when clicked on calls event.stopPropagation to cancel the event on the $(&amp;lsquo;html&amp;rsquo;) element. See the code below for a simplified example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jQuery(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    jQuery(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;html&amp;#39;&lt;/span&gt;).click(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        jQuery.hideSomething();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    jQuery(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;.popup&amp;#39;&lt;/span&gt;).click(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(event) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        event.stopPropagation();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;2-alias_attribute&#34;&gt;2. alias_attribute&lt;/h3&gt;
&lt;p&gt;The alias method in Rails is one that I use frequently. But I recently came across the &lt;a href=&#34;http://apidock.com/rails/Module/alias_attribute&#34;&gt;alias_attribute&lt;/a&gt; method as well. This might make the most sense to use when using shared views for multiple models with varying attributes.&lt;/p&gt;
&lt;h3 id=&#34;3-excel-behavior-in-jquery&#34;&gt;3. Excel behavior in jQuery&lt;/h3&gt;
&lt;p&gt;Recently, there was a bit of discussion about jQuery tools that emulate spreadsheet behavior. A couple of the tools that came up were &lt;a href=&#34;http://warpech.github.com/jquery-handsontable/index.html&#34;&gt;Handsontable&lt;/a&gt; and &lt;a href=&#34;http://datatables.net/&#34;&gt;DataTables&lt;/a&gt;. They are worth checking out if you are looking to add Excel-like behavior to your web application!&lt;/p&gt;
&lt;h3 id=&#34;4-racksslenforcer&#34;&gt;4. Rack::SslEnforcer&lt;/h3&gt;
&lt;p&gt;I recently had a need on a Rails application to force some pages as secure, but have other pages be forced as non-secure. Instead of the common practice of adding controller before filters to force a redirect, this was included via the Gemfile, bundle install, and then configured in config/application.rb. Here’s an example configuration setup that I’m using:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;config.middleware.use &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Rack&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;SslEnforcer&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:only&lt;/span&gt; =&amp;gt; [&lt;span style=&#34;color:#080;background-color:#fff0ff&#34;&gt;/\/checkout\/$/&lt;/span&gt;, &lt;span style=&#34;color:#080;background-color:#fff0ff&#34;&gt;/\/users$/&lt;/span&gt;, &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;‘&lt;/span&gt;/admin&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;’&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:strict&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#080&#34;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The one interesting caveat I found in working with this is that you absolutely must have all CSS and JavaScript assets precompiled in order for them to be served via SSL. The JS and CSS assets would not be forced to SSL, so they must exist in the Rails public directory via the precompiling, or this gem will redirect https requests on a secure page to http, resulting in the browser reporting that some non-secure elements are being served from a secure page.&lt;/p&gt;
&lt;h3 id=&#34;5-setting-a-viewport&#34;&gt;5. Setting a viewport&lt;/h3&gt;
&lt;p&gt;I was recently troubleshooting a CSS issue for a client who was examining their website on an iPad. The iPad was setting the width of the viewport to a value that resulted in mis-alignment of floating elements. After a bit of research, I found that setting the viewport to the desired static width of my page fixed this issue. &lt;a href=&#34;http://dev.opera.com/articles/view/an-introduction-to-meta-viewport-and-viewport/&#34;&gt;Here&lt;/a&gt; is a nice overview of the viewport attribute.&lt;/p&gt;
&lt;h3 id=&#34;6-line-specific-substitution-in-vi&#34;&gt;6. Line Specific Substitution in vi&lt;/h3&gt;
&lt;p&gt;Several of my coworkers are vi experts. When I’m in a shared screen with them, I pick up small tips for improving efficiency. One that I picked up on a few months ago and practiced enough to remember was line-specific substitution, e.g. 4,10s/moo/meow/g will substitute all occurrences of “moo” to “meow” in lines 4 through 10. I use this technique frequently.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Interesting jQuery Modules</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/06/interesting-jquery-modules/"/>
      <id>https://www.endpointdev.com/blog/2012/06/interesting-jquery-modules/</id>
      <published>2012-06-13T00:00:00+00:00</published>
      <author>
        <name>Carl Bailey</name>
      </author>
      <content type="html">
        &lt;p&gt;Marina Lohova talked about her favorite jQuery modules. It was the last talk of the day and she did not have much time.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.flickr.com/photos/80083124@N08/7369948058/&#34; title=&#34;IMG_0760.JPG by endpoint920, on Flickr&#34;&gt;&lt;img alt=&#34;IMG_0760.JPG&#34; height=&#34;375&#34; src=&#34;/blog/2012/06/interesting-jquery-modules/image-0.jpeg&#34; width=&#34;500&#34;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Her focus was on the functional plugins. Interesting modules that she mentioned include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ajax PayPal Cart&lt;/li&gt;
&lt;li&gt;Sisyphus (uses HTML5 LocalStorage)&lt;/li&gt;
&lt;li&gt;jImpress (presentations)&lt;/li&gt;
&lt;li&gt;jPlayer (HTML5)&lt;/li&gt;
&lt;li&gt;ResponseJS&lt;/li&gt;
&lt;li&gt;lqTouch (adds mobile events like swipe)&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
  
    <entry>
      <title>Keeping Your Apps Neat &amp; Tidy With RequireJS</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/05/keeping-your-apps-neat-tidy-with/"/>
      <id>https://www.endpointdev.com/blog/2012/05/keeping-your-apps-neat-tidy-with/</id>
      <published>2012-05-17T00:00:00+00:00</published>
      <author>
        <name>Greg Davidson</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;a href=&#34;http://requirejs.org/&#34;&gt;RequireJS&lt;/a&gt; is a very handy tool for loading files and modules in JavaScript. A short time ago I used it to add a feature to &lt;a href=&#34;http://www.whiskeymilitia.com/&#34;&gt;Whiskey Militia&lt;/a&gt; that promoted a new section of the site. By developing the feature as a RequireJS module, I was able to keep all of its JavaScript, HTML and CSS files neatly organized. Another benefit to this approach was the ability to turn the new feature “on” or “off” on the site by editing a single line of code. In this post I’ll run through a similar example to demonstrate how you could use RequireJS to improve your next project.&lt;/p&gt;
&lt;h3 id=&#34;file-structure&#34;&gt;File Structure&lt;/h3&gt;
&lt;p&gt;The following is the file structure I used for this project:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── index.html
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── scripts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ├── main.js
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ├── my
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── module.js
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── styles.css
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   └── template.html
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ├── require-jquery.js
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ├── requirejs.mustache.js
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── text.js&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The dependencies included RequireJS bundled together with &lt;a href=&#34;https://jquery.com/&#34;&gt;jQuery&lt;/a&gt;, &lt;a href=&#34;https://github.com/janl/mustache.js/&#34;&gt;mustache.js&lt;/a&gt; for templates and the RequireJS &lt;a href=&#34;http://requirejs.org/docs/download.html#text&#34;&gt;text plugin&lt;/a&gt; to include my HTML template file.&lt;/p&gt;
&lt;h3 id=&#34;configuration&#34;&gt;Configuration&lt;/h3&gt;
&lt;p&gt;RequireJS is included in the page with a script tag and the data-main attribute is used to specify additional files to load. In this case “scripts/main” tells RequireJS to load the main.js file that resides in the scripts directory. Require will load the specified files asynchronously. This is what index.html looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;!DOCTYPE html&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;html&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;head&amp;gt;&amp;lt;br/&amp;gt;    &amp;lt;title&amp;gt;RequireJS Example&amp;lt;/title&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;body&amp;gt;&amp;lt;br/&amp;gt;    &amp;lt;h1&amp;gt;RequireJS Example&amp;lt;/h1&amp;gt;&amp;lt;br/&amp;gt;    &amp;lt;!-- This is a special version of jQuery with RequireJS built-in --&amp;gt;&amp;lt;br/&amp;gt;    &amp;lt;script data-main=&amp;#34;scripts/main&amp;#34; src=&amp;#34;scripts/require-jquery.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;/html&amp;gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I was a little skeptical of this approach working on older versions of Internet Explorer so I tested it quickly with IE6 and confirmed that it did indeed work just fine.&lt;/p&gt;
&lt;h3 id=&#34;creating-a-module&#34;&gt;Creating a Module&lt;/h3&gt;
&lt;p&gt;With this in place, we can create our module. The module definition begins with an array of dependencies:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;define([
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;require&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;jquery&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;requirejs.mustache&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text!my/template.html&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ],&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This module depends on require, jQuery, mustache, and our mustache template. Next is the function declaration where our module’s code will live. The arguments specified allow us to map variable names to the dependencies listed earlier:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(require, $, mustache, html) { ... }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this case we’re mapping the $ to jQuery, mustache to requirejs.mustache and, html to our template file.&lt;/p&gt;
&lt;p&gt;Inside the module we’re using Require’s .toUrl() function to grab a URL for our stylesheet. While it is possible to load CSS files asynchronously just like the other dependencies, there are some issues that arise that &lt;a href=&#34;http://requirejs.org/docs/faq-advanced.html#css&#34;&gt;are specific to CSS files&lt;/a&gt;. For our purposes it will be safer to just add a &lt;link&gt; element to the document like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; cssUrl = require.toUrl(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;./styles.css&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;head&amp;#39;&lt;/span&gt;).append($(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;link/&amp;gt;&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    { rel: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt;, media: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;all&amp;#34;&lt;/span&gt;, type: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text/css&amp;#34;&lt;/span&gt;, href: cssUrl }));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next, we define a view with some data for our Mustache template and render it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; view = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      { name: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Apples&amp;#34;&lt;/span&gt;, price: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1.29&lt;/span&gt;, unit: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;lb&amp;#39;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      { name: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Oranges&amp;#34;&lt;/span&gt;, price: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1.49&lt;/span&gt;, unit: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;lb&amp;#39;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      { name: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Kiwis&amp;#34;&lt;/span&gt;, price: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0.33&lt;/span&gt;, unit: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;each&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    soldByPound: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; (&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;unit&amp;#39;&lt;/span&gt;] === &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;lb&amp;#39;&lt;/span&gt;) ? &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt; : &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    soldByEach: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; (&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;unit&amp;#39;&lt;/span&gt;] === &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;each&amp;#39;&lt;/span&gt;) ? &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt; : &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;// render the Mustache template
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; output = mustache.render(html, view);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;// append to the HTML document
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;body&amp;#39;&lt;/span&gt;).append(output);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;the-template&#34;&gt;The Template&lt;/h3&gt;
&lt;p&gt;I really like this approach because it allows me to keep my HTML, CSS and JavaScript separate and also lets me write my templates in HTML instead of long, messy JavaScript strings. This is what our template looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;ul class=&amp;#34;hot-products&amp;#34;&amp;gt;&amp;lt;br/&amp;gt;  {{#products}}&amp;lt;br/&amp;gt;  &amp;lt;li class=&amp;#34;product&amp;#34;&amp;gt;&amp;lt;br/&amp;gt;    {{name}}: ${{price}} {{#soldByEach}}each{{/soldByEach}}{{#soldByPound}}per lb{{/soldByPound}}&amp;lt;br/&amp;gt;  &amp;lt;/li&amp;gt;&amp;lt;br/&amp;gt;  {{/products}}&amp;lt;br/&amp;gt;&amp;lt;/ul&amp;gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;including-the-module&#34;&gt;Including the Module&lt;/h3&gt;
&lt;p&gt;To include our new module in the page, we simply add it to our main.js file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;require([&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;jquery&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;my/module&amp;#34;&lt;/span&gt;], &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;($, module) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// jQuery and my/module have been loaded.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;    $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When we view our page, we see that the template was was rendered and appended to the document:&lt;/p&gt;
&lt;img alt=&#34;Require rendered&#34; border=&#34;0&#34; height=&#34;370&#34; src=&#34;/blog/2012/05/keeping-your-apps-neat-tidy-with/image-0.png&#34; title=&#34;require-rendered.png&#34; width=&#34;600&#34;/&gt;
&lt;h3 id=&#34;optimizing-your-code-with-the-rjs-optimizer&#34;&gt;Optimizing Your Code With The r.js Optimizer&lt;/h3&gt;
&lt;p&gt;One disadvantage of keeping everything separate and using modules in this way is that it adds to the number of HTTP requests on the page. We can combat this by using the the &lt;a href=&#34;http://requirejs.org/docs/optimization.html&#34;&gt;RequireJS Optimizer&lt;/a&gt;. The r.js script can be used a part of a build process and runs on both &lt;a href=&#34;https://nodejs.org/en/&#34;&gt;node.js&lt;/a&gt; and &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino&#34;&gt;Rhino&lt;/a&gt;. The Optimizer script can minify some or all of your dependencies with &lt;a href=&#34;https://github.com/mishoo/UglifyJS&#34;&gt;UglifyJS&lt;/a&gt; or Google’s &lt;a href=&#34;https://developers.google.com/closure/compiler/&#34;&gt;Closure Compiler&lt;/a&gt; and will concatenate everything into a single JavaScript file to improve performance. By following the documentation I was able to create a simple build script for my project and build the project with the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;node ../../r.js -o app.build.js&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This executes the app.build.js script with Node. We can compare the development and built versions of the project with the Network tab in Chrome’s excellent &lt;a href=&#34;https://developers.google.com/web/tools/chrome-devtools/&#34;&gt;Developer Tools&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Development Version:&lt;/p&gt;
&lt;img alt=&#34;Webapp devel&#34; border=&#34;0&#34; height=&#34;357&#34; src=&#34;/blog/2012/05/keeping-your-apps-neat-tidy-with/image-1.png&#34; title=&#34;webapp-devel.png&#34; width=&#34;600&#34;/&gt;
&lt;p&gt;Optimized with the RequireJS r.js optmizer:&lt;/p&gt;
&lt;img alt=&#34;Webapp built&#34; border=&#34;0&#34; height=&#34;356&#34; src=&#34;/blog/2012/05/keeping-your-apps-neat-tidy-with/image-2.png&#34; title=&#34;webapp-built.png&#34; width=&#34;600&#34;/&gt;
&lt;p&gt;It’s great to be able to go from 8 HTTP requests and 360 KB in development mode to 4 HTTP requests and ~118 KB after by running a simple command with Node! I hope this post has been helpful and that you’ll check out RequireJS on your next project.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Three Things: Startups, Rails news, jQuery index</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/03/three-things-startups-rails-news-jquery/"/>
      <id>https://www.endpointdev.com/blog/2012/03/three-things-startups-rails-news-jquery/</id>
      <published>2012-03-23T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;em&gt;I recently had a conversation with &lt;a href=&#34;/team/jon-jensen/&#34;&gt;Jon&lt;/a&gt; about End Point blogging, microblogging, and tweeting. Many of us End Pointer’s have tips and tools that we encounter regularly that aren’t worthy of an entire blog post, but are worthy of sharing. Here’s my first attempt at sharing smaller bits of info – stay tuned to see how it works out.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;1-paul-grahams-ambitious-startup&#34;&gt;1. Paul Graham’s Ambitious Startup&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;http://paulgraham.com/ambitious.html&#34;&gt;Here&lt;/a&gt; is an interesting recent article by Paul Graham entitled &lt;em&gt;Frighteningly Ambitious Startup Ideas&lt;/em&gt;. It’s great. Read it.&lt;/p&gt;
&lt;h3 id=&#34;2-rails-vulnerability-hack&#34;&gt;2. Rails Vulnerability Hack&lt;/h3&gt;
&lt;p&gt;If you aren’t up to speed on things going on in the Rails world, check out &lt;a href=&#34;https://github.com/rails/rails/commit/b83965785db1eec019edf1fc272b1aa393e6dc57&#34;&gt;this recent commit&lt;/a&gt;. A GitHub user was able to exploit Rails’ mass-assignment vulnerability to commit to the Rails core. Check out a few more related links at &lt;a href=&#34;https://web.archive.org/web/20120307145424/http://afreshcup.com/home/2012/3/5/double-shot-831.html&#34;&gt;A Fresh Cup’s post&lt;/a&gt; on the incident.&lt;/p&gt;
&lt;h3 id=&#34;3-jquerys-index-method&#34;&gt;3. jQuery’s index method&lt;/h3&gt;
&lt;table cellpadding=&#34;0&#34; cellspacing=&#34;0&#34; width=&#34;100%&#34;&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td valign=&#34;top&#34;&gt;&lt;p&gt;I recently came across the &lt;a href=&#34;https://api.jquery.com/index/&#34;&gt;index method in jQuery&lt;/a&gt;, and wanted to share an example of its use.&lt;/p&gt;
&lt;p&gt;I’m using &lt;a href=&#34;https://api.jqueryui.com/accordion/&#34;&gt;jQuery UI’s accordion&lt;/a&gt; on four categories (Period, Genre, Theme, Nationality) that have a set of options. A user can click any of the options to filter products, e.g. clicking on &lt;i&gt;Folk Songs&lt;/i&gt; in the screenshot to the right would bring up products that have a Genre of &lt;i&gt;Folk Songs&lt;/i&gt;. On the subsequent page load, the accordion region that includes the filtered option must be visible. Here’s what I came up with using the index method:&lt;/p&gt;
&lt;pre class=&#34;brush:jscript&#34;&gt;
$(function() {
    var active = 0;
    if($(&#39;#accordion a.current&#39;).length) {
        active = $(&#39;#accordion div&#39;).index($(&#39;#accordion a.current&#39;).parent());
    }
    $(&#39;#accordion&#39;).accordion({ active: active, autoHeight: false });
});
&lt;/pre&gt;
&lt;p&gt;And here’s how it breaks down:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First, the default active region is set to 0.&lt;/li&gt;
&lt;li&gt;Next, if an accordion link has a class of current (or a filtered option is selected), the index method is used to determine the position of that link’s parent divider among all the accordion regions.&lt;/li&gt;
&lt;li&gt;The accordion UI is created, set with the active option, which contains the selected link or defaults to the first accordion region.&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td style=&#34;padding-left:10px;&#34; valign=&#34;top&#34;&gt;&lt;img height=&#34;359&#34; src=&#34;/blog/2012/03/three-things-startups-rails-news-jquery/image-0.png&#34; style=&#34;border: 1px solid #999;&#34;/&gt;&lt;p&gt;jQuery’s index method was used to set the active accordion region.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

      </content>
    </entry>
  
    <entry>
      <title>A Little Less of the Middle</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/03/little-less-of-middle/"/>
      <id>https://www.endpointdev.com/blog/2012/03/little-less-of-middle/</id>
      <published>2012-03-14T00:00:00+00:00</published>
      <author>
        <name>Josh Williams</name>
      </author>
      <content type="html">
        &lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center; float:right&#34;&gt;
&lt;img alt=&#34;elephant&#34; border=&#34;0&#34; src=&#34;https://joshwilliams.name/monitoring/5258954374_52b77c8090_m.jpg&#34; style=&#34;clear: right&#34;/&gt;
&lt;br/&gt;&lt;a href=&#34;https://www.flickr.com/photos/34968534@N07/5258954374/&#34;&gt;elephant&lt;/a&gt; by &lt;a href=&#34;https://www.flickr.com/photos/34968534@N07/&#34;&gt;esclarabunda&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;I’ve been meaning to exercise a bit more. You know, just to keep the mid section nice and trim. But getting into that habit doesn’t seem to be so easy. Trimming middleware from an app, that’s something that can catch my attention.&lt;/p&gt;
&lt;p&gt;Something that caught my eye recently is a couple &lt;a href=&#34;https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=5384a73f98d9829725186a7b65bf4f8adb3cfaf1&#34;&gt;recent commits&lt;/a&gt; to Postgres 9.2 that adds a JSON data type. Or more specifically, the &lt;a href=&#34;https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=39909d1d39ae57c3a655fc7010e394e26b90fec9&#34;&gt;second commit&lt;/a&gt; that adds a couple handy output functions: array_to_json() and row_to_json(). If you want to try it out on 9.1, those have been made available &lt;a href=&#34;https://web.archive.org/web/20120208114210/http://people.planetpostgresql.org/andrew/index.php?/archives/255-JSON-for-PG-9.2-...-and-now-for-9.1!.html&#34;&gt;as a backported extension&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Lately I’ve been doing a bit of work with jQuery, using it for AJAX-y stuff but passing &lt;a href=&#34;https://www.json.org/&#34;&gt;JSON&lt;/a&gt; around instead. (AJAJ?) And traditionally that involves something in between the database and the client rewriting rows from one format to another. Not that it’s all that difficult; for example, in Python it’s a simple module call:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jsonresult = json.dumps(cursor.fetchall())&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&amp;hellip; assuming I don’t have any columns needing processing: &lt;em&gt;TypeError: datetime.datetime(2012, 3, 09, 18, 34, 20, 730250, tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=0, name=None)) is not JSON serializable&lt;/em&gt; Similarly in PHP I can stitch together a JSON array to pass back to the front end:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#369&#34;&gt;$row&lt;/span&gt; = pg_fetch_assoc(&lt;span style=&#34;color:#369&#34;&gt;$rs&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#369&#34;&gt;$rows&lt;/span&gt;[] = &lt;span style=&#34;color:#369&#34;&gt;$row&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;$jsonresult&lt;/span&gt; = json_encode(&lt;span style=&#34;color:#369&#34;&gt;$rows&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now I can trim that out, and embed the encoding right into the database query:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;SELECT&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;row_to_json(pages)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;pages&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;WHERE&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;page_id&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;5&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#888&#34;&gt;-- or, to return an array of rows
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;SELECT&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;array_to_json(array_agg(pages))&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;pages&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;WHERE&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;page_title&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;LIKE&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;A Little Less%&amp;#39;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice the use of the row-type reference to the table itself after the SELECT, rather than just a single column. This outputs:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[{&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;page_id&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;105&lt;/span&gt;,&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;today&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;\u03c0 day&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;page_title&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;A Little Less of the Middle&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;contents&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;I&amp;#39;ve been meaning to exercise a bit more.  You...&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;published_on&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;2012-03-15 03:30:00+00&amp;#34;&lt;/span&gt;}]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Compare that to the output from json_encode() above, where the database driver treated everything as a string, even the page_id integer. The other difference is the Postgres code doesn’t do any quoting on Unicode characters:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[{&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;page_id&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;105&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;today&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;π day&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;page_title&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;A Little Less of the Middle&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;contents&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;I&amp;#39;ve been meaning to exercise a bit more.  You...&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;published_on&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;2012-03-15 03:30:00+00&amp;#34;&lt;/span&gt;}]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I’m a bit on the fence about whether it’s a real replacement for doing it in middleware, especially in some web use cases where you typically want to do things like anti-XSS type processing on some fields before sending them off to a browser somewhere. Besides, at the moment at least, there’s no built-in way to break JSON back apart in the database. But I’m sure there’s some places getting direct JSON is helpful, and it’s certainly an interesting start.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Handling outside events with jQuery and Backbone.js</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/03/handling-outside-events-with-jquery-and/"/>
      <id>https://www.endpointdev.com/blog/2012/03/handling-outside-events-with-jquery-and/</id>
      <published>2012-03-02T00:00:00+00:00</published>
      <author>
        <name>Greg Davidson</name>
      </author>
      <content type="html">
        &lt;p&gt;I recently worked on a user interface involving a persistent shopping cart on an ecommerce site. The client asked to have the persistent cart close whenever a user clicked outside or “off” of the cart while it was visible. The cart was built with &lt;a href=&#34;http://backbonejs.org/&#34;&gt;Backbone.js&lt;/a&gt;, and &lt;a href=&#34;https://jquery.com/&#34;&gt;jQuery&lt;/a&gt; so the solution would need to play nicely with those tools.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2012/03/handling-outside-events-with-jquery-and/image-0.png&#34; imageanchor=&#34;1&#34; style=&#34;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2012/03/handling-outside-events-with-jquery-and/image-0.png&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;The first order of business was to develop a way to identify the “outside” click events. I discussed the scenario with a colleague and YUI specialist and he suggested the YUI &lt;a href=&#34;http://yuilibrary.com/gallery/show/outside-events&#34;&gt;Outside Events&lt;/a&gt; module. Since the cart was built with jQuery and I enjoyed using that library, I looked for a comparable jQuery plugin and found &lt;a href=&#34;http://benalman.com/&#34;&gt;Ben Alman’s&lt;/a&gt; &lt;a href=&#34;http://benalman.com/projects/jquery-outside-events-plugin/&#34;&gt;Outside Events plugin&lt;/a&gt;. Both projects seemed suitable and a review of their source code revealed a similar approach. They listened to events on the document or the &lt;html&gt; element and examined the event.target property of the element that was clicked. Checking to see if the element was a descendant of the containing node revealed whether the click was “inside” or “outside”.&lt;/p&gt;
&lt;p&gt;With this in mind, I configured the plugin to listen to clicks outside of the persistent cart like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#modal-cart&amp;#39;&lt;/span&gt;).bind(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;clickoutside&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(event) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The plugin worked just like it said on the tin, however further testing revealed a challenge. The site included ads and several of them were &amp;lt;iframe&amp;gt; elements. Clicks on these ads were not captured by the clickoutside event listener. This was a problem because the outside event listening code could be ignored depending on where the user clicked on the page.&lt;/p&gt;
&lt;p&gt;To mitigate this issue, a second approach was taken. A “mask” element was added below the persistent cart. CSS was used to position the mask below the persistent cart using the z-index property. The mask was invisible to the user because the background was transparent. Instead of listening to clicks outside of the persistent cart, clicks on the mask element could be captured. Thanks to the magic of CSS, the mask covered the entire page (including those pesky &amp;lt;iframes&amp;gt;).&lt;/p&gt;
&lt;p&gt;Now that I was able to handle the “outside” clicks properly, the event handling code needed to be configured inside the Backbone.js cart view. Backbone uses jQuery to handle events behind the scenes but the syntax is a little bit different.&lt;/p&gt;
&lt;p&gt;Where with jQuery you might set up an event handler like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#mask&amp;#39;&lt;/span&gt;).click(maskClickHandler);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This would be the Backbone.js equivalent:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;click #mask&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;maskClickHandler&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here is how it all shaped up inside the Backbone view. First, the event handler on the mask element was configured inside the events object of the view:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;window&lt;/span&gt;.cartView = Backbone.View.extend({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  template: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#cart-template&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  initialize: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _.bindAll(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;render&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.initializeTemplate();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  initializeTemplate: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.template = _.template($(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.template).html());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;// set up event listener on the mask element
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  events: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;click #modal-cart-mask&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;closeCart&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The openCart function was augmented to show the mask element each time the persistent cart was shown:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  openCart: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// show the mask element when the cart is opened
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;    $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.el).find(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#modal-cart-mask&amp;#39;&lt;/span&gt;).show();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.render();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.el).removeClass(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;closed&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.isClosed = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },  
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Lastly, the closeCart function was modified to hide the mask element each time the persistent cart was closed:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  closeCart: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.el).addClass(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;closed&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.isClosed = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// hide the mask element when the cart is closed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;    $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.el).find(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;#modal-cart-mask&amp;#39;&lt;/span&gt;).hide();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  render: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.el).html(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.template(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.model.toJSON()));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With this in place, the outside events were properly captured and handled by the same Backbone view that managed the persistent cart. How’s that for playing nice?&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>jQuery Async AJAX: Interrupts IE, not Firefox, Chrome, Safari</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/03/jquery-async-ajax-interrupts-ie-not/"/>
      <id>https://www.endpointdev.com/blog/2012/03/jquery-async-ajax-interrupts-ie-not/</id>
      <published>2012-03-01T00:00:00+00:00</published>
      <author>
        <name>Carl Bailey</name>
      </author>
      <content type="html">
        &lt;p&gt;I recently worked on a job for a client who uses (&lt;a href=&#34;http://codylindley.com/thickbox/&#34;&gt;Thickbox&lt;/a&gt;). Now, ThickBox is no longer maintained, but the client has used it for a while, and, “if it ain’t broke don’t fix it,” seems to apply. Anyway, the client needed to perform address verification checks through Ajax calls to a web-service when a form is submitted. Since the service sometimes takes a little while to respond, the client wanted to display a ThickBox, warning the user of the ongoing checks, then, depending on the result, either continue to the next page, or allow the user to change their address.&lt;/p&gt;
&lt;p&gt;Since the user has submitted the form and is now waiting for the next page, I chose to have jQuery call the web service with the async=false option of the ajax() function. (Not the best choice, looking back). Everything worked well: Firefox, Safari and Chrome all worked as expected, and then we tested in IE. Internet Explorer would not pop up the initial ThickBox (‘pleaseWait’ below), until the Ajax queries had completed, unless I put an alert in place between them, then the ThickBox would appear as intended.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; myFunc(theForm) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tb_show(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Please wait.&amp;#39;,&amp;#39;#TB_inline?height=50&amp;amp;width=200#inlineID=pleaseWait&amp;amp;modal=true&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $.ajax({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        type : &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        url:  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;call to webservice&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        data:   &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;address to post to the webservice&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;async&lt;/span&gt;:  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        success:  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; (msg) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To make a long story a bit shorter, we finally determined that the culprit was the async setting in the JQuery ajax call. Making the Ajax call in synchronous mode, locked the browser and delayed the display of the ThickBox, even though the tb_show call preceded the ajax call! Setting the async value to true solved the locking problem, and worked fine in all browsers.&lt;/p&gt;
&lt;p&gt;The jQuery Documentation states: “Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active,” which turns out to be true (at least for IE). What surprised me was , in this case, the ThickBox call was requested well before the jQuery AJAX call. This makes me think that maybe tb_show is triggered asynchronously in IE. In any case it is different here than in the other mainstream browsers, and it gets locked up by the synchronous Ajax.&lt;/p&gt;
&lt;p&gt;I worked around the problem by setting the Ajax calls to be asynchronous, then keeping track to make sure both the shipping address and the billing address checks have returned before continuing.&lt;/p&gt;
&lt;p&gt;The lessons here are:&lt;/p&gt;
&lt;p&gt;(1) Be careful using synchronous mode with jQuery AJAX calls. Easier to leave them as default and ensure all your calls have returned before you take the next step.&lt;/p&gt;
&lt;p&gt;(2) As always, don’t assume your solution will work as intended until you see it work in IE.&lt;/p&gt;

      </content>
    </entry>
  
</feed>
