1+ /*global module */
12'use strict' ;
23
3- /**
4- * Binds a CodeMirror widget to a <textarea> element.
5- */
6- angular . module ( 'ui.codemirror' , [ ] )
7- . constant ( 'uiCodemirrorConfig' , { } )
8- . directive ( 'uiCodemirror' , uiCodemirrorDirective ) ;
9-
10- /**
11- * @ngInject
12- */
13- function uiCodemirrorDirective ( $timeout , uiCodemirrorConfig ) {
14-
15- return {
16- restrict : 'EA' ,
17- require : '?ngModel' ,
18- compile : function compile ( ) {
19-
20- // Require CodeMirror
21- if ( angular . isUndefined ( window . CodeMirror ) ) {
22- throw new Error ( 'ui-codemirror needs CodeMirror to work... (o rly?)' ) ;
4+ ( function ( factory ) {
5+ var moduleName = 'ui.codemirror' ;
6+ if ( typeof module === 'object' && module . exports ) {
7+ // Node. Does not work with strict CommonJS, but
8+ // only CommonJS-like environments that support module.exports,
9+ // like Node.
10+ module . exports = moduleName ;
11+ factory ( moduleName ) ;
12+ } else {
13+ factory ( moduleName ) ;
14+ }
15+ } ( function ( moduleName ) {
16+
17+ /**
18+ * Binds a CodeMirror widget to a <textarea> element.
19+ */
20+ angular . module ( moduleName , [ ] )
21+ . constant ( 'uiCodemirrorConfig' , { } )
22+ . directive ( 'uiCodemirror' , [ '$timeout' , 'uiCodemirrorConfig' , uiCodemirrorDirective ] ) ;
23+
24+ /**
25+ * @ngInject
26+ */
27+ function uiCodemirrorDirective ( $timeout , uiCodemirrorConfig ) {
28+
29+ return {
30+ restrict : 'EA' ,
31+ require : '?ngModel' ,
32+ compile : function compile ( ) {
33+
34+ // Require CodeMirror
35+ if ( angular . isUndefined ( window . CodeMirror ) ) {
36+ throw new Error ( 'ui-codemirror needs CodeMirror to work... (o rly?)' ) ;
37+ }
38+
39+ return postLink ;
2340 }
41+ } ;
2442
25- return postLink ;
26- }
27- } ;
43+ function postLink ( scope , iElement , iAttrs , ngModel ) {
2844
29- function postLink ( scope , iElement , iAttrs , ngModel ) {
45+ var codemirrorOptions = angular . extend (
46+ { value : iElement . text ( ) } ,
47+ uiCodemirrorConfig . codemirror || { } ,
48+ scope . $eval ( iAttrs . uiCodemirror ) ,
49+ scope . $eval ( iAttrs . uiCodemirrorOpts )
50+ ) ;
3051
31- var codemirrorOptions = angular . extend (
32- { value : iElement . text ( ) } ,
33- uiCodemirrorConfig . codemirror || { } ,
34- scope . $eval ( iAttrs . uiCodemirror ) ,
35- scope . $eval ( iAttrs . uiCodemirrorOpts )
36- ) ;
52+ var codemirror = newCodemirrorEditor ( iElement , codemirrorOptions ) ;
3753
38- var codemirror = newCodemirrorEditor ( iElement , codemirrorOptions ) ;
54+ configOptionsWatcher (
55+ codemirror ,
56+ iAttrs . uiCodemirror || iAttrs . uiCodemirrorOpts ,
57+ scope
58+ ) ;
3959
40- configOptionsWatcher (
41- codemirror ,
42- iAttrs . uiCodemirror || iAttrs . uiCodemirrorOpts ,
43- scope
44- ) ;
60+ configNgModelLink ( codemirror , ngModel , scope ) ;
61+
62+ configUiRefreshAttribute ( codemirror , iAttrs . uiRefresh , scope ) ;
63+
64+ // Allow access to the CodeMirror instance through a broadcasted event
65+ // eg: $broadcast('CodeMirror', function(cm){...});
66+ scope . $on ( 'CodeMirror' , function ( event , callback ) {
67+ if ( angular . isFunction ( callback ) ) {
68+ callback ( codemirror ) ;
69+ } else {
70+ throw new Error ( 'the CodeMirror event requires a callback function' ) ;
71+ }
72+ } ) ;
4573
46- configNgModelLink ( codemirror , ngModel , scope ) ;
74+ // onLoad callback
75+ if ( angular . isFunction ( codemirrorOptions . onLoad ) ) {
76+ codemirrorOptions . onLoad ( codemirror ) ;
77+ }
78+ }
4779
48- configUiRefreshAttribute ( codemirror , iAttrs . uiRefresh , scope ) ;
80+ function newCodemirrorEditor ( iElement , codemirrorOptions ) {
81+ var codemirrot ;
4982
50- // Allow access to the CodeMirror instance through a broadcasted event
51- // eg: $broadcast('CodeMirror', function(cm){...});
52- scope . $on ( 'CodeMirror' , function ( event , callback ) {
53- if ( angular . isFunction ( callback ) ) {
54- callback ( codemirror ) ;
83+ if ( iElement [ 0 ] . tagName === 'TEXTAREA' ) {
84+ // Might bug but still ...
85+ codemirrot = window . CodeMirror . fromTextArea ( iElement [ 0 ] , codemirrorOptions ) ;
5586 } else {
56- throw new Error ( 'the CodeMirror event requires a callback function' ) ;
87+ iElement . html ( '' ) ;
88+ codemirrot = new window . CodeMirror ( function ( cm_el ) {
89+ iElement . append ( cm_el ) ;
90+ } , codemirrorOptions ) ;
5791 }
58- } ) ;
5992
60- // onLoad callback
61- if ( angular . isFunction ( codemirrorOptions . onLoad ) ) {
62- codemirrorOptions . onLoad ( codemirror ) ;
93+ return codemirrot ;
6394 }
64- }
6595
66- function newCodemirrorEditor ( iElement , codemirrorOptions ) {
67- var codemirrot ;
68-
69- if ( iElement [ 0 ] . tagName === 'TEXTAREA' ) {
70- // Might bug but still ...
71- codemirrot = window . CodeMirror . fromTextArea ( iElement [ 0 ] , codemirrorOptions ) ;
72- } else {
73- iElement . html ( '' ) ;
74- codemirrot = new window . CodeMirror ( function ( cm_el ) {
75- iElement . append ( cm_el ) ;
76- } , codemirrorOptions ) ;
77- }
96+ function configOptionsWatcher ( codemirrot , uiCodemirrorAttr , scope ) {
97+ if ( ! uiCodemirrorAttr ) {
98+ return ;
99+ }
78100
79- return codemirrot ;
80- }
101+ var codemirrorDefaultsKeys = Object . keys ( window . CodeMirror . defaults ) ;
102+ scope . $watch ( uiCodemirrorAttr , updateOptions , true ) ;
81103
82- function configOptionsWatcher ( codemirrot , uiCodemirrorAttr , scope ) {
83- if ( ! uiCodemirrorAttr ) { return ; }
104+ function updateOptions ( newValues , oldValue ) {
105+ if ( ! angular . isObject ( newValues ) ) {
106+ return ;
107+ }
108+ codemirrorDefaultsKeys . forEach ( function ( key ) {
109+ if ( newValues . hasOwnProperty ( key ) ) {
84110
85- var codemirrorDefaultsKeys = Object . keys ( window . CodeMirror . defaults ) ;
86- scope . $watch ( uiCodemirrorAttr , updateOptions , true ) ;
87- function updateOptions ( newValues , oldValue ) {
88- if ( ! angular . isObject ( newValues ) ) { return ; }
89- codemirrorDefaultsKeys . forEach ( function ( key ) {
90- if ( newValues . hasOwnProperty ( key ) ) {
111+ if ( oldValue && newValues [ key ] === oldValue [ key ] ) {
112+ return ;
113+ }
91114
92- if ( oldValue && newValues [ key ] === oldValue [ key ] ) {
93- return ;
115+ codemirrot . setOption ( key , newValues [ key ] ) ;
94116 }
117+ } ) ;
118+ }
119+ }
95120
96- codemirrot . setOption ( key , newValues [ key ] ) ;
121+ function configNgModelLink ( codemirror , ngModel , scope ) {
122+ if ( ! ngModel ) {
123+ return ;
124+ }
125+ // CodeMirror expects a string, so make sure it gets one.
126+ // This does not change the model.
127+ ngModel . $formatters . push ( function ( value ) {
128+ if ( angular . isUndefined ( value ) || value === null ) {
129+ return '' ;
130+ } else if ( angular . isObject ( value ) || angular . isArray ( value ) ) {
131+ throw new Error ( 'ui-codemirror cannot use an object or an array as a model' ) ;
97132 }
133+ return value ;
98134 } ) ;
99- }
100- }
101135
102- function configNgModelLink ( codemirror , ngModel , scope ) {
103- if ( ! ngModel ) { return ; }
104- // CodeMirror expects a string, so make sure it gets one.
105- // This does not change the model.
106- ngModel . $formatters . push ( function ( value ) {
107- if ( angular . isUndefined ( value ) || value === null ) {
108- return '' ;
109- } else if ( angular . isObject ( value ) || angular . isArray ( value ) ) {
110- throw new Error ( 'ui-codemirror cannot use an object or an array as a model' ) ;
111- }
112- return value ;
113- } ) ;
114136
137+ // Override the ngModelController $render method, which is what gets called when the model is updated.
138+ // This takes care of the synchronizing the codeMirror element with the underlying model, in the case that it is changed by something else.
139+ ngModel . $render = function ( ) {
140+ //Code mirror expects a string so make sure it gets one
141+ //Although the formatter have already done this, it can be possible that another formatter returns undefined (for example the required directive)
142+ var safeViewValue = ngModel . $viewValue || '' ;
143+ codemirror . setValue ( safeViewValue ) ;
144+ } ;
115145
116- // Override the ngModelController $render method, which is what gets called when the model is updated.
117- // This takes care of the synchronizing the codeMirror element with the underlying model, in the case that it is changed by something else.
118- ngModel . $render = function ( ) {
119- //Code mirror expects a string so make sure it gets one
120- //Although the formatter have already done this, it can be possible that another formatter returns undefined (for example the required directive)
121- var safeViewValue = ngModel . $viewValue || '' ;
122- codemirror . setValue ( safeViewValue ) ;
123- } ;
124146
147+ // Keep the ngModel in sync with changes from CodeMirror
148+ codemirror . on ( 'change' , function ( instance ) {
149+ var newValue = instance . getValue ( ) ;
150+ if ( newValue !== ngModel . $viewValue ) {
151+ scope . $evalAsync ( function ( ) {
152+ ngModel . $setViewValue ( newValue ) ;
153+ } ) ;
154+ }
155+ } ) ;
156+ }
125157
126- // Keep the ngModel in sync with changes from CodeMirror
127- codemirror . on ( 'change' , function ( instance ) {
128- var newValue = instance . getValue ( ) ;
129- if ( newValue !== ngModel . $viewValue ) {
130- scope . $evalAsync ( function ( ) {
131- ngModel . $setViewValue ( newValue ) ;
132- } ) ;
158+ function configUiRefreshAttribute ( codeMirror , uiRefreshAttr , scope ) {
159+ if ( ! uiRefreshAttr ) {
160+ return ;
133161 }
134- } ) ;
135- }
136162
137- function configUiRefreshAttribute ( codeMirror , uiRefreshAttr , scope ) {
138- if ( ! uiRefreshAttr ) { return ; }
163+ scope . $watch ( uiRefreshAttr , function ( newVal , oldVal ) {
164+ // Skip the initial watch firing
165+ if ( newVal !== oldVal ) {
166+ $timeout ( function ( ) {
167+ codeMirror . refresh ( ) ;
168+ } ) ;
169+ }
170+ } ) ;
171+ }
139172
140- scope . $watch ( uiRefreshAttr , function ( newVal , oldVal ) {
141- // Skip the initial watch firing
142- if ( newVal !== oldVal ) {
143- $timeout ( function ( ) {
144- codeMirror . refresh ( ) ;
145- } ) ;
146- }
147- } ) ;
148173 }
149-
150- }
174+ } ) ) ;
0 commit comments