As I was building my client’s new Vodka site, one of the requirements was a prompt that will ask the viewer for their date of birth. Seems simple enough right? So I started coding. Turns out that it takes a bit of work! There’s form validation, date logic, styling – so I decided to make a plugin out of it. I’m going to call it: AgeCheck.js.
View Demo
View in Github
I anticipate plenty of developers will need this kind of functionality. Now all they have to do is add a couple lines of code – and voila! Ready to start? Let’s begin.
Setting up the plugin:
The code below sets up our plugin code. Basically it allows us to use the function name “ageCheck” and pass in an object (options) as parameters we can use inside our plugin.
(function ($){ $.ageCheck = function(options) { //our code goes here... }; })(jQuery);
We then worry about what options we will allow our users to have. I suspect the minimum age will vary, they may want to have a “redirect” url, the “title” of the popup would be nice and the copy should be changeable as well.
var settings = $.extend({ minAge : 21, redirectTo : '', title : 'Age Verification', copy : 'This Website requires you to be [21] years or older to enter. Please enter your Date of Birth in the fields below in order to continue:' }, options);
The settings variable is using .extend() – which merges our options and our internal object together – allowing it to be accessible throughout our plugin code.
The Heart of our plugin
Plenty of times when writing code – I find myself re-factoring code so it’s easier to digest. The main logic of the program I put in an internal variable called “_this”. This is not accessible anywhere but inside the plugin code itself. It contains all of the variables and methods we need for our plugin to work.
The code below is our main object:
var _this = { month : '', day : '', year : '', age : '', errors : Array(), setValues : function(){ var month = $('.month').val(); var day = $('.day').val() _this.month = month; _this.day = day.replace(/^0+/, ''); //remove leading zero _this.year = $('.year').val(); }, validate : function(){ _this.errors = []; if (/^([0-9]|[12]d|3[0-1])$/.test(_this.day) === false) { _this.errors.push('Day is invalid or empty'); }; if (/^(19|20)d{2}$/.test(_this.year) === false) { _this.errors.push('Year is invalid or empty'); }; _this.clearErrors(); _this.displayErrors(); return _this.errors.length < 1; }, clearErrors : function(){ $('.errors').html(''); }, displayErrors : function(){ var html = '
- ';
for (var i = 0; i < _this.errors.length; i++) {
html += '
- x' + _this.errors[i] + ' '; } html += '
' + settings.title + '
'; html += '' + copy.replace('[21]',''; html += settings.minAge+''); + '
'; html += ''; html += 'Success!
'; successMsg += 'You are now being redirected back to the application...
'; $('.ac-container').html(successMsg); setTimeout(function(){ $('.ac-container').animate({'top':'-350px'},200, function(){ $('.ac-overlay').animate({'opacity':'0'},500, function(){ if (settings.redirectTo != '') { window.location.replace(settings.redirectTo); }else{ $('.ac-overlay, .ac-container').remove(); } }); }); },2000); } }; //end _thisOur object contains everything form validation, re-centering the display, clearing errors, error and success handling and finally building the html. You can easily tell which part is which – by the names I have given the methods. This makes it easy for any programmer to come in and maintain the code.
Now that we have our settings and the main logic – it’s time to execute our code.
Chunks of Events
So first, let’s check if there’s a flag that user is old enough. If you look in our main object, we’re setting a flag if user passes our age check. We called it “ageVerified” and set it to “true”. If they are, we don’t even show the box – we just let them in the site.
if(sessionStorage.getItem("ageVerified") == "true"){ return false; } _this.buildHtml();
If the flag isn’t there, we continue with our popup using our buildHtml() method.
Then the action begins when the click on our button. Below simply ties our methods to a “if, else” wrappers such as below:
$('.ac-container button').on('click', function(){ _this.setValues(); if (_this.validate() === true) { _this.setAge(); if(_this.age >= settings.minAge){ if(!_this.setSessionStorage("ageVerified", "true")){ console.log('sessionStorage not supported by your browser'); }; _this.handleSuccess(); }else{ _this.errors.push('You are not old enough'); _this.displayErrors(); } } });
So to explain, when a user click on our button – we set the values that are coming from the drop down and input fields in our form. It checks if they’re valid inputs – it they are – it sets the age we use in our plugin. Now there’s only 2 possible scenarios we set – if user is old enough or not. We handle both scenarios with letting them through or showing error messages.
Some Styles
Our plugin has to look nice. On top of that, we also don’t want it to clash with other styles of the site. We prefix all of our styles with the “ac-” to namespace our plugin classes.
The CSS for our box is right below:
@import url(http://fonts.googleapis.com/css?family=Bree+Serif); .ac-overlay{ box-sizing: border-box; height:100%; width:100%; position: fixed; top: 0; right: 0; bottom: 0; left: 0; background: rgba(0,0,0,0.8); z-index: 99998; opacity:0; cursor: wait; } .ac-container { box-sizing: border-box; font-family: 'Bree Serif', serif; width: 360px; position: fixed; padding: 20px 20px 30px 20px; background: #fff; z-index: 99999; opacity:0; text-align:center; border-radius: 4px; box-shadow:0px 0px 5px #000; font-weight:normal; } .ac-container h2 { box-sizing: border-box; margin:0 0 14px 0; font-size:26px; border-bottom:1px dashed #ccc; padding-bottom:11px; } .ac-container h3 { box-sizing: border-box; color:#649D09; margin-bottom:5px; margin-top:15px; font-size:26px; } .ac-container p { box-sizing: border-box; margin:0 0 20px 0; font-size: 14px; color:#959595; line-height: 20px; } .ac-container p strong { color:#FF1F1F; } .ac-container select, .ac-container input { box-sizing: border-box; color:#555; padding: 5px 10px; font-size: 12px; line-height: 1.5; border-radius: 3px; margin-right:5px; border:1px solid #ccc; } .ac-container input.day{ box-sizing: border-box; width:45px; height:28px; } .ac-container input.year{ box-sizing: border-box; width:70px; height: 28px; } .ac-container select { box-sizing: border-box; height:28px; padding-left:4px; } .ac-container button { box-sizing: border-box; display: inline-block; margin-bottom: 0; font-weight: bold; text-align: center; white-space: nowrap; vertical-align: middle; -ms-touch-action: manipulation; touch-action: manipulation; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; background-image: none; border: 1px solid transparent; border-radius: 4px; padding: 4px 10px 4px 10px; font-size: 12px; line-height: 1.5; width: 84px; background:#8EB908; color:#fff; text-shadow:1px 1px 0 #84A51D; } .ac-container button:hover{ box-sizing: border-box; background:#82A711; } .ac-container .errors { box-sizing: border-box; margin:0 0 20px 0; font-size: 12px; line-height: 18px; color:#FF1F1F; } .ac-container .errors ul, .ac-container .errors li{ box-sizing: border-box; padding:0 0 3px 0; margin:0 0 0 0; list-style:none; } .ac-container .errors li span { box-sizing: border-box; font-size:9px; background:#ebebeb; border:1px solid #ccc; width: 14px; height:14px; border-radius:7px; display:inline-block; color:#FF1F1F; font-weight: bold; text-align: center; margin-right:5px; line-height: 13px; position:relative; top:-2px; text-shadow: 1px 1px 0 #fff; font-family:arial; } .ac-container .fields { box-sizing: border-box; clear:both; margin:10px 0 10px 0; } @media (max-width: 500px) { .ac-container { box-sizing: border-box; width:auto; margin-right:20px; margin-left:1px; } .ac-container select, .ac-container input.day, .ac-container input.year{ box-sizing: border-box; display:block; margin-bottom:10px; margin-right:0; width:100%; } .ac-container button { box-sizing: border-box; display: block; width: 100%; } }
This will make our box nice and friendly. Note that I’m using Google Fonts to style it. This may not be your taste – so it’s completely optional.
Finally, let’s use the darn thing.
How to Use:
First thing you is to add the jQuery library to your page. Then download the plugin files and simply link to the .js and .css file.
Next, you initialize the plugin by calling $.ageCheck() and pass in the options if necessary. See the section “Options” below for a description of the available options and default values. You can do this inside a document ready handler.
$(document).ready(function(){ $.ageCheck(); });
Note that if you want your whole site to be restricted, you would want this prompt to appear in any of the pages your visitor hits. So the code above will be suitable in a template used throughout the site. In your header or footer is a good spot.
Options:
You pass options in an object literal fashion. For example, if you want to redirect the user to the login page of your site on success, you would add the option like so:
$(document).ready(function(){ $.ageCheck({ "redirectTo" : "http://example.com/login" }); });
As we’ve gone through our settings above, its good to formally list the options available. Below is a nice table that does that:
Option | Type | Description | Default Value |
---|---|---|---|
minAge |
Number | Age to validate against | |
redirectTo |
String | URL to redirect when successful | |
title |
String | Title text above the prompt | |
copy |
String | Paragraph text below the title |
Conclusion
Note that AgeCheck.js is a Javascript solution for verifying date of birth. Users can easily turn off Javascript in their browsers – to easily bypass the plugin. You may want a server side solution so the processing is done regardless of Javascript being on or off.
For more information about how to create jQuery plugins, consult their documentation.
Let me know your thoughts below:
I’m using WordPress and like to know how use this plugin in WordPress. I upload the file in the plugin folder?
No this is not a WordPress plugin. It’s a jQuery plugin. It can work with WordPress if you follow the instructions above.
Hi, Michael. I am trying to create a webpage that has adult content, so I want to use your AgeCheck query. It has been a long time since I created a webpage, so I am a bit rusty. I want it to have an additional button above the “Check My Age” to say “Leave Now” that will direct the user back to their browser homepage. How would I do that?
Hi Amanda
The redirect to when under age is not supported in this version. I can add it to the next update.
I am having a problem getting it to work with IE. It works fine in Chrome, Opera, and Firefox. What could be the issue??
I’m testing it in IE and its fine.
I was getting a message “Internet Explorer has restricted this website from running scripts or Active X controls” with an “Allow” button. Clicking allow and refreshing does not work. I adjusted the settings in IE. It no longer gives me the error message, but it still will not run the AgeCheck script. Suggestions??
Hmm. It sounds like a browser setting. Do you mind posting your url?
I don’t have it online yet. I am just in the creating stage and only have it locally on my home computer. Is there some other way I can get you what you need?
do you have Javscript turned on?
yes, Active Scripting is Enabled for IE.
is there a way to have the entry fields empty? or changing them to “dd” and “yyyy”?
The placeholders can’t be changed at the moment. I will definitely include it in the next version.
This is the first Jquery pop up option that I have gotten to work…well sort of. I want to change the age to 18. I can change it in the css, but then it no longer makes the age stay red and it also doesn’t change the date to an 18 year old…you still have to be 21 . What am I missing to change those parameters. Thanks for a great plugin.
I got it….sorry, you explained it very well, I ma just a little slow.:)
Is there anyway I can add the company logo above the dashed line in the pop up?
The logo is not supported yet. Maybe in the next version.
Nice, elegant useful code. Is there a way to modify this to have the entire overlay hidden until an age has been selected? This would be very useful where different countries have different ages to select.
If you mean to completely make the background overlay dark and opaque? That should be in the plugin css file agecheck.css -> .ac-overlay
I was thinking more along the lines of having ac-overlay & ac-container hidden until a country selector (value=age) is selected and the continue button clicked. This would trigger an onClick to show the hidden ac-overlay & ac-container with the age [value] passed from the .minAge.
I am assuming it requires a two step process since .on (change) doesn’t seem to recognize when ‘select’ actually changes so it needs the button click.
I have tried using $(#ac-container’).hide(); and .show(); with no luck…
I have also tried adding display:none; to each agecheck.css entry… Great for hiding the overlays but I can’t figure out how to change the css back to show via the onClick.
try this:
$(‘your-button’).on(‘click’, function(){
if($(‘country selector’).val() == ‘age’) {
$.ageCheck();
}
})
let me know if its what u need.
That’s not working for me… now the overlays don’t show on page load but they don’t show on the button click either.
The only change I made to your html page was:
Canada
United States
So everything works fine there… the proper var minAge gets created and the [21] changes depending on selection. I just need to remove that first time the overlays pop up when the page first loads… any other thoughts on how to make a user select a country and click before the ageCheck overlay comes in?
Is it possible to set a maximum and a minimum age? So the users age will need to fall in between that range.
I don’t have range in this version.
hi, where did I need to insert the code for have the redirect option?
You pass the redirect url as a parameter
This is great. Thanks for sharing.
How long does the age verification “stick” for? Is a cookie used? How do I specify how frequently a visitor needs to re-identify their age?
Tanks again,
I used sessionStorage – which only lasts per browser session https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API
Great One Bro
Hi bro. Congratulations very good job. I need to use cookies. sessionStorage not , how the cookie?
Please cookie version.
I have this popup coming onto the screen but whatever dates I put in I am not old enough!
What could be wrong?
add your code to jsfiddle so we can take a look.
Im having an issue using a joomla plugin that runs off this js and all years show as invalid. Any ideas?
try doing a console.log(year) as you run it.
I’m getting a “true” stored in my session for the ageVerified Key but instead of getting sent to my redirect, it’s getting sent to the same url but with a ? at the end of it. Any ideas what could be wrong?
Can you paste the code in jsbin so we can inspect?
Need help please, I have no idea how to make this work it keeps saying this site requires you to be 0 years of age and I have no Idea how to edit the script
Are you sure you setup the plugin parameters correctly? Put your code to jsfiddle so we can look.
This is great, thanks. I have a question regarding storing cookies. Is there a way to easily use local storage instead and set it to one day? And if so, is there a way to check if the cookie is present? I am using wordpress and ideally when the user verifies their age, they get a cookies that lasts a day, and each page checks if the cookie is there, and if not redirects them to the home page. Thank you.
did you ver figure out how to do this. I am running into a similar problem
Got it working, but when trying to view in mobile it centers it off screen which makes it inaccessible.
I have been testing this on my Opencart install and found that the session data works to confirm verification was done till I open the cart when it asked that I reconfirm age. I have tried to add the links in the header,footer and even the main.tpl with the same result. I am not sure if its just my browser and plugins, even so I would like to figure out what the issue is so any assitance would be appreciated
does the cart have the same url as the rest of the application?
Yes, its when I click on the Cart in the Header that is does it. I have not tried to recreate it but will give it a bash now. Thanks for the reply though!
Did you ever figure out how to get this working? I’m running into the exact same problem as you!
If I remove the cart from the header is works flawlessly. I think I should mention that this issue is on the latest version of OpenCart
If it’s the same url, then it may be that the application is clearing the session key that the plugin uses. See when the page loads – it looks for that key if the visitor is “ageVerified”. The key is pretty unique though, so i would have to see it to debug it.
Can you show a way to make the popup work every time the page is loaded and have a default min age of 18?
Thanks in advance.
The min age can be passed as an option. The popup to work every time the page loads is not supported for now.
Hello Michael, thank you so much for creating this! It helps so much with SEO.
Is there a way to keep the “not old enough” popup when the browser tab is refreshed? I understand if the browser window closes you have no control, but is there additional code I could add that checks for “fails” and keeps them as fails (so that minors cannot game the system).
That’s not supported at the moment. Maybe in the next update.
Hi Michael,
Thanks for this. Nice work!
Having a problem getting this going on other site pages.
Site Structure is:
/index.html(landing page with agecheck.css & jquery.agecheck.js) – Works Fine here! (All Browsers)
/Home/index.html (page with proper paths to .css & .js for the above) but does not work!
/About/index.html (same as Home)
/Products/index.html (same)
/Contact/index.html (same)
Going straight to any url but the root agecheck does not work even though no input was made on the root. Tried in FF, IE and Chrome – All work to root url, but not to inside pages.
on /index.html paths are:
on /Home/index.html and other internals, paths are:
These are correct as style.css and other .js follow the same paths and work correctly.
Please note this is under development so url = http://www.greenhillvape.com/wip/
A little help please.
Thanks!
I think it’s a path issue. Try using absolute urls and test.
Absolute works on the initial landing page as before, but still not on the inside page.
Tested at http://www.greenhillvape.com/wip/index.html
and http://www.greenhillvape.com/wip/Home/index.html
Compare the source codes.
Scratching my head…
Thanks
Hello,
Would it be okay if I could share this to my blog I am currently working on.
The article I am creating a version of this is for Weebly. Wherein, I simplified the
process they’ll undergo just to install this code to their Weebly website.
Anyway, I also modified the CSS since the original code looks pretty obsolete 😛
Preview:http://rt-project3.weebly.com/
My Blog: gabrielrevilla.weebly.com
Look forward to your reply,
Gabriel R
That should be fine.
Hi great work i want to change the language of the months can i?
Hi there Michael. Thanks for the plugin, it works well.
One glitch I have found (possibly related to my associated coding) is that it sometimes comes up again as though the age confirm has timed out. How do I go about modifying the JS to adjust the timeout? I can see under handleSuccess() a timeout of 2000 – is this 2000 seconds?? Would this be the right value to change? Thanks!
Yes 2000 is 2 seconds. I’m not sure what you mean by it coming up again. Can you explain further?
Michael,
How can a ‘bailout’ or ‘Exit’ button be added to your script so it does not get hung-up on the missing invalid month/day/year entry? I’ve added a new button (next to the submit button) so users can Exit the age verification (they will be directed to http://www.disney.com/) all together. However, the screen is getting stuck on the wrong Month/Day/Year screen and not going to the redirect. Thanks in advance for any assistance you can provide.
My confirmation window appears on every page of the site. Cookies do not work.
Hi – Is it possible to redirect to a page based on a fail (the drinkaware.co.uk website)?
Yes I believe someone has added a callback to the plugin. So you can add a redirect code there.
I added this to a site and it works on most pages. I do have an issue on certain pages that I believe is caused by other code interfering with the age gate code. On the broken pages it says ‘DisplayOrder’ where the bold ’21’ should be. When I input a birthday that is over 21 it denies the user from going further.
Any insight of why this is happening and how to fix?