Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using it's URL and the proper URL extention.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                
<div class="autotabbed-container">

  <div id="example1" class="autotabbed">
    <h3>Bank sort code: XX-XX-XX</h3>
    <input type="text" maxlength="2" size="2" />
    -
    <input type="text" maxlength="2" size="2" />
    -
    <input type="text" maxlength="2" size="2" />
  </div>
  
  
  <div id="example2" class="autotabbed">
    <h3>Date of birth</h3>
    <input type="text" maxlength="2" size="2" placeholder="dd" /> /
    <input type="text" maxlength="2" size="2" placeholder="mm" /> /
    <input type="text" maxlength="4" size="4" placeholder="yyyy" />
  </div>
  
  
  <div id="example3" class="autotabbed">
    <h3>IP Address</h3>
    <input type="text" maxlength="3" size="3" />
    .
    <input type="text" maxlength="3" size="3" />
    .
    <input type="text" maxlength="3" size="3" />
    .
    <input type="text" maxlength="3" size="3" />
  </div>
  
  
  <div id="example4" class="autotabbed">
    <h3>Credit Card No</h3>
    <input type="text" maxlength="4" size="4" />
    <input type="text" maxlength="4" size="4" />
    <input type="text" maxlength="4" size="4" />
    <input type="text" maxlength="4" size="4" />
  </div>
  
  <div class="clear"></div>

</div>
  
<a href="#" id="autotab-toggle" class="on">
   <strong>AUTO-TABBING IS 
     <span class="on">ON</span>
     <span class="off">OFF</span>
  </strong>
</a>

<div class="explain">
  <h1>Auto-tab for everyone</h1>
    
  <p>Fields such as sort codes, birth dates and credit card numbers often have scripts attached that automatically tab you between fields as you fill them up.</p>
  <p>This is <b>awesome</b> for 50% of people that either have that expectation or don't look at the screen while typing, and a <b>horribly frustrating annoyance</b> for people that are have built muscle memory for using the tab key.</p>
  <p><i style="color:#f90">This jquery plugin attempts to please both sets of people.</i></p>
  <p>It starts with "auto-tabbing" enabled by default. But if it detects that you fill in a field then hit tab immediately afterwards, it assumes that you'd prefer to use the tab key, returns your focus to the correct field, turns auto-tabbing off and alerts you that it's done so.</p>
  <p>It's designed to work with multiple input groups on the same page, and if you turn off auto-tabbing on one group, it's disabled for all groups.</p>
  
  <h2>One more thing...</h2>
  
  <p>This plugin also substitutes certain characters for the tab key, for example if you're typing in a date, hyphened code or IP address, eg typing <i>28/07/1972</i> will substitute the "/" for an auto-tab and put each number in the correct box.</p>
  
  <hr>
</div>
              
            
!

CSS

              
                @import compass

/* this bit you'll need */

.popover
  position: absolute
  max-width: 150px
  padding: 10px
  color: #474150
  background: #fafafa
  border: 1px solid #fff
  border-radius: 3px
  box-shadow: 1px 1px 3px #000
  opacity: 0
  @include transition(all 500ms)
  &.on
    opacity: 1
  &:before
    content: ''
    position: absolute
    left: -10px
    top: 10px
    width: 0
    height: 0
    border-top: 10px solid transparent
    border-right: 10px solid #fafafa
    border-bottom: 10px solid transparent

/* this bit is just page formatting */ 

html
  height: 100%
body
  min-height: 100%
  margin: 10px
  color: #fff
  background: #7a7480 
  @include background-image(linear-gradient(top, #474150, #7a7480))
  background-repeat: no-repeat
  font-family: avenir, sans-serif
  font-size: 14px
  
.autotabbed-container
  max-width: 680px
  margin: 0 auto
  
.autotabbed
  width: 300px
  float: left
  margin: 5px
  padding: 10px
  background: rgba(255,255,255,0.05)
  border: 1px solid rgba(255,255,255,0.2)
  font-size: 1.3em
  text-align: center
  h3,input
    margin: 0 0 10px
    font-size: 1em
    
#autotab-toggle
  display: block
  width: 180px
  margin: 10px auto
  padding: 5px 10px
  color: red
  background: rgba(255,0,0,0.1)
  border: 1px solid red
  border-radius: 100px
  text-align: center
  .on
    display: none
  .off
    display: inline
  &.on
    color: #0c0
    background: rgba(0,255,0,0.1)
    border-color: #090
    .on
      display: inline
    .off
      display: none
  
.explain
  max-width: 800px
  margin: 20px auto

.clear
  height: 0
  overflow: hidden
  clear: both
              
            
!

JS

              
                $.fn.autoTab = function() {
  
  autoTabOn = true; // yes, it's global. If you turn off auto tabbing on one input, you turn it off for all
  var autoTabbedInputs = this.find('input');
  var almostTabbedInputs = autoTabbedInputs.not(':last-child'); // note we don't attach tabbing event to the last of an input group. If you tab out of there, you have a reason to
  var justAutoTabbed = false;
  var tabKeyDetected = false;
  var revTabKeyDetected = false;
  var inputField = false;
  
  // init
  var init = function() {
    detectKeyDown();
    detectKeyUp();
  }
  
  // keydown detection, hijack it if it's in the fields we're looking for
  var detectKeyDown = function() {
    autoTabbedInputs.on('keydown',function(ev){
      // the field that you're in when you keydown might not be the field you're in when you keyup
      inputField = this;
      // detect keystroke in the fields 
      ev = ev || event;
      var charCode = null;
      if ("which" in ev)
        charCode = ev.which;
      else if ("keyCode" in e)
        charCode = ev.keyCode;
      else if ("keyCode" in window.event)
        charCode = window.event.keyCode;
      else if ("which" in window.event)
        charCode = window.event.which;
      // if tabbing forward
      if (charCode === 9 && !ev.shiftKey) {
        // if auto tabbing is off, don't change it's behavior
        if (!autoTabOn) {
          return;
        }
        if (justAutoTabbed) {
          ev.preventDefault();
          notifyAutoTabbingOff();
          autoTabOn = false;
          if ($('#autotab-toggle').length > 0) { // only used if toggle is present
            $('#autotab-toggle').removeClass('on');
          }
        }
        tabKeyDetected = true;
      // if tabbing backward
      } else if (charCode === 9 && ev.shiftKey) {
        revTabKeyDetected = true;
      // backspace key fakes reverse tab
      } else if (charCode === 8 && this.value.length == 0) {
        revTabKeyDetected = true;
        $(this).prev("input,select,textarea,a").focus();
      // fake tab keystrokes
      } else if (
        charCode === 191                  // "/" - for dates
        ||
        charCode === 111                  // "/" - for dates (numberpad)
        ||
        charCode === 190                  // "." - for IP addresses
        ||
        charCode === 110                  // "." - for IP addresses (numberpad)
        ||
        charCode === 189                  // "-" - for sortcodes
        ||
        charCode === 109                  // "-" - for sortcodes (numberpad)
      ) {
        ev.preventDefault();
        // if we've not yet hit the max chars for this field, and haven't already just auto-tabbed, fake a tab key
        if (!hasHitMaxChars(this) && !justAutoTabbed) {
          $(this).next("input,select,textarea,a").focus();
        }
      }
      // removed any flag to say we've just auto-tabbed
      justAutoTabbed = false;
    });
  }
  
  // entering text into auto-tabbed fields
  var detectKeyUp = function() {
    almostTabbedInputs.on('keyup',function(ev){
      // if auto tabbing is off, bug out now
      if (!autoTabOn) {
        return;
      }
      // if the complimentary keydown was a tab key, ignore this event (and reset it for the next keyup)
      if (tabKeyDetected) {
        tabKeyDetected = false;
        return;
      }
      // if we were tabbing backwards, don't jump forwards again!
      if (revTabKeyDetected) {
        revTabKeyDetected = false;
        return;
      }
      // edge case: if you've tabbed from one input group to another, the inputField that was used in keyDown hasn't yet been set
      if (!inputField) {
        return;
      }
      // removed flag to say we've just auto-tabbed
      justAutoTabbed = false;
      // else auto-tab if the field is full
      if (hasHitMaxChars(inputField)) {
        $(inputField).next().focus();
        // we've just auto-tabbed - flag it
        justAutoTabbed = true;
      }
    })
  }
  
  // detect if a field has hit max chars
  var hasHitMaxChars = function(el) {
    var elObj = $(el);
    var maxFieldLength = elObj.attr('maxlength') || elObj.attr('size');
    var valueLength = el.value.length;
    if (valueLength>=maxFieldLength) {
      return true;
    }
    return false;
  }
  
  // notify user that autotabbing is off (a popover that fades after 8secs)
  var notifyAutoTabbingOff = function() {
    // already a popover? bug out now.
    if ($('.popover').hasClass('on')) {
      return;
    }
    // last input
    var lastInput = autoTabbedInputs.last();
    // position/size of last input
    var popY = lastInput.offset().top 
      + (
        lastInput.height() 
        + parseInt(lastInput.css('border-width'))
        + parseInt(lastInput.css('padding-top'))
        + parseInt(lastInput.css('padding-bottom'))
      )/2
      - 20;
    var popX = lastInput.offset().left 
      + lastInput.width() 
      + parseInt(lastInput.css('border-width'))
      + parseInt(lastInput.css('padding-left'))
      + parseInt(lastInput.css('padding-right'))
      + 15;
    // create the pop-over (opacity 0 by default)
    $('body').append('<div class="popover" style="top:' + popY + 'px;left:' + popX + 'px">It looks like you prefer the tab key! We\'ve turned auto-tabbing off for you.</div>');
    // fade up, wait, remove pop-over
    setTimeout(function(){
      $('.popover').addClass('on')
      setTimeout(function(){
        removePopOver();
      },8000);
    },0);
    // remove pop-over on click
    $('body').on('click','.popover',function(){
      removePopOver();
    })
  }
  // turn pop-over off
  var removePopOver = function(){
    $('.popover').removeClass('on')
    setTimeout(function(){
      $('.popover').remove;
    },500);
  }
  
  // init function!
  init();
  
}

// set up example
$('#example1').autoTab();
$('#example2').autoTab();
$('#example3').autoTab();
$('#example4').autoTab();

// enable toggle
var toggle = $('#autotab-toggle');
toggle.click(function(ev){
  ev.preventDefault();
  if (toggle.hasClass('on')) {
    autoTabOn = false;
    $('#autotab-toggle').removeClass('on');
  } else {
    autoTabOn = true;
    $('#autotab-toggle').addClass('on');
  }
})
              
            
!
999px

Console