diff --git a/dist/css/ionic-ios7.css b/dist/css/ionic-ios7.css index b75758f7e1..595c52a11d 100644 --- a/dist/css/ionic-ios7.css +++ b/dist/css/ionic-ios7.css @@ -1,4 +1,3 @@ -@charset "UTF-8"; /** * Adapted from normalize.css and some reset.css. We don't care even one * bit about old IE, so we don't need any hacks for that in here. @@ -182,7 +181,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. @@ -1463,7 +1462,7 @@ select:focus, input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { - outline: thin dotted #333333; + outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } @@ -1550,7 +1549,7 @@ input[type="checkbox"][readonly] { 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" */ @@ -1565,7 +1564,7 @@ input[type="checkbox"][readonly] { right: 0; left: 20px; -webkit-transform: none; - transition-delay: 0.05s, 0s; } + transition-delay: .05s, 0s; } /* hide a radio button's icon by default */ .radio-item [class^="icon-"], @@ -1811,7 +1810,7 @@ input[type="checkbox"][readonly] { .button.button-icon:active, .button.button-icon.active { background: none; box-shadow: none; - text-shadow: 0px 0px 10px white; } + text-shadow: 0px 0px 10px #fff; } .button.button-inline { display: inline-block; margin: 0; @@ -1943,7 +1942,7 @@ a.button { width: 100%; background-color: white; border-radius: 2px; - border: 1px solid #dddddd; } + border: 1px solid #ddd; } .card-header { padding: 10px; diff --git a/dist/css/ionic-scoped.css b/dist/css/ionic-scoped.css index bab5c9e234..d1519f0242 100644 --- a/dist/css/ionic-scoped.css +++ b/dist/css/ionic-scoped.css @@ -1,4 +1,3 @@ -@charset "UTF-8"; .ionic { @font-face { font-family: 'ionicons'; @@ -991,7 +990,7 @@ .ionic fieldset { margin: 0 2px; padding: 0.35em 0.625em 0.75em; - border: 1px solid silver; } + border: 1px solid #c0c0c0; } .ionic legend { padding: 0; /* 2 */ @@ -2078,7 +2077,7 @@ .ionic input[type="file"]:focus, .ionic input[type="radio"]:focus, .ionic input[type="checkbox"]:focus { - outline: thin dotted #333333; + outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } .ionic input:-moz-placeholder, @@ -2136,7 +2135,7 @@ border: 1px solid #049cdb; border-radius: 50%; background: white; - transition: background-color 0.1s ease-in-out; } + transition: background-color .1s ease-in-out; } .ionic .checkbox .handle:after { position: absolute; top: 37%; @@ -2148,7 +2147,7 @@ border-right: none; content: ''; opacity: 0; - transition: opacity 0.1s ease-in-out; + transition: opacity .1s ease-in-out; -webkit-transform: rotate(-45deg); transform: rotate(-45deg); } .ionic .checkbox input:checked + .handle { @@ -2435,7 +2434,7 @@ .ionic .button.button-icon:active, .ionic .button.button-icon.active { background: none; box-shadow: none; - text-shadow: 0px 0px 10px white; } + text-shadow: 0px 0px 10px #fff; } .ionic .button.button-inline { display: inline-block; margin: 0; @@ -2547,7 +2546,7 @@ width: 100%; background-color: white; border-radius: 2px; - border: 1px solid #dddddd; } + border: 1px solid #ddd; } .ionic .card-header { padding: 10px; background-color: white; } diff --git a/dist/css/ionic.css b/dist/css/ionic.css index a87c177d41..739bcd6573 100644 --- a/dist/css/ionic.css +++ b/dist/css/ionic.css @@ -1,4 +1,3 @@ -@charset "UTF-8"; @font-face { font-family: 'ionicons'; src: url("fonts/ionicons.eot"); @@ -1246,7 +1245,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. @@ -2550,7 +2549,7 @@ select:focus, input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { - outline: thin dotted #333333; + outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } @@ -2613,7 +2612,7 @@ input[type="checkbox"][readonly] { border: 1px solid #049cdb; border-radius: 50%; background: white; - transition: background-color 0.1s ease-in-out; } + transition: background-color .1s ease-in-out; } .checkbox .handle:after { position: absolute; top: 37%; @@ -2625,7 +2624,7 @@ input[type="checkbox"][readonly] { border-right: none; content: ''; opacity: 0; - transition: opacity 0.1s ease-in-out; + transition: opacity .1s ease-in-out; -webkit-transform: rotate(-45deg); transform: rotate(-45deg); } .checkbox input:checked + .handle { @@ -2929,7 +2928,7 @@ input[type="checkbox"][readonly] { .button.button-icon:active, .button.button-icon.active { background: none; box-shadow: none; - text-shadow: 0px 0px 10px white; } + text-shadow: 0px 0px 10px #fff; } .button.button-inline { display: inline-block; margin: 0; @@ -3061,7 +3060,7 @@ a.button { width: 100%; background-color: white; border-radius: 2px; - border: 1px solid #dddddd; } + border: 1px solid #ddd; } .card-header { padding: 10px; @@ -3088,9 +3087,16 @@ a.button { padding: 10px; } .slide-box { + overflow: hidden; } + +.slide-box-items { position: relative; white-space: nowrap; - -webkit-transition: -webkit-transform 0 ease-in-out; } + -webkit-transition: -webkit-transform 0 ease-in-out; + font-size: 0; } + +.slide-box-animating { + -webkit-transition-duration: 0.2s; } .slide-box-content { display: inline-block; diff --git a/dist/js/ionic.js b/dist/js/ionic.js index e0195276ff..1315a6d931 100644 --- a/dist/js/ionic.js +++ b/dist/js/ionic.js @@ -2297,17 +2297,18 @@ window.ionic = { }, _startDrag: function(e) { var offsetX, content; + console.log("START"); this._initDrag(); // Make sure to grab the element we will slide as our target - content = ionic.DomUtil.getParentOrSelfWithClass(e.target, 'slide-box'); + content = ionic.DomUtil.getParentOrSelfWithClass(e.target, 'slide-box-items'); if(!content) { return; } // Disable transitions during drag - content.style.webkitTransitionDuration = '0'; + content.classList.remove('slide-box-animating'); // Grab the starting X point for the item (for example, so we can tell whether it is open or closed to start) offsetX = parseFloat(content.style.webkitTransform.replace('translate3d(', '').split(',')[0]) || 0; @@ -2320,61 +2321,87 @@ window.ionic = { _handleEndDrag: function(e) { var _this = this; + console.log("END"); + + var finalOffsetX, content, ratio, slideWidth, totalWidth, offsetX; + window.requestAnimationFrame(function() { - // We didn't have a drag, so just init and leave - if(!this._currentDrag) { - this._initDrag(); - return; - } + // We didn't have a drag, so just init and leave + if(!_this._currentDrag) { + _this._initDrag(); + return; + } - // Snap to the correct spot + // Snap to the correct spot - var content = this._currentDrag.content; + content = _this._currentDrag.content; - // Enable transition duration - content.style.webkitTransitionDuration = '0.2s'; + // Enable transition duration + content.classList.add('slide-box-animating'); - var offsetX = Math.abs(parseFloat(content.style.webkitTransform.replace('translate3d(', '').split(',')[0]) || 0); - var slideWidth = content.offsetWidth; - var totalWidth = content.offsetWidth * content.children.length; + offsetX = parseFloat(content.style.webkitTransform.replace('translate3d(', '').split(',')[0]) || 0; + slideWidth = content.offsetWidth; + totalWidth = content.offsetWidth * content.children.length; - // Calculate how far in this slide we've dragged - var ratio = (offsetX % slideWidth) / slideWidth; + // Calculate how far in this slide we've dragged + ratio = (offsetX % slideWidth) / slideWidth; - var finalOffsetX = Math.min(totalWidth, Math.ceil(offsetX / slideWidth) * slideWidth); + if(ratio >= 0) { + // Anything greater than zero is too far left + finalOffsetX = 0; + } else if(ratio >= -0.5) { + finalOffsetX = Math.max(0, Math.floor(Math.abs(offsetX) / slideWidth) * slideWidth); + } else { + // Sliiide to the right + finalOffsetX = Math.min(totalWidth - slideWidth, Math.ceil(Math.abs(offsetX) / slideWidth) * slideWidth); + } - if(ratio < 0.5) { - finalOffsetX = Math.max(0, Math.floor(offsetX / slideWidth) * slideWidth); - } + // Negative offsetX to slide correctly + content.style.webkitTransform = 'translate3d(' + -finalOffsetX + 'px, 0, 0)'; - - content.style.webkitTransform = 'translate3d(' + -finalOffsetX + 'px, 0, 0)'; - - this._initDrag(); + _this._initDrag(); + }); }, /** * Process the drag event to move the item to the left or right. */ _handleDrag: function(e) { var _this = this; + console.log("DRAG"); window.requestAnimationFrame(function() { + var content; + // We really aren't dragging if(!_this._currentDrag) { _this._startDrag(e); } - // 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.deltaX) > _this.dragThresholdX) || (Math.abs(_this._currentDrag.startOffsetX) > 0))) - { + // Sanity + if(!_this._currentDrag) { return; } + + // Check if we should start dragging. Check if we've dragged past the threshold. + if(!_this._isDragging && (Math.abs(e.gesture.deltaX) > _this.dragThresholdX)) { _this._isDragging = true; } if(_this._isDragging) { + content = _this._currentDrag.content; + // Grab the new X point, capping it at zero var newX = Math.min(0, _this._currentDrag.startOffsetX + e.gesture.deltaX); + /* + var rightMostX = -(content.offsetWidth * Math.max(0, content.children.length - 1)); + + if(newX > 0) { + // We are dragging past the leftmost pane, rubber band + newX *= 0.4; + } else if(newX < rightMostX) { + // Dragging past the rightmost pane, rubber band + newX = Math.min(rightMostX, + (((e.gesture.deltaX + buttonsWidth) * 0.4))); + } + */ + _this._currentDrag.content.style.webkitTransform = 'translate3d(' + newX + 'px, 0, 0)'; } }); diff --git a/js/views/slideBox.js b/js/views/slideBox.js index 46c40293ae..d6b8186afd 100644 --- a/js/views/slideBox.js +++ b/js/views/slideBox.js @@ -31,17 +31,18 @@ }, _startDrag: function(e) { var offsetX, content; + console.log("START"); this._initDrag(); // Make sure to grab the element we will slide as our target - content = ionic.DomUtil.getParentOrSelfWithClass(e.target, 'slide-box'); + content = ionic.DomUtil.getParentOrSelfWithClass(e.target, 'slide-box-items'); if(!content) { return; } // Disable transitions during drag - content.style.webkitTransitionDuration = '0'; + content.classList.remove('slide-box-animating'); // Grab the starting X point for the item (for example, so we can tell whether it is open or closed to start) offsetX = parseFloat(content.style.webkitTransform.replace('translate3d(', '').split(',')[0]) || 0; @@ -54,61 +55,87 @@ _handleEndDrag: function(e) { var _this = this; + console.log("END"); + + var finalOffsetX, content, ratio, slideWidth, totalWidth, offsetX; + window.requestAnimationFrame(function() { - // We didn't have a drag, so just init and leave - if(!this._currentDrag) { - this._initDrag(); - return; - } + // We didn't have a drag, so just init and leave + if(!_this._currentDrag) { + _this._initDrag(); + return; + } - // Snap to the correct spot + // Snap to the correct spot - var content = this._currentDrag.content; + content = _this._currentDrag.content; - // Enable transition duration - content.style.webkitTransitionDuration = '0.2s'; + // Enable transition duration + content.classList.add('slide-box-animating'); - var offsetX = Math.abs(parseFloat(content.style.webkitTransform.replace('translate3d(', '').split(',')[0]) || 0); - var slideWidth = content.offsetWidth; - var totalWidth = content.offsetWidth * content.children.length; + offsetX = parseFloat(content.style.webkitTransform.replace('translate3d(', '').split(',')[0]) || 0; + slideWidth = content.offsetWidth; + totalWidth = content.offsetWidth * content.children.length; - // Calculate how far in this slide we've dragged - var ratio = (offsetX % slideWidth) / slideWidth; + // Calculate how far in this slide we've dragged + ratio = (offsetX % slideWidth) / slideWidth; - var finalOffsetX = Math.min(totalWidth, Math.ceil(offsetX / slideWidth) * slideWidth); + if(ratio >= 0) { + // Anything greater than zero is too far left + finalOffsetX = 0; + } else if(ratio >= -0.5) { + finalOffsetX = Math.max(0, Math.floor(Math.abs(offsetX) / slideWidth) * slideWidth); + } else { + // Sliiide to the right + finalOffsetX = Math.min(totalWidth - slideWidth, Math.ceil(Math.abs(offsetX) / slideWidth) * slideWidth); + } - if(ratio < 0.5) { - finalOffsetX = Math.max(0, Math.floor(offsetX / slideWidth) * slideWidth); - } + // Negative offsetX to slide correctly + content.style.webkitTransform = 'translate3d(' + -finalOffsetX + 'px, 0, 0)'; - - content.style.webkitTransform = 'translate3d(' + -finalOffsetX + 'px, 0, 0)'; - - this._initDrag(); + _this._initDrag(); + }); }, /** * Process the drag event to move the item to the left or right. */ _handleDrag: function(e) { var _this = this; + console.log("DRAG"); window.requestAnimationFrame(function() { + var content; + // We really aren't dragging if(!_this._currentDrag) { _this._startDrag(e); } - // 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.deltaX) > _this.dragThresholdX) || (Math.abs(_this._currentDrag.startOffsetX) > 0))) - { + // Sanity + if(!_this._currentDrag) { return; } + + // Check if we should start dragging. Check if we've dragged past the threshold. + if(!_this._isDragging && (Math.abs(e.gesture.deltaX) > _this.dragThresholdX)) { _this._isDragging = true; } if(_this._isDragging) { + content = _this._currentDrag.content; + // Grab the new X point, capping it at zero var newX = Math.min(0, _this._currentDrag.startOffsetX + e.gesture.deltaX); + /* + var rightMostX = -(content.offsetWidth * Math.max(0, content.children.length - 1)); + + if(newX > 0) { + // We are dragging past the leftmost pane, rubber band + newX *= 0.4; + } else if(newX < rightMostX) { + // Dragging past the rightmost pane, rubber band + newX = Math.min(rightMostX, + (((e.gesture.deltaX + buttonsWidth) * 0.4))); + } + */ + _this._currentDrag.content.style.webkitTransform = 'translate3d(' + newX + 'px, 0, 0)'; } }); diff --git a/scss/ionic/_slideBox.scss b/scss/ionic/_slideBox.scss index ce96d99dfb..b67ca29a3a 100644 --- a/scss/ionic/_slideBox.scss +++ b/scss/ionic/_slideBox.scss @@ -1,10 +1,17 @@ .slide-box { + // Make sure items don't scroll over ever + overflow: hidden; +} +.slide-box-items { position: relative; white-space: nowrap; - -webkit-transition: -webkit-transform 0 ease-in-out; + + // Remove the gaps between slide content items + font-size: 0; } -.slide-box.animate { +.slide-box-animating { + -webkit-transition-duration: 0.2s; } .slide-box-content { display: inline-block; diff --git a/test/slideBox.html b/test/slideBox.html index 23037bed6d..8c09a0a1f3 100644 --- a/test/slideBox.html +++ b/test/slideBox.html @@ -18,14 +18,16 @@
-
- -
-
- -
-
- +
+
+ +
+
+ +
+
+ +