Skip to content
This repository was archived by the owner on Apr 4, 2025. It is now read-only.

Commit f731b57

Browse files
committed
fix: enable ngHintEvents
1 parent b7c0d69 commit f731b57

File tree

4 files changed

+81
-45
lines changed

4 files changed

+81
-45
lines changed

hint.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require('./src/modules/log');
77
require('./src/modules/controllers');
88
// require('./src/modules/directives');
99
// require('./src/modules/dom');
10-
// require('./src/modules/events');
10+
require('./src/modules/events');
1111
// require('./src/modules/interpolation');
1212
// require('./src/modules/modules');
1313
require('./src/modules/scopes');
@@ -18,7 +18,7 @@ var AVAILABLE_MODULES = [
1818
'ngHintControllers',
1919
// 'ngHintDirectives',
2020
// 'ngHintDom',
21-
// 'ngHintEvents',
21+
'ngHintEvents',
2222
// 'ngHintInterpolation',
2323
// 'ngHintModules',
2424
'ngHintScopes'

src/lib/event-directives.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
'use strict';
22

3-
module.exports = 'click submit mouseenter mouseleave mousemove mousedown mouseover mouseup dblclick keyup keydown keypress blur focus submit cut copy paste'.split(' ');
3+
var list = 'click submit mouseenter mouseleave mousemove mousedown mouseover mouseup dblclick keyup keydown keypress blur focus submit cut copy paste'.split(' ');
4+
5+
module.exports = list.map(function(eventName) {
6+
return 'ng' + eventName.charAt(0).toUpperCase() + eventName.substr(1);
7+
});

src/modules/events.js

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,59 @@
33
/**
44
* Load necessary functions from /lib into variables.
55
*/
6-
var ngEventDirectives = require('../lib/getEventDirectives')(),
7-
getFunctionNames = require('../lib/getFunctionNames'),
8-
formatResults = require('../lib/formatResults');
6+
var ngEventAttributes = require('../lib/event-directives'),
7+
MODULE_NAME = 'Events';
8+
9+
10+
var getFunctionNames = function(str) {
11+
if (typeof str !== 'string') {
12+
return [];
13+
}
14+
var results = str.replace(/\s+/g, '').split(/[\+\-\/\|\<\>\^=&!%~]/g).map(function(x) {
15+
if (isNaN(+x)) {
16+
if (x.match(/\w+\(.*\)$/)){
17+
return x.substr(0, x.indexOf('('));
18+
}
19+
return x;
20+
}
21+
}).filter(function(x){
22+
return x;
23+
});
24+
return results;
25+
};
926

1027
/**
1128
* Decorate $provide in order to examine ng-event directives
1229
* and hint about their effective use.
1330
*/
1431
angular.module('ngHintEvents', [])
1532
.config(['$provide', function($provide) {
16-
17-
for(var directive in ngEventDirectives) {
18-
var dirName = ngEventDirectives[directive] + 'Directive';
19-
try{
20-
$provide.decorator(dirName, ['$delegate', '$timeout', '$parse', ngEventDirectivesDecorator]);
33+
for (var i = 0; i < ngEventAttributes.length; i++) {
34+
try {
35+
$provide.decorator(ngEventAttributes[i] + 'Directive',
36+
['$delegate', '$parse', ngEventDirectivesDecorator(ngEventAttributes[i])]);
2137
} catch(e) {}
2238
}
2339
}]);
2440

25-
function ngEventDirectivesDecorator($delegate, $timeout, $parse) {
41+
function ngEventDirectivesDecorator(ngEventAttrName) {
42+
return function ($delegate, $parse) {
43+
var originalCompileFn = $delegate[0].compile;
2644

27-
var original = $delegate[0].compile,
28-
falseBinds = [],
29-
messages = [];
45+
$delegate[0].compile = function(element, attrs, transclude) {
46+
var linkFn = originalCompileFn.apply(this, arguments);
3047

31-
$delegate[0].compile = function(element, attrs, transclude) {
32-
var angularAttrs = attrs.$attr;
33-
var linkFn = original.apply(this, arguments);
34-
var messages = [];
35-
return function ngEventHandler(scope, element, attrs) {
36-
for(var attr in angularAttrs) {
37-
var boundFuncs = getFunctionNames(attrs[attr]);
48+
return function ngEventHandler(scope, element, attrs) {
49+
var boundFuncs = getFunctionNames(attrs[ngEventAttrName]);
3850
boundFuncs.forEach(function(boundFn) {
39-
if(ngEventDirectives[attr] && !(boundFn in scope)) {
40-
messages.push({
41-
scope: scope,
42-
element:element,
43-
attrs: attrs,
44-
boundFunc: boundFn
45-
});
51+
if ($parse(boundFn)(scope) === undefined) {
52+
angular.hint.log(MODULE_NAME, boundFn + ' is undefined');
4653
}
4754
});
48-
}
49-
linkFn.apply(this, arguments);
50-
formatResults(messages);
55+
56+
return linkFn.apply(this, arguments);
57+
};
5158
};
52-
};
53-
return $delegate;
59+
return $delegate;
60+
}
5461
}

test/events.spec.js

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
var hintLog = angular.hint;
44

5-
xdescribe('hintEvents', function() {
5+
describe('hintEvents', function() {
66
var $rootScope,
77
$compile,
88
$controller;
@@ -16,23 +16,48 @@ xdescribe('hintEvents', function() {
1616
}));
1717

1818
it('should log a message if the path to handle an ng-event is not found', function() {
19-
var elm = angular.element('<button ng-click="a.b.c()">Fake Increment</button>');
20-
$compile(elm)($rootScope);
19+
var elt = angular.element('<button ng-click="a.b.c()">Fake Increment</button>');
20+
$compile(elt)($rootScope);
2121

2222
$rootScope.$digest();
23-
elm.triggerHandler('click');
24-
expect(angular.hint.log).toHaveBeenCalledWith('a');
23+
elt.triggerHandler('click');
24+
// TODO: fix this 'a' is undefined
25+
expect(angular.hint.log).toHaveBeenCalledWith('Events', 'a.b.c is undefined');
2526
});
2627

27-
it('should log a message if the path to handle an ng-event is not found', function() {
28-
var elm = angular.element('<button ng-click="a.b.c()">Fake Increment</button>');
29-
$compile(elm)($rootScope);
28+
// TODO: implement this
29+
xit('should log a message if the path to handle an ng-event is not found', function() {
30+
var elt = angular.element('<button ng-click="a.b.c()">Fake Increment</button>');
31+
$compile(elt)($rootScope);
3032
$rootScope.a = {};
3133

3234
$rootScope.$digest();
33-
elm.triggerHandler('click');
34-
expect(angular.hint.log).toHaveBeenCalledWith('a.b');
35+
elt.triggerHandler('click');
36+
expect(angular.hint.log).toHaveBeenCalledWith('Events', 'a.b is undefined');
3537
});
3638

3739

38-
});
40+
41+
it('should not break elements with more than one directive on them', function() {
42+
$rootScope.onBlur = jasmine.createSpy('onBlur');
43+
$rootScope.onFocus = jasmine.createSpy('onFocus');
44+
var elt = angular.element('<input type="text" ng-blur="onBlur()" ng-focus="onFocus()">');
45+
$compile(elt)($rootScope);
46+
$rootScope.$digest();
47+
48+
var blurEvent = createEventMock('blur');
49+
var focusEvent = createEventMock('focus');
50+
elt[0].dispatchEvent(blurEvent);
51+
elt[0].dispatchEvent(focusEvent);
52+
53+
expect($rootScope.onBlur).toHaveBeenCalled();
54+
expect($rootScope.onFocus).toHaveBeenCalled();
55+
});
56+
});
57+
58+
function createEventMock (name) {
59+
var ev = document.createEvent('MouseEvent');
60+
ev.initMouseEvent(
61+
name, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
62+
return ev;
63+
}

0 commit comments

Comments
 (0)