Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, width=device-width">
  <title>JS Bin</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.6/hammer.min.js"></script>
  <script src="https://rawgithub.com/marcj/css-element-queries/master/src/ResizeSensor.js"></script>
  <script src="https://rawgithub.com/marcj/css-element-queries/master/src/ElementQueries.js"></script>
</head>
<body ontouchstart="">
  <div class="container">
<div class="fieldlist">
  <div class="field f1">
    <div class="fieldcontent">
      <h1>Short question with input</h1>
      <input type="text" />
    </div>
  </div>
  
  <div class="field f2">
    <div class="fieldcontent">
      <h1>Medium question with input</h1>
      <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
      </p>
      <input type="text" />
    </div>
  </div>
  
  <div class="field f3">
    <div class="fieldcontent">
      <h1>Long question with input</h1>
      <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
      </p>
      <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
      </p>
      <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
      </p>
      <input type="text" />
    </div>
  </div>
  
  <div class="field f4">
    <div class="fieldcontent">
      <h1>Short question with text area</h1>
      <textarea></textarea>
    </div>
  </div>
  <div class="field f5">
    <div class="fieldcontent">
      <h1>Medium question with text area</h1>
      <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
      </p>
      <textarea></textarea>
    </div>
  </div>
  <div class="field f6">
    <div class="fieldcontent">
      <h1>Long question with text area</h1>
      <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
      </p>
      <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
      </p>
      <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
      </p>
      <textarea></textarea>
    </div>
  </div>
</div>
  <div class="buttons">
    <button id="previous">previous</button>
    <button id="next">next</button>
  </div>
    </div>
<script src="http://jsconsole.com/remote.js?EED0E1A8-1548-4951-AAAA-48C9C92F96CE"></script>
</body>
</html>
 
html, body {
  height: 100%;
  margin: 0;
  padding:0;
  color:white;
}
body {
  overflow:hidden; /* prevent pull to refresh chrome mobile */
}
/* "embed" style container */
/* 
.container {
  height:400px;
  width: 200px;
  margin: auto;
}
 */
/* "fullscreen" style container */
.container {
  height:100%;
}
.fieldlist {
  /* field list is only scrollable via JS */
  height:100% !important;
  overflow: hidden !important;
  
  background-color: black;
  font-family:consolas;
}
.field {
  /* field is scrollable via native scroll, 
  but cannot have other positional styles attached:  
  use .fieldContent */
  height:100% !important;
  overflow-y:auto !important;
  margin:0 !important;
  padding: 0 !important;
  -webkit-overflow-scrolling: touch;
  -webkit-transform: translateZ(0px);
  -webkit-transform: translate3d(0,0,0);
  -webkit-perspective: 1000;
}
.fieldcontent {
  margin: 20px;
}
.f1 {
  background-color: #73BEC8
}
.f2 {
  background-color: #E4BA3F 
}
.f3 {
  background-color: #CB732B
}
.f4 {
  background-color: #89BC62 
}
.f5 {
  background-color: #C384C5 
}
.f6 {
  background-color: #C75875 
}
.buttons {
  position:absolute;
  bottom: 0;
  right: 0;
}
.buttons button {
  font-size: 20px;
}
 
var fieldList = document.getElementsByClassName('fieldlist')[0]
var FIELD_HEIGHT = null
var fields =  Array.prototype.slice.call( document.getElementsByClassName('field') )
var currentNode = fields[0]
var hammer = new Hammer.Manager(
  fieldList,
  {touchAction: 'pan-y'}
)
hammer.add(new Hammer.Swipe({
  direction: Hammer.DIRECTION_VERTICAL,
  enable: function (whatever, ev) {
    return canSwipe(ev)
  }
}))
hammer.on("swipe", function(ev) {
  if (canSwipe(ev)){
    snapToPoint(ev.direction)
  }
})
resolveFieldHeight()
document.getElementById('previous').onclick = function () {
  if (hasFieldAbove()) {
    snapToPoint(Hammer.DIRECTION_DOWN)
  }
}
document.getElementById('next').onclick = function () {
  console.log('next')
  if (hasFieldBelow()) {
    snapToPoint(Hammer.DIRECTION_UP)
  }
}
new ResizeSensor(fieldList, function () {
  resolveFieldHeight()
  resetScrollPosition()
})
function resolveFieldHeight () {
  fieldList.style.height = null // reset fieldList.clientHeight to calculated height
  fieldList.style.height = fieldList.clientHeight + 'px' // on chrome/android, maintain keyboard-closed client-height when keyboard open
  FIELD_HEIGHT = fieldList.clientHeight
}
function resetScrollPosition () {
  fieldList.scrollTop = fields.indexOf(currentNode) * FIELD_HEIGHT
}
function canSwipe (ev) {
    if (!ev) return true
    var enabled = ev.direction === Hammer.DIRECTION_UP && canSwipeUp() 
          || ev.direction === Hammer.DIRECTION_DOWN && canSwipeDown()
    return enabled
}
function hasFieldBelow () {
  return fields.indexOf(currentNode) !== fields.length - 1
}
function hasFieldAbove () {
  return fields.indexOf(currentNode) !== 0
}
function canSwipeUp () {
  var canSwipeUp = currentNode.scrollHeight - currentNode.scrollTop <= currentNode.clientHeight + 5
    && hasFieldBelow()
  return canSwipeUp 
}
function canSwipeDown () {
  return currentNode.scrollTop === 0 
    && hasFieldAbove()
}
function blurInputs () {
  Array.prototype.forEach.call(document.querySelectorAll('input[type=text], textarea'), function(input) {
    input.blur()
  })
}
function snapToPoint(direction){
  blurInputs()
  var newScrollPos = null
  var newField = null
  if (direction == Hammer.DIRECTION_UP) {
    newField = fields[fields.indexOf(currentNode) + 1]
  } else {
    newField = fields[fields.indexOf(currentNode) - 1]
  }
  newScrollPos = fields.indexOf(newField) * FIELD_HEIGHT
  currentNode = newField
  animatedScrollTo(fieldList, newScrollPos, 200, resetFieldScrolls)
}
function resetFieldScrolls () {
  fields.forEach(function(field) { 
    field.scrollTop = 0
  })
}
function logScrolls () {
  var thingsToLog = [ // getClientRects, getBoundingClientRect
    'scrollTop',
    'clientHeight',
    'offsetHeight',
    'clientTop',
    function (el) {
      var dimensions = el.getBoundingClientRect()
      return {
        'gbcr.bottom': dimensions.bottom,
        'gbcr.height': dimensions.height,
        'gbcr.top': dimensions.top
      }
    }
  ]
  
  
  var log = {}
  
  log.fieldList = {}
  
  thingsToLog.forEach(function (thingToLog) {
    if (typeof thingToLog === 'function') {
      Object.assign(log.fieldList, thingToLog(fieldList))
    } else {
      log.fieldList[thingToLog] = fieldList[thingToLog]
    }
  })
  
  fields.forEach(function (field, index) {
    elementLog = {}
    thingsToLog.forEach(function (thingToLog) {
      if (typeof thingToLog === 'function') {
        Object.assign(elementLog, thingToLog(field))
      } else {
        elementLog[thingToLog] = field[thingToLog]
      }
    })
    log['f' + index] = elementLog
  })
  console.table(log)
}
;(function (window) {
    var requestAnimFrame = (function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(callback){window.setTimeout(callback,1000/60);};})();
    var easeInOutQuad = function (t, b, c, d) {
        t /= d/2;
        if (t < 1) return c/2*t*t + b;
        t--;
        return -c/2 * (t*(t-2) - 1) + b;
    };
    var animatedScrollTo = function (element, to, duration, callback) {
        var start = element.scrollTop,
        change = to - start,
        animationStart = +new Date();
        var animating = true;
        var lastpos = null;
        var animateScroll = function() {
            if (!animating) {
                return;
            }
            requestAnimFrame(animateScroll);
            var now = +new Date();
            var val = Math.floor(easeInOutQuad(now - animationStart, start, change, duration));
            if (lastpos) {
                if (lastpos === element.scrollTop) {
                    lastpos = val;
                    element.scrollTop = val;
                } else {
                    animating = false;
                }
            } else {
                lastpos = val;
                element.scrollTop = val;
            }
            if (now > animationStart + duration) {
                element.scrollTop = to;
                animating = false;
                if (callback) { callback(); }
            }
        };
        requestAnimFrame(animateScroll);
    };
    if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
        module.exports = animatedScrollTo;
    } else {
        window.animatedScrollTo = animatedScrollTo;
    }
})(window);
window.addEventListener('load', function() {
          var maybePreventPullToRefresh = false;
          var lastTouchY = 0;
          var touchstartHandler = function(e) {
            if (e.touches.length != 1) return;
            lastTouchY = e.touches[0].clientY;
            // Pull-to-refresh will only trigger if the scroll begins when the
            // document's Y offset is zero.
            maybePreventPullToRefresh =
                window.pageYOffset == 0;
          }
          var touchmoveHandler = function(e) {
            var touchY = e.touches[0].clientY;
            var touchYDelta = touchY - lastTouchY;
            lastTouchY = touchY;
            if (maybePreventPullToRefresh) {
              // To suppress pull-to-refresh it is sufficient to preventDefault the
              // first overscrolling touchmove.
              maybePreventPullToRefresh = false;
              if (touchYDelta > 0) {
                console.log()
                e.preventDefault();
                return;
              }
            }
          }
          document.addEventListener('touchstart', touchstartHandler, false);
          document.addEventListener('touchmove', touchmoveHandler, false);      });
/*! iNoBounce - v0.1.0
* https://github.com/lazd/iNoBounce/
* Copyright (c) 2013 Larry Davis <lazdnet@gmail.com>; Licensed BSD */
(function(global) {
  // Stores the Y position where the touch started
  var startY = 0;
  // Store enabled status
  var enabled = false;
  var handleTouchmove = function(evt) {
    // Get the element that was scrolled upon
    var el = evt.target;
    // Check all parent elements for scrollability
    while (el !== document.body) {
      // Get some style properties
      var style = window.getComputedStyle(el);
      if (!style) {
        // If we've encountered an element we can't compute the style for, get out
        break;
      }
      var scrolling = style.getPropertyValue('-webkit-overflow-scrolling');
      var overflowY = style.getPropertyValue('overflow-y');
      var height = parseInt(style.getPropertyValue('height'), 10);
      // Determine if the element should scroll
      var isScrollable = scrolling === 'touch' && (overflowY === 'auto' || overflowY === 'scroll');
      var canScroll = el.scrollHeight > el.offsetHeight;
      if (isScrollable && canScroll) {
        // Get the current Y position of the touch
        var curY = evt.touches ? evt.touches[0].screenY : evt.screenY;
        // Determine if the user is trying to scroll past the top or bottom
        // In this case, the window will bounce, so we have to prevent scrolling completely
        var isAtTop = (startY <= curY && el.scrollTop === 0);
        var isAtBottom = (startY >= curY && el.scrollHeight - el.scrollTop === height);
        // Stop a bounce bug when at the bottom or top of the scrollable element
        if (isAtTop || isAtBottom) {
          evt.preventDefault();
        }
        // No need to continue up the DOM, we've done our job
        return;
      }
      // Test the next parent
      el = el.parentNode;
    }
    // Stop the bouncing -- no parents are scrollable
    evt.preventDefault();
  };
  var handleTouchstart = function(evt) {
    // Store the first Y position of the touch
    startY = evt.touches ? evt.touches[0].screenY : evt.screenY;
  };
  var enable = function() {
    // Listen to a couple key touch events
    window.addEventListener('touchstart', handleTouchstart, false);
    window.addEventListener('touchmove', handleTouchmove, false);
    enabled = true;
  };
  var disable = function() {
    // Stop listening
    window.removeEventListener('touchstart', handleTouchstart, false);
    window.removeEventListener('touchmove', handleTouchmove, false);
    enabled = false;
  };
  var isEnabled = function() {
    return enabled;
  };
  // Enable by default if the browser supports -webkit-overflow-scrolling
  // Test this by setting the property with JavaScript on an element that exists in the DOM
  // Then, see if the property is reflected in the computed style
  var testDiv = document.createElement('div');
  document.documentElement.appendChild(testDiv);
  testDiv.style.WebkitOverflowScrolling = 'touch';
  var scrollSupport = 'getComputedStyle' in window && window.getComputedStyle(testDiv)['-webkit-overflow-scrolling'] === 'touch';
  document.documentElement.removeChild(testDiv);
  if (scrollSupport) {
    enable();
  }
  // A module to support enabling/disabling iNoBounce
  var iNoBounce = {
    enable: enable,
    disable: disable,
    isEnabled: isEnabled
  };
  if (typeof module !== 'undefined' && module.exports) {
    // Node.js Support
    module.exports = iNoBounce;
  }
  if (typeof global.define === 'function') {
    // AMD Support
    (function(define) {
      define(function() { return iNoBounce; });
    }(global.define));
  }
  else {
    // Browser support
    global.iNoBounce = iNoBounce;
  }
}(this));
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
sennettpro
0viewers