- {{> UI.contentBlock}}
+
+
+ {{> UI.contentBlock}}
+
+
-
diff --git a/components/ionReorderButton/ionReorderButton.html b/components/ionReorderButton/ionReorderButton.html
new file mode 100644
index 0000000..a882773
--- /dev/null
+++ b/components/ionReorderButton/ionReorderButton.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/ionReorderButton/ionReorderButton.js b/components/ionReorderButton/ionReorderButton.js
new file mode 100644
index 0000000..a7234a3
--- /dev/null
+++ b/components/ionReorderButton/ionReorderButton.js
@@ -0,0 +1,13 @@
+Template.ionReorderButton.onCreated(function() {
+ let parent = this.parent((t) => t.view.name === "Template.ionItem", true);
+ if (!parent) { throw "Template.ionReorderButton must be a descendant of Template.ionItem."; }
+ _.extend(this, {
+ showReorder: parent.showReorder
+ });
+});
+
+Template.ionReorderButton.helpers({
+ showReorder: function() {
+ return Template.instance().showReorder.get();
+ }
+});
\ No newline at end of file
diff --git a/components/ionScroll/ionScroll.html b/components/ionScroll/ionScroll.html
new file mode 100644
index 0000000..2d08b13
--- /dev/null
+++ b/components/ionScroll/ionScroll.html
@@ -0,0 +1,9 @@
+
+
+ {{> UI.contentBlock}}
+
+
\ No newline at end of file
diff --git a/components/ionScroll/ionScroll.js b/components/ionScroll/ionScroll.js
new file mode 100644
index 0000000..6af1c15
--- /dev/null
+++ b/components/ionScroll/ionScroll.js
@@ -0,0 +1,87 @@
+Template.ionScroll.onCreated(function() {
+ this.nativeScrolling = new ReactiveVar(false);
+ this.direction = new ReactiveVar('y');
+ this.locking = new ReactiveVar(true);
+ this.paging = new ReactiveVar(true);
+ this.onRefresh = new ReactiveVar(true);
+ this.onScroll = new ReactiveVar(() => {});
+ this.scrollBarX = new ReactiveVar(true);
+ this.scrollBarY = new ReactiveVar(true);
+ this.zooming = new ReactiveVar(false);
+ this.minZoom = new ReactiveVar(0.5);
+ this.maxZoom = new ReactiveVar(3);
+ this.hasBouncing = new ReactiveVar(true);
+
+ this.scroller = null;
+
+ _.extend(this, {
+ set_direction: direction => this.direction.set(_.isUndefined(direction) ? 'y' : direction),
+ set_locking: locking => this.locking.set(_.isUndefined(locking) ? true : locking),
+ set_paging: paging => this.paging.set(!!paging),
+ set_onRefresh: onRefresh => this.onRefresh.set(onRefresh),
+ set_onScroll: onScroll => {
+ if (_.isFunction(onScroll)) {
+ if (!!this.scroller) this.scroller.off(this.onScroll.get(onScroll));
+ this.onScroll.set(onScroll);
+ }
+ },
+ set_scrollBarX: scrollBarX => this.scrollBarX.set(_.isUndefined(scrollBarX) ? true : scrollBarX),
+ set_scrollBarY: scrollBarY => this.scrollBarY.set(_.isUndefined(scrollBarY) ? true : scrollBarY),
+ set_zooming: zooming => this.zooming.set(!!zooming),
+ set_minZoom: minZoom => this.minZoom.set(_.isUndefined(minZoom) ? minZoom : 0.5),
+ set_maxZoom: maxZoom => this.maxZoom.set(_.isUndefined(maxZoom) ? maxZoom : 3),
+ set_hasBouncing: hasBouncing => this.hasBouncing.set(_.isUndefined(hasBouncing) ? true: hasBouncing) // todo: Make this platform dependent.
+ });
+
+ this.autorun(() => {
+ if (!Template.currentData()) return;
+ this.nativeScrolling.set(!!Template.currentData().overflowScroll);
+
+ this.set_direction(Template.currentData().direction);
+ this.set_locking(Template.currentData().locking);
+ this.set_paging(Template.currentData().paging);
+ this.set_onRefresh(Template.currentData().onRefresh);
+ this.set_onScroll(Template.currentData().onScroll);
+ this.set_scrollBarX(Template.currentData().scrollBarX);
+ this.set_scrollBarY(Template.currentData().scrollBarY);
+ this.set_zooming(Template.currentData().zooming);
+ this.set_minZoom(Template.currentData().minZoom);
+ this.set_maxZoom(Template.currentData().maxZoom);
+ this.set_hasBouncing(Template.currentData().hasBouncing);
+ });
+});
+
+Template.ionScroll.onRendered(function() {
+ if (!this.nativeScrolling.get()) { // todo: make this reactive? Is there a use case?
+ this.scroller = new IScroll(this.$(".scroller-wrapper").get(0));
+
+ if (!!this.onScroll.get()) { this.scroller.on('scroll', this.onScroll.get()); }
+
+ this.autorun(() => {
+ this.scroller.options = _.extend(this.scroller.options, {
+ scrollX: this.direction.get().indexOf('x') !== -1,
+ scrollY: this.direction.get().indexOf('y') !== -1,
+ freeScroll: !this.locking.get(),
+ zoom: this.zooming.get(),
+ zoomMin: this.minZoom.get(),
+ zoomMax: this.maxZoom.get(),
+ bounce: this.hasBouncing.get()
+ });
+
+ this.scroller.refresh();
+ });
+
+ this.autorun(() => {
+ // only available in ionscroll-probe.
+ //if (_.isFunction(this.onScroll.get())) { console.log(this.onScroll.get()); this.scroller.on('onScroll', this.onScroll.get()); }
+ });
+
+ this.$(".scroller-wrapper").children().load(() => this.scroller.refresh());
+ }
+});
+
+Template.ionScroll.helpers({
+ nativeScrollingClass: function() {
+ return Template.instance().nativeScrolling.get() ? 'overflow-scroll' : '';
+ }
+});
\ No newline at end of file
diff --git a/components/ionSideMenuContainer/ionSideMenuContainer.js b/components/ionSideMenuContainer/ionSideMenuContainer.js
index 618d801..08f4cb7 100644
--- a/components/ionSideMenuContainer/ionSideMenuContainer.js
+++ b/components/ionSideMenuContainer/ionSideMenuContainer.js
@@ -1,40 +1,55 @@
IonSideMenu = {
- snapper: null
-};
+ snapper: null, // Make this private in the future.
-Template.ionSideMenuContainer.created = function () {
- this.data = this.data || {};
- this.side = this.data.side || 'both';
- this.dragContent = true;
- if (typeof this.data.dragContent != 'undefined') {
- this.dragContent = this.data.dragContent
- }
+ // Note that meteor renders most deeply nested template first before the outer most.
+ // Thus, if the child happens toc all any of these, before we are rendered, then
+ // error occurs. To solve that, dummy functions are provided.
+ enable: () => {},
+ disable: () => {}
};
-Template.ionSideMenuContainer.rendered = function () {
- $snapperEl = this.$('.snap-content');
- if (!$snapperEl) {
- return;
- }
-
- var disable;
- if (this.side == 'both') {
- disable = 'none';
- }
- if (this.side == 'left') {
- disable = 'right';
- }
- if (this.side == 'right') {
- disable = 'left';
- }
-
- IonSideMenu.snapper = new Snap({
- element: $snapperEl.get(0),
- disable: disable,
- touchToDrag: this.dragContent
- });
-};
+Template.ionSideMenuContainer.onCreated(function () {
+ this.data = this.data || {};
+ this.side = this.data.side || 'both';
+ this.dragContent = true;
-Template.ionSideMenuContainer.destroyed = function () {
- IonSideMenu.snapper = null;
-};
+ this.hasBouncing = new ReactiveVar(true);
+
+ if (typeof this.data.dragContent != 'undefined') {
+ this.dragContent = this.data.dragContent
+ }
+});
+
+Template.ionSideMenuContainer.onRendered(function () {
+ $snapperEl = this.$('.snap-content');
+ if (!$snapperEl) {
+ return;
+ }
+
+ var disable;
+ if (this.side == 'both') {
+ disable = 'none';
+ }
+ if (this.side == 'left') {
+ disable = 'right';
+ }
+ if (this.side == 'right') {
+ disable = 'left';
+ }
+
+ IonSideMenu.snapper = new Snap({
+ element: $snapperEl.get(0),
+ disable: disable,
+ touchToDrag: this.dragContent
+ });
+
+ IonSideMenu.enable = () => IonSideMenu.snapper.enable();
+ IonSideMenu.disable = () => IonSideMenu.snapper.disable();
+
+ // Watch hasBounce attribute.
+ this.autorun(() => { IonSideMenu.snapper.settings({ hyperextensible: this.hasBouncing.get() }); });
+});
+
+Template.ionSideMenuContainer.onDestroyed(function () {
+ IonSideMenu.snapper = null;
+});
diff --git a/components/ionSlideBox/ionSlideBox.js b/components/ionSlideBox/ionSlideBox.js
index 7b7ca82..7768da5 100644
--- a/components/ionSlideBox/ionSlideBox.js
+++ b/components/ionSlideBox/ionSlideBox.js
@@ -5,6 +5,7 @@ Template.ionSlideBox.created = function () {
this.slideInterval = this.data.slideInterval || 4000;
this.showPager = typeof this.data.showPager != 'undefined' ? this.data.showPager : true;
this.initialSlide = this.data.initialSlide || Session.get('ion-slide-initial-slide') || 0;
+ this.preventPropagation = this.data.preventPropagation || true;
};
Template.ionSlideBox.rendered = function () {
@@ -29,3 +30,11 @@ Template.ionSlideBox.destroyed = function () {
var $slideBox = this.$('.ion-slide-box');
if ($slideBox.hasClass('slick-initialized')) $slideBox.slick('unslick');
};
+
+Template.ionSlideBox.events({
+ 'touchmove .ion-slide-box': function(event, template) {
+ if (template.preventPropagation) {
+ event.stopPropagation();
+ }
+ }
+});
\ No newline at end of file
diff --git a/package.js b/package.js
index 866fdc4..c745900 100644
--- a/package.js
+++ b/package.js
@@ -1,34 +1,45 @@
Package.describe({
- name: "meteoric:ionic",
+ name: "jandres:ionic",
summary: "Ionic components for Meteor. No Angular!",
- version: "0.1.19",
- git: "https://github.com/meteoric/meteor-ionic.git"
+ version: "0.1.43",
+ git: "https://github.com/JoeyAndres/meteor-ionic.git"
});
+
+
Cordova.depends({
'ionic-plugin-keyboard': '1.0.8'
});
Package.onUse(function(api) {
api.versionsFrom("1.0");
+
api.use([
+ "jandres:template-extension@4.0.4",
+ "ecmascript@0.1.6",
"templating",
"underscore",
+ "reactive-var",
"fastclick",
"iron:router@1.0.0",
"tracker",
"session",
- "jquery"
+ "jquery",
+ "jandres:iscroll-zoom@5.1.4",
+ "jandres:snapjs@2.0.2",
+ "fourseven:scss@3.3.3"
], "client");
api.addFiles([
- "vendor/snap.js",
- "vendor/snap.css",
"vendor/slick.js",
"vendor/slick.css",
"vendor/slip.js"
], "client");
+ api.addFiles([
+ "styles/main.scss"
+ ], "client");
+
api.addFiles([
"components/ionActionSheet/ionActionSheet.html",
"components/ionActionSheet/ionActionSheet.js",
@@ -42,6 +53,9 @@ Package.onUse(function(api) {
"components/ionContent/ionContent.html",
"components/ionContent/ionContent.js",
+ "components/ionDeleteButton/ionDeleteButton.html",
+ "components/ionDeleteButton/ionDeleteButton.js",
+
"components/ionFooterBar/ionFooterBar.html",
"components/ionFooterBar/ionFooterBar.js",
@@ -54,6 +68,12 @@ Package.onUse(function(api) {
"components/ionItem/ionItem.html",
"components/ionItem/ionItem.js",
+ "components/ionItemOptions/ionItemOptions.html",
+ "components/ionItemOptions/ionItemOptions.js",
+
+ "components/ionItemContent/ionItemContent.html",
+ "components/ionItemContent/ionItemContent.js",
+
"components/ionKeyboard/ionKeyboard.js",
"components/ionKeyboard/ionInputFocus.js",
@@ -72,6 +92,9 @@ Package.onUse(function(api) {
"components/ionNavBar/ionNavBar.html",
"components/ionNavBar/ionNavBar.js",
+ "components/ionOptionButton/ionOptionButton.html",
+ "components/ionOptionButton/ionOptionButton.js",
+
"components/ionNavBackButton/ionNavBackButton.html",
"components/ionNavBackButton/ionNavBackButton.js",
@@ -90,6 +113,12 @@ Package.onUse(function(api) {
"components/ionRadio/ionRadio.html",
"components/ionRadio/ionRadio.js",
+ "components/ionReorderButton/ionReorderButton.html",
+ "components/ionReorderButton/ionReorderButton.js",
+
+ "components/ionScroll/ionScroll.html",
+ "components/ionScroll/ionScroll.js",
+
"components/ionSideMenu/ionSideMenu.html",
"components/ionSideMenu/ionSideMenu.js",
diff --git a/styles/main.scss b/styles/main.scss
new file mode 100644
index 0000000..42398f1
--- /dev/null
+++ b/styles/main.scss
@@ -0,0 +1,7 @@
+.snap-drawers {
+ .snap-drawer-left {}
+ .item-options.snap-drawer.snap-drawer-right {
+ width: initial;
+ overflow: initial;
+ }
+}
\ No newline at end of file
diff --git a/vendor/slip.js b/vendor/slip.js
index 30ab0a8..aa1af09 100644
--- a/vendor/slip.js
+++ b/vendor/slip.js
@@ -1,115 +1,129 @@
/*
- Slip - swiping and reordering in lists of elements on touch screens, no fuss.
+ Slip - swiping and reordering in lists of elements on touch screens, no fuss.
- Fires these events on list elements:
+ Fires these events on list elements:
- • slip:swipe
- When swipe has been done and user has lifted finger off the screen.
- If you execute event.preventDefault() the element will be animated back to original position.
- Otherwise it will be animated off the list and set to display:none.
+ • slip:swipe
+ When swipe has been done and user has lifted finger off the screen.
+ If you execute event.preventDefault() the element will be animated back to original position.
+ Otherwise it will be animated off the list and set to display:none.
- • slip:beforeswipe
- Fired before first swipe movement starts.
- If you execute event.preventDefault() then element will not move at all.
+ • slip:beforeswipe
+ Fired before first swipe movement starts.
+ If you execute event.preventDefault() then element will not move at all.
- • slip:reorder
- Element has been dropped in new location. event.detail contains the location:
- • insertBefore: DOM node before which element has been dropped (null is the end of the list). Use with node.insertBefore().
- • spliceIndex: Index of element before which current element has been dropped, not counting the element iself.
- For use with Array.splice() if the list is reflecting objects in some array.
+ • slip:reorder
+ Element has been dropped in new location. event.detail contains the location:
+ • insertBefore: DOM node before which element has been dropped (null is the end of the list). Use with node.insertBefore().
+ • spliceIndex: Index of element before which current element has been dropped, not counting the element iself.
+ For use with Array.splice() if the list is reflecting objects in some array.
- • slip:beforereorder
- When reordering movement starts.
- Element being reordered gets class `slip-reordering`.
- If you execute event.preventDefault() then element will not move at all.
+ • slip:beforereorder
+ When reordering movement starts.
+ Element being reordered gets class `slip-reordering`.
+ If you execute event.preventDefault() then element will not move at all.
- • slip:beforewait
- If you execute event.preventDefault() then reordering will begin immediately, blocking ability to scroll the page.
+ • slip:beforewait
+ If you execute event.preventDefault() then reordering will begin immediately, blocking ability to scroll the page.
- • slip:tap
- When element was tapped without being swiped/reordered.
+ • slip:tap
+ When element was tapped without being swiped/reordered.
- • slip:cancelswipe
- Fired when the user stops dragging and the element returns to its original position.
+ • slip:cancelswipe
+ Fired when the user stops dragging and the element returns to its original position.
- Usage:
+ Usage:
- CSS:
- You should set `user-select:none` (and WebKit prefixes, sigh) on list elements,
- otherwise unstoppable and glitchy text selection in iOS will get in the way.
+ CSS:
+ You should set `user-select:none` (and WebKit prefixes, sigh) on list elements,
+ otherwise unstoppable and glitchy text selection in iOS will get in the way.
- You should set `overflow-x: hidden` on the container or body to prevent horizontal scrollbar
- appearing when elements are swiped off the list.
+ You should set `overflow-x: hidden` on the container or body to prevent horizontal scrollbar
+ appearing when elements are swiped off the list.
- var list = document.querySelector('ul#slippylist');
- new Slip(list);
+ var list = document.querySelector('ul#slippylist');
+ new Slip(list);
- list.addEventListener('slip:beforeswipe', function(e) {
- if (shouldNotSwipe(e.target)) e.preventDefault();
- });
+ list.addEventListener('slip:beforeswipe', function(e) {
+ if (shouldNotSwipe(e.target)) e.preventDefault();
+ });
- list.addEventListener('slip:swipe', function(e) {
- // e.target swiped
- if (thatWasSwipeToRemove) {
- e.target.parentNode.removeChild(e.target);
- } else {
- e.preventDefault(); // will animate back to original position
- }
- });
+ list.addEventListener('slip:swipe', function(e) {
+ // e.target swiped
+ if (thatWasSwipeToRemove) {
+ e.target.parentNode.removeChild(e.target);
+ } else {
+ e.preventDefault(); // will animate back to original position
+ }
+ });
- list.addEventListener('slip:beforereorder', function(e) {
- if (shouldNotReorder(e.target)) e.preventDefault();
- });
+ list.addEventListener('slip:beforereorder', function(e) {
+ if (shouldNotReorder(e.target)) e.preventDefault();
+ });
- list.addEventListener('slip:reorder', function(e) {
- // e.target reordered.
- if (reorderedOK) {
- e.target.parentNode.insertBefore(e.target, e.detail.insertBefore);
- } else {
- e.preventDefault();
- }
- });
+ list.addEventListener('slip:reorder', function(e) {
+ // e.target reordered.
+ if (reorderedOK) {
+ e.target.parentNode.insertBefore(e.target, e.detail.insertBefore);
+ } else {
+ e.preventDefault();
+ }
+ });
- Requires:
- • Touch events
- • CSS transforms
- • Function.bind()
+ Requires:
+ • Touch events
+ • CSS transforms
+ • Function.bind()
- Caveats:
- • Elements must not change size while reordering or swiping takes place (otherwise it will be visually out of sync)
-*/
+ Caveats:
+ • Elements must not change size while reordering or swiping takes place (otherwise it will be visually out of sync)
+ */
/*! @license
- Slip.js 1.2.0
+ Slip.js 1.2.0
- © 2014 Kornel Lesiński
. All rights reserved.
+ © 2014 Kornel Lesiński . All rights reserved.
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
- the following disclaimer in the documentation and/or other materials provided with the distribution.
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ the following disclaimer in the documentation and/or other materials provided with the distribution.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
-window['Slip'] = (function(){
+window['Slip'] = (function() {
'use strict';
+ var accessibility = {
+ // Set values to false if you don't want Slip to manage them
+ container: {
+ ariaRole: "listbox",
+ tabIndex: 0,
+ focus: true, // focuses after drop
+ },
+ items: {
+ ariaRole: "option", // If "option" flattens items, try "group": https://www.marcozehe.de/2013/03/08/sometimes-you-have-to-use-illegal-wai-aria-to-make-stuff-work/
+ tabIndex: -1, // 0 will make every item tabbable, which isn't always useful
+ focus: true, // focuses when dragging
+ },
+ };
+
var damnYouChrome = /Chrome\/[34]/.test(navigator.userAgent); // For bugs that can't be programmatically detected :( Intended to catch all versions of Chrome 30-40
var needsBodyHandlerHack = damnYouChrome; // Otherwise I _sometimes_ don't get any touchstart events and only clicks instead.
/* When dragging elements down in Chrome (tested 34-37) dragged element may appear below stationary elements.
- Looks like WebKit bug #61824, but iOS Safari doesn't have that problem. */
+ Looks like WebKit bug #61824, but iOS Safari doesn't have that problem. */
var compositorDoesNotOrderLayers = damnYouChrome;
// -webkit-mess
@@ -127,7 +141,7 @@ window['Slip'] = (function(){
var globalInstances = 0;
var attachedBodyHandlerHack = false;
- var nullHandler = function(){};
+ var nullHandler = function() {};
function Slip(container, options) {
if ('string' === typeof container) container = document.querySelector(container);
@@ -135,7 +149,10 @@ window['Slip'] = (function(){
if (!this || this === window) return new Slip(container, options);
- this.options = options;
+ this.options = options = options || {};
+ this.options.keepSwipingPercent = options.keepSwipingPercent || 0;
+ this.options.minimumSwipeVelocity = options.minimumSwipeVelocity || 1;
+ this.options.minimumSwipeTime = options.minimumSwipeTime || 110;
// Functions used for as event handlers need usable `this` and must not change to be removable
this.cancel = this.setState.bind(this, this.states.idle);
@@ -147,6 +164,7 @@ window['Slip'] = (function(){
this.onMouseUp = this.onMouseUp.bind(this);
this.onMouseLeave = this.onMouseLeave.bind(this);
this.onSelection = this.onSelection.bind(this);
+ this.onContainerFocus = this.onContainerFocus.bind(this);
this.setState(this.states.idle);
this.attach(container);
@@ -156,32 +174,38 @@ window['Slip'] = (function(){
var transform = node.style[transformPrefix];
if (transform) {
return {
- value:transform,
- original:transform,
+ value: transform,
+ original: transform,
};
}
if (window.getComputedStyle) {
var style = window.getComputedStyle(node).getPropertyValue(transformProperty);
- if (style && style !== 'none') return {value:style, original:''};
+ if (style && style !== 'none') return {
+ value: style,
+ original: ''
+ };
}
- return {value:'', original:''};
+ return {
+ value: '',
+ original: ''
+ };
}
function findIndex(target, nodes) {
- var originalIndex = 0;
- var listCount = 0;
-
- for (var i=0; i < nodes.length; i++) {
- if (nodes[i].nodeType === 1) {
- listCount++;
- if (nodes[i] === target.node) {
- originalIndex = listCount-1;
- }
+ var originalIndex = 0;
+ var listCount = 0;
+
+ for (var i = 0; i < nodes.length; i++) {
+ if (nodes[i].nodeType === 1) {
+ listCount++;
+ if (nodes[i] === target.node) {
+ originalIndex = listCount - 1;
+ }
+ }
}
- }
- return originalIndex;
+ return originalIndex;
}
// All functions in states are going to be executed in context of Slip object
@@ -204,9 +228,12 @@ window['Slip'] = (function(){
states: {
idle: function idleStateInit() {
- this.target = null;
- this.usingTouch = false;
this.removeMouseHandlers();
+ if (this.target) {
+ this.target.node.style.willChange = '';
+ this.target = null;
+ }
+ this.usingTouch = false;
return {
allowTextSelection: true,
@@ -215,14 +242,15 @@ window['Slip'] = (function(){
undecided: function undecidedStateInit() {
this.target.height = this.target.node.offsetHeight;
+ this.target.node.style.willChange = transformProperty;
this.target.node.style[transitionPrefix] = '';
if (!this.dispatch(this.target.originalTarget, 'beforewait')) {
- if (this.dispatch(this.target.originalTarget, 'beforereorder')) {
- this.setState(this.states.reorder);
- }
+ if (this.dispatch(this.target.originalTarget, 'beforereorder')) {
+ this.setState(this.states.reorder);
+ }
} else {
- var holdTimer = setTimeout(function(){
+ var holdTimer = setTimeout(function() {
var move = this.getAbsoluteMovement();
if (this.canPreventScrolling && move.x < 15 && move.y < 25) {
if (this.dispatch(this.target.originalTarget, 'beforereorder')) {
@@ -241,7 +269,10 @@ window['Slip'] = (function(){
var move = this.getAbsoluteMovement();
if (move.x > 20 && move.y < Math.max(100, this.target.height)) {
- if (this.dispatch(this.target.originalTarget, 'beforeswipe')) {
+ if (this.dispatch(this.target.originalTarget, 'beforeswipe', {
+ directionX: move.directionX,
+ directionY: move.directionY
+ })) {
this.setState(this.states.swipe);
return false;
} else {
@@ -253,7 +284,7 @@ window['Slip'] = (function(){
}
// Chrome likes sideways scrolling :(
- if (move.x > move.y*1.2) return false;
+ if (move.x > move.y * 1.2) return false;
},
onLeave: function() {
@@ -275,8 +306,9 @@ window['Slip'] = (function(){
var originalIndex = findIndex(this.target, this.container.childNodes);
container.className += ' slip-swiping-container';
+
function removeClass() {
- container.className = container.className.replace(/(?:^| )slip-swiping-container/,'');
+ container.className = container.className.replace(/(?:^| )slip-swiping-container/, '');
}
this.target.height = this.target.node.offsetHeight;
@@ -284,7 +316,7 @@ window['Slip'] = (function(){
return {
leaveState: function() {
if (swipeSuccess) {
- this.animateSwipe(function(target){
+ this.animateSwipe(function(target) {
target.node.style[transformPrefix] = target.baseTransform.original;
target.node.style[transitionPrefix] = '';
if (this.dispatch(target.node, 'afterswipe')) {
@@ -303,7 +335,7 @@ window['Slip'] = (function(){
onMove: function() {
var move = this.getTotalMovement();
- if (Math.abs(move.y) < this.target.height+20) {
+ if (Math.abs(move.y) < this.target.height + 20) {
this.target.node.style[transformPrefix] = 'translate(' + move.x + 'px,0) ' + hwLayerMagic + this.target.baseTransform.value;
return false;
} else {
@@ -316,22 +348,19 @@ window['Slip'] = (function(){
},
onEnd: function() {
- var dx = this.latestPosition.x - this.previousPosition.x;
- var dy = this.latestPosition.y - this.previousPosition.y;
- var velocity = Math.sqrt(dx*dx + dy*dy) / (this.latestPosition.time - this.previousPosition.time + 1);
-
var move = this.getAbsoluteMovement();
- var swiped = velocity > 0.6 && move.time > 110;
+ var velocity = move.x / move.time;
- var direction;
- if (dx > 0) {
- direction = "right";
- } else {
- direction = "left";
- }
+ // How far out has the item been swiped?
+ var swipedPercent = Math.abs((this.startPosition.x - this.previousPosition.x) / this.container.clientWidth) * 100;
+
+ var swiped = (velocity > this.options.minimumSwipeVelocity && move.time > this.options.minimumSwipeTime) || (this.options.keepSwipingPercent && swipedPercent > this.options.keepSwipingPercent);
if (swiped) {
- if (this.dispatch(this.target.node, 'swipe', {direction: direction, originalIndex: originalIndex})) {
+ if (this.dispatch(this.target.node, 'swipe', {
+ direction: move.directionX,
+ originalIndex: originalIndex
+ })) {
swipeSuccess = true; // can't animate here, leaveState overrides anim
}
}
@@ -342,14 +371,18 @@ window['Slip'] = (function(){
},
reorder: function reorderStateInit() {
+ if (this.target.node.focus && accessibility.items.focus) {
+ this.target.node.focus();
+ }
+
this.target.height = this.target.node.offsetHeight;
var nodes = this.container.childNodes;
var originalIndex = findIndex(this.target, nodes);
var mouseOutsideTimer;
- var zero = this.target.node.offsetTop + this.target.height/2;
+ var zero = this.target.node.offsetTop + this.target.height / 2;
var otherNodes = [];
- for(var i=0; i < nodes.length; i++) {
+ for (var i = 0; i < nodes.length; i++) {
if (nodes[i].nodeType != 1 || nodes[i] === this.target.node) continue;
var t = nodes[i].offsetTop;
nodes[i].style[transitionPrefix] = transformProperty + ' 0.2s ease-in-out';
@@ -373,23 +406,23 @@ window['Slip'] = (function(){
if (mouseOutsideTimer) {
// don't care where the mouse is as long as it moves
- clearTimeout(mouseOutsideTimer); mouseOutsideTimer = null;
+ clearTimeout(mouseOutsideTimer);
+ mouseOutsideTimer = null;
}
var move = this.getTotalMovement();
this.target.node.style[transformPrefix] = 'translate(0,' + move.y + 'px) ' + hwTopLayerMagic + this.target.baseTransform.value;
var height = this.target.height;
- otherNodes.forEach(function(o){
+ otherNodes.forEach(function(o) {
var off = 0;
if (o.pos < 0 && move.y < 0 && o.pos > move.y) {
off = height;
- }
- else if (o.pos > 0 && move.y > 0 && o.pos < move.y) {
+ } else if (o.pos > 0 && move.y > 0 && o.pos < move.y) {
off = -height;
}
// FIXME: should change accelerated/non-accelerated state lazily
- o.node.style[transformPrefix] = off ? 'translate(0,'+off+'px) ' + hwLayerMagic + o.baseTransform.value : o.baseTransform.original;
+ o.node.style[transformPrefix] = off ? 'translate(0,' + off + 'px) ' + hwLayerMagic + o.baseTransform.value : o.baseTransform.original;
});
return false;
}
@@ -404,13 +437,17 @@ window['Slip'] = (function(){
this.container.style.webkitTransformStyle = '';
}
- this.target.node.className = this.target.node.className.replace(/(?:^| )slip-reordering/,'');
+ if (this.container.focus && accessibility.container.focus) {
+ this.container.focus();
+ }
+
+ this.target.node.className = this.target.node.className.replace(/(?:^| )slip-reordering/, '');
this.target.node.style[userSelectPrefix] = '';
- this.animateToZero(function(target){
+ this.animateToZero(function(target) {
target.node.style.zIndex = '';
});
- otherNodes.forEach(function(o){
+ otherNodes.forEach(function(o) {
o.node.style[transformPrefix] = o.baseTransform.original;
o.node.style[transitionPrefix] = ''; // FIXME: animate to new position
});
@@ -422,7 +459,7 @@ window['Slip'] = (function(){
// don't let element get stuck if mouse left the window
// but don't cancel immediately as it'd be annoying near window edges
if (mouseOutsideTimer) clearTimeout(mouseOutsideTimer);
- mouseOutsideTimer = setTimeout(function(){
+ mouseOutsideTimer = setTimeout(function() {
mouseOutsideTimer = null;
this.cancel();
}.bind(this), 700);
@@ -431,16 +468,24 @@ window['Slip'] = (function(){
onEnd: function() {
var move = this.getTotalMovement();
if (move.y < 0) {
- for(var i=0; i < otherNodes.length; i++) {
+ for (var i = 0; i < otherNodes.length; i++) {
if (otherNodes[i].pos > move.y) {
- this.dispatch(this.target.node, 'reorder', {spliceIndex:i, insertBefore:otherNodes[i].node, originalIndex: originalIndex});
+ this.dispatch(this.target.node, 'reorder', {
+ spliceIndex: i,
+ insertBefore: otherNodes[i].node,
+ originalIndex: originalIndex
+ });
break;
}
}
} else {
- for(var i=otherNodes.length-1; i >= 0; i--) {
+ for (var i = otherNodes.length - 1; i >= 0; i--) {
if (otherNodes[i].pos < move.y) {
- this.dispatch(this.target.node, 'reorder', {spliceIndex:i+1, insertBefore:otherNodes[i+1] ? otherNodes[i+1].node : null, originalIndex: originalIndex});
+ this.dispatch(this.target.node, 'reorder', {
+ spliceIndex: i + 1,
+ insertBefore: otherNodes[i + 1] ? otherNodes[i + 1].node : null,
+ originalIndex: originalIndex
+ });
break;
}
}
@@ -464,6 +509,17 @@ window['Slip'] = (function(){
}
this.container = container;
+
+ // Accessibility
+ if (false !== accessibility.container.tabIndex) {
+ this.container.tabIndex = accessibility.container.tabIndex;
+ }
+ if (accessibility.container.ariaRole) {
+ this.container.setAttribute('aria-role', accessibility.container.ariaRole);
+ }
+ this.setChildNodesAriaRoles();
+ this.container.addEventListener('focus', this.onContainerFocus, false);
+
this.otherNodes = [];
// selection on iOS interferes with reordering
@@ -496,7 +552,7 @@ window['Slip'] = (function(){
}
},
- setState: function(newStateCtor){
+ setState: function(newStateCtor) {
if (this.state) {
if (this.state.ctor === newStateCtor) return;
if (this.state.leaveState) this.state.leaveState.call(this);
@@ -512,12 +568,29 @@ window['Slip'] = (function(){
},
findTargetNode: function(targetNode) {
- while(targetNode && targetNode.parentNode !== this.container) {
+ while (targetNode && targetNode.parentNode !== this.container) {
targetNode = targetNode.parentNode;
}
return targetNode;
},
+ onContainerFocus: function(e) {
+ this.setChildNodesAriaRoles();
+ },
+
+ setChildNodesAriaRoles: function() {
+ var nodes = this.container.childNodes;
+ for (var i = 0; i < nodes.length; i++) {
+ if (nodes[i].nodeType != 1) continue;
+ if (accessibility.items.ariaRole) {
+ nodes[i].setAttribute('aria-role', accessibility.items.ariaRole);
+ }
+ if (false !== accessibility.items.tabIndex) {
+ nodes[i].tabIndex = accessibility.items.tabIndex;
+ }
+ }
+ },
+
onSelection: function(e) {
var isRelated = e.target === document || this.findTargetNode(e);
if (!isRelated) return;
@@ -606,9 +679,9 @@ window['Slip'] = (function(){
//check for a scrollable parent
var scrollContainer = targetNode.parentNode;
- while (scrollContainer){
- if (scrollContainer.scrollHeight > scrollContainer.clientHeight && window.getComputedStyle(scrollContainer)['overflow-y'] != 'visible') break;
- else scrollContainer = scrollContainer.parentNode;
+ while (scrollContainer) {
+ if (scrollContainer.scrollHeight > scrollContainer.clientHeight && window.getComputedStyle(scrollContainer)['overflow-y'] != 'visible') break;
+ else scrollContainer = scrollContainer.parentNode;
}
this.target = {
@@ -626,8 +699,9 @@ window['Slip'] = (function(){
},
updatePosition: function(e, pos) {
- if(this.target == null)
+ if (this.target == null) {
return;
+ }
this.latestPosition = pos;
var triggerOffset = 40,
@@ -639,16 +713,15 @@ window['Slip'] = (function(){
bottomOffset = Math.min(containerRect.bottom, window.innerHeight) - targetRect.bottom,
topOffset = targetRect.top - Math.max(containerRect.top, 0);
- if (bottomOffset < triggerOffset){
- offset = triggerOffset - bottomOffset;
- }
- else if (topOffset < triggerOffset){
- offset = topOffset - triggerOffset;
+ if (bottomOffset < triggerOffset) {
+ offset = triggerOffset - bottomOffset;
+ } else if (topOffset < triggerOffset) {
+ offset = topOffset - triggerOffset;
}
var prevScrollTop = scrollable.scrollTop;
scrollable.scrollTop += offset;
- if (prevScrollTop != scrollable.scrollTop) this.startPosition.y += prevScrollTop-scrollable.scrollTop;
+ if (prevScrollTop != scrollable.scrollTop) this.startPosition.y += prevScrollTop - scrollable.scrollTop;
if (this.state.onMove) {
if (this.state.onMove.call(this) === false) {
@@ -699,8 +772,8 @@ window['Slip'] = (function(){
getTotalMovement: function() {
return {
- x:this.latestPosition.x - this.startPosition.x,
- y:this.latestPosition.y - this.startPosition.y,
+ x: this.latestPosition.x - this.startPosition.x,
+ y: this.latestPosition.y - this.startPosition.y,
};
},
@@ -708,7 +781,9 @@ window['Slip'] = (function(){
return {
x: Math.abs(this.latestPosition.x - this.startPosition.x),
y: Math.abs(this.latestPosition.y - this.startPosition.y),
- time:this.latestPosition.time - this.startPosition.time,
+ time: this.latestPosition.time - this.startPosition.time,
+ directionX: this.latestPosition.x - this.startPosition.x < 0 ? 'left' : 'right',
+ directionY: this.latestPosition.y - this.startPosition.y < 0 ? 'up' : 'down',
};
},
@@ -727,7 +802,7 @@ window['Slip'] = (function(){
getSiblings: function(target) {
var siblings = [];
var tmp = target.node.nextSibling;
- while(tmp) {
+ while (tmp) {
if (tmp.nodeType == 1) siblings.push({
node: tmp,
baseTransform: getTransform(tmp),
@@ -741,9 +816,9 @@ window['Slip'] = (function(){
// save, because this.target/container could change during animation
target = target || this.target;
- // target.node.style[transitionPrefix] = transformProperty + ' 5s ease-out';
+ target.node.style[transitionPrefix] = transformProperty + ' 0.1s ease-out';
target.node.style[transformPrefix] = 'translate(0,0) ' + hwLayerMagic + target.baseTransform.value;
- setTimeout(function(){
+ setTimeout(function() {
target.node.style[transitionPrefix] = '';
target.node.style[transformPrefix] = target.baseTransform.original;
if (callback) callback.call(this, target);
@@ -759,23 +834,23 @@ window['Slip'] = (function(){
target.node.style[transitionPrefix] = 'all 0.1s linear';
target.node.style[transformPrefix] = ' translate(' + (this.getTotalMovement().x > 0 ? '' : '-') + '100%,0) ' + hwLayerMagic + target.baseTransform.value;
- setTimeout(function(){
+ setTimeout(function() {
if (callback.call(this, target)) {
- siblings.forEach(function(o){
+ siblings.forEach(function(o) {
o.node.style[transitionPrefix] = '';
o.node.style[transformPrefix] = emptySpaceTransform + o.baseTransform.value;
});
- setTimeout(function(){
- siblings.forEach(function(o){
+ setTimeout(function() {
+ siblings.forEach(function(o) {
o.node.style[transitionPrefix] = transformProperty + ' 0.1s ease-in-out';
o.node.style[transformPrefix] = 'translate(0,0) ' + hwLayerMagic + o.baseTransform.value;
});
- setTimeout(function(){
- siblings.forEach(function(o){
+ setTimeout(function() {
+ siblings.forEach(function(o) {
o.node.style[transitionPrefix] = '';
o.node.style[transformPrefix] = o.baseTransform.original;
});
- },101);
+ }, 101);
}, 1);
}
}.bind(this), 101);
@@ -784,9 +859,9 @@ window['Slip'] = (function(){
// AMD
if ('function' === typeof define && define.amd) {
- define(function(){
+ define(function() {
return Slip;
});
}
return Slip;
-})();
+})();
\ No newline at end of file
diff --git a/vendor/snap.css b/vendor/snap.css
deleted file mode 100644
index b09c3a6..0000000
--- a/vendor/snap.css
+++ /dev/null
@@ -1,64 +0,0 @@
-.snap-content {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- width: auto;
- height: auto;
- z-index: 2;
- overflow: auto;
- -webkit-overflow-scrolling: touch;
- -webkit-transform: translate3d(0, 0, 0);
- -moz-transform: translate3d(0, 0, 0);
- -ms-transform: translate3d(0, 0, 0);
- -o-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
-}
-
-.snap-drawers {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- width: auto;
- height: auto;
-}
-
-.snap-drawer {
- position: absolute;
- top: 0;
- right: auto;
- bottom: 0;
- left: auto;
- width: 265px;
- height: auto;
- overflow: auto;
- -webkit-overflow-scrolling: touch;
- -webkit-transition: width 0.3s ease;
- -moz-transition: width 0.3s ease;
- -ms-transition: width 0.3s ease;
- -o-transition: width 0.3s ease;
- transition: width 0.3s ease;
-}
-
-.snap-drawer-left {
- left: 0;
- z-index: 1;
-}
-
-.snap-drawer-right {
- right: 0;
- z-index: 1;
-}
-
-.snapjs-left .snap-drawer-right,
-.snapjs-right .snap-drawer-left {
- display: none;
-}
-
-.snapjs-expand-left .snap-drawer-left,
-.snapjs-expand-right .snap-drawer-right {
- width: 100%;
-}
diff --git a/vendor/snap.js b/vendor/snap.js
deleted file mode 100644
index 07b5a7f..0000000
--- a/vendor/snap.js
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
-* Snap.js
-*
-* Copyright 2013, Jacob Kelley - http://jakiestfu.com/
-* Released under the MIT Licence
-* http://opensource.org/licenses/MIT
-*
-* Github: http://github.com/jakiestfu/Snap.js/
-* Version: 1.9.3
-*/
-/*jslint browser: true*/
-/*global define, module, ender*/
-(function(win, doc) {
- 'use strict';
- var Snap = Snap || function(userOpts) {
- var settings = {
- element: null,
- dragger: null,
- disable: 'none',
- addBodyClasses: true,
- hyperextensible: true,
- resistance: 0.5,
- flickThreshold: 50,
- transitionSpeed: 0.3,
- easing: 'ease',
- maxPosition: 266,
- minPosition: -266,
- tapToClose: true,
- touchToDrag: true,
- slideIntent: 40, // degrees
- minDragDistance: 5
- },
- cache = {
- simpleStates: {
- opening: null,
- towards: null,
- hyperExtending: null,
- halfway: null,
- flick: null,
- translation: {
- absolute: 0,
- relative: 0,
- sinceDirectionChange: 0,
- percentage: 0
- }
- }
- },
- eventList = {},
- utils = {
- hasTouch: ('ontouchstart' in doc.documentElement || win.navigator.msPointerEnabled),
- eventType: function(action) {
- var eventTypes = {
- down: (utils.hasTouch ? 'touchstart' : 'mousedown'),
- move: (utils.hasTouch ? 'touchmove' : 'mousemove'),
- up: (utils.hasTouch ? 'touchend' : 'mouseup'),
- out: (utils.hasTouch ? 'touchcancel' : 'mouseout')
- };
- return eventTypes[action];
- },
- page: function(t, e){
- return (utils.hasTouch && e.touches.length && e.touches[0]) ? e.touches[0]['page'+t] : e['page'+t];
- },
- klass: {
- has: function(el, name){
- return (el.className).indexOf(name) !== -1;
- },
- add: function(el, name){
- if(!utils.klass.has(el, name) && settings.addBodyClasses){
- el.className += " "+name;
- }
- },
- remove: function(el, name){
- if(settings.addBodyClasses){
- el.className = (el.className).replace(name, "").replace(/^\s+|\s+$/g, '');
- }
- }
- },
- dispatchEvent: function(type) {
- if (typeof eventList[type] === 'function') {
- return eventList[type].call();
- }
- },
- vendor: function(){
- var tmp = doc.createElement("div"),
- prefixes = 'webkit Moz O ms'.split(' '),
- i;
- for (i in prefixes) {
- if (typeof tmp.style[prefixes[i] + 'Transition'] !== 'undefined') {
- return prefixes[i];
- }
- }
- },
- transitionCallback: function(){
- return (cache.vendor==='Moz' || cache.vendor==='ms') ? 'transitionend' : cache.vendor+'TransitionEnd';
- },
- canTransform: function(){
- return typeof settings.element.style[cache.vendor+'Transform'] !== 'undefined';
- },
- deepExtend: function(destination, source) {
- var property;
- for (property in source) {
- if (source[property] && source[property].constructor && source[property].constructor === Object) {
- destination[property] = destination[property] || {};
- utils.deepExtend(destination[property], source[property]);
- } else {
- destination[property] = source[property];
- }
- }
- return destination;
- },
- angleOfDrag: function(x, y) {
- var degrees, theta;
- // Calc Theta
- theta = Math.atan2(-(cache.startDragY - y), (cache.startDragX - x));
- if (theta < 0) {
- theta += 2 * Math.PI;
- }
- // Calc Degrees
- degrees = Math.floor(theta * (180 / Math.PI) - 180);
- if (degrees < 0 && degrees > -180) {
- degrees = 360 - Math.abs(degrees);
- }
- return Math.abs(degrees);
- },
- events: {
- addEvent: function addEvent(element, eventName, func) {
- if (element.addEventListener) {
- return element.addEventListener(eventName, func, false);
- } else if (element.attachEvent) {
- return element.attachEvent("on" + eventName, func);
- }
- },
- removeEvent: function addEvent(element, eventName, func) {
- if (element.addEventListener) {
- return element.removeEventListener(eventName, func, false);
- } else if (element.attachEvent) {
- return element.detachEvent("on" + eventName, func);
- }
- },
- prevent: function(e) {
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- }
- },
- parentUntil: function(el, attr) {
- var isStr = typeof attr === 'string';
- while (el.parentNode) {
- if (isStr && el.getAttribute && el.getAttribute(attr)){
- return el;
- } else if(!isStr && el === attr){
- return el;
- }
- el = el.parentNode;
- }
- return null;
- }
- },
- action = {
- translate: {
- get: {
- matrix: function(index) {
-
- if( !utils.canTransform() ){
- return parseInt(settings.element.style.left, 10);
- } else {
- var matrix = win.getComputedStyle(settings.element)[cache.vendor+'Transform'].match(/\((.*)\)/),
- ieOffset = 8;
- if (matrix) {
- matrix = matrix[1].split(',');
- if(matrix.length===16){
- index+=ieOffset;
- }
- return parseInt(matrix[index], 10);
- }
- return 0;
- }
- }
- },
- easeCallback: function(){
- settings.element.style[cache.vendor+'Transition'] = '';
- cache.translation = action.translate.get.matrix(4);
- cache.easing = false;
- clearInterval(cache.animatingInterval);
-
- if(cache.easingTo===0){
- utils.klass.remove(doc.body, 'snapjs-right');
- utils.klass.remove(doc.body, 'snapjs-left');
- }
-
- utils.dispatchEvent('animated');
- utils.events.removeEvent(settings.element, utils.transitionCallback(), action.translate.easeCallback);
- },
- easeTo: function(n) {
-
- if( !utils.canTransform() ){
- cache.translation = n;
- action.translate.x(n);
- } else {
- cache.easing = true;
- cache.easingTo = n;
-
- settings.element.style[cache.vendor+'Transition'] = 'all ' + settings.transitionSpeed + 's ' + settings.easing;
-
- cache.animatingInterval = setInterval(function() {
- utils.dispatchEvent('animating');
- }, 1);
-
- utils.events.addEvent(settings.element, utils.transitionCallback(), action.translate.easeCallback);
- action.translate.x(n);
- }
- if(n===0){
- settings.element.style[cache.vendor+'Transform'] = '';
- }
- },
- x: function(n) {
- if( (settings.disable==='left' && n>0) ||
- (settings.disable==='right' && n<0)
- ){ return; }
-
- if( !settings.hyperextensible ){
- if( n===settings.maxPosition || n>settings.maxPosition ){
- n=settings.maxPosition;
- } else if( n===settings.minPosition || n 0,
- translateTo = whileDragX,
- diff;
-
- // Shown no intent already
- if((cache.intentChecked && !cache.hasIntent)){
- return;
- }
-
- if(settings.addBodyClasses){
- if((absoluteTranslation)>0){
- utils.klass.add(doc.body, 'snapjs-left');
- utils.klass.remove(doc.body, 'snapjs-right');
- } else if((absoluteTranslation)<0){
- utils.klass.add(doc.body, 'snapjs-right');
- utils.klass.remove(doc.body, 'snapjs-left');
- }
- }
-
- if (cache.hasIntent === false || cache.hasIntent === null) {
- var deg = utils.angleOfDrag(thePageX, thePageY),
- inRightRange = (deg >= 0 && deg <= settings.slideIntent) || (deg <= 360 && deg > (360 - settings.slideIntent)),
- inLeftRange = (deg >= 180 && deg <= (180 + settings.slideIntent)) || (deg <= 180 && deg >= (180 - settings.slideIntent));
- if (!inLeftRange && !inRightRange) {
- cache.hasIntent = false;
- } else {
- cache.hasIntent = true;
- }
- cache.intentChecked = true;
- }
-
- if (
- (settings.minDragDistance>=Math.abs(thePageX-cache.startDragX)) || // Has user met minimum drag distance?
- (cache.hasIntent === false)
- ) {
- return;
- }
-
- utils.events.prevent(e);
- utils.dispatchEvent('drag');
-
- cache.dragWatchers.current = thePageX;
- // Determine which direction we are going
- if (cache.dragWatchers.last > thePageX) {
- if (cache.dragWatchers.state !== 'left') {
- cache.dragWatchers.state = 'left';
- cache.dragWatchers.hold = thePageX;
- }
- cache.dragWatchers.last = thePageX;
- } else if (cache.dragWatchers.last < thePageX) {
- if (cache.dragWatchers.state !== 'right') {
- cache.dragWatchers.state = 'right';
- cache.dragWatchers.hold = thePageX;
- }
- cache.dragWatchers.last = thePageX;
- }
- if (openingLeft) {
- // Pulling too far to the right
- if (settings.maxPosition < absoluteTranslation) {
- diff = (absoluteTranslation - settings.maxPosition) * settings.resistance;
- translateTo = whileDragX - diff;
- }
- cache.simpleStates = {
- opening: 'left',
- towards: cache.dragWatchers.state,
- hyperExtending: settings.maxPosition < absoluteTranslation,
- halfway: absoluteTranslation > (settings.maxPosition / 2),
- flick: Math.abs(cache.dragWatchers.current - cache.dragWatchers.hold) > settings.flickThreshold,
- translation: {
- absolute: absoluteTranslation,
- relative: whileDragX,
- sinceDirectionChange: (cache.dragWatchers.current - cache.dragWatchers.hold),
- percentage: (absoluteTranslation/settings.maxPosition)*100
- }
- };
- } else {
- // Pulling too far to the left
- if (settings.minPosition > absoluteTranslation) {
- diff = (absoluteTranslation - settings.minPosition) * settings.resistance;
- translateTo = whileDragX - diff;
- }
- cache.simpleStates = {
- opening: 'right',
- towards: cache.dragWatchers.state,
- hyperExtending: settings.minPosition > absoluteTranslation,
- halfway: absoluteTranslation < (settings.minPosition / 2),
- flick: Math.abs(cache.dragWatchers.current - cache.dragWatchers.hold) > settings.flickThreshold,
- translation: {
- absolute: absoluteTranslation,
- relative: whileDragX,
- sinceDirectionChange: (cache.dragWatchers.current - cache.dragWatchers.hold),
- percentage: (absoluteTranslation/settings.minPosition)*100
- }
- };
- }
- action.translate.x(translateTo + translated);
- }
- },
- endDrag: function(e) {
- if (cache.isDragging) {
- utils.dispatchEvent('end');
- var translated = action.translate.get.matrix(4);
-
- // Tap Close
- if (cache.dragWatchers.current === 0 && translated !== 0 && settings.tapToClose) {
- utils.dispatchEvent('close');
- utils.events.prevent(e);
- action.translate.easeTo(0);
- cache.isDragging = false;
- cache.startDragX = 0;
- return;
- }
-
- // Revealing Left
- if (cache.simpleStates.opening === 'left') {
- // Halfway, Flicking, or Too Far Out
- if ((cache.simpleStates.halfway || cache.simpleStates.hyperExtending || cache.simpleStates.flick)) {
- if (cache.simpleStates.flick && cache.simpleStates.towards === 'left') { // Flicking Closed
- action.translate.easeTo(0);
- } else if (
- (cache.simpleStates.flick && cache.simpleStates.towards === 'right') || // Flicking Open OR
- (cache.simpleStates.halfway || cache.simpleStates.hyperExtending) // At least halfway open OR hyperextending
- ) {
- action.translate.easeTo(settings.maxPosition); // Open Left
- }
- } else {
- action.translate.easeTo(0); // Close Left
- }
- // Revealing Right
- } else if (cache.simpleStates.opening === 'right') {
- // Halfway, Flicking, or Too Far Out
- if ((cache.simpleStates.halfway || cache.simpleStates.hyperExtending || cache.simpleStates.flick)) {
- if (cache.simpleStates.flick && cache.simpleStates.towards === 'right') { // Flicking Closed
- action.translate.easeTo(0);
- } else if (
- (cache.simpleStates.flick && cache.simpleStates.towards === 'left') || // Flicking Open OR
- (cache.simpleStates.halfway || cache.simpleStates.hyperExtending) // At least halfway open OR hyperextending
- ) {
- action.translate.easeTo(settings.minPosition); // Open Right
- }
- } else {
- action.translate.easeTo(0); // Close Right
- }
- }
- cache.isDragging = false;
- cache.startDragX = utils.page('X', e);
- }
- }
- }
- },
- init = function(opts) {
- if (opts.element) {
- utils.deepExtend(settings, opts);
- cache.vendor = utils.vendor();
- action.drag.listen();
- }
- };
- /*
- * Public
- */
- this.open = function(side) {
- utils.dispatchEvent('open');
- utils.klass.remove(doc.body, 'snapjs-expand-left');
- utils.klass.remove(doc.body, 'snapjs-expand-right');
-
- if (side === 'left') {
- cache.simpleStates.opening = 'left';
- cache.simpleStates.towards = 'right';
- utils.klass.add(doc.body, 'snapjs-left');
- utils.klass.remove(doc.body, 'snapjs-right');
- action.translate.easeTo(settings.maxPosition);
- } else if (side === 'right') {
- cache.simpleStates.opening = 'right';
- cache.simpleStates.towards = 'left';
- utils.klass.remove(doc.body, 'snapjs-left');
- utils.klass.add(doc.body, 'snapjs-right');
- action.translate.easeTo(settings.minPosition);
- }
- };
- this.close = function() {
- utils.dispatchEvent('close');
- action.translate.easeTo(0);
- };
- this.expand = function(side){
- var to = win.innerWidth || doc.documentElement.clientWidth;
-
- if(side==='left'){
- utils.dispatchEvent('expandLeft');
- utils.klass.add(doc.body, 'snapjs-expand-left');
- utils.klass.remove(doc.body, 'snapjs-expand-right');
- } else {
- utils.dispatchEvent('expandRight');
- utils.klass.add(doc.body, 'snapjs-expand-right');
- utils.klass.remove(doc.body, 'snapjs-expand-left');
- to *= -1;
- }
- action.translate.easeTo(to);
- };
-
- this.on = function(evt, fn) {
- eventList[evt] = fn;
- return this;
- };
- this.off = function(evt) {
- if (eventList[evt]) {
- eventList[evt] = false;
- }
- };
-
- this.enable = function() {
- utils.dispatchEvent('enable');
- action.drag.listen();
- };
- this.disable = function() {
- utils.dispatchEvent('disable');
- action.drag.stopListening();
- };
-
- this.settings = function(opts){
- utils.deepExtend(settings, opts);
- };
-
- this.state = function() {
- var state,
- fromLeft = action.translate.get.matrix(4);
- if (fromLeft === settings.maxPosition) {
- state = 'left';
- } else if (fromLeft === settings.minPosition) {
- state = 'right';
- } else {
- state = 'closed';
- }
- return {
- state: state,
- info: cache.simpleStates
- };
- };
- init(userOpts);
- };
- if ((typeof module !== 'undefined') && module.exports) {
- module.exports = Snap;
- }
- if (typeof ender === 'undefined') {
- this.Snap = Snap;
- }
- if ((typeof define === "function") && define.amd) {
- define("snap", [], function() {
- return Snap;
- });
- }
- }).call(this, window, document);