Support @import directives in MapCSS files
[potlatch2.git] / net / systemeD / halcyon / styleparser / NestedCSSLoader.as
1 package net.systemeD.halcyon.styleparser {
2
3         /** A class permitting you to load CSS files containing '@import' rules, which will be 
4         *       automatically replaced with the contents of the file.
5         *
6         *   Typical usage:
7         *
8         *               cssLoader=new NestedCSSLoader();
9         *               cssLoader.addEventListener(Event.COMPLETE, doParseCSS);
10         *               cssLoader.load("potlatch.css");
11         *
12         *       doParseCSS can then access the CSS via event.target.css.
13         */
14
15         import flash.events.*;
16         import flash.net.URLLoader;
17         import flash.net.URLLoaderDataFormat;
18         import flash.net.URLRequest;
19
20         public class NestedCSSLoader extends EventDispatcher {
21                 private var sourceCSS:String;
22                 public var css:String;
23                 private var url:String;
24                 private var count:int;
25
26                 private static const IMPORT:RegExp=/@import [^'"]*['"]([^'"]+)['"][^;]*;/g;             // '
27
28                 public function NestedCSSLoader() {
29                 }
30                 
31                 public function load(url:String):void {
32                         this.url=url;
33                         var request:URLRequest=new URLRequest(url+"?d="+Math.random());
34                         var loader:URLLoader = new URLLoader();
35                         loader.dataFormat = URLLoaderDataFormat.TEXT;
36                         loader.addEventListener(Event.COMPLETE, fileLoaded);
37                         loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, fileError);
38                         loader.addEventListener(IOErrorEvent.IO_ERROR, fileError);
39                         loader.load(request);
40                 }
41                 
42                 private function fileLoaded(event:Event):void {
43                         sourceCSS=URLLoader(event.target).data;
44                         css=sourceCSS;
45                         count=0;
46
47                         var result:Object=IMPORT.exec(sourceCSS);
48                         while (result!=null) {
49                                 count++;
50                                 replaceCSS(result[1],result[0]);
51                                 result=IMPORT.exec(sourceCSS);
52                         }
53                         if (count==0) { fireComplete(); }
54                 }
55
56                 private function replaceCSS(filename:String, toReplace:String):void {
57                         var cssLoader:NestedCSSLoader=new NestedCSSLoader();
58                         var replaceText:String=toReplace;
59                         cssLoader.addEventListener(Event.COMPLETE, function(event:Event):void {
60                                 css=css.replace(replaceText,event.target.css);
61                                 decreaseCount();
62                         });
63                         cssLoader.load(filename+"?d="+Math.random());
64                 }
65
66                 private function fileError(event:Event):void {
67                         // just fire a complete event so we don't get an error dialogue
68                         fireComplete();
69                 }
70                 
71                 private function decreaseCount():void {
72                         count--; if (count>0) return;
73                         fireComplete();
74                 }
75                 
76                 private function fireComplete():void {
77                         var event:Event=new Event(Event.COMPLETE);
78                         dispatchEvent(event);
79                 }
80         }
81 }