mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Merge branch 'master' of github.com:driftyco/ionic
This commit is contained in:
14
Gruntfile.js
14
Gruntfile.js
@@ -19,21 +19,18 @@ module.exports = function(grunt) {
|
||||
},
|
||||
bundle: {
|
||||
options: {
|
||||
banner: grunt.file.read('js/_license.js') + '\n' +
|
||||
banner:
|
||||
'/*!\n' +
|
||||
' * ionic.bundle.js is a concatenation of:\n' +
|
||||
' * angular.js,\n'+
|
||||
' * angular-animate.js,\n'+
|
||||
' * angular-ui-router.js,\n'+
|
||||
' * ionic.js,\n'+
|
||||
' * ionic-angular.js\n'+
|
||||
' * ionic.js, angular.js, angular-animate.js,\n'+
|
||||
' * angular-ui-router.js, and ionic-angular.js\n'+
|
||||
' */\n\n'
|
||||
},
|
||||
src: [
|
||||
'dist/js/ionic.js',
|
||||
'config/lib/js/angular/angular.js',
|
||||
'config/lib/js/angular/angular-animate.js',
|
||||
'config/lib/js/angular-ui/angular-ui-router.js',
|
||||
'dist/js/ionic.js',
|
||||
'dist/js/ionic-angular.js'
|
||||
],
|
||||
dest: 'dist/js/ionic.bundle.js'
|
||||
@@ -43,10 +40,10 @@ module.exports = function(grunt) {
|
||||
banner: '<%= concat.bundle.options.banner %>'
|
||||
},
|
||||
src: [
|
||||
'dist/js/ionic.min.js',
|
||||
'config/lib/js/angular/angular.min.js',
|
||||
'config/lib/js/angular/angular-animate.min.js',
|
||||
'config/lib/js/angular-ui/angular-ui-router.min.js',
|
||||
'dist/js/ionic.min.js',
|
||||
'dist/js/ionic-angular.min.js'
|
||||
],
|
||||
dest: 'dist/js/ionic.bundle.min.js'
|
||||
@@ -79,6 +76,7 @@ module.exports = function(grunt) {
|
||||
dist: {
|
||||
files: {
|
||||
'dist/js/ionic.js': 'dist/js/ionic.js',
|
||||
'dist/js/ionic.bundle.js': 'dist/js/ionic.bundle.js',
|
||||
'dist/js/ionic-angular.js': 'dist/js/ionic-angular.js'
|
||||
},
|
||||
options: {
|
||||
|
||||
@@ -95,7 +95,7 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
|
||||
if(tAttrs.type) tElement.addClass(tAttrs.type);
|
||||
|
||||
return function link($scope, $element, $attr) {
|
||||
var canHaveBackButton = !(!tAttrs.backButtonType && !tAttrs.backButtonLabel);
|
||||
var canHaveBackButton = !(!tAttrs.backButtonType && !tAttrs.backButtonLabel && !tAttrs.backButtonIcon);
|
||||
$scope.enableBackButton = canHaveBackButton;
|
||||
|
||||
$rootScope.$on('viewState.showNavBar', function(e, showNavBar) {
|
||||
|
||||
@@ -112,6 +112,13 @@
|
||||
<i class="radio-icon ion-checkmark"></i>
|
||||
</label>
|
||||
|
||||
<div class="item item-checkbox" style="padding-left: 58px !important">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" ng-model="htmlCheckboxData.checkedValue">
|
||||
</label>
|
||||
Checkbox {{ htmlCheckboxData.checkedValue }}</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -130,6 +137,8 @@
|
||||
|
||||
.controller('MyCtrl', function($scope) {
|
||||
|
||||
$scope.htmlCheckboxData = {};
|
||||
|
||||
$scope.otherTests = function() {
|
||||
if($scope.testBtnText == 'HTML') {
|
||||
$scope.testBtnText = 'AngJS';
|
||||
@@ -140,18 +149,18 @@
|
||||
$scope.otherTests();
|
||||
|
||||
$scope.htmlToggleClick = function() {
|
||||
console.log('htmlToggleClick', 'click');
|
||||
console.debug('htmlToggleClick', 'click');
|
||||
$scope.buttonValue = 'html' + Math.floor(Math.random() * 999);
|
||||
};
|
||||
|
||||
$scope.stringClick = 'stringMethod()';
|
||||
$scope.stringMethod = function() {
|
||||
console.log('toggle {{ stringClick }]', 'click');
|
||||
console.debug('toggle {{ stringClick }]', 'click');
|
||||
$scope.buttonValue = 'tg' + Math.floor(Math.random() * 999);
|
||||
};
|
||||
|
||||
$scope.itemClick = function() {
|
||||
console.log('itemClick()', 'click');
|
||||
console.debug('itemClick()', 'click');
|
||||
$scope.buttonValue = 'itm' + Math.floor(Math.random() * 999);
|
||||
};
|
||||
|
||||
@@ -159,28 +168,28 @@
|
||||
{
|
||||
label: 'Item 1',
|
||||
actionItem: function() {
|
||||
console.log('item.actionItem()', 'click')
|
||||
console.debug('item.actionItem()', 'click')
|
||||
$scope.buttonValue = 'itm' + Math.floor(Math.random() * 999);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
$scope.buttonClick = function() {
|
||||
console.log('button ng-click', 'click')
|
||||
console.debug('button ng-click', 'click')
|
||||
$scope.buttonValue = 'btn' + Math.floor(Math.random() * 999);
|
||||
};
|
||||
|
||||
$scope.divClick = function() {
|
||||
console.log('div ng-click', 'click')
|
||||
console.debug('div ng-click', 'click')
|
||||
$scope.buttonValue = 'div' + Math.floor(Math.random() * 999);
|
||||
};
|
||||
$scope.radioModel = {}
|
||||
$scope.radioChange = function() {
|
||||
console.log('radio ng-change', 'change', $scope.radioModel.data);
|
||||
console.debug('radio ng-change', 'change', $scope.radioModel.data);
|
||||
};
|
||||
|
||||
$scope.radioClick = function(val) {
|
||||
console.log('radio ng-click', 'click', val);
|
||||
console.debug('radio ng-click', 'click', val);
|
||||
$scope.buttonValue = 'rd' + Math.floor(Math.random() * 999);
|
||||
};
|
||||
|
||||
@@ -192,23 +201,23 @@
|
||||
}
|
||||
|
||||
document.getElementById('radio1').addEventListener('change', function(){
|
||||
console.log('radio 1', 'change');
|
||||
console.debug('radio 1', 'change');
|
||||
});
|
||||
document.getElementById('radio1').addEventListener('click', function(){
|
||||
console.log('radio 1', 'click');
|
||||
console.debug('radio 1', 'click');
|
||||
});
|
||||
document.getElementById('radio2').addEventListener('change', function(){
|
||||
console.log('radio 2', 'change');
|
||||
console.debug('radio 2', 'change');
|
||||
});
|
||||
document.getElementById('radio2').addEventListener('click', function(){
|
||||
console.log('radio 2', 'click');
|
||||
console.debug('radio 2', 'click');
|
||||
});
|
||||
|
||||
document.addEventListener('touchstart', function(e){
|
||||
console.log('touchstart');
|
||||
console.debug('touchstart');
|
||||
});
|
||||
document.addEventListener('touchend', function(e){
|
||||
console.log('touchend');
|
||||
console.debug('touchend');
|
||||
if(!e.changedTouches || !e.changedTouches.length) return;
|
||||
|
||||
var dot = document.createElement('div');
|
||||
@@ -223,16 +232,16 @@
|
||||
}, 3000);
|
||||
});
|
||||
document.addEventListener('mousedown', function(){
|
||||
console.log('mousedown');
|
||||
console.debug('mousedown');
|
||||
});
|
||||
document.addEventListener('mouseup', function(){
|
||||
console.log('mouseup');
|
||||
console.debug('mouseup');
|
||||
});
|
||||
// document.addEventListener('mousemove', function(event){
|
||||
// console.log('mousemove', 'clientX: ' + event.clientX, 'clientY: ' + event.clientY);
|
||||
// console.debug('mousemove', 'clientX: ' + event.clientX, 'clientY: ' + event.clientY);
|
||||
// });
|
||||
document.addEventListener('click', function(event){
|
||||
console.log('click', 'clientX: ' + event.clientX, 'clientY: ' + event.clientY);
|
||||
console.debug('click', 'clientX: ' + event.clientX, 'clientY: ' + event.clientY);
|
||||
});
|
||||
document.getElementById('clear').addEventListener('click', function(){
|
||||
setTimeout(clearMsgs, 200);
|
||||
@@ -258,10 +267,10 @@
|
||||
for (var i = 0, j = arguments.length; i < j; i++){
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
console.log.apply(this, args);
|
||||
console.debug.apply(this, args);
|
||||
};
|
||||
|
||||
console.log = function() {
|
||||
console.debug = function() {
|
||||
//return;
|
||||
if(stopped) return;
|
||||
|
||||
|
||||
@@ -83,13 +83,41 @@ describe('Ionic View', function() {
|
||||
expect(element.hasClass('bar-positive')).toEqual(true);
|
||||
});
|
||||
|
||||
it('should not show the back button if no back button attributes set', function() {
|
||||
it('should not have the back button if no back button attributes set', function() {
|
||||
var element = compile('<nav-bar></nav-bar>')(scope);
|
||||
scope.$digest();
|
||||
var backButton = element.find('div').find('button');
|
||||
expect(backButton.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should have the back button if back-button-type attributes set', function() {
|
||||
var element = compile('<nav-bar back-button-type="button-icon"></nav-bar>')(scope);
|
||||
scope.$digest();
|
||||
var backButton = element.find('div').find('button');
|
||||
expect(backButton.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should have the back button if back-button-icon attributes set', function() {
|
||||
var element = compile('<nav-bar back-button-icon="ion-back"></nav-bar>')(scope);
|
||||
scope.$digest();
|
||||
var backButton = element.find('div').find('button');
|
||||
expect(backButton.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should have the back button if back-button-label attributes set', function() {
|
||||
var element = compile('<nav-bar back-button-label="Button"></nav-bar>')(scope);
|
||||
scope.$digest();
|
||||
var backButton = element.find('div').find('button');
|
||||
expect(backButton.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should have the back button if all back button attributes set', function() {
|
||||
var element = compile('<nav-bar back-button-type="button-icon" back-button-icon="ion-back" back-button-label="Button"></nav-bar>')(scope);
|
||||
scope.$digest();
|
||||
var backButton = element.find('div').find('button');
|
||||
expect(backButton.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should set just a back button icon, no text', function() {
|
||||
var element = compile('<nav-bar back-button-icon="ion-back" back-button-type="button-icon"></nav-bar>')(scope);
|
||||
scope.$digest();
|
||||
@@ -111,7 +139,7 @@ describe('Ionic View', function() {
|
||||
expect(backButton.html()).toEqual('Back');
|
||||
});
|
||||
|
||||
it('should set a back button with an icon and text, button-clear', function() {
|
||||
it('should set a back button with an icon and text, button-icon', function() {
|
||||
var element = compile('<nav-bar back-button-icon="ion-back" back-button-label="Back" back-button-type="button-icon"></nav-bar>')(scope);
|
||||
scope.$digest();
|
||||
var backButton = element.find('div').find('button');
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
// simulate a normal click by running the element's click method then focus on it
|
||||
if(ele.disabled) return;
|
||||
|
||||
console.debug('tapElement', ele.tagName, ele.className);
|
||||
|
||||
var c = getCoordinates(e);
|
||||
|
||||
// using initMouseEvent instead of MouseEvent for our Android friends
|
||||
@@ -50,7 +52,10 @@
|
||||
}
|
||||
|
||||
// remember the coordinates of this tap so if it happens again we can ignore it
|
||||
recordCoordinates(e);
|
||||
// but only if the coordinates are not already being actively disabled
|
||||
if( !isRecentTap(e) ) {
|
||||
recordCoordinates(e);
|
||||
}
|
||||
|
||||
// set the last tap time so if a click event quickly happens it knows to ignore it
|
||||
ele.lastTap = Date.now();
|
||||
@@ -65,12 +70,14 @@
|
||||
|
||||
if( isRecentTap(e) ) {
|
||||
// if a tap in the same area just happened, don't continue
|
||||
console.debug('tapPolyfill', 'isRecentTap', ele.tagName);
|
||||
return;
|
||||
}
|
||||
|
||||
if(e.target.lastClick && e.target.lastClick + CLICK_PREVENT_DURATION > Date.now()) {
|
||||
if(ele.lastClick && ele.lastClick + CLICK_PREVENT_DURATION > Date.now()) {
|
||||
// if a click recently happend on this element, don't continue
|
||||
// (yes on some devices it's possible for a click to happen before a touchend)
|
||||
console.debug('tapPolyfill', 'recent lastClick', ele.tagName);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -111,6 +118,7 @@
|
||||
if(e.target.control.labelLastTap && e.target.control.labelLastTap + CLICK_PREVENT_DURATION > Date.now()) {
|
||||
// Android will fire a click for the label, and a click for the input which it is associated to
|
||||
// this stops the second ghost click from the label from continuing
|
||||
console.debug('preventGhostClick', 'labelLastTap');
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return false;
|
||||
@@ -122,12 +130,14 @@
|
||||
// The input's click event will propagate so don't bother letting this label's click
|
||||
// propagate cuz it causes double clicks. However, do NOT e.preventDefault(), because
|
||||
// the label still needs to click the input
|
||||
console.debug('preventGhostClick', 'label stopPropagation');
|
||||
e.stopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
if( isRecentTap(e) ) {
|
||||
// a tap has already happened at these coordinates recently, ignore this event
|
||||
console.debug('preventGhostClick', 'isRecentTap', e.target.tagName);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return false;
|
||||
@@ -135,6 +145,7 @@
|
||||
|
||||
if(e.target.lastTap && e.target.lastTap + CLICK_PREVENT_DURATION > Date.now()) {
|
||||
// this element has already had the tap poly fill run on it recently, ignore this event
|
||||
console.debug('preventGhostClick', 'e.target.lastTap', e.target.tagName);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return false;
|
||||
@@ -201,7 +212,7 @@
|
||||
}
|
||||
|
||||
var tapCoordinates = {}; // used to remember coordinates to ignore if they happen again quickly
|
||||
var CLICK_PREVENT_DURATION = 350; // amount of milliseconds to check for ghostclicks
|
||||
var CLICK_PREVENT_DURATION = 450; // amount of milliseconds to check for ghostclicks
|
||||
|
||||
// set global click handler and check if the event should stop or not
|
||||
document.addEventListener('click', preventGhostClick, true);
|
||||
|
||||
@@ -46,6 +46,11 @@ body, .ionic-body {
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
.content {
|
||||
// used for content areas not using the content directive
|
||||
position: relative
|
||||
}
|
||||
|
||||
.scroll-content {
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<html>
|
||||
<html ng-app="ionicApp">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Cards</title>
|
||||
|
||||
<!-- Sets initial viewport load and disables zooming -->
|
||||
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
|
||||
<link href="../dist/css/ionic.css" rel="stylesheet">
|
||||
<script src="../dist/js/ionic.bundle.js"></script>
|
||||
<script>
|
||||
angular.module('ionicApp', ['ionic'])
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -13,7 +15,7 @@
|
||||
<h1 class="title">Cards</h1>
|
||||
</header>
|
||||
|
||||
<main class="content has-header overflow-scroll ionic-pseudo" style="position:fixed">
|
||||
<content has-header="true" class="ionic-pseudo">
|
||||
|
||||
<div class="card">
|
||||
<div class="item item-text-wrap">
|
||||
@@ -136,9 +138,9 @@
|
||||
|
||||
</div>
|
||||
|
||||
<p><a class="button button-secondary" href="../">Homepage</a></p>
|
||||
<p><a class="button button-secondary" href="../">All CSS Tests</a></p>
|
||||
|
||||
</main>
|
||||
</content>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<h1 class="title">Type</h1>
|
||||
</header>
|
||||
|
||||
<main class="content padding has-header" style="margin-top: 80px">
|
||||
<main class="content padding has-header">
|
||||
<h1>I'm an H1 Element</h1>
|
||||
<h2>I'm an H2 Element</h2>
|
||||
<h3>I'm an H3 Element</h3>
|
||||
@@ -23,7 +23,7 @@
|
||||
<p>I'm a paragraph Element!</p>
|
||||
<p>As am I'm a paragraph Element too.</p>
|
||||
<hr>
|
||||
<p><a class="button button-secondary" href="index.html">Homepage</a></p>
|
||||
<p><a class="button button-secondary" href="./">All CSS Tests</a></p>
|
||||
</main>
|
||||
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user