├── .gitignore ├── .jshintrc ├── Gruntfile.js ├── LICENSE ├── README.md ├── bower.json ├── dist └── angular-wait.js ├── grunt ├── jshint.js ├── karma.js ├── ngAnnotate.js └── uglify.js ├── karma.conf.js ├── package.json ├── src └── angular-wait.js └── test ├── angular-wait.js └── mocks └── example-directive.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by http://www.gitignore.io 2 | 3 | ### Bower ### 4 | bower_components 5 | 6 | 7 | ### grunt ### 8 | # Grunt usually compiles files inside this directory 9 | # dist/ # we need this for grunt packages 10 | 11 | # Grunt usually preprocesses files such as coffeescript, compass... inside the .tmp directory 12 | .tmp/ 13 | 14 | 15 | ### WebStorm ### 16 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 17 | 18 | ## Directory-based project format 19 | .idea/ 20 | /*.iml 21 | # if you remove the above rule, at least ignore user-specific stuff: 22 | # .idea/workspace.xml 23 | # .idea/tasks.xml 24 | # .idea/dictionaries 25 | # and these sensitive or high-churn files: 26 | # .idea/dataSources.ids 27 | # .idea/dataSources.xml 28 | # .idea/sqlDataSources.xml 29 | # .idea/dynamic.xml 30 | # and, if using gradle:: 31 | # .idea/gradle.xml 32 | # .idea/libraries 33 | 34 | ## File-based project format 35 | *.ipr 36 | *.iws 37 | 38 | ## Additional for IntelliJ 39 | out/ 40 | 41 | # generated by mpeltonen/sbt-idea plugin 42 | .idea_modules/ 43 | 44 | # generated by JIRA plugin 45 | atlassian-ide-plugin.xml 46 | 47 | # generated by Crashlytics plugin (for Android Studio and Intellij) 48 | com_crashlytics_export_strings.xml 49 | 50 | 51 | ### OSX ### 52 | .DS_Store 53 | .AppleDouble 54 | .LSOverride 55 | 56 | # Icon must end with two \r 57 | Icon 58 | 59 | 60 | # Thumbnails 61 | ._* 62 | 63 | # Files that might appear on external disk 64 | .Spotlight-V100 65 | .Trashes 66 | 67 | # Directories potentially created on remote AFP share 68 | .AppleDB 69 | .AppleDesktop 70 | Network Trash Folder 71 | Temporary Items 72 | .apdisk 73 | 74 | 75 | ### vim ### 76 | [._]*.s[a-w][a-z] 77 | [._]s[a-w][a-z] 78 | *.un~ 79 | Session.vim 80 | .netrwhist 81 | *~ 82 | 83 | 84 | ### Node ### 85 | # Logs 86 | logs 87 | *.log 88 | 89 | # Runtime data 90 | pids 91 | *.pid 92 | *.seed 93 | 94 | # Directory for instrumented libs generated by jscoverage/JSCover 95 | lib-cov 96 | 97 | # Coverage directory used by tools like istanbul 98 | coverage 99 | 100 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 101 | .grunt 102 | 103 | # Compiled binary addons (http://nodejs.org/api/addons.html) 104 | build/Release 105 | 106 | # Dependency directory 107 | # Commenting this out is preferred by some people, see 108 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 109 | node_modules 110 | 111 | # Users Environment Variables 112 | .lock-wscript 113 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": false, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 2, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "regexp": true, 16 | "undef": true, 17 | "unused": false, 18 | "strict": true, 19 | "trailing": true, 20 | "smarttabs": true, 21 | "globals": { 22 | "angular": false, 23 | "after": false, 24 | "afterEach": false, 25 | "before": false, 26 | "beforeEach": false, 27 | "browser": false, 28 | "describe": false, 29 | "expect": false, 30 | "inject": false, 31 | "it": false, 32 | "jasmine": false, 33 | "jQuery": false, 34 | "spyOn": false 35 | } 36 | } -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /* License: MIT. 2 | * Copyright (C) 2014 Michi Kono 3 | */ 4 | 5 | 'use strict'; 6 | 7 | module.exports = function (grunt) { 8 | // configs located in grunt/` 9 | require('load-grunt-config')(grunt); 10 | 11 | grunt.registerTask('test', [ 12 | 'jshint', 13 | 'karma' 14 | ]); 15 | 16 | grunt.registerTask('build', [ 17 | 'jshint', 18 | 'ngAnnotate' 19 | ]); 20 | 21 | grunt.registerTask('default', ['build']); 22 | }; 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Michi Kono 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This Angular directive enables a "loading" view while performing asynchronous requests. The directive watches a specific value you may be 4 | interested in. For example, your controller: 5 | 6 | ```js 7 | angular.module('your app') 8 | .controller('ExampleCtrl', function ($scope, $timeout) { 9 | $timeout(function() { 10 | $scope.myAsyncValue = 'hello from the server'; 11 | }, 2000) 12 | }); 13 | ``` 14 | 15 | And in your view: 16 | 17 | ```html 18 | 19 | loading... 20 | {{myAsyncValue}} 21 | 22 | ``` 23 | 24 | Here's what would happen: 25 | 26 | 1. "Loading" would initially appear 27 | 2. Two seconds later, "hello from the server" would show 28 | 29 | ## Why is this better than ng-if="variableName"? 30 | 31 | This directive helps remove potentially complex condition checking from the view since standard falsey checks in the view 32 | can't always distinguish between incomplete requests and empty responses. This illustrates the example better; see this 33 | controller: 34 | 35 | ```js 36 | angular.module('your app') 37 | .controller('ExampleCtrl', function ($scope, $timeout) { 38 | $timeout(function() { 39 | $scope.myAsyncValue = null; 40 | }, 2000) 41 | }); 42 | ``` 43 | 44 | And in your view: 45 | 46 | ```html 47 | 48 | loading... 49 | 50 |
{{myAsyncValue}}
51 |
No result 52 | 53 | ``` 54 | 55 | This would yield: 56 | 57 | 1. "Loading" would initially appear 58 | 2. Two seconds later, "No result" would show 59 | 60 | Any nested directives (if any) in `wait-done`, would not be processed until the `until` condition is met (see technical notes). 61 | 62 | # Requirements 63 | 64 | Tested in IE8+, latest Chrome, and latest Safari. Angular 1.2+. 65 | 66 | # Installing 67 | 68 | ```shell 69 | bower install -S angular-wait 70 | ``` 71 | 72 | Include the script and then Integrate into your app: 73 | 74 | ```js 75 | var myapp = angular.module('myapp', ['michiKono']); 76 | ``` 77 | 78 | # Usage 79 | 80 | Simply define the `wait` directive with `wait-loading` (mandatory) and `wait-done` nodes inside it as shown below: 81 | 82 | ```html 83 | 84 | shown while waiting 85 | shown when finished 86 | 87 | 88 | 89 | shown while waiting 90 | shown when finished 91 | 92 | 93 | 94 | shown while waiting 95 | shown when finished 96 | 97 | ``` 98 | 99 | ## Wait Until _____ 100 | 101 | All three available attributes to the directive watch the passed condition or variable until its value matches 102 | the asked state. For example the following uses all immediately render the `wait-done` nodes: 103 | 104 | ```html 105 | 106 | not shown 107 | SHOWS IMMEDIATELY 108 | 109 | 110 | 111 | not shown 112 | SHOWS IMMEDIATELY 113 | 114 | 115 | 116 | not shown 117 | SHOWS IMMEDIATELY 118 | 119 | ``` 120 | 121 | Note that the matching is using triple equals (`===`). This means that falsey values for the `until-not-null` do not 122 | necessarily trigger it. The following example illustrates this: 123 | 124 | ```html 125 | 126 | SHOWN 127 | not shown 128 | 129 | 130 | 131 | SHOWN 132 | not shown 133 | 134 | 135 | 136 | SHOWN 137 | not shown 138 | 139 | ``` 140 | 141 | ## Technical notes ## 142 | 143 | The inner contents are using transclusion can handle child directives. Inner directives are not 144 | processed at all (compile or controller methods) until the `wait-done` node renders. 145 | 146 | ## Releases ## 147 | 148 | * 1.0.2 Aug 23, 2014 - Inner directives not processed until done node shows 149 | * 1.0.1 Aug 23, 2014 - Support for minification by using ngAnnotate 150 | * 1.0.0 Aug 23, 2014 - Initial Release 151 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-wait", 3 | "version": "1.0.1", 4 | "authors": [ 5 | "Michi Kono " 6 | ], 7 | "description": "An Angular directive for showing different content while an asynchronous request is pending", 8 | "main": "dist/angular-wait.js", 9 | "keywords": [ 10 | "angular", 11 | "wait", 12 | "waiting", 13 | "directive", 14 | "load", 15 | "loading" 16 | ], 17 | "license": "MIT", 18 | "homepage": "http://www.michikono.com", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "tests" 25 | ], 26 | "dependencies": { 27 | }, 28 | "devDependencies": { 29 | "angular": "~1.2", 30 | "angular-mocks": "~1.2", 31 | "jasmine": "~2.0.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /dist/angular-wait.js: -------------------------------------------------------------------------------- 1 | /** 2 | * angular-wait version 1.0.2 3 | * License: MIT. 4 | * Copyright (C) 2014 Michi Kono 5 | * https://github.com/michikono/angular-wait 6 | */ 7 | 8 | 'use strict'; 9 | 10 | (function (window) { 11 | var angular = window.angular; 12 | angular 13 | .module('michiKono', []) 14 | .controller('waitDirectiveCtrl', ['$scope', '$element', function WaitDirectiveCtrl($scope, $element) { 15 | $scope.show = false; 16 | var childScopes = []; 17 | 18 | var updateChildren = function () { 19 | for (var i = 0; i < childScopes.length; i++) { 20 | childScopes[i].show = $scope.show; 21 | } 22 | }; 23 | this.registerChild = function (scope) { 24 | childScopes.push(scope); 25 | updateChildren(); 26 | }; 27 | 28 | $scope.$watch('untilNotNull', function (newValues, oldValues, scope) { 29 | if (typeof newValues !== 'undefined' && newValues !== null) { 30 | $scope.show = true; 31 | updateChildren(); 32 | } 33 | }); 34 | $scope.$watch('untilNotFalse', function (newValues, oldValues, scope) { 35 | if (typeof newValues !== 'undefined' && newValues !== false) { 36 | $scope.show = true; 37 | updateChildren(); 38 | } 39 | }); 40 | $scope.$watch('untilNotUndefined', function (newValues, oldValues, scope) { 41 | if (typeof newValues !== 'undefined') { 42 | $scope.show = true; 43 | updateChildren(); 44 | } 45 | }); 46 | }]) 47 | .directive('wait', function () { 48 | return { 49 | controller: 'waitDirectiveCtrl', 50 | restrict: 'AE', 51 | scope: { 52 | // these assume "when no longer undefined and..." 53 | untilNotNull: '=', 54 | untilNotFalse: '=', 55 | untilNotUndefined: '=' 56 | }, 57 | link: function postLink(scope, element, attrs) { 58 | } 59 | }; 60 | }) 61 | .directive('waitLoading', function () { 62 | return { 63 | restrict: 'EA', 64 | replace: true, 65 | template: '', 66 | transclude: true, 67 | require: '^wait', 68 | link: function link(scope, $element, attrs, controller, transclude) { 69 | scope.$watch('show', function (contents, old) { 70 | $element.html(''); 71 | if (!contents) { 72 | transclude(scope, function (clone) { 73 | $element.html(''); 74 | $element.append(clone); 75 | }); 76 | } 77 | }); 78 | // why we need something like this: http://stackoverflow.com/questions/16866749/access-parent-scope-in-transcluded-directive 79 | controller.registerChild(scope); 80 | } 81 | }; 82 | }) 83 | .directive('waitDone', function () { 84 | return { 85 | priority: 1, 86 | terminal: true, 87 | restrict: 'EA', 88 | replace: true, 89 | template: '', 90 | transclude: true, 91 | scope: false, 92 | require: '^wait', 93 | link: function link(scope, $element, attrs, controller, transclude) { 94 | scope.$watch('show', function (contents, old) { 95 | $element.html(''); 96 | if (contents) { 97 | transclude(scope, function (clone) { 98 | $element.html(''); 99 | $element.append(clone); 100 | }); 101 | } 102 | }); 103 | controller.registerChild(scope); 104 | } 105 | }; 106 | }); 107 | }(window)); 108 | -------------------------------------------------------------------------------- /grunt/jshint.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | options: { 3 | jshintrc: '.jshintrc' 4 | }, 5 | all: [ 6 | 'Gruntfile.js', 7 | 'grunt/*.js', 8 | 'src/*.js', 9 | 'test/*.js', 10 | 'karma.conf.js' 11 | ] 12 | }; -------------------------------------------------------------------------------- /grunt/karma.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | unit: { 3 | configFile: 'karma.conf.js', 4 | singleRun: true 5 | } 6 | }; -------------------------------------------------------------------------------- /grunt/ngAnnotate.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | options: { 3 | // Tells if ngAnnotate should add annotations (true by default). 4 | add: true, 5 | 6 | // Tells if ngAnnotate should remove annotations (false by default). 7 | remove: false, 8 | 9 | // If provided, only strings matched by the regexp are interpreted as module 10 | // names. You can provide both a regular expression and a string representing 11 | // one. See README of ng-annotate for further details: 12 | // https://npmjs.org/package/ng-annotate 13 | // regexp: regexp, 14 | 15 | // Switches the quote type for strings in the annotations array to single 16 | // ones; e.g. '$scope' instead of "$scope" (false by default). 17 | singleQuotes: true 18 | 19 | // If ngAnnotate supports a new option that is not directly supported via 20 | // this grunt task yet, you can pass it here. These options gets merged 21 | // with the above specific to ngAnnotate. Options passed here have lower 22 | // precedence to the direct ones described above. 23 | // ngAnnotateOptions: {} 24 | }, 25 | dist: { 26 | cwd: '.', 27 | src: 'src/angular-wait.js', 28 | dest: 'dist/angular-wait.js' 29 | } 30 | }; -------------------------------------------------------------------------------- /grunt/uglify.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | dist: { 3 | files: { 4 | 'dist/angular-wait.min.js': 'dist/angular-wait.js' 5 | } 6 | } 7 | }; -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | /* License: MIT. 2 | * Copyright (C) 2013, 2014, Uri Shaked and contributors. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | module.exports = function (config) { 8 | config.set({ 9 | basePath: '', 10 | frameworks: ['jasmine'], 11 | logLevel: config.LOG_INFO, 12 | browsers: ['PhantomJS'], 13 | autoWatch: true, 14 | reporters: ['dots', 'coverage'], 15 | files: [ 16 | 'bower_components/angular/angular.js', 17 | 'src/*.js', 18 | 'bower_components/angular-mocks/angular-mocks.js', 19 | 'test/mocks/*.js', 20 | 'test/*.js' 21 | ], 22 | preprocessors: { 23 | 'src/*.js': 'coverage' 24 | }, 25 | coverageReporter: { 26 | type: 'lcov', 27 | dir: 'coverage/' 28 | } 29 | }); 30 | }; 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-wait", 3 | "version": "1.0.1", 4 | "repository": { 5 | "type": "git", 6 | "url": "https://github.com/michikono/angular-wait.git" 7 | }, 8 | "main": "dist/angular-wait.js", 9 | "dependencies": { 10 | "grunt-ng-annotate": "^0.3.2" 11 | }, 12 | "devDependencies": { 13 | "grunt-cli": "*", 14 | "grunt-contrib-jshint": "~0.10.0", 15 | "grunt-contrib-uglify": "~0.2.7", 16 | "grunt-karma": "~0.8.0", 17 | "jshint-stylish": "~0.1.3", 18 | "karma": "~0.12.0", 19 | "karma-jasmine": "~0.2.2", 20 | "karma-phantomjs-launcher": "~0.1.1", 21 | "load-grunt-config": "^0.12.0", 22 | "load-grunt-tasks": "~0.4.0" 23 | }, 24 | "engines": { 25 | "node": ">=0.10.0" 26 | }, 27 | "scripts": { 28 | "test": "grunt test" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/angular-wait.js: -------------------------------------------------------------------------------- 1 | /** 2 | * angular-wait version 1.0.2 3 | * License: MIT. 4 | * Copyright (C) 2014 Michi Kono 5 | * https://github.com/michikono/angular-wait 6 | */ 7 | 8 | 'use strict'; 9 | 10 | (function (window) { 11 | var angular = window.angular; 12 | angular 13 | .module('michiKono', []) 14 | .controller('waitDirectiveCtrl', function WaitDirectiveCtrl($scope, $element) { 15 | $scope.show = false; 16 | var childScopes = []; 17 | 18 | var updateChildren = function () { 19 | for (var i = 0; i < childScopes.length; i++) { 20 | childScopes[i].show = $scope.show; 21 | } 22 | }; 23 | this.registerChild = function (scope) { 24 | childScopes.push(scope); 25 | updateChildren(); 26 | }; 27 | 28 | $scope.$watch('untilNotNull', function (newValues, oldValues, scope) { 29 | if (typeof newValues !== 'undefined' && newValues !== null) { 30 | $scope.show = true; 31 | updateChildren(); 32 | } 33 | }); 34 | $scope.$watch('untilNotFalse', function (newValues, oldValues, scope) { 35 | if (typeof newValues !== 'undefined' && newValues !== false) { 36 | $scope.show = true; 37 | updateChildren(); 38 | } 39 | }); 40 | $scope.$watch('untilNotUndefined', function (newValues, oldValues, scope) { 41 | if (typeof newValues !== 'undefined') { 42 | $scope.show = true; 43 | updateChildren(); 44 | } 45 | }); 46 | }) 47 | .directive('wait', function () { 48 | return { 49 | controller: 'waitDirectiveCtrl', 50 | restrict: 'AE', 51 | scope: { 52 | // these assume "when no longer undefined and..." 53 | untilNotNull: '=', 54 | untilNotFalse: '=', 55 | untilNotUndefined: '=' 56 | }, 57 | link: function postLink(scope, element, attrs) { 58 | } 59 | }; 60 | }) 61 | .directive('waitLoading', function () { 62 | return { 63 | restrict: 'EA', 64 | replace: true, 65 | template: '', 66 | transclude: true, 67 | require: '^wait', 68 | link: function link(scope, $element, attrs, controller, transclude) { 69 | scope.$watch('show', function (contents, old) { 70 | $element.html(''); 71 | if (!contents) { 72 | transclude(scope, function (clone) { 73 | $element.html(''); 74 | $element.append(clone); 75 | }); 76 | } 77 | }); 78 | // why we need something like this: http://stackoverflow.com/questions/16866749/access-parent-scope-in-transcluded-directive 79 | controller.registerChild(scope); 80 | } 81 | }; 82 | }) 83 | .directive('waitDone', function () { 84 | return { 85 | priority: 1, 86 | terminal: true, 87 | restrict: 'EA', 88 | replace: true, 89 | template: '', 90 | transclude: true, 91 | scope: false, 92 | require: '^wait', 93 | link: function link(scope, $element, attrs, controller, transclude) { 94 | scope.$watch('show', function (contents, old) { 95 | $element.html(''); 96 | if (contents) { 97 | transclude(scope, function (clone) { 98 | $element.html(''); 99 | $element.append(clone); 100 | }); 101 | } 102 | }); 103 | controller.registerChild(scope); 104 | } 105 | }; 106 | }); 107 | }(window)); 108 | -------------------------------------------------------------------------------- /test/angular-wait.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Directive: wait', function () { 4 | // load the directive's module 5 | beforeEach(module('michiKono')); 6 | 7 | var element, 8 | $scope, 9 | $rootScope, 10 | $compile, 11 | $templateCache; 12 | 13 | var doDirective = function (html, $compile) { 14 | element = angular.element(html); 15 | var compiled = $compile(element)($scope); 16 | compiled.scope().$digest(); 17 | return element; 18 | }; 19 | 20 | beforeEach(inject(function (_$compile_, _$rootScope_, _$templateCache_) { 21 | $rootScope = _$rootScope_; 22 | $compile = _$compile_; 23 | $templateCache = _$templateCache_; 24 | $scope = $rootScope.$new(); 25 | })); 26 | 27 | describe('attribute until-not-false', function () { 28 | it('should show "noiseLOADING" while initially waiting and hide wait-done contents', inject(function ($compile) { 29 | element = doDirective('noiseLOADINGnoiseDONE', $compile); 30 | expect(element.html().replace(/ class="ng-scope"/g, '')).toMatch(/>noise<\/span>LOADING<\/span>noise<\/span>DONE<\/span>noiseLOADINGnoiseDONE', $compile); 36 | expect(element.html().replace(/ class="ng-scope"/g, '')).not.toMatch(/>noise<\/span>LOADING<\/span>noise<\/span>DONE<\/span>noiseLOADING', $compile); 42 | expect(element.html().replace(/ class="ng-scope"/g, '')).not.toMatch(/>noise<\/span>LOADING<\/span>noiseLOADINGnoiseDONE', $compile); 48 | expect(element.html().replace(/ class="ng-scope"/g, '')).toMatch(/>noise<\/span>LOADING<\/span>noise<\/span>DONE<\/span>noise<\/span>LOADING<\/span>noise<\/span>DONE<\/span>noiseLOADING" while initially waiting and hide wait-done contents', inject(function ($compile) { 60 | element = doDirective('noiseLOADINGnoiseDONE', $compile); 61 | expect(element.html().replace(/ class="ng-scope"/g, '')).toMatch(/>noise<\/span>LOADING<\/span>noise<\/span>DONE<\/span>noiseLOADINGnoiseDONE', $compile); 67 | expect(element.html().replace(/ class="ng-scope"/g, '')).not.toMatch(/>noise<\/span>LOADING<\/span>noise<\/span>DONE<\/span>noise<\/span>LOADING<\/span>', $compile); 73 | expect(element.html().replace(/ class="ng-scope"/g, '')).not.toMatch(/>noise<\/span>LOADING<\/span>noiseLOADINGnoiseDONE', $compile); 79 | expect(element.html().replace(/ class="ng-scope"/g, '')).toMatch(/>noise<\/span>LOADING<\/span>noise<\/span>DONE<\/span>noise<\/span>LOADING<\/span>noise<\/span>DONE<\/span>noiseLOADING" while initially waiting and hide wait-done contents', inject(function ($compile) { 91 | element = doDirective('noiseLOADINGnoiseDONE', $compile); 92 | expect(element.html().replace(/ class="ng-scope"/g, '')).toMatch(/>noise<\/span>LOADING<\/span>noise<\/span>DONE<\/span>noiseLOADINGnoiseDONE', $compile); 98 | expect(element.html().replace(/ class="ng-scope"/g, '')).not.toMatch(/>noise<\/span>LOADING<\/span>noise<\/span>DONE<\/span>noiseLOADING', $compile); 104 | expect(element.html().replace(/ class="ng-scope"/g, '')).not.toMatch(/>noise<\/span>LOADING<\/span>noiseLOADINGnoiseDONE', $compile); 109 | expect(element.html().replace(/ class="ng-scope"/g, '')).toMatch(/>noise<\/span>LOADING<\/span>noise<\/span>DONE<\/span>noise<\/span>LOADING<\/span>noise<\/span>DONE<\/span>', $compile); 123 | $scope.$digest(); 124 | expect($scope.doNotRender).toBeNull(); 125 | })); 126 | 127 | it('should process inner scope changes when done condition met', inject(function ($compile) { 128 | $scope.doNotRender = null; 129 | element = doDirective('', $compile); 130 | $scope.$digest(); 131 | expect($scope.doNotRender).toEqual('value'); 132 | })); 133 | 134 | it('should run controller and compile methods of inner directives when done condition met', inject(function ($compile) { 135 | $scope.exampleDirective = {}; 136 | element = doDirective('', $compile); 137 | $scope.$digest(); 138 | expect($scope.exampleDirective.controller).toBe(true); 139 | expect($scope.exampleDirective.pre).toBe(true); 140 | expect($scope.exampleDirective.post).toBe(true); 141 | expect(element.html().replace(/ class="ng-scope"/g, '')).toMatch(/<\/example-stub>/); 142 | })); 143 | 144 | it('should not run controller and compile methods of inner directives until done condition met', inject(function ($compile) { 145 | $scope.exampleDirective = {}; 146 | element = doDirective('', $compile); 147 | $scope.$digest(); 148 | expect($scope.exampleDirective.compile).not.toBeDefined(); 149 | expect($scope.exampleDirective.controller).not.toBeDefined(); 150 | expect($scope.exampleDirective.pre).not.toBeDefined(); 151 | expect($scope.exampleDirective.post).not.toBeDefined(); 152 | expect(element.html().replace(/ class="ng-scope"/g, '')).not.toMatch(/<\/example-directive>/); 153 | })); 154 | }); 155 | }); 156 | -------------------------------------------------------------------------------- /test/mocks/example-directive.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function (window) { 4 | var angular = window.angular; 5 | angular 6 | .module('michiKono') 7 | .directive('exampleDirective', function () { 8 | return { 9 | restrict: 'E', 10 | replace: true, 11 | template: '', 12 | controller: function ($scope) { 13 | $scope.exampleDirective.controller = true; 14 | }, 15 | compile: function () { 16 | return { 17 | pre: function ($scope) { 18 | $scope.exampleDirective.pre = true; 19 | }, 20 | post: function ($scope) { 21 | $scope.exampleDirective.post = true; 22 | } 23 | }; 24 | } 25 | }; 26 | }); 27 | }(window)); 28 | --------------------------------------------------------------------------------