mirror of https://github.com/twbs/ratchet.git
Darren Liew
11 years ago
5 changed files with 1644 additions and 48 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,422 @@ |
|||||||
|
// modal
|
||||||
|
!(function () { |
||||||
|
'use strict'; |
||||||
|
|
||||||
|
var findModals = function (target) { |
||||||
|
var i; |
||||||
|
var modals = document.querySelectorAll('a'); |
||||||
|
|
||||||
|
for (; target && target !== document; target = target.parentNode) { |
||||||
|
for (i = modals.length; i--;) { |
||||||
|
if (modals[i] === target) { |
||||||
|
return target; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
var getModal = function (event) { |
||||||
|
var modalToggle = findModals(event.target); |
||||||
|
if (modalToggle && modalToggle.hash && -1 === modalToggle.hash.indexOf('/')) { |
||||||
|
return document.querySelector(modalToggle.hash); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
window.addEventListener('touchend', function (event) { |
||||||
|
var modal = getModal(event); |
||||||
|
if (modal) { |
||||||
|
if (modal && modal.classList.contains('modal')) { |
||||||
|
modal.classList.toggle('active'); |
||||||
|
} |
||||||
|
event.preventDefault(); // prevents rewriting url (apps can still use hash values in url)
|
||||||
|
} |
||||||
|
}); |
||||||
|
}()); |
||||||
|
// popover
|
||||||
|
!(function () { |
||||||
|
'use strict'; |
||||||
|
|
||||||
|
var popover; |
||||||
|
|
||||||
|
var findPopovers = function (target) { |
||||||
|
var i; |
||||||
|
var popovers = document.querySelectorAll('a'); |
||||||
|
|
||||||
|
for (; target && target !== document; target = target.parentNode) { |
||||||
|
for (i = popovers.length; i--;) { |
||||||
|
if (popovers[i] === target) { |
||||||
|
return target; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
var onPopoverHidden = function () { |
||||||
|
popover.style.display = 'none'; |
||||||
|
popover.removeEventListener('webkitTransitionEnd', onPopoverHidden); |
||||||
|
}; |
||||||
|
|
||||||
|
// HACK to hide programatically
|
||||||
|
var hide = function(e){ |
||||||
|
e.preventDefault() |
||||||
|
e.stopPropagation() |
||||||
|
popover.addEventListener('webkitTransitionEnd', onPopoverHidden); |
||||||
|
popover.classList.remove('visible'); |
||||||
|
popover.parentNode.removeChild(backdrop); |
||||||
|
}; |
||||||
|
|
||||||
|
var backdrop = (function () { |
||||||
|
var element = document.createElement('div'); |
||||||
|
|
||||||
|
element.classList.add('backdrop'); |
||||||
|
|
||||||
|
element.addEventListener('click', hide, false); |
||||||
|
|
||||||
|
return element; |
||||||
|
}()); |
||||||
|
|
||||||
|
var getPopover = function (e) { |
||||||
|
var anchor = findPopovers(e.target); |
||||||
|
|
||||||
|
if (!anchor || !anchor.hash || (anchor.hash.indexOf('/') > 0)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
popover = document.querySelector(anchor.hash); |
||||||
|
} catch (error) { |
||||||
|
popover = null; |
||||||
|
} |
||||||
|
|
||||||
|
if (popover === null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (!popover || !popover.classList.contains('popover')) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
return popover; |
||||||
|
}; |
||||||
|
|
||||||
|
var showHidePopover = function (e) { |
||||||
|
var popover = getPopover(e); |
||||||
|
|
||||||
|
if (popover) { |
||||||
|
// if clicked fast enough, function hide may not call at all
|
||||||
|
popover.removeEventListener('webkitTransitionEnd', onPopoverHidden); |
||||||
|
e.preventDefault() |
||||||
|
e.stopPropagation() |
||||||
|
}else{ |
||||||
|
// HACK, click anyway to close existing popover
|
||||||
|
popover = document.querySelector('.popover.visible'); |
||||||
|
if (popover) hide(e); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
popover.style.display = 'block'; |
||||||
|
popover.offsetHeight; |
||||||
|
popover.classList.add('visible'); |
||||||
|
|
||||||
|
popover.parentNode.appendChild(backdrop); |
||||||
|
}; |
||||||
|
|
||||||
|
window.addEventListener('click', showHidePopover); |
||||||
|
|
||||||
|
}()); |
||||||
|
// segmented-controllers
|
||||||
|
!(function () { |
||||||
|
'use strict'; |
||||||
|
|
||||||
|
var getTarget = function (target) { |
||||||
|
var i; |
||||||
|
var segmentedControls = document.querySelectorAll('.segmented-control .control-item'); |
||||||
|
|
||||||
|
for (; target && target !== document; target = target.parentNode) { |
||||||
|
for (i = segmentedControls.length; i--;) { |
||||||
|
if (segmentedControls[i] === target) { |
||||||
|
return target; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
window.addEventListener('touchend', function (e) { |
||||||
|
var activeTab; |
||||||
|
var activeBodies; |
||||||
|
var targetBody; |
||||||
|
var targetTab = getTarget(e.target); |
||||||
|
var className = 'active'; |
||||||
|
var classSelector = '.' + className; |
||||||
|
|
||||||
|
if (!targetTab) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
activeTab = targetTab.parentNode.querySelector(classSelector); |
||||||
|
|
||||||
|
if (activeTab) { |
||||||
|
activeTab.classList.remove(className); |
||||||
|
} |
||||||
|
|
||||||
|
targetTab.classList.add(className); |
||||||
|
|
||||||
|
if (!targetTab.hash) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
targetBody = document.querySelector(targetTab.hash); |
||||||
|
|
||||||
|
if (!targetBody) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
activeBodies = targetBody.parentNode.querySelectorAll(classSelector); |
||||||
|
|
||||||
|
for (var i = 0; i < activeBodies.length; i++) { |
||||||
|
activeBodies[i].classList.remove(className); |
||||||
|
} |
||||||
|
|
||||||
|
targetBody.classList.add(className); |
||||||
|
}); |
||||||
|
|
||||||
|
window.addEventListener('click', function (e) { if (getTarget(e.target)) {e.preventDefault();} }); |
||||||
|
}()); |
||||||
|
// slider
|
||||||
|
!(function () { |
||||||
|
'use strict'; |
||||||
|
|
||||||
|
var pageX; |
||||||
|
var pageY; |
||||||
|
var slider; |
||||||
|
var deltaX; |
||||||
|
var deltaY; |
||||||
|
var offsetX; |
||||||
|
var lastSlide; |
||||||
|
var startTime; |
||||||
|
var resistance; |
||||||
|
var sliderWidth; |
||||||
|
var slideNumber; |
||||||
|
var isScrolling; |
||||||
|
var scrollableArea; |
||||||
|
|
||||||
|
var getSlider = function (target) { |
||||||
|
var i; |
||||||
|
var sliders = document.querySelectorAll('.slider > .slide-group'); |
||||||
|
|
||||||
|
for (; target && target !== document; target = target.parentNode) { |
||||||
|
for (i = sliders.length; i--;) { |
||||||
|
if (sliders[i] === target) { |
||||||
|
return target; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
var getScroll = function () { |
||||||
|
if ('webkitTransform' in slider.style) { |
||||||
|
var translate3d = slider.style.webkitTransform.match(/translate3d\(([^,]*)/); |
||||||
|
var ret = translate3d ? translate3d[1] : 0; |
||||||
|
return parseInt(ret, 10); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
var setSlideNumber = function (offset) { |
||||||
|
var round = offset ? (deltaX < 0 ? 'ceil' : 'floor') : 'round'; |
||||||
|
slideNumber = Math[round](getScroll() / (scrollableArea / slider.children.length)); |
||||||
|
slideNumber += offset; |
||||||
|
slideNumber = Math.min(slideNumber, 0); |
||||||
|
slideNumber = Math.max(-(slider.children.length - 1), slideNumber); |
||||||
|
}; |
||||||
|
|
||||||
|
var onTouchStart = function (e) { |
||||||
|
slider = getSlider(e.target); |
||||||
|
|
||||||
|
if (!slider) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
var firstItem = slider.querySelector('.slide'); |
||||||
|
|
||||||
|
scrollableArea = firstItem.offsetWidth * slider.children.length; |
||||||
|
isScrolling = undefined; |
||||||
|
sliderWidth = slider.offsetWidth; |
||||||
|
resistance = 1; |
||||||
|
lastSlide = -(slider.children.length - 1); |
||||||
|
startTime = +new Date(); |
||||||
|
pageX = e.touches[0].pageX; |
||||||
|
pageY = e.touches[0].pageY; |
||||||
|
deltaX = 0; |
||||||
|
deltaY = 0; |
||||||
|
|
||||||
|
setSlideNumber(0); |
||||||
|
|
||||||
|
slider.style['-webkit-transition-duration'] = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
var onTouchMove = function (e) { |
||||||
|
if (e.touches.length > 1 || !slider) { |
||||||
|
return; // Exit if a pinch || no slider
|
||||||
|
} |
||||||
|
|
||||||
|
deltaX = e.touches[0].pageX - pageX; |
||||||
|
deltaY = e.touches[0].pageY - pageY; |
||||||
|
pageX = e.touches[0].pageX; |
||||||
|
pageY = e.touches[0].pageY; |
||||||
|
|
||||||
|
if (typeof isScrolling === 'undefined') { |
||||||
|
isScrolling = Math.abs(deltaY) > Math.abs(deltaX); |
||||||
|
} |
||||||
|
|
||||||
|
if (isScrolling) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
offsetX = (deltaX / resistance) + getScroll(); |
||||||
|
|
||||||
|
e.preventDefault(); |
||||||
|
|
||||||
|
resistance = slideNumber === 0 && deltaX > 0 ? (pageX / sliderWidth) + 1.25 : |
||||||
|
slideNumber === lastSlide && deltaX < 0 ? (Math.abs(pageX) / sliderWidth) + 1.25 : 1; |
||||||
|
|
||||||
|
slider.style.webkitTransform = 'translate3d(' + offsetX + 'px,0,0)'; |
||||||
|
}; |
||||||
|
|
||||||
|
var onTouchEnd = function (e) { |
||||||
|
if (!slider || isScrolling) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
setSlideNumber( |
||||||
|
(+new Date()) - startTime < 1000 && Math.abs(deltaX) > 15 ? (deltaX < 0 ? -1 : 1) : 0 |
||||||
|
); |
||||||
|
|
||||||
|
offsetX = slideNumber * sliderWidth; |
||||||
|
|
||||||
|
slider.style['-webkit-transition-duration'] = '.2s'; |
||||||
|
slider.style.webkitTransform = 'translate3d(' + offsetX + 'px,0,0)'; |
||||||
|
|
||||||
|
e = new CustomEvent('slide', { |
||||||
|
detail: { slideNumber: Math.abs(slideNumber) }, |
||||||
|
bubbles: true, |
||||||
|
cancelable: true |
||||||
|
}); |
||||||
|
|
||||||
|
slider.parentNode.dispatchEvent(e); |
||||||
|
}; |
||||||
|
|
||||||
|
window.addEventListener('touchstart', onTouchStart); |
||||||
|
window.addEventListener('touchmove', onTouchMove); |
||||||
|
window.addEventListener('touchend', onTouchEnd); |
||||||
|
|
||||||
|
}()); |
||||||
|
// toggle
|
||||||
|
!(function () { |
||||||
|
'use strict'; |
||||||
|
|
||||||
|
var start = {}; |
||||||
|
var touchMove = false; |
||||||
|
var distanceX = false; |
||||||
|
var toggle = false; |
||||||
|
|
||||||
|
var findToggle = function (target) { |
||||||
|
var i; |
||||||
|
var toggles = document.querySelectorAll('.toggle'); |
||||||
|
|
||||||
|
for (; target && target !== document; target = target.parentNode) { |
||||||
|
for (i = toggles.length; i--;) { |
||||||
|
if (toggles[i] === target) { |
||||||
|
return target; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
window.addEventListener('touchstart', function (e) { |
||||||
|
e = e.originalEvent || e; |
||||||
|
|
||||||
|
toggle = findToggle(e.target); |
||||||
|
|
||||||
|
if (!toggle) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
var handle = toggle.querySelector('.toggle-handle'); |
||||||
|
var toggleWidth = toggle.clientWidth; |
||||||
|
var handleWidth = handle.clientWidth; |
||||||
|
var offset = toggle.classList.contains('active') ? (toggleWidth - handleWidth) : 0; |
||||||
|
|
||||||
|
start = { pageX : e.touches[0].pageX - offset, pageY : e.touches[0].pageY }; |
||||||
|
touchMove = false; |
||||||
|
}); |
||||||
|
|
||||||
|
window.addEventListener('touchmove', function (e) { |
||||||
|
e = e.originalEvent || e; |
||||||
|
|
||||||
|
if (e.touches.length > 1) { |
||||||
|
return; // Exit if a pinch
|
||||||
|
} |
||||||
|
|
||||||
|
if (!toggle) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
var handle = toggle.querySelector('.toggle-handle'); |
||||||
|
var current = e.touches[0]; |
||||||
|
var toggleWidth = toggle.clientWidth; |
||||||
|
var handleWidth = handle.clientWidth; |
||||||
|
var offset = toggleWidth - handleWidth; |
||||||
|
|
||||||
|
touchMove = true; |
||||||
|
distanceX = current.pageX - start.pageX; |
||||||
|
|
||||||
|
if (Math.abs(distanceX) < Math.abs(current.pageY - start.pageY)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
e.preventDefault(); |
||||||
|
|
||||||
|
if (distanceX < 0) { |
||||||
|
return (handle.style.webkitTransform = 'translate3d(0,0,0)'); |
||||||
|
} |
||||||
|
if (distanceX > offset) { |
||||||
|
return (handle.style.webkitTransform = 'translate3d(' + offset + 'px,0,0)'); |
||||||
|
} |
||||||
|
|
||||||
|
handle.style.webkitTransform = 'translate3d(' + distanceX + 'px,0,0)'; |
||||||
|
|
||||||
|
toggle.classList[(distanceX > (toggleWidth / 2 - handleWidth / 2)) ? 'add' : 'remove']('active'); |
||||||
|
}); |
||||||
|
|
||||||
|
window.addEventListener('touchend', function (e) { |
||||||
|
if (!toggle) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
var handle = toggle.querySelector('.toggle-handle'); |
||||||
|
var toggleWidth = toggle.clientWidth; |
||||||
|
var handleWidth = handle.clientWidth; |
||||||
|
var offset = (toggleWidth - handleWidth); |
||||||
|
var slideOn = (!touchMove && !toggle.classList.contains('active')) || (touchMove && (distanceX > (toggleWidth / 2 - handleWidth / 2))); |
||||||
|
|
||||||
|
if (slideOn) { |
||||||
|
handle.style.webkitTransform = 'translate3d(' + offset + 'px,0,0)'; |
||||||
|
} else { |
||||||
|
handle.style.webkitTransform = 'translate3d(0,0,0)'; |
||||||
|
} |
||||||
|
|
||||||
|
toggle.classList[slideOn ? 'add' : 'remove']('active'); |
||||||
|
|
||||||
|
e = new CustomEvent('toggle', { |
||||||
|
detail: { isActive: slideOn }, |
||||||
|
bubbles: true, |
||||||
|
cancelable: true |
||||||
|
}); |
||||||
|
|
||||||
|
toggle.dispatchEvent(e); |
||||||
|
|
||||||
|
touchMove = false; |
||||||
|
toggle = false; |
||||||
|
}); |
||||||
|
|
||||||
|
}()); |
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue