Skip to content

Commit a402415

Browse files
committed
fix(uiView): test pass against 1.0.8 and 1.2.4
1 parent e994389 commit a402415

File tree

5 files changed

+200
-138
lines changed

5 files changed

+200
-138
lines changed

files.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ routerFiles = {
2525
angular: function(version) {
2626
return [
2727
'lib/angular-' + version + '/angular.js',
28-
'lib/angular-' + version + '/angular-mocks.js',
29-
];
28+
'lib/angular-' + version + '/angular-mocks.js'
29+
].concat(version === '1.2.4' ? ['lib/angular-' + version + '/angular-animate.js'] : []);
3030
}
3131
};
3232

src/viewDirective.js

+106-75
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
*
1616
* @param {string} ui-view A view name.
1717
*/
18-
$ViewDirective.$inject = ['$state', '$compile', '$controller', '$injector', '$uiViewScroll'];
19-
function $ViewDirective( $state, $compile, $controller, $injector, $uiViewScroll) {
18+
$ViewDirective.$inject = ['$state', '$compile', '$controller', '$injector', '$uiViewScroll', '$document'];
19+
function $ViewDirective( $state, $compile, $controller, $injector, $uiViewScroll, $document) {
2020

2121
function getService() {
2222
return ($injector.has) ? function(service) {
@@ -30,118 +30,149 @@ function $ViewDirective( $state, $compile, $controller, $injector, $ui
3030
};
3131
}
3232

33-
var viewIsUpdating = false, service = getService(),
34-
$animator = service('$animator'), $animate = service('$animate'),
35-
hasAnimator = !!($animator || $animate);
33+
var viewIsUpdating = false,
34+
service = getService(),
35+
$animator = service('$animator'),
36+
$animate = service('$animate');
3637

3738
// Returns a set of DOM manipulation functions based on whether animation
3839
// should be performed
39-
var renderer = function(shouldAnimate) {
40-
return (hasAnimator && shouldAnimate) ? {
41-
remove: function(element) { $animate.leave(element.contents()); },
42-
// remove: function(element) { animate.leave(element.contents(), element); },
43-
restore: function(compiled, element) { $animate.enter(compiled, element); },
44-
// restore: function(compiled, element) { animate.enter(compiled, element); },
45-
populate: function(template, element) {
46-
var contents = angular.element('<div></div>').html(template).contents();
47-
// animate.enter(contents, element);
48-
$animate.enter(contents, element);
49-
return contents;
50-
}
51-
} : {
52-
remove: function(element) { element.html(''); },
53-
restore: function(compiled, element) { element.append(compiled); },
54-
populate: function(template, element) {
55-
element.html(template);
56-
return element.contents();
57-
}
40+
function getRenderer(element, attrs, scope) {
41+
var statics = function() {
42+
return {
43+
leave: function (element) { element.remove(); },
44+
enter: function (element, parent, anchor) { anchor.after(element); }
45+
};
5846
};
59-
};
47+
48+
if ($animate) {
49+
return function(shouldAnimate) {
50+
return !shouldAnimate ? statics() : {
51+
enter: function(element, parent, anchor) { $animate.enter(element, null, anchor); },
52+
leave: function(element) { $animate.leave(element, function() { element.remove(); }); }
53+
};
54+
};
55+
}
56+
57+
if ($animator) {
58+
var animate = $animator && $animator(scope, attrs);
59+
60+
return function(shouldAnimate) {
61+
return !shouldAnimate ? statics() : {
62+
enter: function(element, parent, anchor) { animate.enter(element, parent); },
63+
leave: function(element) { animate.leave(element.contents(), element); }
64+
};
65+
};
66+
}
67+
68+
return statics;
69+
}
6070

6171
var directive = {
6272
restrict: 'ECA',
63-
terminal: true,
64-
priority: 1000,
65-
transclude: true,
66-
compile: function (element, attr, transclude) {
67-
return function(scope, element, attr) {
68-
var viewScope, viewLocals,
69-
name = attr[directive.name] || attr.name || '',
70-
onloadExp = attr.onload || '',
71-
autoscrollExp = attr.autoscroll,
72-
animate = $animator && $animator(scope, attr),
73-
initialView = transclude(scope);
74-
75-
// Put back the compiled initial view
76-
element.append(initialView);
77-
78-
// Find the details of the parent view directive (if any) and use it
79-
// to derive our own qualified view name, then hang our own details
80-
// off the DOM so child directives can find it.
81-
var parent = element.parent().inheritedData('$uiView');
82-
if (name.indexOf('@') < 0) name = name + '@' + (parent ? parent.state.name : '');
73+
compile: function (element, attrs) {
74+
var initial = element.html(),
75+
isDefault = true,
76+
anchor = angular.element($document[0].createComment(' ui-view-anchor ')),
77+
parentEl = element.parent();
78+
79+
element.prepend(anchor);
80+
81+
return function ($scope) {
82+
var inherited = parentEl.inheritedData('$uiView');
83+
84+
var currentScope, currentEl, viewLocals,
85+
name = attrs[directive.name] || attrs.name || '',
86+
onloadExp = attrs.onload || '',
87+
autoscrollExp = attrs.autoscroll,
88+
renderer = getRenderer(element, attrs, $scope);
89+
90+
if (name.indexOf('@') < 0) name = name + '@' + (inherited ? inherited.state.name : '');
8391
var view = { name: name, state: null };
84-
element.data('$uiView', view);
8592

86-
var eventHook = function() {
93+
var eventHook = function () {
8794
if (viewIsUpdating) return;
8895
viewIsUpdating = true;
8996

90-
try { updateView(true); } catch (e) {
97+
try { updateView(); } catch (e) {
9198
viewIsUpdating = false;
9299
throw e;
93100
}
94101
viewIsUpdating = false;
95102
};
96103

97-
scope.$on('$stateChangeSuccess', eventHook);
98-
scope.$on('$viewContentLoading', eventHook);
99-
updateView(false);
104+
$scope.$on('$stateChangeSuccess', eventHook);
105+
$scope.$on('$viewContentLoading', eventHook);
100106

101-
function updateView(doAnimate) {
102-
var locals = $state.$current && $state.$current.locals[name];
103-
if (locals === viewLocals) return; // nothing to do
104-
var render = renderer(doAnimate);
107+
updateView();
105108

106-
// Remove existing content
107-
render.remove(element);
109+
function cleanupLastView() {
110+
if (currentEl) {
111+
renderer(true).leave(currentEl);
112+
currentEl = null;
113+
}
108114

109-
// Destroy previous view scope
110-
if (viewScope) {
111-
viewScope.$destroy();
112-
viewScope = null;
115+
if (currentScope) {
116+
currentScope.$destroy();
117+
currentScope = null;
113118
}
119+
}
114120

115-
if (!locals) {
116-
viewLocals = null;
117-
view.state = null;
121+
function updateView() {
122+
var locals = $state.$current && $state.$current.locals[name];
123+
124+
if (isDefault) {
125+
isDefault = false;
126+
element.replaceWith(anchor);
127+
}
118128

119-
// Restore the initial view
120-
return render.restore(initialView, element);
129+
if (!locals) {
130+
cleanupLastView();
131+
currentEl = element.clone();
132+
currentEl.html(initial);
133+
anchor.after(currentEl);
134+
135+
currentScope = $scope.$new();
136+
$compile(currentEl.contents())(currentScope);
137+
return;
121138
}
122139

140+
if (locals === viewLocals) return; // nothing to do
141+
142+
cleanupLastView();
143+
144+
currentEl = element.clone();
145+
currentEl.html(locals.$template ? locals.$template : initial);
146+
renderer(true).enter(currentEl, parentEl, anchor);
147+
148+
currentEl.data('$uiView', view);
149+
123150
viewLocals = locals;
124151
view.state = locals.$$state;
125152

126-
var link = $compile(render.populate(locals.$template, element));
127-
viewScope = scope.$new();
153+
var link = $compile(currentEl.contents());
154+
155+
currentScope = $scope.$new();
128156

129157
if (locals.$$controller) {
130-
locals.$scope = viewScope;
158+
locals.$scope = currentScope;
131159
var controller = $controller(locals.$$controller, locals);
132-
element.children().data('$ngControllerController', controller);
160+
currentEl.children().data('$ngControllerController', controller);
133161
}
134-
link(viewScope);
135-
viewScope.$emit('$viewContentLoaded');
136-
if (onloadExp) viewScope.$eval(onloadExp);
137162

138-
if (!angular.isDefined(autoscrollExp) || !autoscrollExp || scope.$eval(autoscrollExp)) {
139-
$uiViewScroll(element);
163+
link(currentScope);
164+
165+
currentScope.$emit('$viewContentLoaded');
166+
if (onloadExp) currentScope.$eval(onloadExp);
167+
168+
if (!angular.isDefined(autoscrollExp) || !autoscrollExp || $scope.$eval(autoscrollExp)) {
169+
$uiViewScroll(currentEl);
140170
}
141171
}
142172
};
143173
}
144174
};
175+
145176
return directive;
146177
}
147178

test/compat/matchers.js

+2-6
Original file line numberDiff line numberDiff line change
@@ -149,15 +149,11 @@ beforeEach(function() {
149149
angular.element(this.actual).hasClass(clazz);
150150
},
151151

152-
/**
153-
* innerText compatibility shim for Firefox
154-
*/
155152
toMatchText: function(text) {
156-
var isFirefox = /firefox/i.test(navigator.userAgent);
157153
this.message = function() {
158-
return "Expected '" + this.actual.nodeName + "' element to have text '" + text + "'";
154+
return "Expected '" + (this.actual && this.actual.nodeName) + "' element to have text '" + text + "'";
159155
};
160-
return this.actual[isFirefox ? 'textContent' : 'innerText'] === text;
156+
return this.actual && this.actual.text && this.actual.text() === text;
161157
}
162158

163159
});

test/stateDirectivesSpec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ describe('uiStateRef', function() {
196196
scope.$apply();
197197

198198
$compile(el)(scope);
199-
template = $compile(angular.element('<ui-view></ui-view>'))(scope);
199+
template = $compile(angular.element('<div><ui-view></ui-view><div>'))(scope);
200200
scope.$digest();
201201
}));
202202

0 commit comments

Comments
 (0)