summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorThomas Müller <thomas.mueller@tmit.eu>2014-06-06 11:27:04 +0200
committerThomas Müller <thomas.mueller@tmit.eu>2014-06-06 11:27:04 +0200
commit289accc31bd2adb98833e470162483119924e2e9 (patch)
treea8547b7eb22d481f2752403b486ebe1e8636414a /core
parent3a7b30795c56f1debdb7a9dcd51578b711c2f622 (diff)
parentb2bae9313d3467f945ef02a3091d8cbf52c1382a (diff)
downloadnextcloud-server-289accc31bd2adb98833e470162483119924e2e9.tar.gz
nextcloud-server-289accc31bd2adb98833e470162483119924e2e9.zip
Merge pull request #8159 from owncloud/mobile-sidebar-swipe
Mobile sidebar swipe
Diffstat (limited to 'core')
-rw-r--r--core/css/apps.css23
-rw-r--r--core/css/header.css4
-rw-r--r--core/css/icons.css4
-rw-r--r--core/css/mobile.css88
-rw-r--r--core/css/styles.css18
-rw-r--r--core/img/actions/menu.pngbin0 -> 106 bytes
-rw-r--r--core/img/actions/menu.svg12
-rw-r--r--core/js/js.js54
-rwxr-xr-xcore/js/snap.js568
-rw-r--r--core/js/tests/specHelper.js18
10 files changed, 774 insertions, 15 deletions
diff --git a/core/css/apps.css b/core/css/apps.css
index 4bcf89c7ee4..ebb0c269000 100644
--- a/core/css/apps.css
+++ b/core/css/apps.css
@@ -1,4 +1,5 @@
-/* ---- APP STYLING ---- */
+/* APP STYLING -------------------------------------------------------------- */
+
#app {
height: 100%;
@@ -8,15 +9,26 @@
-moz-box-sizing: border-box; box-sizing: border-box;
}
+
+
+
+
+/* APP-NAVIGATION ------------------------------------------------------------*/
+
+
/* Navigation: folder like structure */
#app-navigation {
- width: 230px;
+ width: 250px;
height: 100%;
float: left;
-moz-box-sizing: border-box; box-sizing: border-box;
background-color: #f8f8f8;
border-right: 1px solid #ccc;
padding-bottom: 44px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
}
#app-navigation > ul {
position: relative;
@@ -166,6 +178,11 @@
+
+
+/* APP-CONTENT ---------------------------------------------------------------*/
+
+
/* Part where the content will be loaded into */
#app-content {
position: relative;
@@ -176,7 +193,7 @@
/* settings area */
#app-settings {
position: fixed;
- width: 229px;
+ width: 249px;
bottom: 0;
border-top: 1px solid #ccc;
}
diff --git a/core/css/header.css b/core/css/header.css
index 83612c67445..d04895d27cf 100644
--- a/core/css/header.css
+++ b/core/css/header.css
@@ -122,10 +122,6 @@
/* NAVIGATION --------------------------------------------------------------- */
-#content-wrapper {
- padding-left: 0;
-}
-
#navigation {
position: fixed;
top: 45px;
diff --git a/core/css/icons.css b/core/css/icons.css
index 75d66a773a1..60f0b1b8c60 100644
--- a/core/css/icons.css
+++ b/core/css/icons.css
@@ -90,6 +90,10 @@
background-image: url('../img/actions/mail.svg');
}
+.icon-menu {
+ background-image: url('../img/actions/menu.svg');
+}
+
.icon-more {
background-image: url('../img/actions/more.svg');
}
diff --git a/core/css/mobile.css b/core/css/mobile.css
index 9cea0dddc8f..98033528210 100644
--- a/core/css/mobile.css
+++ b/core/css/mobile.css
@@ -60,4 +60,92 @@
box-sizing: border-box;
}
+
+/* APP SIDEBAR TOGGLE and SWIPE ----------------------------------------------*/
+
+/* prevent scrollbar when sidebar is open */
+.snapjs-left #content-wrapper {
+ overflow-x: hidden;
+}
+
+#app-navigation,
+#app-content {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+
+#app-navigation {
+ width: 250px !important;
+}
+
+#app-content {
+ width: 100% !important;
+ left: 0 !important;
+ background-color: #fff;
+ overflow-x: hidden !important;
+}
+
+#app-navigation-toggle {
+ position: fixed;
+ display: inline-block !important;
+ top: 45px;
+ left: 0;
+ width: 44px;
+ height: 44px;
+ z-index: 149;
+ background-color: rgba(255, 255, 255, .7);
+ cursor: pointer;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";
+ filter: alpha(opacity=60);
+ opacity: .6;
+}
+#app-navigation-toggle:hover,
+#app-navigation-toggle:focus {
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+ filter: alpha(opacity=100);
+ opacity: 1;
+}
+
+/* fix controls bar for apps which don't use the standard */
+#body-user .app-files #controls,
+#user-controls {
+ left: 0 !important;
+ padding-left: 44px !important;
+}
+/* .viewer-mode is when text editor, PDF viewer, etc is open */
+#body-user .app-files.viewer-mode #controls {
+ padding-left: 0 !important;
+}
+.app-files.viewer-mode #app-navigation-toggle {
+ display: none !important;
+}
+
+table.multiselect thead {
+ left: 0 !important;
+}
+
+/* shorten elements for mobile */
+#uploadprogresswrapper {
+ width: 50px;
+}
+
+
+/* fix controls bar jumping when navigation is slid out */
+.snapjs-left #app-navigation-toggle {
+ top: 0;
+}
+.snapjs-left .app-files #controls,
+.snapjs-left #user-controls {
+ top: 0;
+}
+.snapjs-left table.multiselect thead {
+ top: 44px;
+}
+
+
+
+/* end of media query */
}
diff --git a/core/css/styles.css b/core/css/styles.css
index 9b8a9cc660c..5ad9796137d 100644
--- a/core/css/styles.css
+++ b/core/css/styles.css
@@ -253,6 +253,10 @@ input[type="submit"].enabled {
background: #eee;
border-bottom: 1px solid #e7e7e7;
z-index: 50;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
}
#controls .button,
#controls button,
@@ -272,14 +276,22 @@ input[type="submit"].enabled {
display: none;
}
-#content { position:relative; height:100%; width:100%; }
+#content {
+ position: relative;
+ height: 100%;
+ width: 100%;
+}
#content .hascontrols {
position: relative;
top: 45px;
}
#content-wrapper {
- position:absolute; height:100%; width:100%; padding-left:80px; padding-top: 45px;
- -moz-box-sizing:border-box; box-sizing:border-box;
+ position: absolute;
+ height: 100%;
+ width: 100%;
+ padding-top: 45px;
+ -moz-box-sizing:border-box;
+ box-sizing:border-box;
}
#emptycontent {
diff --git a/core/img/actions/menu.png b/core/img/actions/menu.png
new file mode 100644
index 00000000000..583ce319175
--- /dev/null
+++ b/core/img/actions/menu.png
Binary files differ
diff --git a/core/img/actions/menu.svg b/core/img/actions/menu.svg
new file mode 100644
index 00000000000..f0e33df3737
--- /dev/null
+++ b/core/img/actions/menu.svg
@@ -0,0 +1,12 @@
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata>
+ <rdf:RDF>
+ <cc:Work rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+ <dc:title/>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <path d="m2,2,0,2,12,0,0-2zm0,5,0,2,12,0,0-2zm0,5,0,2,12,0,0-2z"/>
+</svg>
diff --git a/core/js/js.js b/core/js/js.js
index b3cefa83bee..d02dc6445f2 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -1131,6 +1131,60 @@ function initCore() {
}
setupMainMenu();
+
+ // just add snapper for logged in users
+ if($('#body-login, #body-public').length === 0) {
+
+ // App sidebar on mobile
+ var snapper = new Snap({
+ element: document.getElementById('app-content'),
+ disable: 'right',
+ maxPosition: 250
+ });
+ $('#app-content').prepend('<div id="app-navigation-toggle" class="icon-menu" style="display:none;"></div>');
+ $('#app-navigation-toggle').click(function(){
+ if(snapper.state().state == 'left'){
+ snapper.close();
+ } else {
+ snapper.open('left');
+ }
+ });
+ // close sidebar when switching navigation entry
+ var $appNavigation = $('#app-navigation');
+ $appNavigation.delegate('a', 'click', function(event) {
+ var $target = $(event.target);
+ // don't hide navigation when changing settings or adding things
+ if($target.is('.app-navigation-noclose') ||
+ $target.closest('.app-navigation-noclose').length) {
+ return;
+ }
+ if($target.is('.add-new') ||
+ $target.closest('.add-new').length) {
+ return;
+ }
+ if($target.is('#app-settings') ||
+ $target.closest('#app-settings').length) {
+ return;
+ }
+ snapper.close();
+ });
+
+ var toggleSnapperOnSize = function() {
+ if($(window).width() > 768) {
+ snapper.close();
+ snapper.disable();
+ } else {
+ snapper.enable();
+ }
+ };
+
+ $(window).resize(_.debounce(toggleSnapperOnSize, 250));
+
+ // initial call
+ toggleSnapperOnSize();
+
+ }
+
}
$(document).ready(initCore);
diff --git a/core/js/snap.js b/core/js/snap.js
new file mode 100755
index 00000000000..0bbefe44203
--- /dev/null
+++ b/core/js/snap.js
@@ -0,0 +1,568 @@
+/*
+ * 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<settings.minPosition ){
+ n=settings.minPosition;
+ }
+ }
+
+ n = parseInt(n, 10);
+ if(isNaN(n)){
+ n = 0;
+ }
+
+ if( utils.canTransform() ){
+ var theTranslate = 'translate3d(' + n + 'px, 0,0)';
+ settings.element.style[cache.vendor+'Transform'] = theTranslate;
+ } else {
+ settings.element.style.width = (win.innerWidth || doc.documentElement.clientWidth)+'px';
+
+ settings.element.style.left = n+'px';
+ settings.element.style.right = '';
+ }
+ }
+ },
+ drag: {
+ listen: function() {
+ cache.translation = 0;
+ cache.easing = false;
+ utils.events.addEvent(settings.element, utils.eventType('down'), action.drag.startDrag);
+ utils.events.addEvent(settings.element, utils.eventType('move'), action.drag.dragging);
+ utils.events.addEvent(settings.element, utils.eventType('up'), action.drag.endDrag);
+ },
+ stopListening: function() {
+ utils.events.removeEvent(settings.element, utils.eventType('down'), action.drag.startDrag);
+ utils.events.removeEvent(settings.element, utils.eventType('move'), action.drag.dragging);
+ utils.events.removeEvent(settings.element, utils.eventType('up'), action.drag.endDrag);
+ },
+ startDrag: function(e) {
+ // No drag on ignored elements
+ var target = e.target ? e.target : e.srcElement,
+ ignoreParent = utils.parentUntil(target, 'data-snap-ignore');
+
+ if (ignoreParent) {
+ utils.dispatchEvent('ignore');
+ return;
+ }
+
+
+ if(settings.dragger){
+ var dragParent = utils.parentUntil(target, settings.dragger);
+
+ // Only use dragger if we're in a closed state
+ if( !dragParent &&
+ (cache.translation !== settings.minPosition &&
+ cache.translation !== settings.maxPosition
+ )){
+ return;
+ }
+ }
+
+ utils.dispatchEvent('start');
+ settings.element.style[cache.vendor+'Transition'] = '';
+ cache.isDragging = true;
+ cache.hasIntent = null;
+ cache.intentChecked = false;
+ cache.startDragX = utils.page('X', e);
+ cache.startDragY = utils.page('Y', e);
+ cache.dragWatchers = {
+ current: 0,
+ last: 0,
+ hold: 0,
+ state: ''
+ };
+ cache.simpleStates = {
+ opening: null,
+ towards: null,
+ hyperExtending: null,
+ halfway: null,
+ flick: null,
+ translation: {
+ absolute: 0,
+ relative: 0,
+ sinceDirectionChange: 0,
+ percentage: 0
+ }
+ };
+ },
+ dragging: function(e) {
+ if (cache.isDragging && settings.touchToDrag) {
+
+ var thePageX = utils.page('X', e),
+ thePageY = utils.page('Y', e),
+ translated = cache.translation,
+ absoluteTranslation = action.translate.get.matrix(4),
+ whileDragX = thePageX - cache.startDragX,
+ openingLeft = absoluteTranslation > 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);
diff --git a/core/js/tests/specHelper.js b/core/js/tests/specHelper.js
index fc5043c2f49..2af3497051c 100644
--- a/core/js/tests/specHelper.js
+++ b/core/js/tests/specHelper.js
@@ -19,15 +19,12 @@
*
*/
-/* global OC */
-
/**
* Simulate the variables that are normally set by PHP code
*/
// from core/js/config.php
window.TESTING = true;
-window.oc_debug = true;
window.datepickerFormatDate = 'MM d, yy';
window.dayNames = [
'Sunday',
@@ -55,6 +52,8 @@ window.monthNames = [
window.firstDay = 0;
// setup dummy webroots
+/* jshint camelcase: false */
+window.oc_debug = true;
window.oc_webroot = location.href + '/';
window.oc_appswebroots = {
"files": window.oc_webroot + '/apps/files/'
@@ -68,11 +67,20 @@ window.oc_appconfig = {
};
window.oc_defaults = {};
+/* jshint camelcase: true */
+
+// mock for Snap.js plugin
+window.Snap = function() {};
+window.Snap.prototype = {
+ enable: function() {},
+ disable: function() {},
+ close: function() {}
+};
+
// global setup for all tests
(function setupTests() {
var fakeServer = null,
- $testArea = null,
- routesRequestStub;
+ $testArea = null;
beforeEach(function() {
// test area for elements that need absolute selector access or measure widths/heights