From 4a12f398210bf5f9bfce6572b86fc6d3dc6519ee Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 11 Nov 2013 13:47:10 -0600 Subject: [PATCH 01/11] Fixed side menu right/left issue, improved API --- dist/js/ionic-angular.js | 52 +++++---- dist/js/ionic.js | 72 +++++++++--- js/controllers/sideMenuController.js | 28 ++--- js/ext/angular/src/directive/ionicSideMenu.js | 52 +++++---- js/ext/angular/test/sideMenu.html | 39 +++++-- js/utils/utils.js | 11 ++ js/views/sideMenuView.js | 33 ++++++ test/side-menus.html | 103 +++++++----------- 8 files changed, 251 insertions(+), 139 deletions(-) diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index 11199ec5a0..5a9635369a 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -975,27 +975,18 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture']) angular.extend(this, ionic.controllers.SideMenuController.prototype); ionic.controllers.SideMenuController.call(this, { + // Our quick implementation of the left side menu left: { width: 270, - pushDown: function() { - $scope.leftZIndex = -1; - }, - bringUp: function() { - $scope.leftZIndex = 0; - } }, + + // Our quick implementation of the right side menu right: { width: 270, - pushDown: function() { - $scope.rightZIndex = -1; - }, - bringUp: function() { - $scope.rightZIndex = 0; - } } }); - $scope.contentTranslateX = 0; + $scope.sideMenuContentTranslateX = 0; $scope.sideMenuCtrl = this; }) @@ -1027,28 +1018,32 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture']) defaultPrevented = e.defaultPrevented; }); - Gesture.on('drag', function(e) { + var dragFn = function(e) { if(defaultPrevented) { return; } sideMenuCtrl._handleDrag(e); - }, $element[0]); + }; - Gesture.on('release', function(e) { + Gesture.on('drag', dragFn, $element[0]); + + var dragReleaseFn = function(e) { if(!defaultPrevented) { sideMenuCtrl._endDrag(e); } defaultPrevented = false; - }, $element[0]); + }; + + Gesture.on('release', dragReleaseFn, $element[0]); sideMenuCtrl.setContent({ onDrag: function(e) {}, endDrag: function(e) {}, getTranslateX: function() { - return $scope.contentTranslateX || 0; + return $scope.sideMenuContentTranslateX || 0; }, setTranslateX: function(amount) { - $scope.contentTranslateX = amount; + $scope.sideMenuContentTranslateX = amount; $element[0].style.webkitTransform = 'translate3d(' + amount + 'px, 0, 0)'; }, enableAnimation: function() { @@ -1062,6 +1057,12 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture']) $element[0].classList.remove('menu-animated'); } }); + + // Cleanup + $scope.$on('$destroy', function() { + Gesture.off('drag', dragFn); + Gesture.off('release', dragReleaseFn); + }); }; } }; @@ -1080,10 +1081,23 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture']) return function($scope, $element, $attr, sideMenuCtrl) { $scope.side = $attr.side; + if($scope.side == 'left') { sideMenuCtrl.left.isEnabled = true; + sideMenuCtrl.left.pushDown = function() { + $element[0].style.zIndex = -1; + }; + sideMenuCtrl.left.bringUp = function() { + $element[0].style.zIndex = 0; + }; } else if($scope.side == 'right') { sideMenuCtrl.right.isEnabled = true; + sideMenuCtrl.right.pushDown = function() { + $element[0].style.zIndex = -1; + }; + sideMenuCtrl.right.bringUp = function() { + $element[0].style.zIndex = 0; + }; } $element.append(transclude($scope)); diff --git a/dist/js/ionic.js b/dist/js/ionic.js index b12d4a9664..facf3265eb 100644 --- a/dist/js/ionic.js +++ b/dist/js/ionic.js @@ -1836,6 +1836,15 @@ window.ionic = { (function(ionic) { ionic.Utils = { + + // Return a function that will be called with the given context + proxy: function(func, context) { + var args = Array.prototype.slice.call(arguments, 2); + return function() { + return func.apply(context, args.concat(Array.prototype.slice.call(arguments))); + }; + }, + throttle: function(func, wait, options) { var context, args, result; var timeout = null; @@ -1915,9 +1924,11 @@ window.ionic = { } }; + // Bind a few of the most useful functions to the ionic scope ionic.inherit = ionic.Utils.inherit; ionic.extend = ionic.Utils.extend; ionic.throttle = ionic.Utils.throttle; + ionic.proxy = ionic.Utils.proxy; })(window.ionic); ; @@ -3467,6 +3478,39 @@ window.ionic = { } }); + ionic.views.SideMenuContent = ionic.views.View.inherit({ + initialize: function(opts) { + var _this = this; + + ionic.extend(this, { + animationClass: 'menu-animated', + onDrag: function(e) {}, + onEndDrag: function(e) {}, + }, opts); + + ionic.onGesture('drag', ionic.proxy(this._onDrag, this), this.el); + ionic.onGesture('release', ionic.proxy(this._onEndDrag, this), this.el); + }, + _onDrag: function(e) { + this.onDrag && this.onDrag(e); + }, + _onEndDrag: function(e) { + this.onEndDrag && this.onEndDrag(e); + }, + disableAnimation: function() { + this.el.classList.remove(this.animationClass); + }, + enableAnimation: function() { + this.el.classList.add(this.animationClass); + }, + getTranslateX: function() { + return parseFloat(this.el.style.webkitTransform.replace('translate3d(', '').split(',')[0]); + }, + setTranslateX: function(x) { + this.el.style.webkitTransform = 'translate3d(' + x + 'px, 0, 0)'; + } + }); + })(ionic); ; /** @@ -4264,7 +4308,7 @@ ionic.controllers.NavController = ionic.controllers.ViewController.inherit({ self._handleDrag(e); }; - this.content.endDrag = function(e) { + this.content.onEndDrag =function(e) { self._endDrag(e); }; } @@ -4354,12 +4398,12 @@ ionic.controllers.NavController = ionic.controllers.ViewController.inherit({ */ openPercentage: function(percentage) { var p = percentage / 100; - var maxLeft = this.left.width; - var maxRight = this.right.width; - if(percentage >= 0) { - this.openAmount(maxLeft * p); - } else { - this.openAmount(maxRight * p); + + if(this.left && percentage >= 0) { + this.openAmount(this.left.width * p); + } else if(this.right && percentage < 0) { + var maxRight = this.right.width; + this.openAmount(this.right.width * p); } }, @@ -4369,11 +4413,11 @@ ionic.controllers.NavController = ionic.controllers.ViewController.inherit({ * negative value for right menu (only one menu will be visible at a time). */ openAmount: function(amount) { - var maxLeft = this.left.width; - var maxRight = this.right.width; + var maxLeft = this.left && this.left.width || 0; + var maxRight = this.right && this.right.width || 0; // Check if we can move to that side, depending if the left/right panel is enabled - if((!this.left.isEnabled && amount > 0) || (!this.right.isEnabled && amount < 0)) { + if((!(this.left && this.left.isEnabled) && amount > 0) || (!(this.right && this.right.isEnabled) && amount < 0)) { return; } @@ -4388,17 +4432,17 @@ ionic.controllers.NavController = ionic.controllers.ViewController.inherit({ this._rightShowing = false; // Push the z-index of the right menu down - this.right.pushDown(); + this.right && this.right.pushDown(); // Bring the z-index of the left menu up - this.left.bringUp(); + this.left && this.left.bringUp(); } else { this._rightShowing = true; this._leftShowing = false; // Bring the z-index of the right menu up - this.right.bringUp(); + this.right && this.right.bringUp(); // Push the z-index of the left menu down - this.left.pushDown(); + this.left && this.left.pushDown(); } }, diff --git a/js/controllers/sideMenuController.js b/js/controllers/sideMenuController.js index e196d946ac..dd1aff5e15 100644 --- a/js/controllers/sideMenuController.js +++ b/js/controllers/sideMenuController.js @@ -25,7 +25,7 @@ self._handleDrag(e); }; - this.content.endDrag = function(e) { + this.content.onEndDrag =function(e) { self._endDrag(e); }; } @@ -115,12 +115,12 @@ */ openPercentage: function(percentage) { var p = percentage / 100; - var maxLeft = this.left.width; - var maxRight = this.right.width; - if(percentage >= 0) { - this.openAmount(maxLeft * p); - } else { - this.openAmount(maxRight * p); + + if(this.left && percentage >= 0) { + this.openAmount(this.left.width * p); + } else if(this.right && percentage < 0) { + var maxRight = this.right.width; + this.openAmount(this.right.width * p); } }, @@ -130,11 +130,11 @@ * negative value for right menu (only one menu will be visible at a time). */ openAmount: function(amount) { - var maxLeft = this.left.width; - var maxRight = this.right.width; + var maxLeft = this.left && this.left.width || 0; + var maxRight = this.right && this.right.width || 0; // Check if we can move to that side, depending if the left/right panel is enabled - if((!this.left.isEnabled && amount > 0) || (!this.right.isEnabled && amount < 0)) { + if((!(this.left && this.left.isEnabled) && amount > 0) || (!(this.right && this.right.isEnabled) && amount < 0)) { return; } @@ -149,17 +149,17 @@ this._rightShowing = false; // Push the z-index of the right menu down - this.right.pushDown(); + this.right && this.right.pushDown(); // Bring the z-index of the left menu up - this.left.bringUp(); + this.left && this.left.bringUp(); } else { this._rightShowing = true; this._leftShowing = false; // Bring the z-index of the right menu up - this.right.bringUp(); + this.right && this.right.bringUp(); // Push the z-index of the left menu down - this.left.pushDown(); + this.left && this.left.pushDown(); } }, diff --git a/js/ext/angular/src/directive/ionicSideMenu.js b/js/ext/angular/src/directive/ionicSideMenu.js index d596846bcf..07841e7062 100644 --- a/js/ext/angular/src/directive/ionicSideMenu.js +++ b/js/ext/angular/src/directive/ionicSideMenu.js @@ -20,27 +20,18 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture']) angular.extend(this, ionic.controllers.SideMenuController.prototype); ionic.controllers.SideMenuController.call(this, { + // Our quick implementation of the left side menu left: { width: 270, - pushDown: function() { - $scope.leftZIndex = -1; - }, - bringUp: function() { - $scope.leftZIndex = 0; - } }, + + // Our quick implementation of the right side menu right: { width: 270, - pushDown: function() { - $scope.rightZIndex = -1; - }, - bringUp: function() { - $scope.rightZIndex = 0; - } } }); - $scope.contentTranslateX = 0; + $scope.sideMenuContentTranslateX = 0; $scope.sideMenuCtrl = this; }) @@ -72,28 +63,32 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture']) defaultPrevented = e.defaultPrevented; }); - Gesture.on('drag', function(e) { + var dragFn = function(e) { if(defaultPrevented) { return; } sideMenuCtrl._handleDrag(e); - }, $element[0]); + }; - Gesture.on('release', function(e) { + Gesture.on('drag', dragFn, $element[0]); + + var dragReleaseFn = function(e) { if(!defaultPrevented) { sideMenuCtrl._endDrag(e); } defaultPrevented = false; - }, $element[0]); + }; + + Gesture.on('release', dragReleaseFn, $element[0]); sideMenuCtrl.setContent({ onDrag: function(e) {}, endDrag: function(e) {}, getTranslateX: function() { - return $scope.contentTranslateX || 0; + return $scope.sideMenuContentTranslateX || 0; }, setTranslateX: function(amount) { - $scope.contentTranslateX = amount; + $scope.sideMenuContentTranslateX = amount; $element[0].style.webkitTransform = 'translate3d(' + amount + 'px, 0, 0)'; }, enableAnimation: function() { @@ -107,6 +102,12 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture']) $element[0].classList.remove('menu-animated'); } }); + + // Cleanup + $scope.$on('$destroy', function() { + Gesture.off('drag', dragFn); + Gesture.off('release', dragReleaseFn); + }); }; } }; @@ -125,10 +126,23 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture']) return function($scope, $element, $attr, sideMenuCtrl) { $scope.side = $attr.side; + if($scope.side == 'left') { sideMenuCtrl.left.isEnabled = true; + sideMenuCtrl.left.pushDown = function() { + $element[0].style.zIndex = -1; + }; + sideMenuCtrl.left.bringUp = function() { + $element[0].style.zIndex = 0; + }; } else if($scope.side == 'right') { sideMenuCtrl.right.isEnabled = true; + sideMenuCtrl.right.pushDown = function() { + $element[0].style.zIndex = -1; + }; + sideMenuCtrl.right.bringUp = function() { + $element[0].style.zIndex = 0; + }; } $element.append(transclude($scope)); diff --git a/js/ext/angular/test/sideMenu.html b/js/ext/angular/test/sideMenu.html index a4bb9ae2fe..a5cb930f14 100644 --- a/js/ext/angular/test/sideMenu.html +++ b/js/ext/angular/test/sideMenu.html @@ -16,24 +16,37 @@
-
- +
+

Slide me

-

Slide me side to side!

+

Content

-

Left

- +
+

Left

+
+ + +
-

Items

+
+

Right

+
+ + +
@@ -43,6 +56,12 @@ angular.module('sideMenuTest', ['ionic']) .controller('MenuCtrl', function($scope) { + $scope.list = []; + for(var i = 0; i < 20; i++) { + $scope.list.push({ + text: 'Item ' + i + }); + } $scope.openLeft = function() { $scope.sideMenuCtrl.toggleLeft(); }; diff --git a/js/utils/utils.js b/js/utils/utils.js index 6d571eceb9..7ed13215e0 100644 --- a/js/utils/utils.js +++ b/js/utils/utils.js @@ -1,6 +1,15 @@ (function(ionic) { ionic.Utils = { + + // Return a function that will be called with the given context + proxy: function(func, context) { + var args = Array.prototype.slice.call(arguments, 2); + return function() { + return func.apply(context, args.concat(Array.prototype.slice.call(arguments))); + }; + }, + throttle: function(func, wait, options) { var context, args, result; var timeout = null; @@ -80,8 +89,10 @@ } }; + // Bind a few of the most useful functions to the ionic scope ionic.inherit = ionic.Utils.inherit; ionic.extend = ionic.Utils.extend; ionic.throttle = ionic.Utils.throttle; + ionic.proxy = ionic.Utils.proxy; })(window.ionic); diff --git a/js/views/sideMenuView.js b/js/views/sideMenuView.js index 4314ce3fcd..230e89404c 100644 --- a/js/views/sideMenuView.js +++ b/js/views/sideMenuView.js @@ -22,4 +22,37 @@ } }); + ionic.views.SideMenuContent = ionic.views.View.inherit({ + initialize: function(opts) { + var _this = this; + + ionic.extend(this, { + animationClass: 'menu-animated', + onDrag: function(e) {}, + onEndDrag: function(e) {}, + }, opts); + + ionic.onGesture('drag', ionic.proxy(this._onDrag, this), this.el); + ionic.onGesture('release', ionic.proxy(this._onEndDrag, this), this.el); + }, + _onDrag: function(e) { + this.onDrag && this.onDrag(e); + }, + _onEndDrag: function(e) { + this.onEndDrag && this.onEndDrag(e); + }, + disableAnimation: function() { + this.el.classList.remove(this.animationClass); + }, + enableAnimation: function() { + this.el.classList.add(this.animationClass); + }, + getTranslateX: function() { + return parseFloat(this.el.style.webkitTransform.replace('translate3d(', '').split(',')[0]); + }, + setTranslateX: function(x) { + this.el.style.webkitTransform = 'translate3d(' + x + 'px, 0, 0)'; + } + }); + })(ionic); diff --git a/test/side-menus.html b/test/side-menus.html index 1728daeb75..22bcbdcad1 100644 --- a/test/side-menus.html +++ b/test/side-menus.html @@ -4,77 +4,54 @@ Side Menus - - + - + - - + + + From 2ffb925a97c0473598cab9b4e64961d068e61014 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 11 Nov 2013 16:09:46 -0600 Subject: [PATCH 02/11] Add list item type to directive --- dist/js/ionic-angular.js | 28 +++++++++-------------- js/ext/angular/src/directive/ionicList.js | 28 +++++++++-------------- js/ext/angular/test/list.html | 6 +++-- js/ext/angular/test/tabs.html | 4 ++-- test/lists.html | 4 +++- 5 files changed, 31 insertions(+), 39 deletions(-) diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index 5a9635369a..2b3ebcfe71 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -560,10 +560,10 @@ angular.module('ionic.ui.content', []) angular.module('ionic.ui.list', ['ngAnimate']) -.directive('listItem', ['$timeout', function($timeout) { +.directive('item', ['$timeout', function($timeout) { return { restrict: 'E', - require: ['?^list', '?^virtualList'], + require: ['?^list'], replace: true, transclude: true, scope: { @@ -574,8 +574,9 @@ angular.module('ionic.ui.list', ['ngAnimate']) canReorder: '@', canSwipe: '@', buttons: '=', + type: '@' }, - template: '\ + template: '\
\ \
\ @@ -589,20 +590,6 @@ angular.module('ionic.ui.list', ['ngAnimate']) \
', - /* - template: '
  • \ -
    \ - \ -
    \ -
    \ -
    \ -
    \ - \ -
    \ -
    \ - \ -
    \ -
  • ',*/ link: function($scope, $element, $attr, list) { // Grab the parent list controller if(list[0]) { @@ -611,6 +598,13 @@ angular.module('ionic.ui.list', ['ngAnimate']) list = list[1]; } + // Add the list item type class + $element.addClass($attr.type || 'item-slider'); + + if($attr.type !== 'item-slider') { + $scope.canSwipe = false; + } + $scope.isEditing = false; $scope.deleteIcon = list.scope.deleteIcon; $scope.reorderIcon = list.scope.reorderIcon; diff --git a/js/ext/angular/src/directive/ionicList.js b/js/ext/angular/src/directive/ionicList.js index c5fd09d2ec..2dbbf3bbfe 100644 --- a/js/ext/angular/src/directive/ionicList.js +++ b/js/ext/angular/src/directive/ionicList.js @@ -3,10 +3,10 @@ angular.module('ionic.ui.list', ['ngAnimate']) -.directive('listItem', ['$timeout', function($timeout) { +.directive('item', ['$timeout', function($timeout) { return { restrict: 'E', - require: ['?^list', '?^virtualList'], + require: ['?^list'], replace: true, transclude: true, scope: { @@ -17,8 +17,9 @@ angular.module('ionic.ui.list', ['ngAnimate']) canReorder: '@', canSwipe: '@', buttons: '=', + type: '@' }, - template: '\ + template: '\
    \ \
    \ @@ -32,20 +33,6 @@ angular.module('ionic.ui.list', ['ngAnimate']) \
    ', - /* - template: '
  • \ -
    \ - \ -
    \ -
    \ -
    \ -
    \ - \ -
    \ -
    \ - \ -
    \ -
  • ',*/ link: function($scope, $element, $attr, list) { // Grab the parent list controller if(list[0]) { @@ -54,6 +41,13 @@ angular.module('ionic.ui.list', ['ngAnimate']) list = list[1]; } + // Add the list item type class + $element.addClass($attr.type || 'item-slider'); + + if($attr.type !== 'item-slider') { + $scope.canSwipe = false; + } + $scope.isEditing = false; $scope.deleteIcon = list.scope.deleteIcon; $scope.reorderIcon = list.scope.reorderIcon; diff --git a/js/ext/angular/test/list.html b/js/ext/angular/test/list.html index acf6b55c85..4ba5bb714a 100644 --- a/js/ext/angular/test/list.html +++ b/js/ext/angular/test/list.html @@ -67,16 +67,18 @@ - + {{item.text}} - + diff --git a/js/ext/angular/test/tabs.html b/js/ext/angular/test/tabs.html index f7fde31dc3..1e726f0e24 100644 --- a/js/ext/angular/test/tabs.html +++ b/js/ext/angular/test/tabs.html @@ -60,7 +60,7 @@

    Tasks

    - +
    @@ -68,7 +68,7 @@
    -
    -
    +
    @@ -500,6 +500,8 @@ return false; }); + + From 262a4cc9a85562e32b9e9a7719589f17ec171086 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 11 Nov 2013 16:54:01 -0600 Subject: [PATCH 03/11] Fixed #113 - scroll bouncing regardless of window size, fixes pull to refresh --- dist/js/ionic-angular.js | 3 +- dist/js/ionic.js | 4 +-- js/ext/angular/src/directive/ionicList.js | 3 +- js/ext/angular/test/list.html | 42 +++++++---------------- js/views/listView.js | 2 -- js/views/scrollView.js | 2 ++ 6 files changed, 21 insertions(+), 35 deletions(-) diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index 2b3ebcfe71..a93e58d01e 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -641,6 +641,7 @@ angular.module('ionic.ui.list', ['ngAnimate']) isEditing: '=', deleteIcon: '@', reorderIcon: '@', + hasPullToRefresh: '@', onRefresh: '&', onRefreshOpening: '&' }, @@ -663,7 +664,7 @@ angular.module('ionic.ui.list', ['ngAnimate']) var lv = new ionic.views.ListView({ el: $element[0], listEl: $element[0].children[0], - hasPullToRefresh: (typeof $scope.onRefresh !== 'undefined'), + hasPullToRefresh: (typeof $scope.hasPullToRefresh !== 'false'), onRefresh: function() { $scope.onRefresh(); }, diff --git a/dist/js/ionic.js b/dist/js/ionic.js index facf3265eb..fb9933e15e 100644 --- a/dist/js/ionic.js +++ b/dist/js/ionic.js @@ -2411,6 +2411,7 @@ window.ionic = { var parentWidth = this.el.parentNode.offsetWidth; var parentHeight = this.el.parentNode.offsetHeight; + /* var maxX = Math.min(0, (-totalWidth + parentWidth)); var maxY = Math.min(0, (-totalHeight + parentHeight)); @@ -2418,6 +2419,7 @@ window.ionic = { if((this.isHorizontalEnabled && maxX == 0) || (this.isVerticalEnabled && maxY == 0)) { return; } + */ this.x = scrollLeft; this.y = scrollTop; @@ -3176,8 +3178,6 @@ window.ionic = { this._isDragging = false; - console.log(e.gesture.direction); - // Check if this is a reorder drag if(ionic.DomUtil.getParentOrSelfWithClass(e.target, ITEM_DRAG_CLASS) && (e.gesture.direction == 'up' || e.gesture.direction == 'down')) { var item = this._getItem(e.target); diff --git a/js/ext/angular/src/directive/ionicList.js b/js/ext/angular/src/directive/ionicList.js index 2dbbf3bbfe..026597a62c 100644 --- a/js/ext/angular/src/directive/ionicList.js +++ b/js/ext/angular/src/directive/ionicList.js @@ -84,6 +84,7 @@ angular.module('ionic.ui.list', ['ngAnimate']) isEditing: '=', deleteIcon: '@', reorderIcon: '@', + hasPullToRefresh: '@', onRefresh: '&', onRefreshOpening: '&' }, @@ -106,7 +107,7 @@ angular.module('ionic.ui.list', ['ngAnimate']) var lv = new ionic.views.ListView({ el: $element[0], listEl: $element[0].children[0], - hasPullToRefresh: (typeof $scope.onRefresh !== 'undefined'), + hasPullToRefresh: (typeof $scope.hasPullToRefresh !== 'false'), onRefresh: function() { $scope.onRefresh(); }, diff --git a/js/ext/angular/test/list.html b/js/ext/angular/test/list.html index 4ba5bb714a..915f46cf13 100644 --- a/js/ext/angular/test/list.html +++ b/js/ext/angular/test/list.html @@ -64,9 +64,19 @@
    - - - + + + +
    + +
    +
    angular.module('navTest', ['ionic.ui.list', 'ionic.ui.content', 'ngAnimate']) - .directive('spinner', function() { - return { - restrict: 'E', - replace: true, - scope: { - ratio: '=' - }, - template: '
    ', - link: function($scope, $element, $attr) { - $scope.$watch('ratio', function(value) { - if(value > 0.97) { - value = 1; - } - - var a = (value * 360) % 360; - var r = (a * Math.PI) / 180; - var x = (Math.sin(r) * 20) + 14; - var y = (Math.cos(r) * -20) + 14; - - $element[0].firstElementChild.style.webkitTransform = 'translate3d(' + x + 'px, ' + y + 'px, 0)'; - //$element[0].firstElementChild.setAttribute('d', anim); - }); - } - } - }) - .controller('TestCtrl', function($scope) { $scope.refreshRatio = { ratio: 0 }; var removeItem = function(item) { diff --git a/js/views/listView.js b/js/views/listView.js index 6e0ea87ecc..8d8986f765 100644 --- a/js/views/listView.js +++ b/js/views/listView.js @@ -376,8 +376,6 @@ this._isDragging = false; - console.log(e.gesture.direction); - // Check if this is a reorder drag if(ionic.DomUtil.getParentOrSelfWithClass(e.target, ITEM_DRAG_CLASS) && (e.gesture.direction == 'up' || e.gesture.direction == 'down')) { var item = this._getItem(e.target); diff --git a/js/views/scrollView.js b/js/views/scrollView.js index e23d38bdc4..f1c51d9030 100644 --- a/js/views/scrollView.js +++ b/js/views/scrollView.js @@ -463,6 +463,7 @@ var parentWidth = this.el.parentNode.offsetWidth; var parentHeight = this.el.parentNode.offsetHeight; + /* var maxX = Math.min(0, (-totalWidth + parentWidth)); var maxY = Math.min(0, (-totalHeight + parentHeight)); @@ -470,6 +471,7 @@ if((this.isHorizontalEnabled && maxX == 0) || (this.isVerticalEnabled && maxY == 0)) { return; } + */ this.x = scrollLeft; this.y = scrollTop; From 53862a434caf11ce95b315db6584d3541e0c421b Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 11 Nov 2013 16:54:36 -0600 Subject: [PATCH 04/11] My bad --- dist/js/ionic-angular.js | 2 +- js/ext/angular/src/directive/ionicList.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index a93e58d01e..7a91d5837b 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -664,7 +664,7 @@ angular.module('ionic.ui.list', ['ngAnimate']) var lv = new ionic.views.ListView({ el: $element[0], listEl: $element[0].children[0], - hasPullToRefresh: (typeof $scope.hasPullToRefresh !== 'false'), + hasPullToRefresh: ($scope.hasPullToRefresh !== 'false'), onRefresh: function() { $scope.onRefresh(); }, diff --git a/js/ext/angular/src/directive/ionicList.js b/js/ext/angular/src/directive/ionicList.js index 026597a62c..d8ea69d64a 100644 --- a/js/ext/angular/src/directive/ionicList.js +++ b/js/ext/angular/src/directive/ionicList.js @@ -107,7 +107,7 @@ angular.module('ionic.ui.list', ['ngAnimate']) var lv = new ionic.views.ListView({ el: $element[0], listEl: $element[0].children[0], - hasPullToRefresh: (typeof $scope.hasPullToRefresh !== 'false'), + hasPullToRefresh: ($scope.hasPullToRefresh !== 'false'), onRefresh: function() { $scope.onRefresh(); }, From fa315677c6c46067950c9f7654dbe07996098b33 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 11 Nov 2013 17:37:32 -0600 Subject: [PATCH 05/11] Working on custom refresher --- dist/css/ionic.css | 16 +++++++++++++ dist/js/ionic-angular.js | 24 ++++++++++++++++++-- js/ext/angular/src/directive/ionicContent.js | 22 ++++++++++++++++-- js/ext/angular/src/directive/ionicList.js | 2 ++ scss/_scaffolding.scss | 17 ++++++++++++++ 5 files changed, 77 insertions(+), 4 deletions(-) diff --git a/dist/css/ionic.css b/dist/css/ionic.css index b8d816ee7b..0dff314fd5 100644 --- a/dist/css/ionic.css +++ b/dist/css/ionic.css @@ -2327,6 +2327,22 @@ body, .ionic-body { text-align: center; position: relative; } +.ionic-refresher-content { + height: 100%; + width: 100%; + text-align: center; + position: relative; } + +.ionic-refresher { + width: 10px; + height: 10px; + border-radius: 50%; + background-color: #4a87ee; + position: absolute; + left: 50%; + margin-left: -5px; + bottom: 15px; } + .scroll-refreshing { -webkit-transition: height 0.1s ease-in-out; } diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index 7a91d5837b..0c30d7a4aa 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -548,11 +548,29 @@ angular.module('ionic.ui.content', []) return { restrict: 'E', replace: true, - transclude: true, - template: '
    ' + require: ['^?content', '^?list'], + template: '
    ', + scope: true, + link: function($scope, $element, $attr, scrollCtrl) { + $scope.$on('onRefresh', function() { + }); + $scope.$on('onRefreshOpening', function(amt) { + console.log('On refresh opening', amt); + }); + } } }) +.directive('scroll-refresher', function() { + return { + restrict: 'E', + replace: true, + transclude: true, + template: '
    ' + } +}); + + })(); ; (function() { @@ -667,9 +685,11 @@ angular.module('ionic.ui.list', ['ngAnimate']) hasPullToRefresh: ($scope.hasPullToRefresh !== 'false'), onRefresh: function() { $scope.onRefresh(); + $scope.$broadcast('onRefresh'); }, onRefreshOpening: function(amt) { $scope.onRefreshOpening({amount: amt}); + $scope.$broadcast('onRefreshOpening', amt); } }); diff --git a/js/ext/angular/src/directive/ionicContent.js b/js/ext/angular/src/directive/ionicContent.js index c15d895daf..0d988b4cd0 100644 --- a/js/ext/angular/src/directive/ionicContent.js +++ b/js/ext/angular/src/directive/ionicContent.js @@ -76,9 +76,27 @@ angular.module('ionic.ui.content', []) return { restrict: 'E', replace: true, - transclude: true, - template: '
    ' + require: ['^?content', '^?list'], + template: '
    ', + scope: true, + link: function($scope, $element, $attr, scrollCtrl) { + $scope.$on('onRefresh', function() { + }); + $scope.$on('onRefreshOpening', function(amt) { + console.log('On refresh opening', amt); + }); + } } }) +.directive('scroll-refresher', function() { + return { + restrict: 'E', + replace: true, + transclude: true, + template: '
    ' + } +}); + + })(); diff --git a/js/ext/angular/src/directive/ionicList.js b/js/ext/angular/src/directive/ionicList.js index d8ea69d64a..57eed15e3e 100644 --- a/js/ext/angular/src/directive/ionicList.js +++ b/js/ext/angular/src/directive/ionicList.js @@ -110,9 +110,11 @@ angular.module('ionic.ui.list', ['ngAnimate']) hasPullToRefresh: ($scope.hasPullToRefresh !== 'false'), onRefresh: function() { $scope.onRefresh(); + $scope.$broadcast('onRefresh'); }, onRefreshOpening: function(amt) { $scope.onRefreshOpening({amount: amt}); + $scope.$broadcast('onRefreshOpening', amt); } }); diff --git a/scss/_scaffolding.scss b/scss/_scaffolding.scss index 496d24da60..2b52c14702 100644 --- a/scss/_scaffolding.scss +++ b/scss/_scaffolding.scss @@ -122,6 +122,23 @@ body, .ionic-body { //@include display-flex(); //@include align-items(center); } +.ionic-refresher-content { + height: 100%; + width: 100%; + text-align: center; + position: relative; +} +.ionic-refresher { + // A custom refresher + width: 10px; + height: 10px; + border-radius: 50%; + background-color: $brand-primary; + position: absolute; + left: 50%; + margin-left: -5px; + bottom: 15px; +} .scroll-refreshing { -webkit-transition: height 0.1s ease-in-out; } From e0b5cd26afc37067f28357ece7a5751e97f82cc3 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 11 Nov 2013 19:05:43 -0600 Subject: [PATCH 06/11] Make awesome shit --- js/_license.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/_license.js b/js/_license.js index bac744f1fb..6e4dc6a37b 100644 --- a/js/_license.js +++ b/js/_license.js @@ -8,4 +8,6 @@ http://ionicframework.com/ By @maxlynch, @helloimben, @adamdbradley <3 Licensed under the MIT license. Please see LICENSE for more information. + +Make awesome shit. */ From d8163fdd06d318e43ef9d4e98a7884f1dec507dc Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 11 Nov 2013 20:06:58 -0600 Subject: [PATCH 07/11] Pull to refresh default style Needs optimizing though --- dist/css/ionic.css | 33 ++++++++++++++------ dist/css/themes/ionic-ios7.css | 5 ++- dist/js/ionic-angular.js | 20 +++++++++--- dist/js/ionic.js | 2 ++ js/ext/angular/src/directive/ionicContent.js | 16 ++++++++-- js/ext/angular/src/directive/ionicList.js | 4 +-- scss/_scaffolding.scss | 13 +++++++- 7 files changed, 69 insertions(+), 24 deletions(-) diff --git a/dist/css/ionic.css b/dist/css/ionic.css index 0dff314fd5..9ec0a586a5 100644 --- a/dist/css/ionic.css +++ b/dist/css/ionic.css @@ -49,7 +49,7 @@ .white { color: white; } -/* +/*! Ionicons, v1.3.3 Created by Ben Sperry for the Ionic Framework, http://ionicons.com/ https://twitter.com/helloimben https://twitter.com/ionicframework @@ -2091,7 +2091,7 @@ sub { fieldset { margin: 0 2px; padding: 0.35em 0.625em 0.75em; - border: 1px solid silver; } + border: 1px solid #c0c0c0; } /** * 1. Correct `color` not being inherited in IE 8/9. @@ -2341,10 +2341,23 @@ body, .ionic-body { position: absolute; left: 50%; margin-left: -5px; - bottom: 15px; } + bottom: 25px; } .scroll-refreshing { -webkit-transition: height 0.1s ease-in-out; } + .scroll-refreshing .ionic-refresher { + -webkit-animation: refresher-pulsate 1.5s linear; + -webkit-animation-iteration-count: infinite; } + +@-webkit-keyframes refresher-pulsate { + 0% { + -webkit-transform: scale(2, 2); } + + 50% { + -webkit-transform: scale(1.5, 1.5); } + + 100% { + -webkit-transform: scale(2, 2); } } .overflow-scroll { overflow: auto; @@ -2499,13 +2512,13 @@ address { font-style: normal; line-height: 1.42857; } -a.subdued‎ { +a.subduedΓÇÄ { padding-right: 10px; color: #555555; text-decoration: none; } - a.subdued‎:hover { + a.subduedΓÇÄ:hover { text-decoration: none; } - a.subdued‎:last-child { + a.subduedΓÇÄ:last-child { padding-right: 0; } /** @@ -3990,7 +4003,7 @@ input[type="file"] { line-height: 34px; } select { - border: 1px solid #cccccc; + border: 1px solid #ccc; background-color: white; } select[multiple], @@ -4049,7 +4062,7 @@ input[type="checkbox"][readonly] { border-radius: 50%; background: white; content: ' '; - transition: background-color 0.1s ease-in-out; } + transition: background-color .1s ease-in-out; } /* the checkmark within the box */ .checkbox input:after { @@ -4064,7 +4077,7 @@ input[type="checkbox"][readonly] { border-right: 0; content: ' '; opacity: 0; - transition: opacity 0.05s ease-in-out; + transition: opacity .05s ease-in-out; -webkit-transform: rotate(-45deg); transform: rotate(-45deg); } @@ -4493,7 +4506,7 @@ input[type="range"] { .button-icon:active, .button-icon.active { background: none; box-shadow: none; - text-shadow: 0px 0px 10px white; } + text-shadow: 0px 0px 10px #fff; } .padding > .button.block:first-child { margin-top: 0; } diff --git a/dist/css/themes/ionic-ios7.css b/dist/css/themes/ionic-ios7.css index e027d9919a..e119d59757 100644 --- a/dist/css/themes/ionic-ios7.css +++ b/dist/css/themes/ionic-ios7.css @@ -1,4 +1,3 @@ -@charset "UTF-8"; /** * Mixins * -------------------------------------------------- @@ -124,7 +123,7 @@ right: 20px; transition: 0.2s ease; transition-property: left, right; - transition-delay: 0s, 0.05s; } + transition-delay: 0s, .05s; } .toggle :checked + .track { /* When the toggle is "on" */ @@ -139,4 +138,4 @@ right: 0; left: 20px; -webkit-transform: none; - transition-delay: 0.05s, 0s; } + transition-delay: .05s, 0s; } diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index 0c30d7a4aa..61a93d3aaf 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -552,11 +552,21 @@ angular.module('ionic.ui.content', []) template: '
    ', scope: true, link: function($scope, $element, $attr, scrollCtrl) { - $scope.$on('onRefresh', function() { + var icon = $element[0].querySelector('.ionic-refresher'); + + // Scale up the refreshing icon + var onRefreshOpening = ionic.throttle(function(e, amt) { + icon.style[ionic.CSS.TRANSFORM] = 'scale(' + Math.min((1 + amt), 2) + ')'; + }, 100); + + $scope.$on('onRefreshing', function(e) { + icon.style[ionic.CSS.TRANSFORM] = 'scale(2)'; }); - $scope.$on('onRefreshOpening', function(amt) { - console.log('On refresh opening', amt); + + $scope.$on('onRefresh', function(e) { + icon.style[ionic.CSS.TRANSFORM] = 'scale(1)'; }); + $scope.$on('onRefreshOpening', onRefreshOpening); } } }) @@ -685,11 +695,11 @@ angular.module('ionic.ui.list', ['ngAnimate']) hasPullToRefresh: ($scope.hasPullToRefresh !== 'false'), onRefresh: function() { $scope.onRefresh(); - $scope.$broadcast('onRefresh'); + $scope.$parent.$broadcast('onRefresh'); }, onRefreshOpening: function(amt) { $scope.onRefreshOpening({amount: amt}); - $scope.$broadcast('onRefreshOpening', amt); + $scope.$parent.$broadcast('onRefreshOpening', amt); } }); diff --git a/dist/js/ionic.js b/dist/js/ionic.js index fb9933e15e..3eb612815c 100644 --- a/dist/js/ionic.js +++ b/dist/js/ionic.js @@ -8,6 +8,8 @@ http://ionicframework.com/ By @maxlynch, @helloimben, @adamdbradley <3 Licensed under the MIT license. Please see LICENSE for more information. + +Make awesome shit. */ ; diff --git a/js/ext/angular/src/directive/ionicContent.js b/js/ext/angular/src/directive/ionicContent.js index 0d988b4cd0..97d9796083 100644 --- a/js/ext/angular/src/directive/ionicContent.js +++ b/js/ext/angular/src/directive/ionicContent.js @@ -80,11 +80,21 @@ angular.module('ionic.ui.content', []) template: '
    ', scope: true, link: function($scope, $element, $attr, scrollCtrl) { - $scope.$on('onRefresh', function() { + var icon = $element[0].querySelector('.ionic-refresher'); + + // Scale up the refreshing icon + var onRefreshOpening = ionic.throttle(function(e, amt) { + icon.style[ionic.CSS.TRANSFORM] = 'scale(' + Math.min((1 + amt), 2) + ')'; + }, 100); + + $scope.$on('onRefreshing', function(e) { + icon.style[ionic.CSS.TRANSFORM] = 'scale(2)'; }); - $scope.$on('onRefreshOpening', function(amt) { - console.log('On refresh opening', amt); + + $scope.$on('onRefresh', function(e) { + icon.style[ionic.CSS.TRANSFORM] = 'scale(1)'; }); + $scope.$on('onRefreshOpening', onRefreshOpening); } } }) diff --git a/js/ext/angular/src/directive/ionicList.js b/js/ext/angular/src/directive/ionicList.js index 57eed15e3e..64e84b8080 100644 --- a/js/ext/angular/src/directive/ionicList.js +++ b/js/ext/angular/src/directive/ionicList.js @@ -110,11 +110,11 @@ angular.module('ionic.ui.list', ['ngAnimate']) hasPullToRefresh: ($scope.hasPullToRefresh !== 'false'), onRefresh: function() { $scope.onRefresh(); - $scope.$broadcast('onRefresh'); + $scope.$parent.$broadcast('onRefresh'); }, onRefreshOpening: function(amt) { $scope.onRefreshOpening({amount: amt}); - $scope.$broadcast('onRefreshOpening', amt); + $scope.$parent.$broadcast('onRefreshOpening', amt); } }); diff --git a/scss/_scaffolding.scss b/scss/_scaffolding.scss index 2b52c14702..b00a6cf23d 100644 --- a/scss/_scaffolding.scss +++ b/scss/_scaffolding.scss @@ -137,10 +137,21 @@ body, .ionic-body { position: absolute; left: 50%; margin-left: -5px; - bottom: 15px; + bottom: 25px; } .scroll-refreshing { -webkit-transition: height 0.1s ease-in-out; + + .ionic-refresher { + -webkit-animation: refresher-pulsate 1.5s linear; + -webkit-animation-iteration-count: infinite; + } +} + +@-webkit-keyframes refresher-pulsate { + 0% {-webkit-transform: scale(2, 2); } + 50% {-webkit-transform: scale(1.5, 1.5); } + 100% {-webkit-transform: scale(2, 2); } } .overflow-scroll { From 58dc717ab97e940f2b354b60c7250f94ad8e6f24 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 11 Nov 2013 20:34:58 -0600 Subject: [PATCH 08/11] Reduced drag banding resistance --- dist/js/ionic-angular.js | 2 +- dist/js/ionic.js | 2 +- js/ext/angular/src/directive/ionicNav.js | 2 +- js/ext/angular/test/nav.html | 14 ++++++++------ js/views/scrollView.js | 2 +- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index 61a93d3aaf..c6b5bf0b1b 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -797,7 +797,7 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges // Compile the template with the new scrope, and append it to the navigation's content area var el = $compile(templateString)(childScope, function(cloned, scope) { - var content = angular.element($element[0].querySelector('.content')); + var content = angular.element($element[0].querySelector('.content, .scroll')); //content.append(cloned); //angular.element(content).append(cloned); diff --git a/dist/js/ionic.js b/dist/js/ionic.js index 3eb612815c..13271d85df 100644 --- a/dist/js/ionic.js +++ b/dist/js/ionic.js @@ -1990,7 +1990,7 @@ window.ionic = { dragThreshold: 10, // Resistance when scrolling too far up or down - rubberBandResistance: 3, + rubberBandResistance: 2, // Scroll event names. These are custom so can be configured scrollEventName: 'momentumScrolled', diff --git a/js/ext/angular/src/directive/ionicNav.js b/js/ext/angular/src/directive/ionicNav.js index 128ff4cbba..84f284b4b4 100644 --- a/js/ext/angular/src/directive/ionicNav.js +++ b/js/ext/angular/src/directive/ionicNav.js @@ -57,7 +57,7 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges // Compile the template with the new scrope, and append it to the navigation's content area var el = $compile(templateString)(childScope, function(cloned, scope) { - var content = angular.element($element[0].querySelector('.content')); + var content = angular.element($element[0].querySelector('.content, .scroll')); //content.append(cloned); //angular.element(content).append(cloned); diff --git a/js/ext/angular/test/nav.html b/js/ext/angular/test/nav.html index 23a933f219..4fe1fef4f3 100644 --- a/js/ext/angular/test/nav.html +++ b/js/ext/angular/test/nav.html @@ -7,9 +7,9 @@ - - - + + +