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