JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.4.2
[ckeditor.git] / _source / core / skins.js
1 /*\r
2 Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
3 For licensing, see LICENSE.html or http://ckeditor.com/license\r
4 */\r
5 \r
6 /**\r
7  * @fileOverview Defines the {@link CKEDITOR.skins} object, which is used to\r
8  *              manage skins loading.\r
9  */\r
10 \r
11 /**\r
12  * Manages skins loading.\r
13  * @namespace\r
14  * @example\r
15  */\r
16 CKEDITOR.skins = (function()\r
17 {\r
18         // Holds the list of loaded skins.\r
19         var loaded = {},\r
20                 preloaded = {},\r
21                 paths = {};\r
22 \r
23         var loadPart = function( editor, skinName, part, callback )\r
24         {\r
25                 // Get the skin definition.\r
26                 var skinDefinition = loaded[ skinName ];\r
27 \r
28                 if ( !editor.skin )\r
29                 {\r
30                         editor.skin = skinDefinition;\r
31 \r
32                         // Trigger init function if any.\r
33                         if ( skinDefinition.init )\r
34                                 skinDefinition.init( editor );\r
35                 }\r
36 \r
37                 var appendSkinPath = function( fileNames )\r
38                 {\r
39                         for ( var n = 0 ; n < fileNames.length ; n++ )\r
40                         {\r
41                                 fileNames[ n ] = CKEDITOR.getUrl( paths[ skinName ] + fileNames[ n ] );\r
42                         }\r
43                 };\r
44 \r
45                 function fixCSSTextRelativePath( cssStyleText, baseUrl )\r
46                 {\r
47                         return cssStyleText.replace( /url\s*\(([\s'"]*)(.*?)([\s"']*)\)/g,\r
48                                         function( match, opener, path, closer )\r
49                                         {\r
50                                                 if ( /^\/|^\w?:/.test( path ) )\r
51                                                         return match;\r
52                                                 else\r
53                                                         return 'url(' + baseUrl + opener +  path + closer + ')';\r
54                                         } );\r
55                 }\r
56 \r
57                 // Check if we need to preload images from it.\r
58                 var preload = skinDefinition.preload;\r
59                 if ( preload && preload.length > 0 )\r
60                 {\r
61                         if ( !preloaded[ skinName ] )\r
62                         {\r
63                                 // Prepare image URLs\r
64                                 appendSkinPath( preload );\r
65 \r
66                                 // Get preloader event dispatcher object.\r
67                                 preloaded[ skinName ] = CKEDITOR.imageCacher.load( preload );\r
68                         }\r
69 \r
70                         if ( !preloaded[ skinName ].finished )\r
71                         {\r
72                                 // Bind listener for this editor instance.\r
73                                 preloaded[ skinName ].on( 'loaded', function()\r
74                                         {\r
75                                                 loadPart( editor, skinName, part, callback );\r
76                                         }\r
77                                 );\r
78 \r
79                                 // Execution will be continued from event listener.\r
80                                 return;\r
81                         }\r
82                 }\r
83 \r
84                 // Get the part definition.\r
85                 part = skinDefinition[ part ];\r
86                 var partIsLoaded = !part || !!part._isLoaded;\r
87 \r
88                 // Call the callback immediately if already loaded.\r
89                 if ( partIsLoaded )\r
90                         callback && callback();\r
91                 else\r
92                 {\r
93                         // Put the callback in a queue.\r
94                         var pending = part._pending || ( part._pending = [] );\r
95                         pending.push( callback );\r
96 \r
97                         // We may have more than one skin part load request. Just the first\r
98                         // one must do the loading job.\r
99                         if ( pending.length > 1 )\r
100                                 return;\r
101 \r
102                         // Check whether the "css" and "js" properties have been defined\r
103                         // for that part.\r
104                         var cssIsLoaded = !part.css || !part.css.length,\r
105                                 jsIsLoaded = !part.js || !part.js.length;\r
106 \r
107                         // This is the function that will trigger the callback calls on\r
108                         // load.\r
109                         var checkIsLoaded = function()\r
110                         {\r
111                                 if ( cssIsLoaded && jsIsLoaded )\r
112                                 {\r
113                                         // Mark the part as loaded.\r
114                                         part._isLoaded = 1;\r
115 \r
116                                         // Call all pending callbacks.\r
117                                         for ( var i = 0 ; i < pending.length ; i++ )\r
118                                         {\r
119                                                 if ( pending[ i ] )\r
120                                                         pending[ i ]();\r
121                                         }\r
122                                 }\r
123                         };\r
124 \r
125                         // Load the "css" pieces.\r
126                         if ( !cssIsLoaded )\r
127                         {\r
128                                 var cssPart = part.css;\r
129 \r
130                                 if ( CKEDITOR.tools.isArray( cssPart ) )\r
131                                 {\r
132                                         appendSkinPath( cssPart );\r
133                                         for ( var c = 0 ; c < cssPart.length ; c++ )\r
134                                                 CKEDITOR.document.appendStyleSheet( cssPart[ c ] );\r
135                                 }\r
136                                 else\r
137                                 {\r
138                                         cssPart = fixCSSTextRelativePath(\r
139                                                                 cssPart, CKEDITOR.getUrl( paths[ skinName ] ) );\r
140                                         // Processing Inline CSS part.\r
141                                         CKEDITOR.document.appendStyleText( cssPart );\r
142                                 }\r
143 \r
144                                 part.css = cssPart;\r
145 \r
146                                 cssIsLoaded = 1;\r
147                         }\r
148 \r
149                         // Load the "js" pieces.\r
150                         if ( !jsIsLoaded )\r
151                         {\r
152                                 appendSkinPath( part.js );\r
153                                 CKEDITOR.scriptLoader.load( part.js, function()\r
154                                         {\r
155                                                 jsIsLoaded = 1;\r
156                                                 checkIsLoaded();\r
157                                         });\r
158                         }\r
159 \r
160                         // We may have nothing to load, so check it immediately.\r
161                         checkIsLoaded();\r
162                 }\r
163         };\r
164 \r
165         return /** @lends CKEDITOR.skins */ {\r
166 \r
167                 /**\r
168                  * Registers a skin definition.\r
169                  * @param {String} skinName The skin name.\r
170                  * @param {Object} skinDefinition The skin definition.\r
171                  * @example\r
172                  */\r
173                 add : function( skinName, skinDefinition )\r
174                 {\r
175                         loaded[ skinName ] = skinDefinition;\r
176 \r
177                         skinDefinition.skinPath = paths[ skinName ]\r
178                                 || ( paths[ skinName ] =\r
179                                                 CKEDITOR.getUrl(\r
180                                                         '_source/' +    // @Packager.RemoveLine\r
181                                                         'skins/' + skinName + '/' ) );\r
182                 },\r
183 \r
184                 /**\r
185                  * Loads a skin part. Skins are defined in parts, which are basically\r
186                  * separated CSS files. This function is mainly used by the core code and\r
187                  * should not have much use out of it.\r
188                  * @param {String} skinName The name of the skin to be loaded.\r
189                  * @param {String} skinPart The skin part to be loaded. Common skin parts\r
190                  *              are "editor" and "dialog".\r
191                  * @param {Function} [callback] A function to be called once the skin\r
192                  *              part files are loaded.\r
193                  * @example\r
194                  */\r
195                 load : function( editor, skinPart, callback )\r
196                 {\r
197                         var skinName = editor.skinName,\r
198                                 skinPath = editor.skinPath;\r
199 \r
200                         if ( loaded[ skinName ] )\r
201                                 loadPart( editor, skinName, skinPart, callback );\r
202                         else\r
203                         {\r
204                                 paths[ skinName ] = skinPath;\r
205                                 CKEDITOR.scriptLoader.load( CKEDITOR.getUrl( skinPath + 'skin.js' ), function()\r
206                                                 {\r
207                                                          loadPart( editor, skinName, skinPart, callback );\r
208                                                 });\r
209                         }\r
210                 }\r
211         };\r
212 })();\r