Justin A. Parr - Technologist

Technology, Strategy, Insights, and Tech Support

  • HOME
  • Quick Facts
  • CygUlarn Win32
  • About Me

HOME

Posted by Justin A. Parr on April 28, 2013
Posted in: Main Page.

JPLogo

Hi!  Thanks for stopping by, and please feel free to look around.

Please register to leave comments – polite feedback is always appreciated.

Log In or Register to post a comment.

RSS Link:  https://justinparrtech.com/JustinParr-Tech/feed

MORE Updates on the Gate Controller

Some fun things to occupy your time:

  • Find the center of a circle
  • Make some quiche
  • Enumerate permutations of things
  • Have some laughs here, here, here, here, or here.

Excel – Number of Sundays – A better Answer

Posted by Justin A. Parr on February 23, 2025
Posted in: Other Stuff. Leave a Comment

Excel – Number of Sundays – A better Answer

I looked up how to count the number of Sundays between two dates…. the so-called answer shocked me.  There are a couple of popular answers, but they are horribly inefficient.

Let me show you a better way…..

Update 4/22/2025

Due to a severe copy and paste error, the formulas were completely wrong.  8-(

These have now been corrected.

 

Solution

Let’s say we have the following cells:

A B
1 Start 1/1/2025
2 End 5/1/2025
3 Which Day 1

We will follow the Excel convention, where Sunday = 1, to find the number of “1” days (cell B3) between 1/1/2025 (cell B1) and 5/1/2025 (cell B2).

Between the two dates:

=INT((B2-(B1+B3-WEEKDAY(B1)+7))/7)+1

Correctly returns 17

Between and including the two dates:

=INT((B2-(B1+B3-WEEKDAY(B1)+7))/7)+1+IF(WEEKDAY(B1)=B3,1,0)

Correctly returns 17.  If we were to change B1 to 1/5 (a Sunday), the result would be 16 without the extra IF term.

 

For a more detailed explanation…

Continue Reading

Cache Busting using Javascript

Posted by Justin A. Parr on August 10, 2024
Posted in: Tech Support. Tagged: cache busting, cachebusting, javascript. Leave a Comment

Cache Busting using Javascript

 

Problem

Google Chrome (and possibly, other browsers) don’t properly honor the Cache-Control header.

If you are on Page A, click a link for Page B, then hit the back button to go back to Page A, Chrome uses a pre-rendered, cached version of Page A, which may now have stale content.

Action Location
Start Page A
8:05 AM
Click link on Page A Page B
8:10 AM
Hit browser back button Page A
8:05 AM

At this point, Page A is basically static.  Any dynamic content won’t be refreshed, even if it executes in Javascript.

Disrupting this behavior is known as “cache busting”.

 

Solution

Add this Javascript to your page’s <HEAD> section:

<SCRIPT>
function nocache(){
  var tc3=new Date();
  var delta=tc3-tc1;
  if (delta>2000) {
    window.location.reload();
  } else {
    tc1=tc3;
  }
}
var tc1=new Date();
setInterval(nocache,1000);
</SCRIPT>

 

How it Works

When the page first executes, it creates a Javascript variable tc1 with a current timestamp.

Then, it sets up a timer callback function, nocache(), which executes every 1 second.

When nocache executes, it creates a new timestamp (tc3), and if the difference between the two is greater than 2 seconds, it reloads the current page.  If not, it updates the tc1 timestamp to current.

The result is that if the page remains static for more than 2 seconds, it will refresh.  However, as long as the page is active, it keeps updating the timestamp in tc1 instead.

If you click the link to Page B, wait 2 or more seconds, then hit the browser’s back button, the timestamp in tc1 will be the point in time from when the link was clicked (more than 2 seconds ago).  One second after you hit the back button, the nocache function sees that tc1 is more than 2 seconds out of date and reloads the page.  If the page successfully reloads, tc1 is updated in the process.  If not, it simply retries the reload every 1 second.

Also, if your page uses JSON or XML to dynamically render content, the nocache timer function can simply call your page’s update function rather than reload the entire page.

 

Conclusion

When you hit the browser’s back button, Chrome tries very hard to use a pre-rendered page from cache rather than use the Cache-Control header or contact the server to see if the page is stale (which it should be doing).  This means that when you hit the back button, any dynamic code has already executed, and the page picks up where it left off from a script execution standpoint.  Unfortunately, this includes any events that have fired, which means that the pre-rendered version of the page is basically static.

I have seen other solutions that use the onpageshow event, or other event hooks.  However, I have found these to be unreliable in Chrome for cache busting.  In contrast, the timer hook must be honored for basic page functionality, and therefore can’t simply be killed off like other events.

A side effect of this approach is that if the server is unavailable and the page tries to refresh, it will get stuck in a refresh loop until the server is available again.  This is not necessarily a negative behavior, but could easily be fine tuned using a counter, for example, to only try to refresh a set number of times and then stop.  During page load, “retries” is set to some number, n.  “Retries > 0” is then added as a condition to the if block, which then decrements retries during each execution.  If retries hits zero, it updates tc1 to current, which stops all attempts.  In another variation, retries can be its own, outer “if” block, so that some other exit action can be executed, for example, alerting the user that the server is offline and the page is stale.

A fleshed-out version would look like this:

<SCRIPT>
  function nocache() {
    var tc3=new Date();
    var delta=tc3-tc1;
    if (retries>0) {
      // Normal action
      if (delta>2000) {
        retries-=1; 
        window.location.reload();
      } else { 
        tc1=tc3; 
      }
    } else {
      // When retries hits zero, set error text, make the element visible, and disable the nocache timer
      var e=document.getElementById("ErrorText");
      e.innerHTML="The server is offline and this page is dead.  Have a nice day.";
      e.style.visibility="visible";
      clearInterval(nocachetimer);
    }
  } 
  var tc1=new Date();
  var retries=3;
  var nocachetimer=setInterval(nocache,1000); 
</SCRIPT>
<DIV ID=ErrorText STYLE='visibility:hidden; display:block;'>&nbsp;</DIV>

I hope you find this useful, and thanks for reading!

Javascript Calculator

Posted by Justin A. Parr on May 8, 2023
Posted in: Other Stuff. Leave a Comment

Update, 5/14/2023:  Version 3.2

Update, 5/11/2023:  Version 3.1.  Original: Version 2


I wrote a javascript calculator while I was waiting for something the other day.  Here it is:

Permalink: Here

 

Technical Details

  • Single, self-contained HTML file with embedded CSS and Javascript.
  • The display width is configurable via a variable – currently 20 digits
  • The top line is a “register” – normally this would be hidden on a desktop calculator.  The two variables, “register” and “display” are global, which simplifies the architecture.
  • The buttons are created using a function
  • Binary math functions are performed by a wrapper that sanitizes the input values and then performs a callback to the underlying math operation – the pointer to the callback function is passed via onclick.
  • Unary math functions are basically handled the same as binary operations, where onclick calls a wrapper, and the wrapper executes a callback.

To Do

(Updated, 5/11/2023)

  • Add MS, MR, M+, and M-, which will require a separate register.
  • Add a configurable table of constants.
  • Tool tips with enable/disable button.
  • Hex and binary functions, although these might be a separate calculator
    Update:  I think I will just make a dedicated programming calculator the next time I’m bored :-)

Funny Story about 3.1 vs 3.2

I uploaded version 3.1, and patted myself on the back for having done such a great job.  Right-click, save as HTML, fire it up in Chrome, and…everything was rendering twice.

What happened??

The UI is dynamic, but the saved version of the page had BOTH a static copy of the dynamically-generated HTML, as well as the javascript code to dynamically generate the HTML.  So every UI element was rendered TWICE.  Worse, if you modify the Javascript at the top of the file to alter the constants or the display size, you would have one copy that’s correct because it’s dynamic, but the static copy would still be wrong.

Interestingly, if you View Source and save from there, it won’t have that problem, but that’s not what I was after.

To fix this, I changed from document.write to using extra SPANs for each block of UI elements, and setting innerHTML.  Despite the fact that saving the file includes a static copy of the HTML, the dynamic code simply overwrites it each time the page is loaded.  So if you change a Javascript variable and reload, the dynamic code blows away the static HTML and replaces it with a correct version.

 

Do you like it?  Feel free to copy it.  Click the permalink.  Then right-click the calculator, and select “Save as html”.

Ideas or suggestions?  Please feel free to leave me a comment.

Gatetrilogy Saga: The Front Gate Part III, The Final Gate Opener

Posted by Justin A. Parr on April 30, 2023
Posted in: Other Stuff. 1 comment

After 7 months of continuous issues, I think I finally beat the problems with the front gate, but the way I did it might surprise you.

Continue Reading

The Dangers of Old Code – A Cautionary Tale

Posted by Justin A. Parr on April 28, 2023
Posted in: Good Design - Bad Design. Leave a Comment

Two bad lines of code took this entire site down.  Here is what you can learn from my mistake.

Continue Reading

Quantum Chicken Joke

Posted by Justin A. Parr on April 16, 2023
Posted in: Other Stuff. Leave a Comment

Why did the quantum chicken cross the road?

  • Because he was already there.

Why did the quantum cat cross the road?

  • Because he was entangled with the chicken.

Calculate the Dimensions of a TV or Monitor

Posted by Justin A. Parr on January 7, 2023
Posted in: Other Stuff. Leave a Comment

Calculate the Dimensions of a TV or Monitor

As a follow-up to Monitor and TV Buying Guide – 2022, I built a simple calculator to tell you the approximate width and height of the screen, given its diagonal measurement and aspect ratio.

 

Permalink: Screen Size Calculator

MORE Things to Check Before You Buy A House

Posted by Justin A. Parr on December 18, 2022
Posted in: Other Stuff. Leave a Comment

In 2015, I wrote this post: Justin’s Rules for Buying a House.

These were things that I had learned when I was shopping for a house in 2002, and solidified in to a tangible list when a couple of friends of mine were house shopping in 2015.

After shopping for a house in 2019 and moving out to the country, here are a few more things I’ve added to my list.

Continue Reading

Travel Tech and Tips – 2023

Posted by Justin A. Parr on December 12, 2022
Posted in: Tech Recommendations, Tech Support. 1 comment

If you travel in 2023, travelling with tech is unavoidable.  After reading a completely unhelpful, but similarly-titled ZD article that read more like an Apple fanboy post, I decided to write something that’s actually helpful.

Continue Reading

Ranged (Inequality) Searches On Encrypted Data

Posted by Justin A. Parr on November 27, 2022
Posted in: Other Stuff. Leave a Comment

Updated to v1.2 on 1/3/2023.

Although it’s widely agreed that field-level data encryption provides the best protection against data breaches, it also limits an application’s ability to perform ranged searches, where an inequality comparison is performed against search terms.

Although there are existing strategies which use search trees, these depend on complex key management schemes, or trees with fixed intervals.

Another common approach is to assign artificial search keys, but the general problem with this approach is that it can result in information disclosure as well as key collisions. If the keys are regularly-spaced, this can lead to an inference about the underlying data values, and if the spacing is too narrow, this can lead to insufficient search keys when presented with a large quantity of data values for given key interval.

In the scheme proposed herein, a binary tree is used to generate integer search keys, called comparators, that are non-sequential but maintain the same ordinal relationship as the underlying data.  Because comparators have no fixed relationship to each other, they don’t leak any information, but because they maintain an ordinal relationship, they can be searched with a ranged query.

Click here to view or download:

Searching Encrypted Data

Posts navigation

← Older Entries
  • Search!

  • Temperature at Casa de Parr

  • Recent Posts

    • Excel – Number of Sundays – A better Answer
    • Cache Busting using Javascript
    • Javascript Calculator
    • Gatetrilogy Saga: The Front Gate Part III, The Final Gate Opener
    • The Dangers of Old Code – A Cautionary Tale
    • Quantum Chicken Joke
    • Calculate the Dimensions of a TV or Monitor
    • MORE Things to Check Before You Buy A House
    • Travel Tech and Tips – 2023
    • Ranged (Inequality) Searches On Encrypted Data
  • Topics

    • Analyses and Responses (27)
    • Good Design – Bad Design (33)
    • IT Management (1)
    • Justinisms (8)
    • Main Page (1)
    • Math and Science (30)
    • Other Stuff (38)
    • Quick Facts (7)
    • Rants (17)
    • Tech Support (61)
      • Food and Cooking (10)
      • Tech Recommendations (12)
      • Tech Tip (7)
      • Wordpress Stuff (3)
      • Zen Cart Stuff (1)
    • The Light Side (37)
  • Links

    Log in or Register to post comments

    RSS Feed
    https://justinparrtech.com/JustinParr-Tech/feed

    View my LinkedIn Profile
    http://www.linkedin.com/in/justinparr

    About Me
    Justin A. Parr

    Who is Jill Parr
    Find out here.

  • Older Posts

    • February 2025 (1)
    • August 2024 (1)
    • May 2023 (1)
    • April 2023 (3)
    • January 2023 (1)
    • December 2022 (2)
    • November 2022 (2)
    • September 2022 (1)
    • August 2022 (3)
    • June 2022 (2)
    • March 2022 (1)
    • January 2022 (2)
    • December 2021 (1)
    • July 2021 (1)
    • May 2021 (1)
    • March 2021 (1)
    • February 2021 (2)
    • November 2020 (4)
    • October 2020 (1)
    • September 2020 (1)
    • August 2020 (1)
    • July 2020 (1)
    • June 2020 (1)
    • May 2020 (2)
    • April 2020 (1)
    • March 2020 (8)
    • February 2020 (2)
    • January 2020 (1)
    • November 2019 (2)
    • August 2019 (3)
    • July 2019 (1)
    • June 2019 (1)
    • April 2019 (1)
    • February 2019 (3)
    • January 2019 (1)
    • December 2018 (1)
    • November 2018 (1)
    • October 2018 (2)
    • September 2018 (1)
    • August 2018 (2)
    • July 2018 (1)
    • June 2018 (1)
    • April 2018 (1)
    • February 2018 (2)
    • January 2018 (2)
    • December 2017 (1)
    • November 2017 (2)
    • August 2017 (2)
    • July 2017 (1)
    • March 2017 (1)
    • February 2017 (2)
    • January 2017 (1)
    • December 2016 (5)
    • November 2016 (3)
    • September 2016 (5)
    • August 2016 (2)
    • April 2016 (1)
    • March 2016 (3)
    • February 2016 (2)
    • January 2016 (7)
    • December 2015 (3)
    • November 2015 (1)
    • October 2015 (3)
    • August 2015 (5)
    • July 2015 (3)
    • June 2015 (2)
    • May 2015 (4)
    • April 2015 (4)
    • March 2015 (3)
    • February 2015 (4)
    • January 2015 (8)
    • December 2014 (8)
    • September 2014 (1)
    • August 2014 (1)
    • July 2014 (2)
    • June 2014 (4)
    • May 2014 (1)
    • April 2014 (2)
    • March 2014 (3)
    • February 2014 (5)
    • January 2014 (1)
    • December 2013 (2)
    • October 2013 (2)
    • July 2013 (3)
    • April 2013 (1)
    • October 2010 (1)
    • August 2010 (1)
    • July 2009 (1)
    • April 2009 (1)
    • November 2008 (1)
    • October 2008 (1)
    • September 2008 (1)
    • May 2008 (1)
    • March 2008 (1)
    • January 2008 (1)
    • June 2005 (1)
    • May 2005 (4)
Proudly powered by WordPress Theme: Parament by Automattic.