Browse Source

Adding Master-Detail View for iPad

pull/207/head
Tslmy 11 years ago
parent
commit
36b01f903d
  1. 31
      Master-Detail View Usage.md
  2. 17
      lib/css/masterdetail.css
  3. 19
      lib/css/overallfixing.css
  4. 1
      lib/js/inobounce.min.js
  5. 0
      lib/js/masterdetail.js
  6. 31
      test/masterdetail/Master-Detail View Usage.md
  7. 108
      test/masterdetail/index.html
  8. 1
      test/masterdetail/inobounce.min.js
  9. 17
      test/masterdetail/masterdetail.css
  10. 0
      test/masterdetail/masterdetail.js
  11. 19
      test/masterdetail/overallfixing.css
  12. 1292
      test/masterdetail/ratchet.css
  13. 767
      test/masterdetail/ratchet.js

31
Master-Detail View Usage.md

@ -0,0 +1,31 @@
Master-Detail View Usage
===================
I([tslmy](http://www.tslimi.tk/)) think _Ratchet_ should not limit its great power to iPhone and iPod touch. Instead, iPad should be taken into consideration as well. The most different part in styling an app(between iPhone/iPod touch and iPad, of course) is that iPad has a "master-detail" view. While iPhone/iPod touch switches from master view and detail view back and forth, iPad show them simultaneously.
Best example is your Settings app.
Usage
------
Since I haven't merge my code into _Ratchet_ itself, you have to import/link to/include my files manually.
This can be achieved by adding the following codes into `<head>`:
<script src="inobounce.min.js"></script>
<link rel="stylesheet" href="overallfixing.css">
<link rel="stylesheet" href="masterdetail.css">
(Yes, I highly recommend you add `inobounce.min.js`, which solve the problem of _moving the view up and down_ perfectly.)
Then, change `<body>` into:
<body class="masterDetail">
Wrap a panel(an orginal page, or "`<body>`") with `<div class="master">` and another with `<div class="detail">`.
You are good to go.
To do
-----
1. Currently, `masterdetail.js` is still empty(so there's no need to include it in `<head>` presently).
2. List links in master panel should target at detail panel.
3. Some apps may want the detail panel to take over the whole screen, leaving master panel sliding in and out from the left side.

17
lib/css/masterdetail.css

@ -0,0 +1,17 @@
.masterDetail .master, .masterDetail .detail {
height:100%;
overflow:hidden;
}
.masterDetail .bar-title{
position: static;
}
.masterDetail .master {
position:absolute;
width:299px;
left:0;
}
.masterDetail .detail{
position:absolute;
left:300px;
right:0;
}

19
lib/css/overallfixing.css

@ -0,0 +1,19 @@
body {
background:black;
}
.scrollable {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
header.bar-title {
border-radius: 7px 7px 0 0;
}
.content {
position:absolute;
border-radius: 0 0 5px 5px;
overflow: auto;
bottom: 0px;
left: 0px;
}

1
lib/js/inobounce.min.js vendored

@ -0,0 +1 @@
!function(global){var startY=0;var enabled=false;var handleTouchmove=function(evt){var el=evt.target;while(el!==document.body){var style=window.getComputedStyle(el);var scrolling=style.getPropertyValue("-webkit-overflow-scrolling");var overflow=style.getPropertyValue("overflow");var height=parseInt(style.getPropertyValue("height"),10);var isScrollable=scrolling==="touch"&&overflow==="auto";var canScroll=el.scrollHeight>el.offsetHeight;if(isScrollable&&canScroll){var curY=evt.touches?evt.touches[0].screenY:evt.screenY;var isAtTop=startY<=curY&&el.scrollTop===0;var isAtBottom=startY>=curY&&el.scrollHeight-el.scrollTop===height;if(isAtTop||isAtBottom){evt.preventDefault()}return}el=el.parentNode}evt.preventDefault()};var handleTouchstart=function(evt){startY=evt.touches?evt.touches[0].screenY:evt.screenY};var enable=function(){window.addEventListener("touchstart",handleTouchstart,false);window.addEventListener("touchmove",handleTouchmove,false);enabled=true};var disable=function(){window.removeEventListener("touchstart",handleTouchstart,false);window.removeEventListener("touchmove",handleTouchmove,false);enabled=false};var isEnabled=function(){return enabled};var scrollSupport=window.getComputedStyle(document.createElement("div"))["-webkit-overflow-scrolling"];if(typeof scrollSupport!=="undefined"){enable()}var iNoBounce={enable:enable,disable:disable,isEnabled:isEnabled};if(typeof global.define==="function"){!function(define){define(function(){return iNoBounce})}(global.define)}else{global.iNoBounce=iNoBounce}}(this);

0
lib/js/masterdetail.js

31
test/masterdetail/Master-Detail View Usage.md

@ -0,0 +1,31 @@
Master-Detail View Usage
===================
I([tslmy](http://www.tslimi.tk/)) think _Ratchet_ should not limit its great power to iPhone and iPod touch. Instead, iPad should be taken into consideration as well. The most different part in styling an app(between iPhone/iPod touch and iPad, of course) is that iPad has a "master-detail" view. While iPhone/iPod touch switches from master view and detail view back and forth, iPad show them simultaneously.
Best example is your Settings app.
Usage
------
Since I haven't merge my code into _Ratchet_ itself, you have to import/link to/include my files manually.
This can be achieved by adding the following codes into `<head>`:
<script src="inobounce.min.js"></script>
<link rel="stylesheet" href="overallfixing.css">
<link rel="stylesheet" href="masterdetail.css">
(Yes, I highly recommend you add `inobounce.min.js`, which solve the problem of _moving the view up and down_ perfectly.)
Then, change `<body>` into:
<body class="masterDetail">
Wrap a panel(an orginal page, or "`<body>`") with `<div class="master">` and another with `<div class="detail">`.
You are good to go.
To do
-----
1. Currently, `masterdetail.js` is still empty(so there's no need to include it in `<head>` presently).
2. List links in master panel should target at detail panel.
3. Some apps may want the detail panel to take over the whole screen, leaving master panel sliding in and out from the left side.

108
test/masterdetail/index.html

@ -0,0 +1,108 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ratchet template page</title>
<!-- Sets initial viewport load and disables zooming -->
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- Makes your prototype chrome-less once bookmarked to your phone's home screen -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<!-- Set a shorter title for iOS6 devices when saved to home screen -->
<meta name="apple-mobile-web-app-title" content="Ratchet">
<!-- Set Apple icons for when prototype is saved to home screen -->
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="touch-icons/apple-touch-icon-114x114.png">
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="touch-icons/apple-touch-icon-72x72.png">
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="touch-icons/apple-touch-icon-57x57.png">
<!-- Include the compiled Ratchet CSS -->
<link rel="stylesheet" href="ratchet.css">
<link rel="stylesheet" href="overallfixing.css">
<link rel="stylesheet" href="masterdetail.css">
<!-- Include the compiled Ratchet JS -->
<script src="inobounce.min.js"></script>
<script src="ratchet.js"></script>
<script src="masterdetail.js"></script>
<!-- Intro paragraph styles. Delete once you start using this page -->
<style type="text/css">
.welcome {
line-height: 1.5;
color: #555;
}
</style>
</head>
<body class="masterDetail">
<div class="master">
<!-- Make sure all your bars are the first things in your <body> -->
<header class="bar-title">
<h1 class="title">Master</h1>
</header>
<!-- Wrap all non-bar HTML in the .content div (this is actually what scrolls) -->
<div class="content scrollable">
<ul class="list">
<li><a href="http://www.baidu.com/" target="article">baidu</a></li>
<li><a href="#">List item 1</a></li>
<li class="list-divider">List Divider</li>
<li><a href="#">List item 1</a></li>
</ul>
</div>
</div>
<div class="detail">
<!-- Make sure all your bars are the first things in your <body> -->
<header class="bar-title">
<a class="button-prev" href="#">
Previous
</a>
<h1 class="title">Detail</h1>
<a class="button" href="#">
Right
</a>
</header>
<!-- Wrap all non-bar HTML in the .content div (this is actually what scrolls) -->
<div class="content scrollable" name="article">
<div class="content-padded">
<p class="welcome">Thanks for downloading Ratchet. This is an example HTML page that's linked up to compiled Ratchet CSS and JS, has the proper meta tags and the HTML structure. Need some more help before you start filling this with your own content? Check out some Ratchet resources:</p>
</div>
<ul class="list inset">
<li>
<a href="http://maker.github.com/ratchet/">
<strong>Ratchet documentation</strong>
<span class="chevron"></span>
</a>
</li>
<li>
<a href="http://www.github.com/maker/ratchet/">
<strong>Ratchet on Github</strong>
<span class="chevron"></span>
</a>
</li>
<li>
<a href="https://groups.google.com/forum/#!forum/goratchet">
<strong>Ratchet Google group</strong>
<span class="chevron"></span>
</a>
</li>
<li>
<a href="http://www.twitter.com/GoRatchet">
<strong>Ratchet on Twitter</strong>
<span class="chevron"></span>
</a>
</li>
</ul>
</div>
</div>
</body>
</html>

1
test/masterdetail/inobounce.min.js vendored

@ -0,0 +1 @@
!function(global){var startY=0;var enabled=false;var handleTouchmove=function(evt){var el=evt.target;while(el!==document.body){var style=window.getComputedStyle(el);var scrolling=style.getPropertyValue("-webkit-overflow-scrolling");var overflow=style.getPropertyValue("overflow");var height=parseInt(style.getPropertyValue("height"),10);var isScrollable=scrolling==="touch"&&overflow==="auto";var canScroll=el.scrollHeight>el.offsetHeight;if(isScrollable&&canScroll){var curY=evt.touches?evt.touches[0].screenY:evt.screenY;var isAtTop=startY<=curY&&el.scrollTop===0;var isAtBottom=startY>=curY&&el.scrollHeight-el.scrollTop===height;if(isAtTop||isAtBottom){evt.preventDefault()}return}el=el.parentNode}evt.preventDefault()};var handleTouchstart=function(evt){startY=evt.touches?evt.touches[0].screenY:evt.screenY};var enable=function(){window.addEventListener("touchstart",handleTouchstart,false);window.addEventListener("touchmove",handleTouchmove,false);enabled=true};var disable=function(){window.removeEventListener("touchstart",handleTouchstart,false);window.removeEventListener("touchmove",handleTouchmove,false);enabled=false};var isEnabled=function(){return enabled};var scrollSupport=window.getComputedStyle(document.createElement("div"))["-webkit-overflow-scrolling"];if(typeof scrollSupport!=="undefined"){enable()}var iNoBounce={enable:enable,disable:disable,isEnabled:isEnabled};if(typeof global.define==="function"){!function(define){define(function(){return iNoBounce})}(global.define)}else{global.iNoBounce=iNoBounce}}(this);

17
test/masterdetail/masterdetail.css

@ -0,0 +1,17 @@
.masterDetail .master, .masterDetail .detail {
height:100%;
overflow:hidden;
}
.masterDetail .bar-title{
position: static;
}
.masterDetail .master {
position:absolute;
width:299px;
left:0;
}
.masterDetail .detail{
position:absolute;
left:300px;
right:0;
}

0
test/masterdetail/masterdetail.js

19
test/masterdetail/overallfixing.css

@ -0,0 +1,19 @@
body {
background:black;
}
.scrollable {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
header.bar-title {
border-radius: 7px 7px 0 0;
}
.content {
position:absolute;
border-radius: 0 0 5px 5px;
overflow: auto;
bottom: 0px;
left: 0px;
}

1292
test/masterdetail/ratchet.css

File diff suppressed because it is too large Load Diff

767
test/masterdetail/ratchet.js

@ -0,0 +1,767 @@
/**
* ==================================
* Ratchet v1.0.2
* Licensed under The MIT License
* http://opensource.org/licenses/MIT
* ==================================
*/
/* ----------------------------------
* MODAL v1.0.0
* Licensed under The MIT License
* http://opensource.org/licenses/MIT
* ---------------------------------- */
!function () {
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) return document.querySelector(modalToggle.hash);
};
window.addEventListener('touchend', function (event) {
var modal = getModal(event);
if (modal) modal.classList.toggle('active');
});
}();/* ----------------------------------
* POPOVER v1.0.0
* Licensed under The MIT License
* http://opensource.org/licenses/MIT
* ---------------------------------- */
!function () {
var popover;
var findPopovers = function (target) {
var i, 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 () {
document.body.removeChild(backdrop);
popover.style.display = 'none';
popover.removeEventListener('webkitTransitionEnd', onPopoverHidden);
}
var backdrop = function () {
var element = document.createElement('div');
element.classList.add('backdrop');
element.addEventListener('touchend', function () {
popover.addEventListener('webkitTransitionEnd', onPopoverHidden);
popover.classList.remove('visible');
});
return element;
}();
var getPopover = function (e) {
var anchor = findPopovers(e.target);
if (!anchor || !anchor.hash) return;
popover = document.querySelector(anchor.hash);
if (!popover || !popover.classList.contains('popover')) return;
return popover;
}
window.addEventListener('touchend', function (e) {
var popover = getPopover(e);
if (!popover) return;
popover.style.display = 'block';
popover.offsetHeight;
popover.classList.add('visible');
popover.parentNode.appendChild(backdrop);
});
window.addEventListener('click', function (e) { if (getPopover(e)) e.preventDefault(); });
}();
/* ----------------------------------
* PUSH v1.0.0
* Licensed under The MIT License
* inspired by chris's jquery.pjax.js
* http://opensource.org/licenses/MIT
* ---------------------------------- */
!function () {
var noop = function () {};
// Pushstate cacheing
// ==================
var isScrolling;
var maxCacheLength = 20;
var cacheMapping = sessionStorage;
var domCache = {};
var transitionMap = {
'slide-in' : 'slide-out',
'slide-out' : 'slide-in',
'fade' : 'fade'
};
var bars = {
bartab : '.bar-tab',
bartitle : '.bar-title',
barfooter : '.bar-footer',
barheadersecondary : '.bar-header-secondary'
};
var cacheReplace = function (data, updates) {
PUSH.id = data.id;
if (updates) data = getCached(data.id);
cacheMapping[data.id] = JSON.stringify(data);
window.history.replaceState(data.id, data.title, data.url);
domCache[data.id] = document.body.cloneNode(true);
};
var cachePush = function () {
var id = PUSH.id;
var cacheForwardStack = JSON.parse(cacheMapping.cacheForwardStack || '[]');
var cacheBackStack = JSON.parse(cacheMapping.cacheBackStack || '[]');
cacheBackStack.push(id);
while (cacheForwardStack.length) delete cacheMapping[cacheForwardStack.shift()];
while (cacheBackStack.length > maxCacheLength) delete cacheMapping[cacheBackStack.shift()];
window.history.pushState(null, '', cacheMapping[PUSH.id].url);
cacheMapping.cacheForwardStack = JSON.stringify(cacheForwardStack);
cacheMapping.cacheBackStack = JSON.stringify(cacheBackStack);
};
var cachePop = function (id, direction) {
var forward = direction == 'forward';
var cacheForwardStack = JSON.parse(cacheMapping.cacheForwardStack || '[]');
var cacheBackStack = JSON.parse(cacheMapping.cacheBackStack || '[]');
var pushStack = forward ? cacheBackStack : cacheForwardStack;
var popStack = forward ? cacheForwardStack : cacheBackStack;
if (PUSH.id) pushStack.push(PUSH.id);
popStack.pop();
cacheMapping.cacheForwardStack = JSON.stringify(cacheForwardStack);
cacheMapping.cacheBackStack = JSON.stringify(cacheBackStack);
};
var getCached = function (id) {
return JSON.parse(cacheMapping[id] || null) || {};
};
var getTarget = function (e) {
var target = findTarget(e.target);
if (
! target
|| e.which > 1
|| e.metaKey
|| e.ctrlKey
|| isScrolling
|| location.protocol !== target.protocol
|| location.host !== target.host
|| !target.hash && /#/.test(target.href)
|| target.hash && target.href.replace(target.hash, '') === location.href.replace(location.hash, '')
|| target.getAttribute('data-ignore') == 'push'
) return;
return target;
};
// Main event handlers (touchend, popstate)
// ==========================================
var touchend = function (e) {
var target = getTarget(e);
if (!target) return;
e.preventDefault();
PUSH({
url : target.href,
hash : target.hash,
timeout : target.getAttribute('data-timeout'),
transition : target.getAttribute('data-transition')
});
};
var popstate = function (e) {
var key;
var barElement;
var activeObj;
var activeDom;
var direction;
var transition;
var transitionFrom;
var transitionFromObj;
var id = e.state;
if (!id || !cacheMapping[id]) return;
direction = PUSH.id < id ? 'forward' : 'back';
cachePop(id, direction);
activeObj = getCached(id);
activeDom = domCache[id];
if (activeObj.title) document.title = activeObj.title;
if (direction == 'back') {
transitionFrom = JSON.parse(direction == 'back' ? cacheMapping.cacheForwardStack : cacheMapping.cacheBackStack);
transitionFromObj = getCached(transitionFrom[transitionFrom.length - 1]);
} else {
transitionFromObj = activeObj;
}
if (direction == 'back' && !transitionFromObj.id) return PUSH.id = id;
transition = direction == 'back' ? transitionMap[transitionFromObj.transition] : transitionFromObj.transition;
if (!activeDom) {
return PUSH({
id : activeObj.id,
url : activeObj.url,
title : activeObj.title,
timeout : activeObj.timeout,
transition : transition,
ignorePush : true
});
}
if (transitionFromObj.transition) {
activeObj = extendWithDom(activeObj, '.content', activeDom.cloneNode(true));
for (key in bars) {
barElement = document.querySelector(bars[key])
if (activeObj[key]) swapContent(activeObj[key], barElement);
else if (barElement) barElement.parentNode.removeChild(barElement);
}
}
swapContent(
(activeObj.contents || activeDom).cloneNode(true),
document.querySelector('.content'),
transition
);
PUSH.id = id;
document.body.offsetHeight; // force reflow to prevent scroll
};
// Core PUSH functionality
// =======================
var PUSH = function (options) {
var key;
var data = {};
var xhr = PUSH.xhr;
options.container = options.container || options.transition ? document.querySelector('.content') : document.body;
for (key in bars) {
options[key] = options[key] || document.querySelector(bars[key]);
}
if (xhr && xhr.readyState < 4) {
xhr.onreadystatechange = noop;
xhr.abort()
}
xhr = new XMLHttpRequest();
xhr.open('GET', options.url, true);
xhr.setRequestHeader('X-PUSH', 'true');
xhr.onreadystatechange = function () {
if (options._timeout) clearTimeout(options._timeout);
if (xhr.readyState == 4) xhr.status == 200 ? success(xhr, options) : failure(options.url);
};
if (!PUSH.id) {
cacheReplace({
id : +new Date,
url : window.location.href,
title : document.title,
timeout : options.timeout,
transition : null
});
}
if (options.timeout) {
options._timeout = setTimeout(function () { xhr.abort('timeout'); }, options.timeout);
}
xhr.send();
if (xhr.readyState && !options.ignorePush) cachePush();
};
// Main XHR handlers
// =================
var success = function (xhr, options) {
var key;
var barElement;
var data = parseXHR(xhr, options);
if (!data.contents) return locationReplace(options.url);
if (data.title) document.title = data.title;
if (options.transition) {
for (key in bars) {
barElement = document.querySelector(bars[key])
if (data[key]) swapContent(data[key], barElement);
else if (barElement) barElement.parentNode.removeChild(barElement);
}
}
swapContent(data.contents, options.container, options.transition, function () {
cacheReplace({
id : options.id || +new Date,
url : data.url,
title : data.title,
timeout : options.timeout,
transition : options.transition
}, options.id);
triggerStateChange();
});
if (!options.ignorePush && window._gaq) _gaq.push(['_trackPageview']) // google analytics
if (!options.hash) return;
};
var failure = function (url) {
throw new Error('Could not get: ' + url)
};
// PUSH helpers
// ============
var swapContent = function (swap, container, transition, complete) {
var enter;
var containerDirection;
var swapDirection;
if (!transition) {
if (container) container.innerHTML = swap.innerHTML;
else if (swap.classList.contains('content')) document.body.appendChild(swap);
else document.body.insertBefore(swap, document.querySelector('.content'));
} else {
enter = /in$/.test(transition);
if (transition == 'fade') {
container.classList.add('in');
container.classList.add('fade');
swap.classList.add('fade');
}
if (/slide/.test(transition)) {
swap.classList.add(enter ? 'right' : 'left');
swap.classList.add('slide');
container.classList.add('slide');
}
container.parentNode.insertBefore(swap, container);
}
if (!transition) complete && complete();
if (transition == 'fade') {
container.offsetWidth; // force reflow
container.classList.remove('in');
container.addEventListener('webkitTransitionEnd', fadeContainerEnd);
function fadeContainerEnd() {
container.removeEventListener('webkitTransitionEnd', fadeContainerEnd);
swap.classList.add('in');
swap.addEventListener('webkitTransitionEnd', fadeSwapEnd);
}
function fadeSwapEnd () {
swap.removeEventListener('webkitTransitionEnd', fadeSwapEnd);
container.parentNode.removeChild(container);
swap.classList.remove('fade');
swap.classList.remove('in');
complete && complete();
}
}
if (/slide/.test(transition)) {
container.offsetWidth; // force reflow
swapDirection = enter ? 'right' : 'left'
containerDirection = enter ? 'left' : 'right'
container.classList.add(containerDirection);
swap.classList.remove(swapDirection);
swap.addEventListener('webkitTransitionEnd', slideEnd);
function slideEnd() {
swap.removeEventListener('webkitTransitionEnd', slideEnd);
swap.classList.remove('slide');
swap.classList.remove(swapDirection);
container.parentNode.removeChild(container);
complete && complete();
}
}
};
var triggerStateChange = function () {
var e = new CustomEvent('push', {
detail: { state: getCached(PUSH.id) },
bubbles: true,
cancelable: true
});
window.dispatchEvent(e);
};
var findTarget = function (target) {
var i, toggles = document.querySelectorAll('a');
for (; target && target !== document; target = target.parentNode) {
for (i = toggles.length; i--;) { if (toggles[i] === target) return target; }
}
};
var locationReplace = function (url) {
window.history.replaceState(null, '', '#');
window.location.replace(url);
};
var parseURL = function (url) {
var a = document.createElement('a'); a.href = url; return a;
};
var extendWithDom = function (obj, fragment, dom) {
var i;
var result = {};
for (i in obj) result[i] = obj[i];
Object.keys(bars).forEach(function (key) {
var el = dom.querySelector(bars[key]);
if (el) el.parentNode.removeChild(el);
result[key] = el;
});
result.contents = dom.querySelector(fragment);
return result;
};
var parseXHR = function (xhr, options) {
var head;
var body;
var data = {};
var responseText = xhr.responseText;
data.url = options.url;
if (!responseText) return data;
if (/<html/i.test(responseText)) {
head = document.createElement('div');
body = document.createElement('div');
head.innerHTML = responseText.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0]
body.innerHTML = responseText.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0]
} else {
head = body = document.createElement('div');
head.innerHTML = responseText;
}
data.title = head.querySelector('title');
data.title = data.title && data.title.innerText.trim();
if (options.transition) data = extendWithDom(data, '.content', body);
else data.contents = body;
return data;
};
// Attach PUSH event handlers
// ==========================
window.addEventListener('touchstart', function () { isScrolling = false; });
window.addEventListener('touchmove', function () { isScrolling = true; })
window.addEventListener('touchend', touchend);
window.addEventListener('click', function (e) { if (getTarget(e)) e.preventDefault(); });
window.addEventListener('popstate', popstate);
}();
/* ----------------------------------
* TABS v1.0.0
* Licensed under The MIT License
* http://opensource.org/licenses/MIT
* ---------------------------------- */
!function () {
var getTarget = function (target) {
var i, popovers = document.querySelectorAll('.segmented-controller li a');
for (; target && target !== document; target = target.parentNode) {
for (i = popovers.length; i--;) { if (popovers[i] === target) return target; }
}
};
window.addEventListener("touchend", function (e) {
var activeTab;
var activeBody;
var targetBody;
var targetTab;
var className = 'active';
var classSelector = '.' + className;
var targetAnchor = getTarget(e.target);
if (!targetAnchor) return;
targetTab = targetAnchor.parentNode;
activeTab = targetTab.parentNode.querySelector(classSelector);
if (activeTab) activeTab.classList.remove(className);
targetTab.classList.add(className);
if (!targetAnchor.hash) return;
targetBody = document.querySelector(targetAnchor.hash);
if (!targetBody) return;
activeBody = targetBody.parentNode.querySelector(classSelector);
if (activeBody) activeBody.classList.remove(className);
targetBody.classList.add(className)
});
window.addEventListener('click', function (e) { if (getTarget(e.target)) e.preventDefault(); });
}();/* ----------------------------------
* SLIDER v1.0.1
* Licensed under The MIT License
* Adapted from Brad Birdsall's swipe
* http://opensource.org/licenses/MIT
* ---------------------------------- */
!function () {
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, sliders = document.querySelectorAll('.slider > ul');
for (; target && target !== document; target = target.parentNode) {
for (i = sliders.length; i--;) { if (sliders[i] === target) return target; }
}
}
var getScroll = function () {
var translate3d = slider.style.webkitTransform.match(/translate3d\(([^,]*)/);
return parseInt(translate3d ? translate3d[1] : 0)
};
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('li');
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;
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 v1.0.0
* Licensed under The MIT License
* http://opensource.org/licenses/MIT
* ---------------------------------- */
!function () {
var start = {};
var touchMove = false;
var distanceX = false;
var toggle = false;
var findToggle = function (target) {
var i, 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.offsetWidth;
var handleWidth = handle.offsetWidth;
var offset = toggle.classList.contains('active') ? toggleWidth - handleWidth : 0;
start = { pageX : e.touches[0].pageX - offset, pageY : e.touches[0].pageY };
touchMove = false;
// todo: probably should be moved to the css
toggle.style['-webkit-transition-duration'] = 0;
});
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.offsetWidth;
var handleWidth = handle.offsetWidth;
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.offsetWidth;
var handleWidth = handle.offsetWidth;
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;
});
}();
Loading…
Cancel
Save