Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8af4fde

Browse files
committedJan 25, 2012
add($compile): add compiler v2.0 - not connected
1 parent 5001c1a commit 8af4fde

File tree

10 files changed

+2001
-554
lines changed

10 files changed

+2001
-554
lines changed
 

‎src/Angular.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,22 @@ function copy(source, destination){
626626
return destination;
627627
}
628628

629+
/**
630+
* Create a shallow copy of an object
631+
* @param src
632+
*/
633+
function shallowCopy(src) {
634+
var dst = {},
635+
key;
636+
for(key in src) {
637+
if (src.hasOwnProperty(key)) {
638+
dst[key] = src[key];
639+
}
640+
}
641+
return dst;
642+
}
643+
644+
629645
/**
630646
* @ngdoc function
631647
* @name angular.equals
@@ -750,6 +766,19 @@ function toBoolean(value) {
750766
return value;
751767
}
752768

769+
/**
770+
* @returns {string} Returns the string representation of the element.
771+
*/
772+
function startingTag(element) {
773+
element = jqLite(element).clone();
774+
try {
775+
// turns out IE does not let you set .html() on elements which
776+
// are not allowed to have children. So we just ignore it.
777+
element.html('');
778+
} catch(e) {};
779+
return jqLite('<div>').append(element).html().replace(/\<\/[\w\:\-]+\>$/, '');
780+
}
781+
753782

754783
/////////////////////////////////////////////////
755784

@@ -918,6 +947,14 @@ function bootstrap(element, modules) {
918947
return injector;
919948
}
920949

950+
var SNAKE_CASE_REGEXP = /[A-Z]/g;
951+
function snake_case(name, separator){
952+
separator = separator || '_';
953+
return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
954+
return (pos ? separator : '') + letter.toLowerCase();
955+
});
956+
}
957+
921958
function bindJQuery() {
922959
// bind to jQuery if present;
923960
jQuery = window.jQuery;
@@ -951,6 +988,7 @@ function assertArg(arg, name, reason) {
951988
}
952989

953990
function assertArgFn(arg, name) {
991+
assertArg(arg, name);
954992
assertArg(isFunction(arg), name, 'not a function, got ' +
955993
(typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));
956994
return arg;

‎src/angular-mocks.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -684,19 +684,17 @@ angular.mock.dump = function(object) {
684684
*
685685
* <pre>
686686
// controller
687-
function MyController($http) {
688-
var scope = this;
689-
687+
function MyController($scope, $http) {
690688
$http.get('/auth.py').success(function(data) {
691-
scope.user = data;
689+
$scope.user = data;
692690
});
693691
694692
this.saveMessage = function(message) {
695-
scope.status = 'Saving...';
693+
$scope.status = 'Saving...';
696694
$http.post('/add-msg.py', message).success(function(response) {
697-
scope.status = '';
695+
$scope.status = '';
698696
}).error(function() {
699-
scope.status = 'ERROR!';
697+
$scope.status = 'ERROR!';
700698
});
701699
};
702700
}

‎src/jqLite.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,27 @@ function getStyle(element) {
100100
}
101101

102102

103+
var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
104+
var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i;
105+
var MOZ_HACK_REGEXP = /^moz([A-Z])/;
103106
/**
104-
* Converts dash-separated names to camelCase. Useful for dealing with css properties.
107+
* Converts all accepted directives format into proper directive name.
108+
* All of these will become 'myDirective':
109+
* my:DiRective
110+
* my-directive
111+
* x-my-directive
112+
* data-my:directive
113+
*
114+
* Also there is special case for Moz prefix starting with upper case letter.
115+
* @param name Name to normalize
105116
*/
106117
function camelCase(name) {
107-
return name.replace(/\-(\w)/g, function(all, letter, offset){
108-
return (offset == 0 && letter == 'w') ? 'w' : letter.toUpperCase();
109-
});
118+
return name.
119+
replace(PREFIX_REGEXP, '').
120+
replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
121+
return offset ? letter.toUpperCase() : letter;
122+
}).
123+
replace(MOZ_HACK_REGEXP, 'Moz$1');
110124
}
111125

112126
/////////////////////////////////////////////

‎src/service/compiler.js

Lines changed: 715 additions & 318 deletions
Large diffs are not rendered by default.

‎src/service/formFactory.js

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -56,41 +56,43 @@
5656
});
5757
}
5858
59-
angular.directive('ng:contenteditable', function() {
60-
return ['$formFactory', '$element', function ($formFactory, element) {
61-
var exp = element.attr('ng:contenteditable'),
62-
form = $formFactory.forElement(element),
63-
widget;
64-
element.attr('contentEditable', true);
65-
widget = form.$createWidget({
66-
scope: this,
67-
model: exp,
68-
controller: HTMLEditorWidget,
69-
controllerArgs: {$element: element}});
70-
// if the element is destroyed, then we need to notify the form.
71-
element.bind('$destroy', function() {
72-
widget.$destroy();
73-
});
74-
}];
75-
});
76-
</script>
77-
<form name='editorForm' ng:controller="EditorCntl">
78-
<div ng:contenteditable="html"></div>
79-
<hr/>
80-
HTML: <br/>
81-
<textarea ng:model="html" cols=80></textarea>
82-
<hr/>
83-
<pre>editorForm = {{editorForm}}</pre>
84-
</form>
85-
</doc:source>
86-
<doc:scenario>
87-
it('should enter invalid HTML', function() {
88-
expect(element('form[name=editorForm]').prop('className')).toMatch(/ng-valid/);
89-
input('html').enter('<');
90-
expect(element('form[name=editorForm]').prop('className')).toMatch(/ng-invalid/);
91-
});
92-
</doc:scenario>
93-
</doc:example>
59+
angular.module('formModule', [], function($compileProvider){
60+
$compileProvider.directive('ngHtmlEditorModel', function ($formFactory) {
61+
return function(scope, element, attr) {
62+
var form = $formFactory.forElement(element),
63+
widget;
64+
element.attr('contentEditable', true);
65+
widget = form.$createWidget({
66+
scope: scope,
67+
model: attr.ngHtmlEditorModel,
68+
controller: HTMLEditorWidget,
69+
controllerArgs: {$element: element}});
70+
// if the element is destroyed, then we need to
71+
// notify the form.
72+
element.bind('$destroy', function() {
73+
widget.$destroy();
74+
});
75+
};
76+
});
77+
});
78+
</script>
79+
<form name='editorForm' ng:controller="EditorCntl">
80+
<div ng:html-editor-model="htmlContent"></div>
81+
<hr/>
82+
HTML: <br/>
83+
<textarea ng:model="htmlContent" cols="80"></textarea>
84+
<hr/>
85+
<pre>editorForm = {{editorForm|json}}</pre>
86+
</form>
87+
</doc:source>
88+
<doc:scenario>
89+
it('should enter invalid HTML', function() {
90+
expect(element('form[name=editorForm]').prop('className')).toMatch(/ng-valid/);
91+
input('htmlContent').enter('<');
92+
expect(element('form[name=editorForm]').prop('className')).toMatch(/ng-invalid/);
93+
});
94+
</doc:scenario>
95+
</doc:example>
9496
*/
9597

9698
/**

‎test/AngularSpec.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,22 @@ describe('angular', function() {
7575
});
7676
});
7777

78+
describe('shallow copy', function() {
79+
it('should make a copy', function() {
80+
var original = {key:{}};
81+
var copy = shallowCopy(original);
82+
expect(copy).toEqual(original);
83+
expect(copy.key).toBe(original.key);
84+
});
85+
});
86+
87+
describe('elementHTML', function() {
88+
it('should dump element', function() {
89+
expect(lowercase(startingTag('<div attr="123">something<span></span></div>'))).
90+
toEqual('<div attr="123">');
91+
});
92+
});
93+
7894
describe('equals', function() {
7995
it('should return true if same object', function() {
8096
var o = {};
@@ -501,4 +517,11 @@ describe('angular', function() {
501517
dealoc(element);
502518
});
503519
});
520+
521+
522+
describe('startingElementHtml', function(){
523+
it('should show starting element tag only', function(){
524+
expect(startingTag('<ng:abc x="2"><div>text</div></ng:abc>')).toEqual('<ng:abc x="2">');
525+
});
526+
});
504527
});

‎test/directivesSpec.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22

33
describe("directive", function() {
44

5-
var $filterProvider;
5+
var $filterProvider, element;
66

77
beforeEach(module(['$filterProvider', function(provider){
88
$filterProvider = provider;
99
}]));
1010

11+
afterEach(function() {
12+
dealoc(element);
13+
});
14+
1115
it("should ng:init", inject(function($rootScope, $compile) {
12-
var element = $compile('<div ng:init="a=123"></div>')($rootScope);
16+
element = $compile('<div ng:init="a=123"></div>')($rootScope);
1317
expect($rootScope.a).toEqual(123);
1418
}));
1519

‎test/jqLiteSpec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
'use strict';
21

32
describe('jqLite', function() {
43
var scope, a, b, c;
@@ -880,6 +879,7 @@ describe('jqLite', function() {
880879
it('should covert dash-separated strings to camelCase', function() {
881880
expect(camelCase('foo-bar')).toBe('fooBar');
882881
expect(camelCase('foo-bar-baz')).toBe('fooBarBaz');
882+
expect(camelCase('foo:bar_baz')).toBe('fooBarBaz');
883883
});
884884

885885

‎test/service/compilerSpec.js

Lines changed: 1154 additions & 186 deletions
Large diffs are not rendered by default.

‎test/testabilityPatch.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ function dealoc(obj) {
6767
}
6868
}
6969

70-
70+
/**
71+
* @param {DOMElement} element
72+
* @param {boolean=} showNgClass
73+
*/
7174
function sortedHtml(element, showNgClass) {
7275
var html = "";
7376
forEach(jqLite(element), function toString(node) {

0 commit comments

Comments
 (0)
Please sign in to comment.