1+ <!doctype html>
2+ < html lang ="en " ng-app ="Demo ">
3+ < head >
4+ < meta charset ="utf-8 " />
5+
6+ < title >
7+ Hacking Scoped CSS Modules Into A Brownfield AngularJS 1.2.22 Application
8+ </ title >
9+
10+ < link rel ="stylesheet " type ="text/css " href ="https://fonts.googleapis.com/css?family=Permanent+Marker " />
11+ </ head >
12+ < body >
13+
14+ < h1 >
15+ Hacking Scoped CSS Modules Into A Brownfield AngularJS 1.2.22 Application
16+ </ h1 >
17+
18+ < h2 >
19+ Using "compile" Approach
20+ </ h2 >
21+
22+ < bn:name-tag style ="margin-right: 30px ; ">
23+ Ben
24+ </ bn:name-tag >
25+
26+ < bn:name-tag style ="background-color: blue ; ">
27+ Kimmie
28+ </ bn:name-tag >
29+
30+
31+ <!-- Load scripts. -->
32+ < script type ="text/javascript " src ="../../../vendor/angularjs/angular-1.2.22.min.js "> </ script >
33+ < script type ="text/javascript ">
34+
35+ // Create an application module for our demo.
36+ var app = angular . module ( "Demo" , [ ] ) ;
37+
38+ // --------------------------------------------------------------------------- //
39+ // --------------------------------------------------------------------------- //
40+
41+ // I return a directive compile function that injects the given CSS module name
42+ // as an attribute on the host element and all of the embedded elements.
43+ app . value (
44+ "fakeCssModuleCompiler" ,
45+ function fakeCssModuleCompiler ( cssModuleName , link ) {
46+
47+ return ( compileDirective ) ;
48+
49+ function compileDirective ( tElement , tAttributes ) {
50+
51+ // Add the CSS module name to the host element.
52+ tElement
53+ . addClass ( cssModuleName )
54+ . attr ( cssModuleName , "" )
55+ ;
56+
57+ // Add the CSS module name to every embedded element.
58+ angular . forEach (
59+ tElement . find ( "*" ) ,
60+ function iterator ( tChild ) {
61+
62+ tChild . setAttribute ( cssModuleName , "" ) ;
63+
64+ }
65+ ) ;
66+
67+ // Return optional post-link function.
68+ return ( link || undefined ) ;
69+
70+ }
71+
72+ }
73+ ) ;
74+
75+ // --------------------------------------------------------------------------- //
76+ // --------------------------------------------------------------------------- //
77+
78+ </ script >
79+ < script type ="text/javascript ">
80+
81+ app . directive (
82+ "bnNameTag" ,
83+ function bnNameTagDirective ( fakeCssModuleCompiler ) {
84+
85+ // Return the directive configuration.
86+ // --
87+ // Because we don't have native CSS module support, we are compiling the
88+ // module class name into the directive template and host element at
89+ // runtime. To keep the class names small and globally unique, I'm just
90+ // taking the first 6-letters of the hash of the directive element name.
91+ // --
92+ // MD5 ("bn:name-tag") = ee8f6b215d4299bac64b16c3d804f7f8
93+ return ( {
94+ compile : fakeCssModuleCompiler ( "m-ee8f6b" ) ,
95+ restrict : "E" ,
96+ scope : { } ,
97+ templateUrl : "bn-name-tag.htm" ,
98+ transclude : true
99+ } ) ;
100+
101+ }
102+ )
103+
104+ </ script >
105+ < style type ="text/less ">
106+
107+ // Set embedded element styles based on the injected attribute. Since we want
108+ // to tie these classes to this module, we are using the "&" (parent selector)
109+ // in order to create a compound selector that won't leak outside of this
110+ // pseudo module.
111+ [m-ee8f6b ] {
112+
113+ // Set HOST styles.
114+ // --
115+ // NOTE: The host element uses both a class AND an attribute. This allows us
116+ // to use a class-based selector (which is faster than an attribute selector,
117+ // or so I've read); and, it helps us differentiate the host element from the
118+ // embedded elements.
119+ & .m-ee8f6b {
120+ background-color : # ff0000 ;
121+ border : 10px solid # ffffff ;
122+ border-radius : 15px 15px 15px 15px ;
123+ box-shadow : 0px 0px 6px rgba ( 0 , 0 , 0 , 0.2 ) ;
124+ box-sizing : border-box ;
125+ display : inline-block ;
126+ min-width : 300px ;
127+ }
128+
129+ & .wrapper {
130+ padding : 0px 0px 13px 0px ;
131+ }
132+
133+ & .header {
134+ color : # ffffff ;
135+ padding : 10px 0px 10px 0px ;
136+ font-family : helvetica, arial, sans-serif ;
137+ text-align : center ;
138+ text-transform : uppercase ;
139+ }
140+
141+ & .title {
142+ display : block ;
143+ font-size : 38px ;
144+ font-weight : bold ;
145+ line-height : 43px ;
146+ letter-spacing : 4px ;
147+ }
148+
149+ & .sub-title {
150+ display : block ;
151+ font-size : 18px ;
152+ line-height : 22px ;
153+ letter-spacing : 1px ;
154+ }
155+
156+ & .name {
157+ background-color : # ffffff ;
158+ color : inherit ;
159+ font-family : "Permanent Marker" , sans-serif ;
160+ font-size : 36px ;
161+ letter-spacing : 3px ;
162+ line-height : 41px ;
163+ padding : 25px 20px 26px 20px ;
164+ text-align : center ;
165+ }
166+ }
167+
168+ </ style >
169+ < script type ="text/ng-template " id ="bn-name-tag.htm ">
170+
171+ < div class = "wrapper" >
172+
173+ < header class = "header" >
174+ < span class = "title" >
175+ Hello
176+ </ span >
177+ < span class = "sub-title" >
178+ My name is
179+ </ span >
180+ </ header >
181+
182+ < div class = "name" ng-transclude >
183+ <!-- Name goes here. -->
184+ </ div >
185+
186+ </ div >
187+
188+ </ script >
189+
190+ <!-- The browser-based LESS compiler has to be included AFTER the LESS blocks. -->
191+ < script type ="text/javascript " src ="../../../vendor/less/3.9.0/less.min.js "> </ script >
192+
193+ </ body >
194+ </ html >
0 commit comments