Skip to content

Commit f5f5851

Browse files
committed
fix(ionItem): make target attribute work properly
Closes #1521
1 parent e88659c commit f5f5851

File tree

4 files changed

+203
-192
lines changed

4 files changed

+203
-192
lines changed

Diff for: js/angular/directive/item.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
var ITEM_TPL_CONTENT_ANCHOR =
2-
'<a class="item-content" ng-href="{{$href()}}"></a>';
2+
'<a class="item-content" ng-href="{{$href()}}" target="{{$target()}}"></a>';
33
var ITEM_TPL_CONTENT =
44
'<div class="item-content"></div>';
55
/**
@@ -58,6 +58,9 @@ function($animate, $compile) {
5858
$scope.$href = function() {
5959
return $attrs.href || $attrs.ngHref;
6060
};
61+
$scope.$target = function() {
62+
return $attrs.target || '_self';
63+
};
6164
};
6265
}
6366
};

Diff for: test/unit/angular/directive/item.unit.js

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
describe('ionItem directive', function() {
2+
beforeEach(module('ionic'));
3+
function setup(attrs, content) {
4+
var el;
5+
inject(function($rootScope, $compile) {
6+
el = angular.element('<ion-item '+(attrs||'')+'>').html(content || '');
7+
el.data('$ionListController', {});
8+
$compile(el)($rootScope);
9+
$rootScope.$apply();
10+
});
11+
return el;
12+
}
13+
14+
it('should be simple item by default', function() {
15+
var el = setup('', '{{1}} <b>2</b>');
16+
expect(el.html()).toBe('1 <b>2</b>');
17+
expect(el.hasClass('item')).toBe(true);
18+
expect(el.hasClass('item-complex')).toBe(false);
19+
});
20+
it('should be complex if ui-sref', function() {
21+
var el = setup('ui-sref="something"');
22+
expect(el.hasClass('item item-complex')).toBe(true);
23+
expect(el.children()[0].tagName).toBe('A');
24+
expect(el.children().hasClass('item-content')).toBe(true);
25+
});
26+
['href', 'ng-href'].forEach(function(attr) {
27+
it('should be complex anchor if '+attr+' is defined', function() {
28+
var el = setup(attr+'="something/{{foo}}"');
29+
expect(el.hasClass('item item-complex')).toBe(true);
30+
expect(el.children()[0].tagName).toBe('A');
31+
expect(el.children().hasClass('item-content')).toBe(true);
32+
expect(el.children().attr('href')).toBe('something/');
33+
el.scope().$apply('foo = 44');
34+
expect(el.children().attr('href')).toBe('something/44');
35+
});
36+
});
37+
it('complex item should have target self by default', function() {
38+
var el = setup('href="foo"');
39+
expect(el.find('a').attr('target')).toBe('_self');
40+
});
41+
it('complex item should have target if specified', function() {
42+
var el = setup('href="foo" target="bar"');
43+
expect(el.find('a').attr('target')).toBe('bar');
44+
});
45+
['ion-option-button','ion-reorder-button','ion-delete-button'].forEach(function(tag) {
46+
it('should be complex div if '+tag+' is found', function() {
47+
var el = setup('', tag);
48+
expect(el.hasClass('item item-complex')).toBe(true);
49+
expect(el.children()[0].tagName).toBe('DIV');
50+
expect(el.children().hasClass('item-content')).toBe(true);
51+
expect(el.children().html()).toBe(tag);
52+
});
53+
});
54+
});
55+
56+
describe('ionDeleteButton directive', function() {
57+
beforeEach(module('ionic'));
58+
it('should have delete button', inject(function($compile, $rootScope) {
59+
var setSpy = jasmine.createSpy('setDeleteButton');
60+
var el = angular.element('<ion-item><ion-delete-button></ion-delete-button></ion-item>');
61+
el.data('$ionListController', {
62+
showDelete: function() { return false; }
63+
});
64+
$compile(el)($rootScope.$new());
65+
$rootScope.$apply();
66+
67+
var deleteContainer = angular.element(el[0].querySelector('.item-left-edit.item-delete.ng-hide'));
68+
expect(deleteContainer.length).toBe(1);
69+
expect(deleteContainer.children().hasClass('button icon button-icon')).toBe(true);
70+
}));
71+
it('should unhide if delete is shown', inject(function($compile, $rootScope) {
72+
var setSpy = jasmine.createSpy('setDeleteButton');
73+
var el = angular.element('<ion-item><ion-delete-button></ion-delete-button></ion-item>');
74+
el.data('$ionListController', {
75+
showDelete: function() { return true; }
76+
});
77+
$compile(el)($rootScope.$new());
78+
$rootScope.$apply();
79+
80+
var deleteContainer = angular.element(el[0].querySelector('.item-left-edit.item-delete'));
81+
expect(deleteContainer.length).toBe(1);
82+
expect(deleteContainer.hasClass('ng-hide')).toBe(false);
83+
}));
84+
});
85+
86+
describe('ionReorderButton directive', function() {
87+
beforeEach(module('ionic'));
88+
it('should have reorder button', inject(function($compile, $rootScope) {
89+
var setSpy = jasmine.createSpy('setReorderButton');
90+
var el = angular.element('<ion-item><ion-reorder-button></ion-reorder-button></ion-item>');
91+
el.data('$ionListController', {
92+
showReorder: function() { return false; }
93+
});
94+
$compile(el)($rootScope.$new());
95+
$rootScope.$apply();
96+
97+
var reorderContainer = angular.element(el[0].querySelector('.item-right-edit.item-reorder.ng-hide'));
98+
expect(reorderContainer.length).toBe(1);
99+
expect(reorderContainer.children().hasClass('button icon button-icon')).toBe(true);
100+
expect(reorderContainer.attr('data-prevent-scroll')).toBe('true');
101+
expect(reorderContainer.children().attr('data-prevent-scroll')).toBe('true');
102+
}));
103+
it('should remove ng-hide if reorder is already active', inject(function($compile, $rootScope) {
104+
var setSpy = jasmine.createSpy('setReorderButton');
105+
var el = angular.element('<ion-item><ion-reorder-button></ion-reorder-button></ion-item>');
106+
el.data('$ionListController', {
107+
showReorder: function() { return true; }
108+
});
109+
$compile(el)($rootScope.$new());
110+
$rootScope.$apply();
111+
var reorderContainer = angular.element(el[0].querySelector('.item-right-edit.item-reorder'));
112+
expect(reorderContainer.length).toBe(1);
113+
expect(reorderContainer.hasClass('ng-hide')).toBe(false);
114+
}));
115+
});
116+
117+
describe('ionOptionButton directive', function() {
118+
beforeEach(module('ionic'));
119+
it('should have option button', inject(function($compile, $rootScope) {
120+
var setSpy = jasmine.createSpy('setOptionButton');
121+
var el = angular.element('<ion-item><ion-option-button></ion-option-button></ion-item>');
122+
el.data('$ionListController', {
123+
showDelete: function() { return false; }
124+
});
125+
$compile(el)($rootScope.$new());
126+
$rootScope.$apply();
127+
128+
var optionContainer = angular.element(el[0].querySelector('.item-options'));
129+
expect(optionContainer.length).toBe(1);
130+
expect(optionContainer.children().hasClass('button')).toBe(true);
131+
}));
132+
});

Diff for: test/unit/angular/directive/list.unit.js

-191
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,3 @@
1-
describe('$ionicList controller', function() {
2-
beforeEach(module('ionic'));
3-
function setup(attrs) {
4-
var ctrl;
5-
inject(function($controller, $rootScope) {
6-
var scope = $rootScope.$new();
7-
ctrl = $controller('$ionicList', {
8-
$scope: scope,
9-
$attrs: attrs || {},
10-
});
11-
ctrl.$scope = scope;
12-
});
13-
return ctrl;
14-
}
15-
16-
it('should register with handle', inject(function($ionicListDelegate) {
17-
spyOn($ionicListDelegate, '_registerInstance');
18-
var ctrl = setup({delegateHandle: 'foobar'});
19-
expect($ionicListDelegate._registerInstance)
20-
.toHaveBeenCalledWith(ctrl, 'foobar');
21-
}));
22-
23-
it('should register with given handle and deregister on destroy', inject(function($ionicListDelegate) {
24-
var deregisterSpy = jasmine.createSpy('deregister');
25-
spyOn($ionicListDelegate, '_registerInstance').andCallFake(function() {
26-
return deregisterSpy;
27-
});
28-
var ctrl = setup({
29-
delegateHandle: 'something'
30-
});
31-
expect($ionicListDelegate._registerInstance)
32-
.toHaveBeenCalledWith(ctrl, 'something');
33-
34-
expect(deregisterSpy).not.toHaveBeenCalled();
35-
ctrl.$scope.$destroy();
36-
expect(deregisterSpy).toHaveBeenCalled();
37-
}));
38-
39-
it('.showReorder sets/gets', function() {
40-
var ctrl = setup();
41-
expect(ctrl.showReorder()).toBe(false);
42-
ctrl.showReorder(true);
43-
expect(ctrl.showReorder()).toBe(true);
44-
});
45-
46-
it('.showDelete sets/gets', function() {
47-
var ctrl = setup();
48-
expect(ctrl.showDelete()).toBe(false);
49-
ctrl.showDelete(true);
50-
expect(ctrl.showDelete()).toBe(true);
51-
});
52-
53-
it('.canSwipeItems sets/gets', function() {
54-
var ctrl = setup();
55-
expect(ctrl.canSwipeItems()).toBe(true);
56-
ctrl.canSwipeItems(false);
57-
expect(ctrl.canSwipeItems()).toBe(false);
58-
});
59-
60-
it('.closeOptionButtons closes calls clearDragEffects', function() {
61-
var ctrl = setup();
62-
ctrl.listView = { clearDragEffects: jasmine.createSpy('clearDragEffects') };
63-
ctrl.closeOptionButtons();
64-
expect(ctrl.listView.clearDragEffects).toHaveBeenCalled();
65-
});
66-
});
67-
681
describe('ionList directive', function() {
692
beforeEach(module('ionic'));
703

@@ -228,127 +161,3 @@ describe('ionList directive', function() {
228161
}));
229162
});
230163

231-
describe('ionItem directive', function() {
232-
beforeEach(module('ionic'));
233-
function setup(attrs, content) {
234-
var el;
235-
inject(function($rootScope, $compile) {
236-
el = angular.element('<ion-item '+(attrs||'')+'>').html(content || '');
237-
el.data('$ionListController', {});
238-
$compile(el)($rootScope);
239-
$rootScope.$apply();
240-
});
241-
return el;
242-
}
243-
244-
it('should be simple item by default', function() {
245-
var el = setup('', '{{1}} <b>2</b>');
246-
expect(el.html()).toBe('1 <b>2</b>');
247-
expect(el.hasClass('item')).toBe(true);
248-
expect(el.hasClass('item-complex')).toBe(false);
249-
});
250-
it('should be complex if ui-sref', function() {
251-
var el = setup('ui-sref="something"');
252-
expect(el.hasClass('item item-complex')).toBe(true);
253-
expect(el.children()[0].tagName).toBe('A');
254-
expect(el.children().hasClass('item-content')).toBe(true);
255-
});
256-
['href', 'ng-href'].forEach(function(attr) {
257-
it('should be complex anchor if '+attr+' is defined', function() {
258-
var el = setup(attr+'="something/{{foo}}"');
259-
expect(el.hasClass('item item-complex')).toBe(true);
260-
expect(el.children()[0].tagName).toBe('A');
261-
expect(el.children().hasClass('item-content')).toBe(true);
262-
expect(el.children().attr('href')).toBe('something/');
263-
el.scope().$apply('foo = 44');
264-
expect(el.children().attr('href')).toBe('something/44');
265-
});
266-
});
267-
['ion-option-button','ion-reorder-button','ion-delete-button'].forEach(function(tag) {
268-
it('should be complex div if '+tag+' is found', function() {
269-
var el = setup('', tag);
270-
expect(el.hasClass('item item-complex')).toBe(true);
271-
expect(el.children()[0].tagName).toBe('DIV');
272-
expect(el.children().hasClass('item-content')).toBe(true);
273-
expect(el.children().html()).toBe(tag);
274-
});
275-
});
276-
});
277-
278-
describe('ionDeleteButton directive', function() {
279-
beforeEach(module('ionic'));
280-
it('should have delete button', inject(function($compile, $rootScope) {
281-
var setSpy = jasmine.createSpy('setDeleteButton');
282-
var el = angular.element('<ion-item><ion-delete-button></ion-delete-button></ion-item>');
283-
el.data('$ionListController', {
284-
showDelete: function() { return false; }
285-
});
286-
$compile(el)($rootScope.$new());
287-
$rootScope.$apply();
288-
289-
var deleteContainer = angular.element(el[0].querySelector('.item-left-edit.item-delete.ng-hide'));
290-
expect(deleteContainer.length).toBe(1);
291-
expect(deleteContainer.children().hasClass('button icon button-icon')).toBe(true);
292-
}));
293-
it('should unhide if delete is shown', inject(function($compile, $rootScope) {
294-
var setSpy = jasmine.createSpy('setDeleteButton');
295-
var el = angular.element('<ion-item><ion-delete-button></ion-delete-button></ion-item>');
296-
el.data('$ionListController', {
297-
showDelete: function() { return true; }
298-
});
299-
$compile(el)($rootScope.$new());
300-
$rootScope.$apply();
301-
302-
var deleteContainer = angular.element(el[0].querySelector('.item-left-edit.item-delete'));
303-
expect(deleteContainer.length).toBe(1);
304-
expect(deleteContainer.hasClass('ng-hide')).toBe(false);
305-
}));
306-
});
307-
308-
describe('ionReorderButton directive', function() {
309-
beforeEach(module('ionic'));
310-
it('should have reorder button', inject(function($compile, $rootScope) {
311-
var setSpy = jasmine.createSpy('setReorderButton');
312-
var el = angular.element('<ion-item><ion-reorder-button></ion-reorder-button></ion-item>');
313-
el.data('$ionListController', {
314-
showReorder: function() { return false; }
315-
});
316-
$compile(el)($rootScope.$new());
317-
$rootScope.$apply();
318-
319-
var reorderContainer = angular.element(el[0].querySelector('.item-right-edit.item-reorder.ng-hide'));
320-
expect(reorderContainer.length).toBe(1);
321-
expect(reorderContainer.children().hasClass('button icon button-icon')).toBe(true);
322-
expect(reorderContainer.attr('data-prevent-scroll')).toBe('true');
323-
expect(reorderContainer.children().attr('data-prevent-scroll')).toBe('true');
324-
}));
325-
it('should remove ng-hide if reorder is already active', inject(function($compile, $rootScope) {
326-
var setSpy = jasmine.createSpy('setReorderButton');
327-
var el = angular.element('<ion-item><ion-reorder-button></ion-reorder-button></ion-item>');
328-
el.data('$ionListController', {
329-
showReorder: function() { return true; }
330-
});
331-
$compile(el)($rootScope.$new());
332-
$rootScope.$apply();
333-
var reorderContainer = angular.element(el[0].querySelector('.item-right-edit.item-reorder'));
334-
expect(reorderContainer.length).toBe(1);
335-
expect(reorderContainer.hasClass('ng-hide')).toBe(false);
336-
}));
337-
});
338-
339-
describe('ionOptionButton directive', function() {
340-
beforeEach(module('ionic'));
341-
it('should have option button', inject(function($compile, $rootScope) {
342-
var setSpy = jasmine.createSpy('setOptionButton');
343-
var el = angular.element('<ion-item><ion-option-button></ion-option-button></ion-item>');
344-
el.data('$ionListController', {
345-
showDelete: function() { return false; }
346-
});
347-
$compile(el)($rootScope.$new());
348-
$rootScope.$apply();
349-
350-
var optionContainer = angular.element(el[0].querySelector('.item-options'));
351-
expect(optionContainer.length).toBe(1);
352-
expect(optionContainer.children().hasClass('button')).toBe(true);
353-
}));
354-
});

0 commit comments

Comments
 (0)