From a23522cb06241361b794efe1df3dc7dae98dd384 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 29 Oct 2013 13:03:14 -0500 Subject: [PATCH] Fixed most tests, started moving to Backbone VC for #62 --- Gruntfile.js | 6 +- dist/js/ionic-angular.js | 2 + dist/js/ionic.js | 191 ++++-------------- js/controllers/tabBarController.js | 42 ++-- js/controllers/viewController.js | 15 +- js/ext/angular/src/directive/ionicTabBar.js | 2 + .../test/directive/ionicTabBar.unit.js | 49 ++++- js/ext/angular/test/tabs.html | 2 +- 8 files changed, 129 insertions(+), 180 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index eeb10e55e0..44d99ed84d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -37,7 +37,11 @@ module.exports = function(grunt) { 'js/views/toggleView.js', // Controllers - 'js/controllers/**/*.js' + 'js/controllers/viewController.js', + + 'js/controllers/navController.js', + 'js/controllers/sideMenuController.js', + 'js/controllers/tabBarController.js' ], dest: 'dist/js/<%= pkg.name %>.js' diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index e55d36580a..0791263645 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -975,6 +975,7 @@ angular.module('ionic.ui.tabs', ['ngAnimate']) require: '^tabs', scope: { title: '@', + icon: '@', iconOn: '@', iconOff: '@', active: '=', @@ -991,6 +992,7 @@ angular.module('ionic.ui.tabs', ['ngAnimate']) }, template: '' + + '' + '' + ' {{title}}' + '' diff --git a/dist/js/ionic.js b/dist/js/ionic.js index e9f81f40da..7769b6f701 100644 --- a/dist/js/ionic.js +++ b/dist/js/ionic.js @@ -4422,6 +4422,23 @@ ionic.views.TabBar.prototype = { initialize: function() {} }); +})(window.ionic); +; +(function(ionic) { +'use strict'; + ionic.controllers.ViewController = function(options) { + this.initialize.apply(this, arguments); + }; + + ionic.controllers.ViewController.inherit = ionic.inherit; + + ionic.extend(ionic.controllers.ViewController.prototype, { + initialize: function() {}, + // Destroy this view controller, including all child views + destroy: function() { + } + }); + })(window.ionic); ; (function(ionic) { @@ -4580,122 +4597,6 @@ ionic.controllers.NavController.prototype = { }; })(window.ionic); ; -/** - * Adapted from Backbone.js - */ -(function(ionic) { -'use strict'; - var optionalParam = /\((.*?)\)/g; - var namedParam = /(\(\?)?:\w+/g; - var splatParam = /\*\w+/g; - var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g; - - // Cached regex for stripping a leading hash/slash and trailing space. - var routeStripper = /^[#\/]|\s+$/g; - - // Cached regex for stripping leading and trailing slashes. - var rootStripper = /^\/+|\/+$/g; - - // Cached regex for removing a trailing slash. - var trailingSlash = /\/$/; - - ionic.controllers.RouteViewController = function(options) { - this.options = options; - - this.root = this.options.root || '/'; - this.root = ('/' + this.root + '/').replace(rootStripper, '/'); - - this.handlers = []; - - this._bindEvents(); - - this.location = window.location; - this.history = window.history; - }; - - ionic.controllers.RouteViewController.prototype = { - when: function(route, callback) { - var _this = this; - - route = this._routeToRegExp(route); - - this.handlers.unshift({ - route: route, - callback: function(fragment) { - var args = _this._extractParameters(route, fragment); - callback && callback.apply(_this, args); - } - }); - }, - - // Convert a route string into a regular expression, suitable for matching - // against the current location hash. - _routeToRegExp: function(route) { - route = route.replace(escapeRegExp, '\\$&') - .replace(optionalParam, '(?:$1)?') - .replace(namedParam, function(match, optional){ - return optional ? match : '([^\/]+)'; - }) - .replace(splatParam, '(.*?)'); - return new RegExp('^' + route + '$'); - }, - - // Given a route, and a URL fragment that it matches, return the array of - // extracted decoded parameters. Empty or unmatched parameters will be - // treated as `null` to normalize cross-browser behavior. - _extractParameters: function(route, fragment) { - var params = route.exec(fragment).slice(1); - var extracted = []; - for(var i = 0; i < params.length; i++) { - if(param) { - extracted.push(decodeURIComponent(param)); - } - } - }, - - _bindEvents: function() { - var _this = this; - - window.addEventListener('popstate', function(event) { - _this.checkUrl(event); - }); - }, - checkUrl: function(e) { - var current = this.getFragment(); - if (current === this.fragment) return false; - this.loadUrl() || this.loadUrl(this.getHash()); - }, - getFragment: function(fragment, forcePushState) { - if (fragment == null) { - fragment = this.location.pathname; - var root = this.root.replace(this.trailingSlash, ''); - if (!fragment.indexOf(root)) fragment = fragment.substr(root.length); - } - return fragment.replace(routeStripper, ''); - }, - getHash: function(window) { - var match = (window || this).location.href.match(/#(.*)$/); - return match ? match[1] : ''; - }, - - // Attempt to load the current URL fragment. If a route succeeds with a - // match, returns `true`. If no defined routes matches the fragment, - // returns `false`. - loadUrl: function(fragmentOverride) { - var fragment = this.fragment = this.getFragment(fragmentOverride); - var matched = false; - for(var i = 0; i < this.handlers.length; i++) { - var h = this.handlers[i]; - if (h.route.test(fragment)) { - h.callback(fragment); - matched = true; - } - } - return matched; - }, - }; -})(window.ionic); -; (function(ionic) { 'use strict'; @@ -4968,27 +4869,37 @@ ionic.controllers.NavController.prototype = { (function(ionic) { 'use strict'; -ionic.controllers.TabBarController = function(options) { - this.tabBar = options.tabBar; +/** + * The TabBarController handles a set of view controllers powered by a tab strip + * at the bottom (or possibly top) of a screen. + * + * The API here is somewhat modelled off of UITabController in the sense that the + * controllers actually define what the tab will look like (title, icon, etc.). + * + * Tabs shouldn't be interacted with through your own code. Instead, use the controller + * methods which will power the tab bar. + */ +ionic.controllers.TabBarController = ionic.controllers.ViewController.inherit({ + initialize: function(options) { + this.tabBar = options.tabBar; - this._bindEvents(); + this._bindEvents(); - this.controllers = []; + this.controllers = []; - var controllers = options.controllers || []; + var controllers = options.controllers || []; - for(var i = 0; i < controllers.length; i++) { - this.addController(controllers[i]); - } + for(var i = 0; i < controllers.length; i++) { + this.addController(controllers[i]); + } - // Bind or set our tabWillChange callback - this.controllerWillChange = options.controllerWillChange || function(controller) {}; - this.controllerChanged = options.controllerChanged || function(controller) {}; + // Bind or set our tabWillChange callback + this.controllerWillChange = options.controllerWillChange || function(controller) {}; + this.controllerChanged = options.controllerChanged || function(controller) {}; - this.setSelectedController(0); -}; - -ionic.controllers.TabBarController.prototype = { + // Try to select the first controller if we have one + this.setSelectedController(0); + }, // Start listening for events on our tab bar _bindEvents: function() { var _this = this; @@ -5090,22 +5001,6 @@ ionic.controllers.TabBarController.prototype = { this._clearSelected(); this.selectController(0); }, -}; +}); })(window.ionic); -; -(function(ionic) { -'use strict'; - ionic.ViewController = function(options) { - this.init(); - }; - - ionic.ViewController.prototype = { - // Initialize this view controller - init: function() { - }, - // Destroy this view controller, including all child views - destroy: function() { - } - }; -})(window.ionic); diff --git a/js/controllers/tabBarController.js b/js/controllers/tabBarController.js index 52491f163b..34f9383846 100644 --- a/js/controllers/tabBarController.js +++ b/js/controllers/tabBarController.js @@ -1,27 +1,37 @@ (function(ionic) { 'use strict'; -ionic.controllers.TabBarController = function(options) { - this.tabBar = options.tabBar; +/** + * The TabBarController handles a set of view controllers powered by a tab strip + * at the bottom (or possibly top) of a screen. + * + * The API here is somewhat modelled off of UITabController in the sense that the + * controllers actually define what the tab will look like (title, icon, etc.). + * + * Tabs shouldn't be interacted with through your own code. Instead, use the controller + * methods which will power the tab bar. + */ +ionic.controllers.TabBarController = ionic.controllers.ViewController.inherit({ + initialize: function(options) { + this.tabBar = options.tabBar; - this._bindEvents(); + this._bindEvents(); - this.controllers = []; + this.controllers = []; - var controllers = options.controllers || []; + var controllers = options.controllers || []; - for(var i = 0; i < controllers.length; i++) { - this.addController(controllers[i]); - } + for(var i = 0; i < controllers.length; i++) { + this.addController(controllers[i]); + } - // Bind or set our tabWillChange callback - this.controllerWillChange = options.controllerWillChange || function(controller) {}; - this.controllerChanged = options.controllerChanged || function(controller) {}; + // Bind or set our tabWillChange callback + this.controllerWillChange = options.controllerWillChange || function(controller) {}; + this.controllerChanged = options.controllerChanged || function(controller) {}; - this.setSelectedController(0); -}; - -ionic.controllers.TabBarController.prototype = { + // Try to select the first controller if we have one + this.setSelectedController(0); + }, // Start listening for events on our tab bar _bindEvents: function() { var _this = this; @@ -123,6 +133,6 @@ ionic.controllers.TabBarController.prototype = { this._clearSelected(); this.selectController(0); }, -}; +}); })(window.ionic); diff --git a/js/controllers/viewController.js b/js/controllers/viewController.js index c679ef828e..036e6c0a1e 100644 --- a/js/controllers/viewController.js +++ b/js/controllers/viewController.js @@ -1,15 +1,16 @@ (function(ionic) { 'use strict'; - ionic.ViewController = function(options) { - this.init(); + ionic.controllers.ViewController = function(options) { + this.initialize.apply(this, arguments); }; - ionic.ViewController.prototype = { - // Initialize this view controller - init: function() { - }, + ionic.controllers.ViewController.inherit = ionic.inherit; + + ionic.extend(ionic.controllers.ViewController.prototype, { + initialize: function() {}, // Destroy this view controller, including all child views destroy: function() { } - }; + }); + })(window.ionic); diff --git a/js/ext/angular/src/directive/ionicTabBar.js b/js/ext/angular/src/directive/ionicTabBar.js index 040dbd9ab3..6c1b285842 100644 --- a/js/ext/angular/src/directive/ionicTabBar.js +++ b/js/ext/angular/src/directive/ionicTabBar.js @@ -123,6 +123,7 @@ angular.module('ionic.ui.tabs', ['ngAnimate']) require: '^tabs', scope: { title: '@', + icon: '@', iconOn: '@', iconOff: '@', active: '=', @@ -139,6 +140,7 @@ angular.module('ionic.ui.tabs', ['ngAnimate']) }, template: '' + + '' + '' + ' {{title}}' + '' diff --git a/js/ext/angular/test/directive/ionicTabBar.unit.js b/js/ext/angular/test/directive/ionicTabBar.unit.js index 7fcdce8467..02dcb91ce8 100644 --- a/js/ext/angular/test/directive/ionicTabBar.unit.js +++ b/js/ext/angular/test/directive/ionicTabBar.unit.js @@ -10,7 +10,30 @@ describe('Tab Bar Controller', function() { })); it('Select item in controller works', function() { + // Verify no items selected + expect(ctrl.getSelectedControllerIndex()).toEqual(undefined); + + // Try selecting beyond the bounds ctrl.selectController(1); + expect(ctrl.getSelectedControllerIndex()).toEqual(undefined); + + // Add a controller + ctrl.add({ + title: 'Cats', + icon: 'icon-kitty-kat' + }); + + expect(ctrl.getSelectedControllerIndex()).toEqual(0); + + ctrl.add({ + title: 'Cats', + icon: 'icon-kitty-kat' + }); + + expect(ctrl.getSelectedControllerIndex()).toEqual(0); + + ctrl.select(1); + expect(ctrl.getSelectedControllerIndex()).toEqual(1); }); }); @@ -27,7 +50,7 @@ describe('Tab Bar directive', function() { it('Has section wrapper class', function() { element = compile('')(scope); - expect(element.hasClass('view-wrapper')).toBe(true); + expect(element.hasClass('tabs')).toBe(true); }); }); @@ -44,19 +67,28 @@ describe('Tabs directive', function() { it('Has tab class', function() { element = compile('')(scope); scope.$digest(); - console.log(element); expect(element.find('.tabs').hasClass('tabs')).toBe(true); }); it('Has tab children', function() { - scope.tabs = [ + element = compile('')(scope); + scope = element.scope(); + scope.controllers = [ { text: 'Home', icon: 'icon-home' }, { text: 'Fun', icon: 'icon-fun' }, { text: 'Beer', icon: 'icon-beer' }, ]; - element = compile('')(scope); scope.$digest(); - expect(element.find('li').length).toBe(3); + expect(element.find('a').length).toBe(3); + }); + + it('Has compiled children', function() { + element = compile('' + + '' + + '' + + '')(scope); + scope.$digest(); + expect(element.find('a').length).toBe(2); }); }); @@ -70,16 +102,19 @@ describe('Tab Item directive', function() { scope = $rootScope; element = compile('' + - '' + + '' + '')(scope); scope.$digest(); })); it('Default text works', function() { - expect(element.find('a').first().text()).toEqual('Item'); + console.log(element); + expect(element.find('a').first().text().trim()).toEqual('Item'); }); it('Default icon works', function() { + console.log(element); + scope.$digest(); expect(element.find('i').hasClass('icon-default')).toEqual(true); }); diff --git a/js/ext/angular/test/tabs.html b/js/ext/angular/test/tabs.html index b09dd8dc94..2e6b3901f2 100644 --- a/js/ext/angular/test/tabs.html +++ b/js/ext/angular/test/tabs.html @@ -74,7 +74,7 @@ - +

Deadlines