Weird adventures in javascript

This is the introduction....

The page needed to display:

  • the page title
  • a sorted list of links to articles

Pretty simple right? Well..... There were a few catches...

  • The links needed to be in alphabetical order (A - Z)
  • They also needed to be in numeric order (meaning 10 comes after 9 and not after 1)
  • The whole thing needed to be supported by IE9 (no, I'm not kidding)

So let's go!

 

HTML

Because each entry on the page was generated by WordPress as a post, the markup for each entry looked like this:

        
          <article id="post-597" class="clearfix post-597 post type-post status-publish format-standard hentry cadtegory-computed-tomography category-neuroradiology">
	<header class="entry-header">
		<h1 class="entry-title"><a href="https://health.uconn.edu/radiology-online/2018/02/01/hypertensive-intracranial-hemorrhage/" rel="bookmark">Hypertensive Intracranial Hemorrhage</a></h1>
		<div class="entry-meta">
		    <span class="posted-on">Posted on <a href="https://health.uconn.edu/radiology-online/2018/02/01/hypertensive-intracranial-hemorrhage/" rel="bookmark"><time class="entry-date published" datetime="2018-02-01T14:14:47+00:00">February 1, 2018</time><time class="updated" datetime="2018-02-01T14:17:44+00:00">February 1, 2018</time></a></span><span class="byline"> by <span class="author vcard"><a class="url fn n" href="https://health.uconn.edu/radiology-online/author/slr04007/">slr04007</a></span></span>		
		</div><!-- .entry-meta -->
	</header><!-- .entry-header -->

	<div class="entry-content">
		<p><a href="https://health.uconn.edu/radiology-online/wp-content/uploads/sites/175/2018/01/SH-4-Neuro-CT-Hypertensive-intracranial-hemorrhage.pdf">Hypertensive Intracranial Hemorrhage</a></p>
	</div><!-- .entry-content -->

	<footer class="entry-footer">
		<span class="cat-links">
		Posted in <a href="https://health.uconn.edu/radiology-online/category/computed-tomography/" rel="category tag">Computed Tomography</a>, <a href="https://health.uconn.edu/radiology-online/category/neuroradiology/" rel="category tag">Neuroradiology</a></span>
		<span class="edit-link"><a class="post-edit-link" href="https://health.uconn.edu/radiology-online/wp-admin/post.php?post=597&amp;action=edit">Edit</a></span>	
	</footer><!-- .entry-footer -->
</article>        
    

Which was kind of a lot to work with since all that was displayed on the page was...

        
          <div class="entry-content">
	<p>
	    <a href="really-long-link.pdf">
	        Hypertensive Intracranial Hemorrhage
        </a>
    </p>
</div>        
    

Sadly, I couldn't edit the theme files to manage this (it's a big multisite network and this was an unusual case). But, there's a plugin on the site that lets admins add custom javascript as needed. So, I decided the best I could do was use javascript to manage everything. But wait! Lest you think it's going to be too easy,

  • I wasn't going to be able to use any "fancy" ES6 syntax (needed to support IE9...) and
  • it would have to only run on one page

But at least I could use jQuery!

For the record, if it sounds like I'm complaining, I'm not. It was kind of a fun problem to solve. So, quick review...

  • Needs IE support
  • No ES6
  • Needs to be alphabetically and numerically ordered
  • Only run it on one page on the site
  • I can use jQuery

Let's go!

Javascript

The easiest thing to get out of the way was making sure the code only ran on certain pages. Fortunately, the body for those pages all had a class called category. So, the first thing I did was make sure that if that class wasn't detected, the code wouldn't run.

        
          jQuery(document).ready(function($) {
    if (!$('body').hasClass('category')) return;
});        
    

The next thing to do was get the two parts of the page I really needed.

  • the title
  • the links from each article
        
          jQuery(document).ready(function($) {

    // only run the code if we're on the correct page
    if (!$('body').hasClass('category')) return;
    
    var pageTitle = $('.page-title');
    var articleLinks = $('.entry-content');
});        
    

Next, it's time to sort the the links. At first I started with something like this:

        
          jQuery(document).ready(function($) {

    // only run the code if we're on the correct page
    if (!$('body').hasClass('category')) return;
    
    var pageTitle = $('.page-title');
    var articleLinks = $('.entry-content');
    
    var sortedLinks = articleLinks.sort(function(a, b) {
        var titleA = a.textContent.trim().toLowerCase();
        var titleB = b.textContent.trim().toLowerCase();
        
        if (titleA < titleB) {
    	  return -1;
    	} else {
    	  return 1;
	    }
    })
});        
    

But there's a problem with this. It works for alphabetical sorting, but it doesn't work for numeric sorting. When the titles contained numbers at the beginning, they would go in this order: 1, 10, 2, 3, etc.... Fortunately there's a really nice string method called localeCompare that takes care of that problem.

The way it works is you compare stringA to stringB, give it a language, and set some options. In this case, the important option was the numeric property. Using it, I was able to account for numeric and alphabetical sorting like this:

        
          jQuery(document).ready(function($) {

    // only run the code if we're on the correct page
    if (!$('body').hasClass('category')) return;
    
    var pageTitle = $('.page-title');
    var articleLinks = $('.entry-content');
    
    var sortedLinks = articleLinks.sort(function(a, b) {
        var titleA = a.textContent.trim().toLowerCase();
        var titleB = b.textContent.trim().toLowerCase();
        
        return titleA.localeCompare(titleB, 'en', {
            sensitivity: 'base',
            numeric: true
        })
    })
});        
    

The last two things to do were get rid of all the unneeded markup and put back just the title and newly sorted links.

        
          jQuery(document).ready(function($) {

    // only run the code if we're on the correct page
    if (!$('body').hasClass('category')) return;
    
    var pageTitle = $('.page-title');
    var articleLinks = $('.entry-content');
    
    var sortedLinks = articleLinks.sort(function(a, b) {
        var titleA = a.textContent.trim().toLowerCase();
        var titleB = b.textContent.trim().toLowerCase();
        
        return titleA.localeCompare(titleB, 'en', {
            sensitivity: 'base',
            numeric: true
        })
    })
    
    // get rid of all the markup from the container
    // add back the title and links
    
    $('.main').empty().append(pageTitle, sortedLinks);
});        
    

Conclusion

Sometimes when we're working on large and/or old systems it's not possible to use the most modern techniques. Sometimes it's worth knowing how to handle issues with whatever tools happen to be available.

Posted by Adam Berkowitz