From 6e8fcb0daf149d627c62df674c3d770e58cd0d1d Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 16 Oct 2013 10:26:10 -0500 Subject: [PATCH 1/3] Working dynamic slide box --- dist/css/ionic.css | 6 ++-- dist/js/ionic.js | 73 +++++++++++++++++++++++++++++++++++++++ js/views/slideBox.js | 73 +++++++++++++++++++++++++++++++++++++++ scss/ionic/_slideBox.scss | 5 ++- test/slideBox.html | 26 ++++++++------ 5 files changed, 166 insertions(+), 17 deletions(-) diff --git a/dist/css/ionic.css b/dist/css/ionic.css index 279e1839ff..a76de70d7f 100644 --- a/dist/css/ionic.css +++ b/dist/css/ionic.css @@ -3034,12 +3034,12 @@ a.button { .slide-box-animating { -webkit-transition-duration: 0.2s; } -.slide { +.slide-box-slide { display: inline-block; vertical-align: top; width: 100%; height: 100%; } - .slide img { + .slide-box-slide img { width: 100%; } .slide-box-pager { @@ -3052,7 +3052,7 @@ a.button { text-decoration: none; margin: 0px 5px; color: #fff; - opacity: 0.5; } + opacity: 0.3; } .slide-box-pager > *.active { -webkit-transition: opacity 0.4s ease-in; opacity: 1; } diff --git a/dist/js/ionic.js b/dist/js/ionic.js index f237e14b2d..13326d6202 100644 --- a/dist/js/ionic.js +++ b/dist/js/ionic.js @@ -2311,6 +2311,51 @@ window.ionic = { }, prependSlide: function(el) { + var content = this.el.firstElementChild; + if(!content) { return; } + + var slideWidth = content.offsetWidth; + var offsetX = parseFloat(content.style.webkitTransform.replace('translate3d(', '').split(',')[0]) || 0; + var newOffsetX = Math.min(0, offsetX - slideWidth); + + content.insertBefore(el, content.firstChild); + + content.classList.remove('slide-box-animating'); + content.style.webkitTransform = 'translate3d(' + newOffsetX + 'px, 0, 0)'; + + this._prependPagerIcon(); + this.slideIndex = (this.slideIndex + 1) % content.children.length; + this._updatePager(); + }, + + appendSlide: function(el) { + var content = this.el.firstElementChild; + if(!content) { return; } + + content.classList.remove('slide-box-animating'); + content.appendChild(el); + + this._appendPagerIcon(); + this._updatePager(); + }, + + removeSlide: function(index) { + var content = this.el.firstElementChild; + if(!content) { return; } + + var items = this.el.firstElementChild; + items.removeChild(items.firstElementChild); + + var slideWidth = content.offsetWidth; + var offsetX = parseFloat(content.style.webkitTransform.replace('translate3d(', '').split(',')[0]) || 0; + var newOffsetX = Math.min(0, offsetX + slideWidth); + + content.classList.remove('slide-box-animating'); + content.style.webkitTransform = 'translate3d(' + newOffsetX + 'px, 0, 0)'; + + this._removePagerIcon(); + this.slideIndex = Math.max(0, (this.slideIndex - 1) % content.children.length); + this._updatePager(); }, /** @@ -2359,6 +2404,26 @@ window.ionic = { return this.slideIndex; }, + _appendPagerIcon: function() { + if(!this.pager || !this.pager.children.length) { return; } + + var newPagerChild = this.pager.children[0].cloneNode(); + this.pager.appendChild(newPagerChild); + }, + + _prependPagerIcon: function() { + if(!this.pager || !this.pager.children.length) { return; } + + var newPagerChild = this.pager.children[0].cloneNode(); + this.pager.insertBefore(newPagerChild, this.pager.firstChild); + }, + + _removePagerIcon: function() { + if(!this.pager || !this.pager.children.length) { return; } + + this.pager.removeChild(this.pager.firstElementChild); + }, + /** * If we have a pager, update the active page when the current slide * changes. @@ -2367,6 +2432,14 @@ window.ionic = { if(!this.pager) { return; } + + var numPagerChildren = this.pager.children.length; + if(!numPagerChildren) { + // No children to update + return; + } + + // Update the active state of the pager icons for(var i = 0, j = this.pager.children.length; i < j; i++) { if(i == this.slideIndex) { this.pager.children[i].classList.add('active'); diff --git a/js/views/slideBox.js b/js/views/slideBox.js index 34a494e0de..2c8dea0d18 100644 --- a/js/views/slideBox.js +++ b/js/views/slideBox.js @@ -45,6 +45,51 @@ }, prependSlide: function(el) { + var content = this.el.firstElementChild; + if(!content) { return; } + + var slideWidth = content.offsetWidth; + var offsetX = parseFloat(content.style.webkitTransform.replace('translate3d(', '').split(',')[0]) || 0; + var newOffsetX = Math.min(0, offsetX - slideWidth); + + content.insertBefore(el, content.firstChild); + + content.classList.remove('slide-box-animating'); + content.style.webkitTransform = 'translate3d(' + newOffsetX + 'px, 0, 0)'; + + this._prependPagerIcon(); + this.slideIndex = (this.slideIndex + 1) % content.children.length; + this._updatePager(); + }, + + appendSlide: function(el) { + var content = this.el.firstElementChild; + if(!content) { return; } + + content.classList.remove('slide-box-animating'); + content.appendChild(el); + + this._appendPagerIcon(); + this._updatePager(); + }, + + removeSlide: function(index) { + var content = this.el.firstElementChild; + if(!content) { return; } + + var items = this.el.firstElementChild; + items.removeChild(items.firstElementChild); + + var slideWidth = content.offsetWidth; + var offsetX = parseFloat(content.style.webkitTransform.replace('translate3d(', '').split(',')[0]) || 0; + var newOffsetX = Math.min(0, offsetX + slideWidth); + + content.classList.remove('slide-box-animating'); + content.style.webkitTransform = 'translate3d(' + newOffsetX + 'px, 0, 0)'; + + this._removePagerIcon(); + this.slideIndex = Math.max(0, (this.slideIndex - 1) % content.children.length); + this._updatePager(); }, /** @@ -93,6 +138,26 @@ return this.slideIndex; }, + _appendPagerIcon: function() { + if(!this.pager || !this.pager.children.length) { return; } + + var newPagerChild = this.pager.children[0].cloneNode(); + this.pager.appendChild(newPagerChild); + }, + + _prependPagerIcon: function() { + if(!this.pager || !this.pager.children.length) { return; } + + var newPagerChild = this.pager.children[0].cloneNode(); + this.pager.insertBefore(newPagerChild, this.pager.firstChild); + }, + + _removePagerIcon: function() { + if(!this.pager || !this.pager.children.length) { return; } + + this.pager.removeChild(this.pager.firstElementChild); + }, + /** * If we have a pager, update the active page when the current slide * changes. @@ -101,6 +166,14 @@ if(!this.pager) { return; } + + var numPagerChildren = this.pager.children.length; + if(!numPagerChildren) { + // No children to update + return; + } + + // Update the active state of the pager icons for(var i = 0, j = this.pager.children.length; i < j; i++) { if(i == this.slideIndex) { this.pager.children[i].classList.add('active'); diff --git a/scss/ionic/_slideBox.scss b/scss/ionic/_slideBox.scss index 2b8413cd4e..e0ad0667e9 100644 --- a/scss/ionic/_slideBox.scss +++ b/scss/ionic/_slideBox.scss @@ -15,7 +15,7 @@ .slide-box-animating { -webkit-transition-duration: 0.2s; } -.slide { +.slide-box-slide { display: inline-block; vertical-align: top; width: 100%; @@ -38,8 +38,7 @@ margin: 0px 5px; color: #fff; - opacity: 0.5; - + opacity: 0.3; &.active { -webkit-transition: opacity 0.4s ease-in; diff --git a/test/slideBox.html b/test/slideBox.html index 003bd7faa8..30b8870b98 100644 --- a/test/slideBox.html +++ b/test/slideBox.html @@ -22,24 +22,25 @@
- - + + +
-
+
-
+
-
+
- 1 - 2 - 3 + + +
@@ -56,7 +57,7 @@ }); document.getElementById('prepend').addEventListener('click', function(e) { var content = document.createElement('div'); - content.className = 'slide-box-content'; + content.className = 'slide-box-slide'; content.innerHTML = '';//http://1.bp.blogspot.com/_6bMuhb3yWOA/TSiS2nYfQoI/AAAAAAAAAGA/AXOlDxrmMNQ/s1600/cow.jpg">'; @@ -78,9 +79,8 @@ }); document.getElementById('append').addEventListener('click', function(e) { var content = document.createElement('div'); - content.className = 'slide-box-content'; + content.className = 'slide-box-slide'; content.innerHTML = '';//http://1.bp.blogspot.com/_6bMuhb3yWOA/TSiS2nYfQoI/AAAAAAAAAGA/AXOlDxrmMNQ/s1600/cow.jpg">'; - var items = b.querySelector('.slide-box-items'); box.appendSlide(content); @@ -92,6 +92,10 @@ */ }); + document.getElementById('remove').addEventListener('click', function(e) { + var items = b.querySelector('.slide-box-slides'); + box.removeSlide(0); + }); /* */ From 3ae53811a6ce45fcd0bc84d56bdcf5337aa996bd Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 16 Oct 2013 11:22:01 -0500 Subject: [PATCH 2/3] Basic pull to refresh shell --- dist/css/ionic-scoped.css | 7 ++++ dist/css/ionic.css | 8 ++++ dist/js/ionic.js | 78 +++++++++++++++++++++++++++++++++-- js/ext/angular/test/list.html | 9 +++- js/views/listView.js | 78 +++++++++++++++++++++++++++++++++-- scss/ionic/_listview.scss | 11 +++++ test/slideBox.html | 2 +- 7 files changed, 185 insertions(+), 8 deletions(-) diff --git a/dist/css/ionic-scoped.css b/dist/css/ionic-scoped.css index 1d80df1e43..ca50bd8c54 100644 --- a/dist/css/ionic-scoped.css +++ b/dist/css/ionic-scoped.css @@ -171,6 +171,9 @@ /** * A list divider. */ + /** + * List refreser elements + */ /* the overall container of the toggle */ /* hide the actual checkbox */ /* the background of the toggle's track area */ @@ -1856,6 +1859,10 @@ .ionic .list-item-text { margin-bottom: 0; line-height: 1.3; } + .ionic .list-refresher { + background-color: red; + height: 0; + overflow: hidden; } .ionic form { margin: 0 0 1.42857; } .ionic legend { diff --git a/dist/css/ionic.css b/dist/css/ionic.css index a76de70d7f..ff698604d4 100644 --- a/dist/css/ionic.css +++ b/dist/css/ionic.css @@ -2291,6 +2291,14 @@ a.list-item { margin-bottom: 0; line-height: 1.3; } +/** + * List refreser elements + */ +.list-refresher { + background-color: red; + height: 0; + overflow: hidden; } + form { margin: 0 0 1.42857; } diff --git a/dist/js/ionic.js b/dist/js/ionic.js index 13326d6202..b4787e0658 100644 --- a/dist/js/ionic.js +++ b/dist/js/ionic.js @@ -1852,6 +1852,65 @@ window.ionic = { } }; + var PullToRefreshDrag = function(opts) { + this.dragThresholdY = opts.dragThresholdY || 10; + this.el = opts.el; + }; + PullToRefreshDrag.prototype = new DragOp(); + PullToRefreshDrag.prototype.start = function(e) { + var content, refresher; + + content = ionic.DomUtil.getParentOrSelfWithClass(e.target, 'list'); + if(!content) { return; } + + // Grab the refresher element that will show as you drag down + refresher = content.querySelector('.list-refresher'); + if(!refresher) { + refresher = this._injectRefresher(); + } + + this._currentDrag = { + refresher: refresher, + content: content + }; + }; + PullToRefreshDrag.prototype._injectRefresher = function() { + var refresher = document.createElement('div'); + refresher.className = 'list-refresher'; + this.el.insertBefore(refresher, this.el.firstChild); + return refresher; + }; + PullToRefreshDrag.prototype.drag = function(e) { + var _this = this; + + window.requestAnimationFrame(function() { + // We really aren't dragging + if(!_this._currentDrag) { + return; + } + + // Check if we should start dragging. Check if we've dragged past the threshold, + // or we are starting from the open state. + if(!_this._isDragging && Math.abs(e.gesture.deltaY) > _this.dragThresholdY) { + _this._isDragging = true; + } + + if(_this._isDragging) { + var currentHeight = parseFloat(_this._currentDrag.refresher.style.height); + _this._currentDrag.refresher.style.height = e.gesture.deltaY + 'px'; + + var newHeight = parseFloat(_this._currentDrag.refresher.style.height = e.gesture.deltaY); + var firstChildHeight = parseFloat(_this._currentDrag.refresher.firstElementChild.style.height); + console.log('New Height must pass', firstChildHeight); + if(newHeight > firstChildHeight) { + console.log('PASSED', firstChildHeight); + } + } + }); + }; + PullToRefreshDrag.prototype.end = function(e) { + }; + var SlideDrag = function(opts) { this.dragThresholdX = opts.dragThresholdX || 10; this.el = opts.el; @@ -2078,6 +2137,8 @@ window.ionic = { doneCallback && doneCallback(); }; + + /** * The ListView handles a list of items. It will process drag animations, edit mode, * and other operations that are common on mobile lists or table views. @@ -2103,10 +2164,12 @@ window.ionic = { }; ionic.views.List.prototype = { + _initDrag: function() { this._isDragging = false; this._dragOp = null; }, + // Return the list item from the given target _getItem: function(target) { while(target) { @@ -2117,6 +2180,8 @@ window.ionic = { } return null; }, + + _startDrag: function(e) { this._isDragging = false; @@ -2128,16 +2193,22 @@ window.ionic = { this._dragOp = new ReorderDrag({ el: item }); this._dragOp.start(e); } - return; - } + } + // Check if this is a "pull down" drag for pull to refresh + else if(e.gesture.direction == 'down') { + this._dragOp = new PullToRefreshDrag({ el: this.el }); + this._dragOp.start(e); + } + // Or check if this is a swipe to the side drag - if(e.gesture.direction == 'left' || e.gesture.direction == 'right') { + else if(e.gesture.direction == 'left' || e.gesture.direction == 'right') { this._dragOp = new SlideDrag({ el: this.el }); this._dragOp.start(e); } }, + _handleEndDrag: function(e) { var _this = this; @@ -2150,6 +2221,7 @@ window.ionic = { _this._initDrag(); }); }, + /** * Process the drag event to move the item to the left or right. */ diff --git a/js/ext/angular/test/list.html b/js/ext/angular/test/list.html index 1ae68c13aa..81569fdf7f 100644 --- a/js/ext/angular/test/list.html +++ b/js/ext/angular/test/list.html @@ -49,7 +49,10 @@ - + +
+
REFRESHING
+
_this.dragThresholdY) { + _this._isDragging = true; + } + + if(_this._isDragging) { + var currentHeight = parseFloat(_this._currentDrag.refresher.style.height); + _this._currentDrag.refresher.style.height = e.gesture.deltaY + 'px'; + + var newHeight = parseFloat(_this._currentDrag.refresher.style.height = e.gesture.deltaY); + var firstChildHeight = parseFloat(_this._currentDrag.refresher.firstElementChild.style.height); + console.log('New Height must pass', firstChildHeight); + if(newHeight > firstChildHeight) { + console.log('PASSED', firstChildHeight); + } + } + }); + }; + PullToRefreshDrag.prototype.end = function(e) { + }; + var SlideDrag = function(opts) { this.dragThresholdX = opts.dragThresholdX || 10; this.el = opts.el; @@ -236,6 +295,8 @@ doneCallback && doneCallback(); }; + + /** * The ListView handles a list of items. It will process drag animations, edit mode, * and other operations that are common on mobile lists or table views. @@ -261,10 +322,12 @@ }; ionic.views.List.prototype = { + _initDrag: function() { this._isDragging = false; this._dragOp = null; }, + // Return the list item from the given target _getItem: function(target) { while(target) { @@ -275,6 +338,8 @@ } return null; }, + + _startDrag: function(e) { this._isDragging = false; @@ -286,16 +351,22 @@ this._dragOp = new ReorderDrag({ el: item }); this._dragOp.start(e); } - return; - } + } + // Check if this is a "pull down" drag for pull to refresh + else if(e.gesture.direction == 'down') { + this._dragOp = new PullToRefreshDrag({ el: this.el }); + this._dragOp.start(e); + } + // Or check if this is a swipe to the side drag - if(e.gesture.direction == 'left' || e.gesture.direction == 'right') { + else if(e.gesture.direction == 'left' || e.gesture.direction == 'right') { this._dragOp = new SlideDrag({ el: this.el }); this._dragOp.start(e); } }, + _handleEndDrag: function(e) { var _this = this; @@ -308,6 +379,7 @@ _this._initDrag(); }); }, + /** * Process the drag event to move the item to the left or right. */ diff --git a/scss/ionic/_listview.scss b/scss/ionic/_listview.scss index e77869fc49..2bd4a4f4b7 100644 --- a/scss/ionic/_listview.scss +++ b/scss/ionic/_listview.scss @@ -253,3 +253,14 @@ a.list-item { margin-bottom: 0; line-height: 1.3; } + +/** + * List refreser elements + */ +.list-refresher { + background-color: red; + height: 0; + overflow: hidden; +} +.list-refreshing { +} diff --git a/test/slideBox.html b/test/slideBox.html index 30b8870b98..ecea42ec0a 100644 --- a/test/slideBox.html +++ b/test/slideBox.html @@ -8,7 +8,7 @@ From 8d33d38c31e55759f9d01999055fa05c6d5c1bc4 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 16 Oct 2013 11:24:57 -0500 Subject: [PATCH 3/3] Hacky list refresher angular --- js/ext/angular/test/list.html | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/js/ext/angular/test/list.html b/js/ext/angular/test/list.html index 81569fdf7f..9016e72b6b 100644 --- a/js/ext/angular/test/list.html +++ b/js/ext/angular/test/list.html @@ -50,8 +50,16 @@ -
-
REFRESHING
+ + +
PULL TO REFRESH
+
+ +
RELEASE TO REFRESH
+
+ +
REFRESHING
+