diff --git a/dist/css/ionic.css b/dist/css/ionic.css index 0ef9c299d9..ad7a4b8d2e 100644 --- a/dist/css/ionic.css +++ b/dist/css/ionic.css @@ -4884,6 +4884,13 @@ a.button { -webkit-animation: fadeIn 0.3s; animation: fadeIn 0.3s; } +.fade-in-not-out.ng-enter, .fade-in-not-out .ng-enter { + position: relative; + -webkit-animation: fadeIn 0.3s; + animation: fadeIn 0.3s; } +.fade-in-not-out.ng-leave, .fade-in-not-out .ng-leave { + display: none; } + @-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } } diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index 531d9da694..f07eaed42a 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -23165,13 +23165,15 @@ angular.module('ionic.service.modal', ['ionic.service.templateLoad', 'ngAnimate' }, // Show the modal show: function() { + var _this = this; var element = angular.element(this.el); if(!element.parent().length) { - $animate.enter(element, angular.element($document[0].body)); + $animate.enter(element, angular.element($document[0].body), null, function() { + ionic.views.Modal.prototype.show.call(_this); + }); } - $animate.addClass(element, this.animation); - - ionic.views.Modal.prototype.show.call(this); + $animate.addClass(element, this.animation, function() { + }); }, // Hide the modal hide: function() { @@ -23542,35 +23544,48 @@ angular.module('ionic.ui.checkbox', []) restrict: 'E', replace: true, require: '?ngModel', - scope: true, - template: '
', + scope: {}, + template: '', + link: function($scope, $element, $attr, ngModel) { - var checkbox, handle; + var checkbox; if(!ngModel) { return; } checkbox = $element.children().eq(0); - handle = $element.children().eq(1); - if(!checkbox.length || !handle.length) { return; } + if(!checkbox.length) { return; } - $scope.checkbox = new ionic.views.Checkbox({ - el: $element[0], - checkbox: checkbox[0], - handle: handle[0] - }); - - $element.bind('click', function(e) { - $scope.checkbox.tap(e); + var tapHandler = function(e) { + checkbox[0].checked = !checkbox[0].checked; $scope.$apply(function() { ngModel.$setViewValue(checkbox[0].checked); }); + e.preventDefault(); + }; + + var clickHandler = function(e) { + checkbox[0].checked = !checkbox[0].checked; + $scope.$apply(function() { + ngModel.$setViewValue(checkbox[0].checked); + }); + }; + + $scope.$on('$destroy', function() { + $element.unbind('tap', tapHandler); + $element.unbind('click', clickHandler); }); - ngModel.$render = function() { - $scope.checkbox.val(ngModel.$viewValue); - }; + if(ngModel) { + $element.bind('tap', tapHandler); + $element.bind('click', clickHandler); + + ngModel.$render = function() { + console.log('checkbox redern', ngModel.$viewValue); + checkbox[0].checked = ngModel.$viewValue; + }; + } } }; }); @@ -24171,11 +24186,11 @@ angular.module('ionic.ui.radio', []) }, transclude: true, template: '', + \ +
\ +
\ + \ + ', link: function($scope, $element, $attr, ngModel) { var radio; @@ -24186,20 +24201,34 @@ angular.module('ionic.ui.radio', []) if(!radio.length) { return; } - radio.bind('click', function(e) { - $scope.$apply(function() { - ngModel.$setViewValue($scope.$eval($attr.ngValue)); - }); + var tapHandler = function(e) { + radio[0].checked = true; + ngModel.$setViewValue($scope.$eval($attr.ngValue)); + e.preventDefault(); + }; + + var clickHandler = function(e) { + ngModel.$setViewValue($scope.$eval($attr.ngValue)); + }; + + $scope.$on('$destroy', function() { + $element.unbind('tap', tapHandler); + $element.unbind('click', clickHandler); }); - ngModel.$render = function() { - var val = $scope.$eval($attr.ngValue); - if(val === ngModel.$viewValue) { - radio.attr('checked', 'checked'); - } else { - radio.removeAttr('checked'); - } - }; + if(ngModel) { + $element.bind('tap', tapHandler); + $element.bind('click', clickHandler); + + ngModel.$render = function() { + var val = $scope.$eval($attr.ngValue); + if(val === ngModel.$viewValue) { + radio.attr('checked', 'checked'); + } else { + radio.removeAttr('checked'); + } + }; + } } }; }); diff --git a/dist/js/ionic.js b/dist/js/ionic.js index 2b5ff978a7..40d60c3c8d 100644 --- a/dist/js/ionic.js +++ b/dist/js/ionic.js @@ -1769,7 +1769,7 @@ window.ionic = { ionic.Platform.detect(); })(window.ionic); ; -(function(ionic) { +(function(window, document, ionic) { 'use strict'; // From the man himself, Mr. Paul Irish. @@ -1799,7 +1799,71 @@ window.ionic = { } })(); -})(window.ionic); + + // polyfill use to simulate native "tap" + function inputTapPolyfill(ele, e) { + if(ele.type === "radio" || ele.type === "checkbox") { + console.log('RADIOPOLY'); + ele.checked = !ele.checked; + } else if(ele.type === "submit" || ele.type === "button") { + ele.click(); + } else { + ele.focus(); + } + e.stopPropagation(); + e.preventDefault(); + return false; + } + + function tapPolyfill(e) { + // if the source event wasn't from a touch event then don't use this polyfill + if(!e.gesture || e.gesture.pointerType !== "touch" || !e.gesture.srcEvent) return; + + if(e.defaultPrevented) { + e.stopPropagation(); + e.preventDefault(); + return false; + } + + e = e.gesture.srcEvent; // evaluate the actual source event, not the created event by gestures.js + + var ele = e.target; + + while(ele) { + if( ele.tagName === "INPUT" || ele.tagName === "TEXTAREA" || ele.tagName === "SELECT" ) { + return inputTapPolyfill(ele, e); + } else if( ele.tagName === "LABEL" ) { + if(ele.control) { + return inputTapPolyfill(ele.control, e); + } + } + /* Let ng-click handle this + else if( ele.tagName === "A" || ele.tagName === "BUTTON" ) { + ele.click(); + e.stopPropagation(); + e.preventDefault(); + return false; + } + */ + ele = ele.parentElement; + } + + // they didn't tap one of the above elements + // if the currently active element is an input, and they tapped outside + // of the current input, then unset its focus (blur) so the keyboard goes away + var activeElement = document.activeElement; + if(activeElement && (activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA" || activeElement.tagName === "SELECT")) { + activeElement.blur(); + e.stopPropagation(); + e.preventDefault(); + return false; + } + } + + // global tap event listener polyfill for HTML elements that were "tapped" by the user + ionic.on("tap", tapPolyfill, window); + +})(this, document, ionic); ; (function(ionic) { @@ -2779,30 +2843,6 @@ window.ionic = { } }); -})(ionic); -; -(function(ionic) { -'use strict'; - - ionic.views.Checkbox = ionic.views.View.inherit({ - initialize: function(opts) { - this.el = opts.el; - this.checkbox = opts.checkbox; - this.handle = opts.handle; - }, - - tap: function(e) { - this.val( !this.checkbox.checked ); - }, - - val: function(value) { - if(value === true || value === false) { - this.checkbox.checked = value; - } - return this.checkbox.checked; - } - }); - })(ionic); ; (function(ionic) { diff --git a/js/ext/angular/src/directive/ionicCheckbox.js b/js/ext/angular/src/directive/ionicCheckbox.js index d230b10d85..5d03b93274 100644 --- a/js/ext/angular/src/directive/ionicCheckbox.js +++ b/js/ext/angular/src/directive/ionicCheckbox.js @@ -9,35 +9,48 @@ angular.module('ionic.ui.checkbox', []) restrict: 'E', replace: true, require: '?ngModel', - scope: true, - template: '
', + scope: {}, + template: '', + link: function($scope, $element, $attr, ngModel) { - var checkbox, handle; + var checkbox; if(!ngModel) { return; } checkbox = $element.children().eq(0); - handle = $element.children().eq(1); - if(!checkbox.length || !handle.length) { return; } + if(!checkbox.length) { return; } - $scope.checkbox = new ionic.views.Checkbox({ - el: $element[0], - checkbox: checkbox[0], - handle: handle[0] - }); - - $element.bind('click', function(e) { - $scope.checkbox.tap(e); + var tapHandler = function(e) { + checkbox[0].checked = !checkbox[0].checked; $scope.$apply(function() { ngModel.$setViewValue(checkbox[0].checked); }); + e.preventDefault(); + }; + + var clickHandler = function(e) { + checkbox[0].checked = !checkbox[0].checked; + $scope.$apply(function() { + ngModel.$setViewValue(checkbox[0].checked); + }); + }; + + $scope.$on('$destroy', function() { + $element.unbind('tap', tapHandler); + $element.unbind('click', clickHandler); }); - ngModel.$render = function() { - $scope.checkbox.val(ngModel.$viewValue); - }; + if(ngModel) { + $element.bind('tap', tapHandler); + $element.bind('click', clickHandler); + + ngModel.$render = function() { + console.log('checkbox redern', ngModel.$viewValue); + checkbox[0].checked = ngModel.$viewValue; + }; + } } }; }); diff --git a/js/ext/angular/src/directive/ionicRadio.js b/js/ext/angular/src/directive/ionicRadio.js index f4b93c20e2..49bc0c1676 100644 --- a/js/ext/angular/src/directive/ionicRadio.js +++ b/js/ext/angular/src/directive/ionicRadio.js @@ -15,11 +15,11 @@ angular.module('ionic.ui.radio', []) }, transclude: true, template: '', + \ +
\ +
\ + \ + ', link: function($scope, $element, $attr, ngModel) { var radio; @@ -30,20 +30,34 @@ angular.module('ionic.ui.radio', []) if(!radio.length) { return; } - radio.bind('click', function(e) { - $scope.$apply(function() { - ngModel.$setViewValue($scope.$eval($attr.ngValue)); - }); + var tapHandler = function(e) { + radio[0].checked = true; + ngModel.$setViewValue($scope.$eval($attr.ngValue)); + e.preventDefault(); + }; + + var clickHandler = function(e) { + ngModel.$setViewValue($scope.$eval($attr.ngValue)); + }; + + $scope.$on('$destroy', function() { + $element.unbind('tap', tapHandler); + $element.unbind('click', clickHandler); }); - ngModel.$render = function() { - var val = $scope.$eval($attr.ngValue); - if(val === ngModel.$viewValue) { - radio.attr('checked', 'checked'); - } else { - radio.removeAttr('checked'); - } - }; + if(ngModel) { + $element.bind('tap', tapHandler); + $element.bind('click', clickHandler); + + ngModel.$render = function() { + var val = $scope.$eval($attr.ngValue); + if(val === ngModel.$viewValue) { + radio.attr('checked', 'checked'); + } else { + radio.removeAttr('checked'); + } + }; + } } }; }); diff --git a/js/ext/angular/src/service/ionicModal.js b/js/ext/angular/src/service/ionicModal.js index 2725aeec28..f7b544e7b0 100644 --- a/js/ext/angular/src/service/ionicModal.js +++ b/js/ext/angular/src/service/ionicModal.js @@ -9,13 +9,15 @@ angular.module('ionic.service.modal', ['ionic.service.templateLoad', 'ngAnimate' }, // Show the modal show: function() { + var _this = this; var element = angular.element(this.el); if(!element.parent().length) { - $animate.enter(element, angular.element($document[0].body)); + $animate.enter(element, angular.element($document[0].body), null, function() { + ionic.views.Modal.prototype.show.call(_this); + }); } - $animate.addClass(element, this.animation); - - ionic.views.Modal.prototype.show.call(this); + $animate.addClass(element, this.animation, function() { + }); }, // Hide the modal hide: function() { diff --git a/js/ext/angular/test/checkbox.html b/js/ext/angular/test/checkbox.html index 1324ab67e5..01655c1f1b 100644 --- a/js/ext/angular/test/checkbox.html +++ b/js/ext/angular/test/checkbox.html @@ -9,12 +9,14 @@ - -

- - - -
+
+ +

+ + + +
+
diff --git a/js/ext/angular/test/input.html b/js/ext/angular/test/input.html new file mode 100644 index 0000000000..b069982e52 --- /dev/null +++ b/js/ext/angular/test/input.html @@ -0,0 +1,35 @@ + + + + Checkbox + + + + + + + +
+ +
+ + +
+
+
+ + + + + + + diff --git a/js/utils/poly.js b/js/utils/poly.js index 82a598b2b3..014e7376fa 100644 --- a/js/utils/poly.js +++ b/js/utils/poly.js @@ -1,4 +1,4 @@ -(function(ionic) { +(function(window, document, ionic) { 'use strict'; // From the man himself, Mr. Paul Irish. @@ -28,4 +28,68 @@ } })(); -})(window.ionic); + + // polyfill use to simulate native "tap" + function inputTapPolyfill(ele, e) { + if(ele.type === "radio" || ele.type === "checkbox") { + console.log('RADIOPOLY'); + ele.checked = !ele.checked; + } else if(ele.type === "submit" || ele.type === "button") { + ele.click(); + } else { + ele.focus(); + } + e.stopPropagation(); + e.preventDefault(); + return false; + } + + function tapPolyfill(e) { + // if the source event wasn't from a touch event then don't use this polyfill + if(!e.gesture || e.gesture.pointerType !== "touch" || !e.gesture.srcEvent) return; + + if(e.defaultPrevented) { + e.stopPropagation(); + e.preventDefault(); + return false; + } + + e = e.gesture.srcEvent; // evaluate the actual source event, not the created event by gestures.js + + var ele = e.target; + + while(ele) { + if( ele.tagName === "INPUT" || ele.tagName === "TEXTAREA" || ele.tagName === "SELECT" ) { + return inputTapPolyfill(ele, e); + } else if( ele.tagName === "LABEL" ) { + if(ele.control) { + return inputTapPolyfill(ele.control, e); + } + } + /* Let ng-click handle this + else if( ele.tagName === "A" || ele.tagName === "BUTTON" ) { + ele.click(); + e.stopPropagation(); + e.preventDefault(); + return false; + } + */ + ele = ele.parentElement; + } + + // they didn't tap one of the above elements + // if the currently active element is an input, and they tapped outside + // of the current input, then unset its focus (blur) so the keyboard goes away + var activeElement = document.activeElement; + if(activeElement && (activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA" || activeElement.tagName === "SELECT")) { + activeElement.blur(); + e.stopPropagation(); + e.preventDefault(); + return false; + } + } + + // global tap event listener polyfill for HTML elements that were "tapped" by the user + ionic.on("tap", tapPolyfill, window); + +})(this, document, ionic); diff --git a/js/views/checkboxView.js b/js/views/checkboxView.js deleted file mode 100644 index 1328e1a6f2..0000000000 --- a/js/views/checkboxView.js +++ /dev/null @@ -1,23 +0,0 @@ -(function(ionic) { -'use strict'; - - ionic.views.Checkbox = ionic.views.View.inherit({ - initialize: function(opts) { - this.el = opts.el; - this.checkbox = opts.checkbox; - this.handle = opts.handle; - }, - - tap: function(e) { - this.val( !this.checkbox.checked ); - }, - - val: function(value) { - if(value === true || value === false) { - this.checkbox.checked = value; - } - return this.checkbox.checked; - } - }); - -})(ionic); diff --git a/scss/_animations.scss b/scss/_animations.scss index 72f4b60d03..07c97fb6de 100644 --- a/scss/_animations.scss +++ b/scss/_animations.scss @@ -198,6 +198,17 @@ $slide-in-up-function: cubic-bezier(.1, .7, .1, 1); } } +.fade-in-not-out { + &.ng-enter, .ng-enter { + position: relative; + -webkit-animation: fadeIn 0.3s; + animation: fadeIn 0.3s; + } + &.ng-leave, .ng-leave { + display: none; + } +} + @-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } } @@ -210,3 +221,4 @@ $slide-in-up-function: cubic-bezier(.1, .7, .1, 1); transform:rotate(360deg); } } +