Index: branches/MwEmbedStandAlone/loader.js |
— | — | @@ -46,15 +46,15 @@ |
47 | 47 | * is transcluded into base mwEmbed class include. |
48 | 48 | */ |
49 | 49 | var mwEnabledModuleList = [ |
50 | | - 'AddMedia', |
51 | | - 'ClipEdit', |
52 | 50 | 'EmbedPlayer', |
53 | | - 'ApiProxy', |
54 | | - 'Sequencer', |
55 | 51 | 'TimedText', |
56 | 52 | 'SmilPlayer', |
57 | 53 | 'MediaRss', |
58 | | - 'SwarmTransport' |
| 54 | + 'SwarmTransport', |
| 55 | + 'AddMedia', |
| 56 | + 'ClipEdit', |
| 57 | + 'SequenceEdit', |
| 58 | + 'ApiProxy' |
59 | 59 | ]; |
60 | 60 | |
61 | 61 | /** |
Index: branches/MwEmbedStandAlone/mwEmbed.js |
— | — | @@ -16,18 +16,18 @@ |
17 | 17 | */ |
18 | 18 | |
19 | 19 | /** |
20 | | -* Setup the "mw" global: |
21 | | -*/ |
| 20 | + * Setup the "mw" global: |
| 21 | + */ |
22 | 22 | if ( typeof window.mw == 'undefined' ) { |
23 | 23 | window.mw = { }; |
24 | 24 | } |
25 | 25 | |
26 | 26 | /** |
27 | | -* Set the mwEmbedVersion |
28 | | -*/ |
| 27 | + * Set the mwEmbedVersion |
| 28 | + */ |
29 | 29 | var MW_EMBED_VERSION = '1.1g'; |
30 | 30 | |
31 | | -// Globals to pre-set ready functions in dynamic loading of mwEmbed |
| 31 | +// Globals to pre-set ready functions in dynamic loading of mwEmbed |
32 | 32 | if( typeof preMwEmbedReady == 'undefined'){ |
33 | 33 | var preMwEmbedReady = []; |
34 | 34 | } |
— | — | @@ -37,8 +37,8 @@ |
38 | 38 | } |
39 | 39 | |
40 | 40 | /** |
41 | | -* The global mw object: |
42 | | -*/ |
| 41 | + * The global mw object: |
| 42 | + */ |
43 | 43 | ( function( mw ) { |
44 | 44 | // The version of mwEmbed |
45 | 45 | mw.version = MW_EMBED_VERSION |
— | — | @@ -46,31 +46,32 @@ |
47 | 47 | // List valid skins here: |
48 | 48 | mw.validSkins = [ 'mvpcf', 'kskin' ]; |
49 | 49 | |
50 | | - // Storage variable for loaded style sheet keys |
| 50 | + // Storage variable for loaded style sheet keys |
51 | 51 | mw.style = { }; |
52 | 52 | |
53 | 53 | /** |
54 | | - * Configuration System: |
55 | | - */ |
| 54 | + * Configuration System: |
| 55 | + */ |
56 | 56 | |
57 | 57 | // Local scope configuration var: |
58 | 58 | if( !mwConfig ){ |
59 | 59 | var mwConfig = { }; |
60 | 60 | } |
61 | 61 | |
62 | | - // Local scope mwUserConfig var. Stores user configuration |
| 62 | + // Local scope mwUserConfig var. Stores user configuration |
63 | 63 | var mwUserConfig = { }; |
64 | 64 | |
65 | 65 | /** |
66 | | - * Setter for configuration values |
67 | | - * |
68 | | - * @param [Mixed] name Name of configuration value |
69 | | - * {Object} Will iderate through each key and call setConfig |
70 | | - * {String} Will set configuration by string name to value |
71 | | - * @param |
72 | | - * {String} value Value of configuration name |
73 | | - * {Object} value Set of values to be merged |
74 | | - */ |
| 66 | + * Setter for configuration values |
| 67 | + * |
| 68 | + * @param [Mixed] |
| 69 | + * name Name of configuration value {Object} Will iderate through |
| 70 | + * each key and call setConfig {String} Will set configuration by |
| 71 | + * string name to value |
| 72 | + * @param {String} |
| 73 | + * value Value of configuration name {Object} value Set of values |
| 74 | + * to be merged |
| 75 | + */ |
75 | 76 | mw.setConfig = function ( name, value ) { |
76 | 77 | if( typeof name == 'object' ) { |
77 | 78 | for( var i in name ) { |
— | — | @@ -89,12 +90,14 @@ |
90 | 91 | } |
91 | 92 | |
92 | 93 | /** |
93 | | - * Set a default config value |
94 | | - * Will only update configuration if no value is present |
95 | | - * @param [Mixed] value Set configuration name to value |
96 | | - * {Object} Will iderate through each key and call setDefaultConfig |
97 | | - * {String} Will set configuration by string name to value |
98 | | - */ |
| 94 | + * Set a default config value Will only update configuration if no value is |
| 95 | + * present |
| 96 | + * |
| 97 | + * @param [Mixed] |
| 98 | + * value Set configuration name to value {Object} Will iderate |
| 99 | + * through each key and call setDefaultConfig {String} Will set |
| 100 | + * configuration by string name to value |
| 101 | + */ |
99 | 102 | mw.setDefaultConfig = function( name, value ) { |
100 | 103 | if( typeof name == 'object' ) { |
101 | 104 | for( var i in name ) { |
— | — | @@ -102,19 +105,21 @@ |
103 | 106 | } |
104 | 107 | return ; |
105 | 108 | } |
106 | | - // Only update the controls if undefined ( ie don't override false properties ) |
| 109 | + // Only update the controls if undefined ( ie don't override false |
| 110 | + // properties ) |
107 | 111 | if( typeof mwConfig[ name ] == 'undefined') { |
108 | 112 | mwConfig[ name ] = value; |
109 | 113 | } |
110 | 114 | } |
111 | 115 | |
112 | 116 | /** |
113 | | - * Getter for configuration values |
114 | | - * |
115 | | - * @param {String} name of configuration value to get |
116 | | - * @return {Mixed} value of configuration key |
117 | | - * returns "false" if key not found |
118 | | - */ |
| 117 | + * Getter for configuration values |
| 118 | + * |
| 119 | + * @param {String} |
| 120 | + * name of configuration value to get |
| 121 | + * @return {Mixed} value of configuration key returns "false" if key not |
| 122 | + * found |
| 123 | + */ |
119 | 124 | mw.getConfig = function ( name ) { |
120 | 125 | if( mwConfig[ name ] ) |
121 | 126 | return mwConfig[ name ]; |
— | — | @@ -122,19 +127,20 @@ |
123 | 128 | } |
124 | 129 | |
125 | 130 | /** |
126 | | - * Loads the mwUserConfig from a cookie. |
127 | | - * |
128 | | - * Modules that want to use "User Config" should call |
129 | | - * this setup function in their moduleLoader code. |
130 | | - * |
131 | | - * For performance interfaces using "user config" |
132 | | - * should load '$j.cookie' & 'JSON' in their module loader |
133 | | - * |
134 | | - * By abstracting user preference we could eventually integrate |
135 | | - * a persistent per-account preference system on the server. |
136 | | - * |
137 | | - * @parma {Function} callback Function to be called once userPrefrences are loaded |
138 | | - */ |
| 131 | + * Loads the mwUserConfig from a cookie. |
| 132 | + * |
| 133 | + * Modules that want to use "User Config" should call this setup function in |
| 134 | + * their moduleLoader code. |
| 135 | + * |
| 136 | + * For performance interfaces using "user config" should load '$j.cookie' & |
| 137 | + * 'JSON' in their module loader |
| 138 | + * |
| 139 | + * By abstracting user preference we could eventually integrate a persistent |
| 140 | + * per-account preference system on the server. |
| 141 | + * |
| 142 | + * @parma {Function} callback Function to be called once userPrefrences are |
| 143 | + * loaded |
| 144 | + */ |
139 | 145 | var setupUserConfigFlag = false; |
140 | 146 | mw.setupUserConfig = function( callback ) { |
141 | 147 | if( setupUserConfigFlag ) { |
— | — | @@ -143,7 +149,7 @@ |
144 | 150 | } |
145 | 151 | return ; |
146 | 152 | } |
147 | | - // Do Setup user config: |
| 153 | + // Do Setup user config: |
148 | 154 | mw.load( [ '$j.cookie', 'JSON' ], function() { |
149 | 155 | if( $j.cookie( 'mwUserConfig' ) ) { |
150 | 156 | mwUserConfig = JSON.parse( $j.cookie( 'mwUserConfig' ) ); |
— | — | @@ -156,12 +162,14 @@ |
157 | 163 | } |
158 | 164 | |
159 | 165 | /** |
160 | | - * Save a user configuration var to a cookie & local global variable |
161 | | - * Loads the cookie plugin if not already loaded |
162 | | - * |
163 | | - * @param {String} name Name of user configuration value |
164 | | - * @param {String} value Value of configuration name |
165 | | - */ |
| 166 | + * Save a user configuration var to a cookie & local global variable Loads |
| 167 | + * the cookie plugin if not already loaded |
| 168 | + * |
| 169 | + * @param {String} |
| 170 | + * name Name of user configuration value |
| 171 | + * @param {String} |
| 172 | + * value Value of configuration name |
| 173 | + */ |
166 | 174 | mw.setUserConfig = function ( name, value, cookieOptions ) { |
167 | 175 | if( ! setupUserConfigFlag ) { |
168 | 176 | mw.log( "Error: userConfig not setup" ); |
— | — | @@ -170,18 +178,18 @@ |
171 | 179 | // Update local value |
172 | 180 | mwUserConfig[ name ] = value; |
173 | 181 | |
174 | | - // Update the cookie ( '$j.cookie' & 'JSON' should already be loaded ) |
| 182 | + // Update the cookie ( '$j.cookie' & 'JSON' should already be loaded ) |
175 | 183 | $j.cookie( 'mwUserConfig', JSON.stringify( mwUserConfig ) ); |
176 | 184 | } |
177 | 185 | |
178 | 186 | /** |
179 | | - * Save a user configuration var to a cookie & local global variable |
180 | | - * |
181 | | - * @param {String} name Name of user configuration value |
182 | | - * @return |
183 | | - * value of the configuration name |
184 | | - * false if the configuration name could not be found |
185 | | - */ |
| 187 | + * Save a user configuration var to a cookie & local global variable |
| 188 | + * |
| 189 | + * @param {String} |
| 190 | + * name Name of user configuration value |
| 191 | + * @return value of the configuration name false if the configuration name |
| 192 | + * could not be found |
| 193 | + */ |
186 | 194 | mw.getUserConfig = function ( name ) { |
187 | 195 | if( mwUserConfig[ name ] ) |
188 | 196 | return mwUserConfig[ name ]; |
— | — | @@ -189,25 +197,28 @@ |
190 | 198 | } |
191 | 199 | |
192 | 200 | /** |
193 | | - * Add a hook system for a target object / interface |
194 | | - * |
195 | | - * depricated you should instead use jQuery's bind and trigger |
196 | | - * |
197 | | - * @param {Object} targetObj Interface Object to add hook system to. |
198 | | - */ |
| 201 | + * Add a hook system for a target object / interface |
| 202 | + * |
| 203 | + * depricated you should instead use jQuery's bind and trigger |
| 204 | + * |
| 205 | + * @param {Object} |
| 206 | + * targetObj Interface Object to add hook system to. |
| 207 | + */ |
199 | 208 | mw.addHookSystem = function( targetObj ) { |
200 | 209 | |
201 | 210 | // Setup the target object hook holder: |
202 | 211 | targetObj[ 'hooks' ] = { }; |
203 | 212 | |
204 | 213 | /** |
205 | | - * Adds a hook to the target object |
206 | | - * |
207 | | - * Should be called by clients to setup named hooks |
208 | | - * |
209 | | - * @param {String} hookName Name of hook to be added |
210 | | - * @param {Function} hookFunction Function to be called at hook time |
211 | | - */ |
| 214 | + * Adds a hook to the target object |
| 215 | + * |
| 216 | + * Should be called by clients to setup named hooks |
| 217 | + * |
| 218 | + * @param {String} |
| 219 | + * hookName Name of hook to be added |
| 220 | + * @param {Function} |
| 221 | + * hookFunction Function to be called at hook time |
| 222 | + */ |
212 | 223 | targetObj.addHook = function( hookName, hookFunction ) { |
213 | 224 | if( ! this.hooks[ hookName ] ) { |
214 | 225 | this.hooks[ hookName ] = [ ]; |
— | — | @@ -216,15 +227,15 @@ |
217 | 228 | } |
218 | 229 | |
219 | 230 | /** |
220 | | - * Runs all the hooks by a given name with reference to the host object |
221 | | - * |
222 | | - * Should be called by the host object at named execution points |
223 | | - * |
224 | | - * @param {String} hookName Name of hook to be called |
225 | | - * @return Value of hook result |
226 | | - * true interface should continue function execution |
227 | | - * false interface should stop or return from method |
228 | | - */ |
| 231 | + * Runs all the hooks by a given name with reference to the host object |
| 232 | + * |
| 233 | + * Should be called by the host object at named execution points |
| 234 | + * |
| 235 | + * @param {String} |
| 236 | + * hookName Name of hook to be called |
| 237 | + * @return Value of hook result true interface should continue function |
| 238 | + * execution false interface should stop or return from method |
| 239 | + */ |
229 | 240 | targetObj.runHook = function( hookName, options ) { |
230 | 241 | if( this.hooks[ hookName ] ) { |
231 | 242 | for( var i =0; i < this.hooks[ hookName ].length; i ++ ) { |
— | — | @@ -244,89 +255,93 @@ |
245 | 256 | |
246 | 257 | |
247 | 258 | /** |
248 | | - * Top level loader prototype: |
249 | | - */ |
| 259 | + * Top level loader prototype: |
| 260 | + */ |
250 | 261 | mw.loader = { |
251 | 262 | /** |
252 | | - * Javascript Module Loader functions |
253 | | - * @key Name of Module |
254 | | - * @value function code to load module |
255 | | - */ |
| 263 | + * Javascript Module Loader functions |
| 264 | + * |
| 265 | + * @key Name of Module |
| 266 | + * @value function code to load module |
| 267 | + */ |
256 | 268 | moduleLoaders : [], |
257 | 269 | |
258 | 270 | /** |
259 | | - * Module resource list queue. |
260 | | - * @key Name of Module |
261 | | - * @value |
262 | | - * .resourceList list of resources to be loaded |
263 | | - * .functionQueue list of functions to be run once module is ready |
264 | | - */ |
| 271 | + * Module resource list queue. |
| 272 | + * |
| 273 | + * @key Name of Module |
| 274 | + * @value .resourceList list of resources to be loaded .functionQueue |
| 275 | + * list of functions to be run once module is ready |
| 276 | + */ |
265 | 277 | moduleLoadQueue: { }, |
266 | 278 | |
267 | 279 | /** |
268 | | - * Javascript Class Paths |
269 | | - * @key Name of resource |
270 | | - * @value Class file path |
271 | | - */ |
| 280 | + * Javascript Class Paths |
| 281 | + * |
| 282 | + * @key Name of resource |
| 283 | + * @value Class file path |
| 284 | + */ |
272 | 285 | resourcePaths : { }, |
273 | 286 | |
274 | 287 | /** |
275 | | - * javascript Resource Paths |
276 | | - * @key Name of resource |
277 | | - * @value Name of depenent style sheet |
278 | | - */ |
| 288 | + * javascript Resource Paths |
| 289 | + * |
| 290 | + * @key Name of resource |
| 291 | + * @value Name of depenent style sheet |
| 292 | + */ |
279 | 293 | resourceStyleDependency: { }, |
280 | 294 | |
281 | 295 | /** |
282 | | - * Core load function: |
283 | | - * |
284 | | - * @param {Mixed} loadRequest: |
285 | | - * |
286 | | - * {String} Name of a module to be loaded |
287 | | - * Modules are added via addModuleLoader and can define custom |
288 | | - * code needed to check config and return a list of resources |
289 | | - * to be loaded |
290 | | - * |
291 | | - * {String} Name of a resource to loaded. |
292 | | - * Resources are added via addResourcePaths function |
293 | | - * Using defined resource names avoids loading the same resource |
294 | | - * twice by first checking if the named resource is defined in |
295 | | - * the global javascript scope variable |
296 | | - * |
297 | | - * {String} Absolute or relative to url path |
298 | | - * The same file won't be loaded twice |
299 | | - * |
300 | | - * {Array} can be an array of any combination of the above strings. |
301 | | - * Will be loaded in-order or in a single resource loader request |
302 | | - * if scriptLoader is available. |
303 | | - * |
304 | | - * {Array} {Array} Can be a set of Arrays for loading. |
305 | | - * Some browsers execute included scripts out of order. |
306 | | - * This lets you chain sets of request for those browsers. |
307 | | - * If using the server side resource loader order is preserved |
308 | | - * in output and a single request will be used. |
309 | | - * |
310 | | - * @param {Function} callback Function called once loading is complete |
311 | | - * |
312 | | - */ |
| 296 | + * Core load function: |
| 297 | + * |
| 298 | + * @param {Mixed} |
| 299 | + * loadRequest: |
| 300 | + * |
| 301 | + * {String} Name of a module to be loaded Modules are added via |
| 302 | + * addModuleLoader and can define custom code needed to check config and |
| 303 | + * return a list of resources to be loaded |
| 304 | + * |
| 305 | + * {String} Name of a resource to loaded. Resources are added via |
| 306 | + * addResourcePaths function Using defined resource names avoids loading |
| 307 | + * the same resource twice by first checking if the named resource is |
| 308 | + * defined in the global javascript scope variable |
| 309 | + * |
| 310 | + * {String} Absolute or relative to url path The same file won't be |
| 311 | + * loaded twice |
| 312 | + * |
| 313 | + * {Array} can be an array of any combination of the above strings. Will |
| 314 | + * be loaded in-order or in a single resource loader request if |
| 315 | + * scriptLoader is available. |
| 316 | + * |
| 317 | + * {Array} {Array} Can be a set of Arrays for loading. Some browsers |
| 318 | + * execute included scripts out of order. This lets you chain sets of |
| 319 | + * request for those browsers. If using the server side resource loader |
| 320 | + * order is preserved in output and a single request will be used. |
| 321 | + * |
| 322 | + * @param {Function} |
| 323 | + * callback Function called once loading is complete |
| 324 | + * |
| 325 | + */ |
313 | 326 | load: function( loadRequest, instanceCallback ) { |
314 | | - //mw.log("mw.load:: " + loadRequest ); |
| 327 | + // mw.log("mw.load:: " + loadRequest ); |
315 | 328 | |
316 | 329 | // Throw out any loadRequests that are not strings |
317 | 330 | loadRequest = this.cleanLoadRequest( loadRequest ); |
318 | 331 | |
319 | | - // Ensure the callback is only called once per load instance |
| 332 | + // Ensure the callback is only called once per load instance |
320 | 333 | var callback = function(){ |
321 | | - //mw.log( 'instanceCallback::running callback: ' + instanceCallback ); |
| 334 | + // mw.log( 'instanceCallback::running callback: ' + |
| 335 | + // instanceCallback ); |
322 | 336 | if( instanceCallback ){ |
323 | | - // We pass the loadRequest back to the callback for easy debugging of concurrency issues. |
324 | | - // ( normally its not used ) |
| 337 | + // We pass the loadRequest back to the callback for easy |
| 338 | + // debugging of concurrency issues. |
| 339 | + // ( normally its not used ) |
325 | 340 | instanceCallback( loadRequest ); |
326 | 341 | instanceCallback = null; |
327 | 342 | } |
328 | 343 | } |
329 | 344 | |
330 | | - // Check for empty loadRequest ( directly return the callback ) |
| 345 | + // Check for empty loadRequest ( directly return the callback ) |
331 | 346 | if( mw.isEmpty( loadRequest ) ) { |
332 | 347 | mw.log( 'Empty load request: ( ' + loadRequest + ' ) ' ); |
333 | 348 | callback( loadRequest ); |
— | — | @@ -334,18 +349,18 @@ |
335 | 350 | } |
336 | 351 | |
337 | 352 | |
338 | | - // Check if its a multi-part request: |
| 353 | + // Check if its a multi-part request: |
339 | 354 | if( typeof loadRequest == 'object' ) { |
340 | 355 | if( loadRequest.length > 1 ) { |
341 | 356 | this.loadMany ( loadRequest, callback ); |
342 | 357 | return ; |
343 | 358 | }else{ |
344 | | - // If an array of length 1 set as first element |
| 359 | + // If an array of length 1 set as first element |
345 | 360 | loadRequest = loadRequest[0]; |
346 | 361 | } |
347 | 362 | } |
348 | 363 | |
349 | | - // Check for the module name loader function |
| 364 | + // Check for the module name loader function |
350 | 365 | if( this.moduleLoaders[ loadRequest ] ) { |
351 | 366 | var resourceSet = this.getModuleResourceSet( loadRequest ); |
352 | 367 | if( !resourceSet ){ |
— | — | @@ -354,9 +369,10 @@ |
355 | 370 | } |
356 | 371 | |
357 | 372 | // xxx should use refactor "ready" stuff into a "domReady" class |
358 | | - // So we would not have local scope globals like this: |
| 373 | + // So we would not have local scope globals like this: |
359 | 374 | if ( mwReadyFlag ) { |
360 | | - // Load the module directly if load request is after mw.ready has run |
| 375 | + // Load the module directly if load request is after |
| 376 | + // mw.ready has run |
361 | 377 | this.load( resourceSet, callback ); |
362 | 378 | } else { |
363 | 379 | this.addToModuleLoaderQueue( |
— | — | @@ -368,7 +384,7 @@ |
369 | 385 | return ; |
370 | 386 | } |
371 | 387 | |
372 | | - // Check for javascript resource |
| 388 | + // Check for javascript resource |
373 | 389 | if( this.getResourcePath( loadRequest ) ) { |
374 | 390 | this.loadResource( loadRequest, callback ); |
375 | 391 | return ; |
— | — | @@ -383,7 +399,7 @@ |
384 | 400 | return ; |
385 | 401 | } |
386 | 402 | |
387 | | - // Possible error? |
| 403 | + // Possible error? |
388 | 404 | mw.log( "Error could not handle load request: " + loadRequest ); |
389 | 405 | }, |
390 | 406 | |
— | — | @@ -393,14 +409,14 @@ |
394 | 410 | // Add the result of the module loader function |
395 | 411 | return this.moduleLoaders[ moduleName ](); |
396 | 412 | } else if( typeof ( this.moduleLoaders[ moduleName ] ) == 'object' ){ |
397 | | - // set resourceSet directly |
| 413 | + // set resourceSet directly |
398 | 414 | return this.moduleLoaders[ moduleName ]; |
399 | 415 | } |
400 | 416 | return false; |
401 | 417 | }, |
402 | 418 | |
403 | 419 | /** |
404 | | - * Clean the loadRequest ( throw out any non-string items ) |
| 420 | + * Clean the loadRequest ( throw out any non-string items ) |
405 | 421 | */ |
406 | 422 | cleanLoadRequest: function( loadRequest ){ |
407 | 423 | var cleanRequest = []; |
— | — | @@ -418,31 +434,35 @@ |
419 | 435 | return cleanRequest; |
420 | 436 | }, |
421 | 437 | /** |
422 | | - * Load a set of scripts. |
423 | | - * Will issue many load requests or package the request for the resource loader |
424 | | - * |
425 | | - * @param {Object} loadSet Set of scripts to be loaded |
426 | | - * @param {Function} callback Function to call once all scripts are loaded. |
427 | | - */ |
| 438 | + * Load a set of scripts. Will issue many load requests or package the |
| 439 | + * request for the resource loader |
| 440 | + * |
| 441 | + * @param {Object} |
| 442 | + * loadSet Set of scripts to be loaded |
| 443 | + * @param {Function} |
| 444 | + * callback Function to call once all scripts are loaded. |
| 445 | + */ |
428 | 446 | loadMany: function( loadSet, callback ) { |
429 | 447 | var _this = this; |
430 | | - // Setup up the local "loadStates" |
| 448 | + // Setup up the local "loadStates" |
431 | 449 | var loadStates = { }; |
432 | 450 | |
433 | | - // Check if we can load via the "resource loader" ( mwEmbed was included via scriptLoader ) |
| 451 | + // Check if we can load via the "resource loader" ( mwEmbed was |
| 452 | + // included via scriptLoader ) |
434 | 453 | if( mw.getResourceLoaderPath() ) { |
435 | | - // Get the grouped loadStates variable |
| 454 | + // Get the grouped loadStates variable |
436 | 455 | loadStates = this.getGroupLoadState( loadSet ); |
437 | 456 | if( mw.isEmpty( loadStates ) ) { |
438 | | - //mw.log( 'loadMany:all resources already loaded'); |
| 457 | + // mw.log( 'loadMany:all resources already loaded'); |
439 | 458 | callback(); |
440 | 459 | return ; |
441 | 460 | } |
442 | 461 | }else{ |
443 | | - // Check if its a dependency set ( nested objects ) |
| 462 | + // Check if its a dependency set ( nested objects ) |
444 | 463 | if( typeof loadSet [ 0 ] == 'object' ) { |
445 | 464 | _this.dependencyChainCallFlag[ loadSet ] = false; |
446 | | - //Load sets of resources ( to preserver order for some browsers ) |
| 465 | + // Load sets of resources ( to preserver order for some |
| 466 | + // browsers ) |
447 | 467 | _this.loadDependencyChain( loadSet, callback ); |
448 | 468 | return ; |
449 | 469 | } |
— | — | @@ -457,25 +477,25 @@ |
458 | 478 | // We are infact loading many: |
459 | 479 | mw.log("mw.load: LoadMany:: " + loadSet ); |
460 | 480 | |
461 | | - // Issue the load request check check loadStates to see if we are "done" |
| 481 | + // Issue the load request check check loadStates to see if we are |
| 482 | + // "done" |
462 | 483 | for( var loadName in loadStates ) { |
463 | | - //mw.log("loadMany: load: " + loadName ); |
| 484 | + // mw.log("loadMany: load: " + loadName ); |
464 | 485 | this.load( loadName, function ( loadName ) { |
465 | 486 | loadStates[ loadName ] = 1; |
466 | 487 | |
467 | 488 | /* |
468 | | - for( var i in loadStates ) { |
469 | | - mw.log( loadName + ' finished of: ' + i + ' : ' + loadStates[i] ); |
470 | | - } |
471 | | - */ |
| 489 | + * for( var i in loadStates ) { mw.log( loadName + ' |
| 490 | + * finished of: ' + i + ' : ' + loadStates[i] ); } |
| 491 | + */ |
472 | 492 | |
473 | | - //Check if all load request states are set 1 |
| 493 | + // Check if all load request states are set 1 |
474 | 494 | var loadDone = true; |
475 | 495 | for( var j in loadStates ) { |
476 | 496 | if( loadStates[ j ] === 0 ) |
477 | 497 | loadDone = false; |
478 | 498 | } |
479 | | - // Run the parent scope callback for "loadMany" |
| 499 | + // Run the parent scope callback for "loadMany" |
480 | 500 | if( loadDone ) { |
481 | 501 | callback( loadName ); |
482 | 502 | } |
— | — | @@ -484,16 +504,16 @@ |
485 | 505 | }, |
486 | 506 | |
487 | 507 | /** |
488 | | - * Get grouped load state for script loader |
489 | | - * |
490 | | - * Groups the scriptRequest where possible: |
491 | | - * Modules include "loader code" so they are separated |
492 | | - * into pre-condition code to be run for subsequent requests |
493 | | - * |
494 | | - * @param {Object} loadSet Loadset to return grouped |
495 | | - * @return {Object} |
496 | | - * grouped loadSet |
497 | | - */ |
| 508 | + * Get grouped load state for script loader |
| 509 | + * |
| 510 | + * Groups the scriptRequest where possible: Modules include "loader |
| 511 | + * code" so they are separated into pre-condition code to be run for |
| 512 | + * subsequent requests |
| 513 | + * |
| 514 | + * @param {Object} |
| 515 | + * loadSet Loadset to return grouped |
| 516 | + * @return {Object} grouped loadSet |
| 517 | + */ |
498 | 518 | getGroupLoadState: function( loadSet ) { |
499 | 519 | var groupedLoadSet = []; |
500 | 520 | var loadStates = { }; |
— | — | @@ -501,12 +521,12 @@ |
502 | 522 | if( typeof loadSet[0] == 'object' ) { |
503 | 523 | for( var i = 0; i < loadSet.length ; i++ ) { |
504 | 524 | for( var j = 0; j < loadSet[i].length ; j++ ) { |
505 | | - // Make sure we have not already included it: |
| 525 | + // Make sure we have not already included it: |
506 | 526 | groupedLoadSet.push( loadSet[i][j] ); |
507 | 527 | } |
508 | 528 | } |
509 | 529 | } else { |
510 | | - // Use the loadSet directly: |
| 530 | + // Use the loadSet directly: |
511 | 531 | groupedLoadSet = loadSet; |
512 | 532 | } |
513 | 533 | |
— | — | @@ -518,7 +538,7 @@ |
519 | 539 | |
520 | 540 | |
521 | 541 | if( this.getResourcePath( loadName ) ) { |
522 | | - // Only add to group request if not already set: |
| 542 | + // Only add to group request if not already set: |
523 | 543 | if ( !mw.isset( loadName ) ) { |
524 | 544 | groupClassKey += coma + loadName |
525 | 545 | coma = ','; |
— | — | @@ -530,7 +550,8 @@ |
531 | 551 | } |
532 | 552 | } else if ( this.moduleLoaders[ loadName ] ) { |
533 | 553 | |
534 | | - // Module loaders break up grouped script requests ( add the current groupClassKey ) |
| 554 | + // Module loaders break up grouped script requests ( add the |
| 555 | + // current groupClassKey ) |
535 | 556 | if( groupClassKey != '' ) { |
536 | 557 | loadStates[ groupClassKey ] = 0; |
537 | 558 | groupClassKey = coma = ''; |
— | — | @@ -540,7 +561,7 @@ |
541 | 562 | } |
542 | 563 | } |
543 | 564 | |
544 | | - // Add groupClassKey if set: |
| 565 | + // Add groupClassKey if set: |
545 | 566 | if( groupClassKey != '' ) { |
546 | 567 | loadStates [ groupClassKey ] = 0; |
547 | 568 | } |
— | — | @@ -548,16 +569,17 @@ |
549 | 570 | return loadStates; |
550 | 571 | }, |
551 | 572 | |
552 | | - // Array to register that a callback has been called |
| 573 | + // Array to register that a callback has been called |
553 | 574 | dependencyChainCallFlag: { }, |
554 | 575 | |
555 | 576 | /** |
556 | | - * Load a sets of scripts satisfy dependency order for browsers that execute |
557 | | - * dynamically included scripts out of order |
558 | | - * |
559 | | - * @param {Object} loadChain A set of javascript arrays to be loaded. |
560 | | - * Sets are requested in array order. |
561 | | - */ |
| 577 | + * Load a sets of scripts satisfy dependency order for browsers that |
| 578 | + * execute dynamically included scripts out of order |
| 579 | + * |
| 580 | + * @param {Object} |
| 581 | + * loadChain A set of javascript arrays to be loaded. Sets |
| 582 | + * are requested in array order. |
| 583 | + */ |
562 | 584 | loadDependencyChain: function( loadChain, callback ) { |
563 | 585 | var _this = this; |
564 | 586 | // Load with dependency checks |
— | — | @@ -566,8 +588,8 @@ |
567 | 589 | if ( loadChain.length != 0 ) { |
568 | 590 | _this.loadDependencyChain( loadChain, callback ); |
569 | 591 | } else { |
570 | | - // NOTE: IE gets called twice so we have check the |
571 | | - // dependencyChainCallFlag before calling the callback |
| 592 | + // NOTE: IE gets called twice so we have check the |
| 593 | + // dependencyChainCallFlag before calling the callback |
572 | 594 | if( _this.dependencyChainCallFlag[ callSet ] == callback ) { |
573 | 595 | mw.log("... already called this callback for " + callSet ); |
574 | 596 | return ; |
— | — | @@ -579,12 +601,12 @@ |
580 | 602 | }, |
581 | 603 | |
582 | 604 | /** |
583 | | - * Add to the module loader queue |
584 | | - */ |
| 605 | + * Add to the module loader queue |
| 606 | + */ |
585 | 607 | addToModuleLoaderQueue: function( moduleName, resourceSet, callback ) { |
586 | 608 | mw.log(" addToModuleLoaderQueue:: " + moduleName + ' resourceSet: ' + resourceSet ); |
587 | 609 | if( this.moduleLoadQueue[ moduleName ] ){ |
588 | | - // If the module is already in the queue just add its callback: |
| 610 | + // If the module is already in the queue just add its callback: |
589 | 611 | this.moduleLoadQueue[ moduleName ].functionQueue.push( callback ); |
590 | 612 | } else { |
591 | 613 | // create the moduleLoadQueue item |
— | — | @@ -597,13 +619,14 @@ |
598 | 620 | }, |
599 | 621 | |
600 | 622 | /** |
601 | | - * Loops over all modules in queue, builds request sets based on config request type |
602 | | - */ |
| 623 | + * Loops over all modules in queue, builds request sets based on config |
| 624 | + * request type |
| 625 | + */ |
603 | 626 | runModuleLoadQueue: function(){ |
604 | 627 | var _this = this; |
605 | 628 | mw.log( "mw.runModuleLoadQueue:: " ); |
606 | 629 | var runModuleFunctionQueue = function(){ |
607 | | - // Run all the callbacks |
| 630 | + // Run all the callbacks |
608 | 631 | for( var moduleName in _this.moduleLoadQueue ){ |
609 | 632 | while( _this.moduleLoadQueue[moduleName].functionQueue.length ) { |
610 | 633 | _this.moduleLoadQueue[moduleName].functionQueue.shift()(); |
— | — | @@ -611,10 +634,11 @@ |
612 | 635 | } |
613 | 636 | } |
614 | 637 | |
615 | | - // Check for single request or javascript debug based loading: |
| 638 | + // Check for single request or javascript debug based loading: |
616 | 639 | if( !mw.getResourceLoaderPath() || mw.getConfig( 'loader.groupStrategy' ) == 'single' ){ |
617 | | - // if not using the resource load just do a normal array merge |
618 | | - // ( for browsers like IE that don't follow first append first execute rule ) |
| 640 | + // if not using the resource load just do a normal array merge |
| 641 | + // ( for browsers like IE that don't follow first append first |
| 642 | + // execute rule ) |
619 | 643 | var fullResourceList = []; |
620 | 644 | for( var moduleName in this.moduleLoadQueue ) { |
621 | 645 | var resourceSet = this.moduleLoadQueue[ moduleName ].resourceSet; |
— | — | @@ -633,13 +657,16 @@ |
634 | 658 | var sharedResourceList = []; |
635 | 659 | |
636 | 660 | for( var moduleName in this.moduleLoadQueue ) { |
637 | | - // Build a shared dependencies list and load that separately "first" |
638 | | - // ( in IE we have to wait until its "ready" since it does not follow dom order ) |
| 661 | + // Build a shared dependencies list and load that separately |
| 662 | + // "first" |
| 663 | + // ( in IE we have to wait until its "ready" since it does |
| 664 | + // not follow dom order ) |
639 | 665 | var moduleResourceList = this.getFlatModuleResourceList( moduleName ); |
640 | | - // Build the sharedResourceList |
| 666 | + // Build the sharedResourceList |
641 | 667 | for( var i=0; i < moduleResourceList.length; i++ ){ |
642 | 668 | var moduleResource = moduleResourceList[i]; |
643 | | - // Check if already in the full resource list if so add to shared. |
| 669 | + // Check if already in the full resource list if so add |
| 670 | + // to shared. |
644 | 671 | if( fullResourceList[ moduleResource ] ){ |
645 | 672 | if( $j.inArray( moduleResource, sharedResourceList ) == -1 ){ |
646 | 673 | sharedResourceList.push( moduleResource ); |
— | — | @@ -650,7 +677,8 @@ |
651 | 678 | } |
652 | 679 | } |
653 | 680 | |
654 | | - // Local module request set ( stores the actual request we will make after grouping shared resources |
| 681 | + // Local module request set ( stores the actual request we will |
| 682 | + // make after grouping shared resources |
655 | 683 | var moduleRequestSet = {}; |
656 | 684 | |
657 | 685 | // Only add non-shared to respective modules load requests |
— | — | @@ -677,7 +705,8 @@ |
678 | 706 | } |
679 | 707 | runModuleFunctionQueue(); |
680 | 708 | } |
681 | | - // Local instance of load requests to retain resourceSet context: |
| 709 | + // Local instance of load requests to retain resourceSet |
| 710 | + // context: |
682 | 711 | var localLoadCallInstance = function( moduleName, resourceSet ){ |
683 | 712 | mw.load( resourceSet, function(){ |
684 | 713 | _this.moduleLoadQueue[ moduleName ].loaded = true; |
— | — | @@ -685,25 +714,26 @@ |
686 | 715 | }); |
687 | 716 | } |
688 | 717 | |
689 | | - // Load the shared resources |
| 718 | + // Load the shared resources |
690 | 719 | mw.load( sharedResourceList, function(){ |
691 | | - //mw.log("Shared Resources loaded"); |
692 | | - // xxx check if we are in "IE" and dependencies need to be loaded "first" |
| 720 | + // mw.log("Shared Resources loaded"); |
| 721 | + // xxx check if we are in "IE" and dependencies need to be |
| 722 | + // loaded "first" |
693 | 723 | sharedResourceLoadDone = true; |
694 | 724 | checkModulesDone(); |
695 | 725 | }); |
696 | | - // Load all module Request Set |
| 726 | + // Load all module Request Set |
697 | 727 | for( var moduleName in moduleRequestSet ){ |
698 | 728 | localLoadCallInstance( moduleName, moduleRequestSet[ moduleName ] ); |
699 | 729 | } |
700 | 730 | } |
701 | | - // xxx Here we could also do some "intelligent" grouping |
| 731 | + // xxx Here we could also do some "intelligent" grouping |
702 | 732 | }, |
703 | 733 | |
704 | 734 | getFlatModuleResourceList: function( moduleName ){ |
705 | 735 | var moduleList = []; |
706 | 736 | for( var j in this.moduleLoadQueue[moduleName].resourceSet ){ |
707 | | - // Check if we have a multi-set array: |
| 737 | + // Check if we have a multi-set array: |
708 | 738 | if( typeof this.moduleLoadQueue[moduleName].resourceSet[j] == 'object' ){ |
709 | 739 | moduleList = $j.merge( moduleList, this.moduleLoadQueue[moduleName].resourceSet[j] ); |
710 | 740 | } else { |
— | — | @@ -713,21 +743,23 @@ |
714 | 744 | return moduleList; |
715 | 745 | }, |
716 | 746 | /** |
717 | | - * Loads javascript or css associated with a resourceName |
718 | | - * |
719 | | - * @param {String} resourceName Name of resource to load |
720 | | - * @param {Function} callback Function to run once resource is loaded |
721 | | - */ |
| 747 | + * Loads javascript or css associated with a resourceName |
| 748 | + * |
| 749 | + * @param {String} |
| 750 | + * resourceName Name of resource to load |
| 751 | + * @param {Function} |
| 752 | + * callback Function to run once resource is loaded |
| 753 | + */ |
722 | 754 | loadResource: function( resourceName , callback) { |
723 | | - //mw.log("LoadResource:" + resourceName ); |
| 755 | + // mw.log("LoadResource:" + resourceName ); |
724 | 756 | var _this = this; |
725 | 757 | |
726 | | - // Check for css dependency on resource name |
| 758 | + // Check for css dependency on resource name |
727 | 759 | if( this.resourceStyleDependency[ resourceName ] ) { |
728 | 760 | if( ! mw.isset( this.resourceStyleDependency[ resourceName ] )){ |
729 | 761 | mw.log("loadResource:: dependent css resource: " + this.resourceStyleDependency[ resourceName ] ); |
730 | 762 | _this.loadResource( this.resourceStyleDependency[ resourceName ] , function() { |
731 | | - // Continue the original loadResource request. |
| 763 | + // Continue the original loadResource request. |
732 | 764 | _this.loadResource( resourceName, callback ); |
733 | 765 | }); |
734 | 766 | return ; |
— | — | @@ -736,16 +768,17 @@ |
737 | 769 | |
738 | 770 | // Make sure the resource is not already defined: |
739 | 771 | if ( mw.isset( resourceName ) ) { |
740 | | - //mw.log( 'Class ( ' + resourceName + ' ) already defined ' ); |
| 772 | + // mw.log( 'Class ( ' + resourceName + ' ) already defined ' ); |
741 | 773 | callback( resourceName ); |
742 | 774 | return ; |
743 | 775 | } |
744 | 776 | |
745 | | - // Setup the Script Request var: |
| 777 | + // Setup the Script Request var: |
746 | 778 | var scriptRequest = null; |
747 | 779 | |
748 | 780 | |
749 | | - // If the scriptloader is enabled use the resourceName as the scriptRequest: |
| 781 | + // If the scriptloader is enabled use the resourceName as the |
| 782 | + // scriptRequest: |
750 | 783 | if( mw.getResourceLoaderPath() ) { |
751 | 784 | scriptRequest = resourceName; |
752 | 785 | }else{ |
— | — | @@ -766,9 +799,10 @@ |
767 | 800 | // Include resource defined check for older browsers |
768 | 801 | var resourceDone = false; |
769 | 802 | |
770 | | - // Set the loadDone callback per the provided resourceName |
| 803 | + // Set the loadDone callback per the provided resourceName |
771 | 804 | mw.setLoadDoneCB( resourceName, callback ); |
772 | | - // Issue the request to load the resource (include resource name in result callback: |
| 805 | + // Issue the request to load the resource (include resource name in |
| 806 | + // result callback: |
773 | 807 | mw.getScript( scriptRequest, function( scriptRequest ) { |
774 | 808 | // If its a "style sheet" manually set its resource to true |
775 | 809 | var ext = scriptRequest.substr( scriptRequest.split('?')[0].lastIndexOf( '.' ), 4 ).toLowerCase(); |
— | — | @@ -783,53 +817,58 @@ |
784 | 818 | + _this.getResourcePath( resourceName ) ); |
785 | 819 | } |
786 | 820 | |
787 | | - // If ( debug mode ) and the script include is missing resource messages |
788 | | - // do a separate request to retrieve the msgs |
| 821 | + // If ( debug mode ) and the script include is missing resource |
| 822 | + // messages |
| 823 | + // do a separate request to retrieve the msgs |
789 | 824 | if( mw.currentClassMissingMessages ) { |
790 | 825 | mw.log( " resourceName " + resourceName + " is missing messages" ); |
791 | 826 | // Reset the currentClassMissingMessages flag |
792 | 827 | mw.currentClassMissingMessages = false; |
793 | 828 | |
794 | | - // Load msgs for this resource: |
| 829 | + // Load msgs for this resource: |
795 | 830 | mw.loadResourceMessages( resourceName, function() { |
796 | | - // Run the onDone callback |
| 831 | + // Run the onDone callback |
797 | 832 | mw.loadDone( resourceName ); |
798 | 833 | } ); |
799 | 834 | } else { |
800 | | - // If not using the resource loader make sure the resourceName is available before firing the loadDone |
| 835 | + // If not using the resource loader make sure the |
| 836 | + // resourceName is available before firing the loadDone |
801 | 837 | if( !mw.getResourceLoaderPath() ) { |
802 | 838 | mw.waitForObject( resourceName, function( resourceName ) { |
803 | | - // Once object is ready run loadDone |
| 839 | + // Once object is ready run loadDone |
804 | 840 | mw.loadDone( resourceName ); |
805 | 841 | } ); |
806 | 842 | } else { |
807 | | - // loadDone should be appended to the bottom of the resource loader response |
808 | | - //mw.loadDone( resourceName ); |
| 843 | + // loadDone should be appended to the bottom of the |
| 844 | + // resource loader response |
| 845 | + // mw.loadDone( resourceName ); |
809 | 846 | } |
810 | 847 | } |
811 | 848 | } ); |
812 | 849 | }, |
813 | 850 | |
814 | 851 | /** |
815 | | - * Adds a module to the mwLoader object |
816 | | - * |
817 | | - * @param {String} name Name of module |
818 | | - * @param {Function} moduleLoader Function that |
819 | | - * loads dependencies for a module |
820 | | - */ |
| 852 | + * Adds a module to the mwLoader object |
| 853 | + * |
| 854 | + * @param {String} |
| 855 | + * name Name of module |
| 856 | + * @param {Function} |
| 857 | + * moduleLoader Function that loads dependencies for a module |
| 858 | + */ |
821 | 859 | addModuleLoader: function( name, moduleLoader ) { |
822 | 860 | this.moduleLoaders [ name ] = moduleLoader; |
823 | 861 | }, |
824 | 862 | |
825 | 863 | /** |
826 | | - * Adds resource file path key value pairs |
827 | | - * |
828 | | - * @param {Object} resourceSet JSON formated list of |
829 | | - * resource name file path pairs. |
830 | | - * |
831 | | - * resourceSet must be strict JSON to allow the |
832 | | - * php scriptLoader to parse the file paths. |
833 | | - */ |
| 864 | + * Adds resource file path key value pairs |
| 865 | + * |
| 866 | + * @param {Object} |
| 867 | + * resourceSet JSON formated list of resource name file path |
| 868 | + * pairs. |
| 869 | + * |
| 870 | + * resourceSet must be strict JSON to allow the php scriptLoader to |
| 871 | + * parse the file paths. |
| 872 | + */ |
834 | 873 | addResourcePaths: function( resourceSet ) { |
835 | 874 | var prefix = ( mw.getConfig( 'loaderContext' ) )? |
836 | 875 | mw.getConfig( 'loaderContext' ): ''; |
— | — | @@ -840,11 +879,11 @@ |
841 | 880 | }, |
842 | 881 | |
843 | 882 | /* |
844 | | - * Adds a named style sheet dependency to a named resource |
845 | | - * |
846 | | - * @parma {Object} resourceSet JSON formated list of resource names |
847 | | - * and associated style sheet names |
848 | | - */ |
| 883 | + * Adds a named style sheet dependency to a named resource |
| 884 | + * |
| 885 | + * @parma {Object} resourceSet JSON formated list of resource names and |
| 886 | + * associated style sheet names |
| 887 | + */ |
849 | 888 | addStyleResourceDependency: function( resourceSet ){ |
850 | 889 | for( var i in resourceSet ){ |
851 | 890 | this.resourceStyleDependency[ i ] = resourceSet[i]; |
— | — | @@ -852,9 +891,9 @@ |
853 | 892 | }, |
854 | 893 | |
855 | 894 | /** |
856 | | - * Get a resource path from a resourceName |
857 | | - * if no resource found return false |
858 | | - */ |
| 895 | + * Get a resource path from a resourceName if no resource found return |
| 896 | + * false |
| 897 | + */ |
859 | 898 | getResourcePath: function( resourceName ) { |
860 | 899 | if( this.resourcePaths[ resourceName ] ) |
861 | 900 | return this.resourcePaths[ resourceName ] |
— | — | @@ -863,15 +902,17 @@ |
864 | 903 | } |
865 | 904 | |
866 | 905 | /** |
867 | | - * Load done callback for script loader |
868 | | - * @param {String} requestName Name of the load request |
869 | | - */ |
| 906 | + * Load done callback for script loader |
| 907 | + * |
| 908 | + * @param {String} |
| 909 | + * requestName Name of the load request |
| 910 | + */ |
870 | 911 | mw.loadDone = function( requestName ) { |
871 | 912 | if( !mwLoadDoneCB[ requestName ] ) { |
872 | 913 | return true; |
873 | 914 | } |
874 | 915 | while( mwLoadDoneCB[ requestName ].length ) { |
875 | | - // check if mwLoadDoneCB is already "done" |
| 916 | + // check if mwLoadDoneCB is already "done" |
876 | 917 | // the function list is not an object |
877 | 918 | if( typeof mwLoadDoneCB[ requestName ] != 'object' ) |
878 | 919 | { |
— | — | @@ -879,7 +920,8 @@ |
880 | 921 | } |
881 | 922 | var func = mwLoadDoneCB[ requestName ].pop(); |
882 | 923 | if( typeof func == 'function' ) { |
883 | | - //mw.log( "LoadDone: " + requestName + ' run callback::' + func); |
| 924 | + // mw.log( "LoadDone: " + requestName + ' run callback::' + |
| 925 | + // func); |
884 | 926 | func( requestName ); |
885 | 927 | }else{ |
886 | 928 | mw.log('mwLoadDoneCB: Error non callback function on stack'); |
— | — | @@ -890,10 +932,13 @@ |
891 | 933 | }; |
892 | 934 | |
893 | 935 | /** |
894 | | - * Set a load done callback |
895 | | - * @param {String} requestName Name of resource or request set |
896 | | - * @param {Function} callback Function called once requestName is ready |
897 | | - */ |
| 936 | + * Set a load done callback |
| 937 | + * |
| 938 | + * @param {String} |
| 939 | + * requestName Name of resource or request set |
| 940 | + * @param {Function} |
| 941 | + * callback Function called once requestName is ready |
| 942 | + */ |
898 | 943 | mw.setLoadDoneCB = function( requestName, callback ) { |
899 | 944 | // If the requestName is already done loading just callback |
900 | 945 | if( mwLoadDoneCB[ requestName ] == 'done' ) { |
— | — | @@ -907,31 +952,29 @@ |
908 | 953 | }; |
909 | 954 | |
910 | 955 | /** |
911 | | - * Shortcut entry points / convenience functions: |
912 | | - * Lets you write mw.load() instead of mw.loader.load() |
913 | | - * only these entry points should be used. |
914 | | - * |
915 | | - * future closure optimizations could minify internal |
916 | | - * function names |
917 | | - */ |
| 956 | + * Shortcut entry points / convenience functions: Lets you write mw.load() |
| 957 | + * instead of mw.loader.load() only these entry points should be used. |
| 958 | + * |
| 959 | + * future closure optimizations could minify internal function names |
| 960 | + */ |
918 | 961 | |
919 | 962 | /** |
920 | | - * Load Object entry point: Loads a requested set of javascript |
921 | | - */ |
| 963 | + * Load Object entry point: Loads a requested set of javascript |
| 964 | + */ |
922 | 965 | mw.load = function( loadRequest, callback ) { |
923 | 966 | return mw.loader.load( loadRequest, callback ); |
924 | 967 | } |
925 | 968 | |
926 | 969 | /** |
927 | | - * Add module entry point: Adds a module to the mwLoader object |
928 | | - */ |
| 970 | + * Add module entry point: Adds a module to the mwLoader object |
| 971 | + */ |
929 | 972 | mw.addModuleLoader = function ( name, loaderFunction ) { |
930 | 973 | return mw.loader.addModuleLoader( name, loaderFunction ); |
931 | 974 | } |
932 | 975 | |
933 | 976 | /** |
934 | | - * Add Class File Paths entry point: |
935 | | - */ |
| 977 | + * Add Class File Paths entry point: |
| 978 | + */ |
936 | 979 | mw.addResourcePaths = function ( resourceSet ) { |
937 | 980 | return mw.loader.addResourcePaths( resourceSet ); |
938 | 981 | } |
— | — | @@ -941,23 +984,23 @@ |
942 | 985 | } |
943 | 986 | |
944 | 987 | /** |
945 | | - * Get Class File Path entry point: |
946 | | - */ |
| 988 | + * Get Class File Path entry point: |
| 989 | + */ |
947 | 990 | mw.getResourcePath = function( resourceName ) { |
948 | 991 | return mw.loader.getResourcePath( resourceName ); |
949 | 992 | } |
950 | 993 | |
951 | 994 | |
952 | 995 | /** |
953 | | - * Utility Functions |
954 | | - */ |
| 996 | + * Utility Functions |
| 997 | + */ |
955 | 998 | |
956 | 999 | /** |
957 | | - * addLoaderDialog |
958 | | - * small helper for displaying a loading dialog |
959 | | - * |
960 | | - * @param {String} dialogHtml text Html of the loader msg |
961 | | - */ |
| 1000 | + * addLoaderDialog small helper for displaying a loading dialog |
| 1001 | + * |
| 1002 | + * @param {String} |
| 1003 | + * dialogHtml text Html of the loader msg |
| 1004 | + */ |
962 | 1005 | mw.addLoaderDialog = function( dialogHtml ) { |
963 | 1006 | $dialog = mw.addDialog( dialogHtml, dialogHtml + '<br>' + |
964 | 1007 | $j('<div />') |
— | — | @@ -986,16 +1029,20 @@ |
987 | 1030 | } |
988 | 1031 | |
989 | 1032 | /** |
990 | | - * Add a (temporary) dialog window: |
991 | | - * @param {String} title Title string for the dialog |
992 | | - * @param {String} dialogHtml String to be inserted in msg box |
993 | | - * @param {Mixed} buttonOption A button object for the dialog |
994 | | - * Can be a string for the close buton |
995 | | - */ |
| 1033 | + * Add a (temporary) dialog window: |
| 1034 | + * |
| 1035 | + * @param {String} |
| 1036 | + * title Title string for the dialog |
| 1037 | + * @param {String} |
| 1038 | + * dialogHtml String to be inserted in msg box |
| 1039 | + * @param {Mixed} |
| 1040 | + * buttonOption A button object for the dialog Can be a string |
| 1041 | + * for the close buton |
| 1042 | + */ |
996 | 1043 | mw.addDialog = function ( title, dialogHtml, buttons ) { |
997 | 1044 | $j( '#mwTempLoaderDialog' ).remove(); |
998 | 1045 | |
999 | | - // Append the style free loader ontop: |
| 1046 | + // Append the style free loader ontop: |
1000 | 1047 | $j( 'body' ).append( |
1001 | 1048 | $j('<div />') |
1002 | 1049 | .attr( { |
— | — | @@ -1049,14 +1096,14 @@ |
1050 | 1097 | |
1051 | 1098 | |
1052 | 1099 | /** |
1053 | | - * Similar to php isset function checks if the variable exists. |
1054 | | - * Does a safe check of a descendant method or variable |
1055 | | - * |
1056 | | - * @param {String} objectPath |
1057 | | - * @return {Boolean} |
1058 | | - * true if objectPath exists |
1059 | | - * false if objectPath is undefined |
1060 | | - */ |
| 1100 | + * Similar to php isset function checks if the variable exists. Does a safe |
| 1101 | + * check of a descendant method or variable |
| 1102 | + * |
| 1103 | + * @param {String} |
| 1104 | + * objectPath |
| 1105 | + * @return {Boolean} true if objectPath exists false if objectPath is |
| 1106 | + * undefined |
| 1107 | + */ |
1061 | 1108 | mw.isset = function( objectPath ) { |
1062 | 1109 | if ( !objectPath ) { |
1063 | 1110 | return false; |
— | — | @@ -1075,18 +1122,21 @@ |
1076 | 1123 | } |
1077 | 1124 | |
1078 | 1125 | /** |
1079 | | - * Wait for a object to be defined and the call the callback |
1080 | | - * |
1081 | | - * @param {Object} objectName Name of object to be defined |
1082 | | - * @param {Function} callback Function to call once object is defined |
1083 | | - * @param {Null} callNumber Used internally to keep track of |
1084 | | - * number of times waitForObject has been called |
1085 | | - */ |
1086 | | - var waitTime = 1200; // About 30 seconds |
| 1126 | + * Wait for a object to be defined and the call the callback |
| 1127 | + * |
| 1128 | + * @param {Object} |
| 1129 | + * objectName Name of object to be defined |
| 1130 | + * @param {Function} |
| 1131 | + * callback Function to call once object is defined |
| 1132 | + * @param {Null} |
| 1133 | + * callNumber Used internally to keep track of number of times |
| 1134 | + * waitForObject has been called |
| 1135 | + */ |
| 1136 | + var waitTime = 1200; // About 30 seconds |
1087 | 1137 | mw.waitForObject = function( objectName, callback, _callNumber) { |
1088 | | - //mw.log( 'waitForObject: ' + objectName + ' cn: ' + _callNumber); |
| 1138 | + // mw.log( 'waitForObject: ' + objectName + ' cn: ' + _callNumber); |
1089 | 1139 | |
1090 | | - // Increment callNumber: |
| 1140 | + // Increment callNumber: |
1091 | 1141 | if( !_callNumber ) { |
1092 | 1142 | _callNumber = 1; |
1093 | 1143 | } else { |
— | — | @@ -1110,14 +1160,15 @@ |
1111 | 1161 | } |
1112 | 1162 | |
1113 | 1163 | /** |
1114 | | - * Check if an object is empty or if its an empty string. |
1115 | | - * |
1116 | | - * @param {Object} object Object to be checked |
1117 | | - */ |
| 1164 | + * Check if an object is empty or if its an empty string. |
| 1165 | + * |
| 1166 | + * @param {Object} |
| 1167 | + * object Object to be checked |
| 1168 | + */ |
1118 | 1169 | mw.isEmpty = function( object ) { |
1119 | 1170 | if( typeof object == 'string' ) { |
1120 | 1171 | if( object == '' ) return true; |
1121 | | - // Non empty string: |
| 1172 | + // Non empty string: |
1122 | 1173 | return false; |
1123 | 1174 | } |
1124 | 1175 | |
— | — | @@ -1127,7 +1178,7 @@ |
1128 | 1179 | return true; |
1129 | 1180 | } |
1130 | 1181 | |
1131 | | - // Else check as an object: |
| 1182 | + // Else check as an object: |
1132 | 1183 | for( var i in object ) { return false; } |
1133 | 1184 | |
1134 | 1185 | // Else object is empty: |
— | — | @@ -1135,16 +1186,17 @@ |
1136 | 1187 | } |
1137 | 1188 | |
1138 | 1189 | /** |
1139 | | - * Log a string msg to the console |
1140 | | - * |
1141 | | - * all mw.log statements will be removed on minification so |
1142 | | - * lots of mw.log calls will not impact performance in non debug mode |
1143 | | - * |
1144 | | - * @param {String} string String to output to console |
1145 | | - */ |
| 1190 | + * Log a string msg to the console |
| 1191 | + * |
| 1192 | + * all mw.log statements will be removed on minification so lots of mw.log |
| 1193 | + * calls will not impact performance in non debug mode |
| 1194 | + * |
| 1195 | + * @param {String} |
| 1196 | + * string String to output to console |
| 1197 | + */ |
1146 | 1198 | mw.log = function( string ) { |
1147 | 1199 | |
1148 | | - // Add any prepend debug strings if necessary |
| 1200 | + // Add any prepend debug strings if necessary |
1149 | 1201 | if ( mw.getConfig( 'pre-append-log' ) ){ |
1150 | 1202 | string = mw.getConfig( 'pre-append-log' ) + string; |
1151 | 1203 | } |
— | — | @@ -1153,40 +1205,39 @@ |
1154 | 1206 | window.console.log( string ); |
1155 | 1207 | } else { |
1156 | 1208 | /** |
1157 | | - * Old IE and non-Firebug debug: ( commented out for now ) |
| 1209 | + * Old IE and non-Firebug debug: ( commented out for now ) |
1158 | 1210 | */ |
1159 | | - /*var log_elm = document.getElementById('mv_js_log'); |
1160 | | - if(!log_elm) { |
1161 | | - document.getElementsByTagName("body")[0].innerHTML = document.getElementsByTagName("body")[0].innerHTML + |
1162 | | - '<div style="position:absolute;z-index:500;bottom:0px;left:0px;right:0px;height:200px;">'+ |
1163 | | - '<textarea id="mv_js_log" cols="120" rows="12"></textarea>'+ |
1164 | | - '</div>'; |
1165 | | - |
1166 | | - var log_elm = document.getElementById('mv_js_log'); |
1167 | | - } |
1168 | | - if(log_elm) { |
1169 | | - log_elm.value+=string+"\n"; |
1170 | | - }*/ |
| 1211 | + /* |
| 1212 | + * var log_elm = document.getElementById('mv_js_log'); if(!log_elm) { |
| 1213 | + * document.getElementsByTagName("body")[0].innerHTML = |
| 1214 | + * document.getElementsByTagName("body")[0].innerHTML + '<div |
| 1215 | + * style="position:absolute;z-index:500;bottom:0px;left:0px;right:0px;height:200px;">'+ '<textarea |
| 1216 | + * id="mv_js_log" cols="120" rows="12"></textarea>'+ '</div>'; |
| 1217 | + * |
| 1218 | + * var log_elm = document.getElementById('mv_js_log'); } if(log_elm) { |
| 1219 | + * log_elm.value+=string+"\n"; } |
| 1220 | + */ |
1171 | 1221 | } |
1172 | 1222 | } |
1173 | 1223 | |
1174 | | - //Setup the local mwOnLoadFunctions array: |
| 1224 | + // Setup the local mwOnLoadFunctions array: |
1175 | 1225 | var mwOnLoadFunctions = []; |
1176 | 1226 | |
1177 | | - //mw Ready flag ( set once mwEmbed is ready ) |
| 1227 | + // mw Ready flag ( set once mwEmbed is ready ) |
1178 | 1228 | var mwReadyFlag = false; |
1179 | 1229 | |
1180 | 1230 | /** |
1181 | | - * Enables load hooks to run once mwEmbeed is "ready" |
1182 | | - * Will ensure jQuery is available, is in the $j namespace |
1183 | | - * and mw interfaces and configuration has been loaded and applied |
1184 | | - * |
1185 | | - * This is different from jQuery(document).ready() |
1186 | | - * ( jQuery ready is not friendly with dynamic includes |
1187 | | - * and not friendly with core interface asynchronous build out. ) |
1188 | | - * |
1189 | | - * @param {Function} callback Function to run once DOM and jQuery are ready |
1190 | | - */ |
| 1231 | + * Enables load hooks to run once mwEmbeed is "ready" Will ensure jQuery is |
| 1232 | + * available, is in the $j namespace and mw interfaces and configuration has |
| 1233 | + * been loaded and applied |
| 1234 | + * |
| 1235 | + * This is different from jQuery(document).ready() ( jQuery ready is not |
| 1236 | + * friendly with dynamic includes and not friendly with core interface |
| 1237 | + * asynchronous build out. ) |
| 1238 | + * |
| 1239 | + * @param {Function} |
| 1240 | + * callback Function to run once DOM and jQuery are ready |
| 1241 | + */ |
1191 | 1242 | mw.ready = function( callback ) { |
1192 | 1243 | if( mwReadyFlag === false ) { |
1193 | 1244 | // Add the callbcak to the onLoad function stack |
— | — | @@ -1198,51 +1249,54 @@ |
1199 | 1250 | } |
1200 | 1251 | |
1201 | 1252 | /** |
1202 | | - * Runs all the queued functions |
1203 | | - * called by mwEmbedSetup |
1204 | | - */ |
| 1253 | + * Runs all the queued functions called by mwEmbedSetup |
| 1254 | + */ |
1205 | 1255 | mw.runReadyFunctions = function ( ) { |
1206 | 1256 | mw.log('mw.runReadyFunctions: ' + mwOnLoadFunctions.length ); |
1207 | | - // Run any pre-setup ready functions |
| 1257 | + // Run any pre-setup ready functions |
1208 | 1258 | while( preMwEmbedReady.length ){ |
1209 | 1259 | preMwEmbedReady.shift()(); |
1210 | 1260 | } |
1211 | | - // Run all the queued functions: |
| 1261 | + // Run all the queued functions: |
1212 | 1262 | while( mwOnLoadFunctions.length ) { |
1213 | 1263 | mwOnLoadFunctions.shift()(); |
1214 | | - } |
1215 | | - |
1216 | | - // Once we have run all the queued functions |
1217 | | - mw.loader.runModuleLoadQueue(); |
| 1264 | + } |
1218 | 1265 | |
1219 | 1266 | // Sets mwReadyFlag to true so that future mw.ready run the |
1220 | 1267 | // callback directly |
1221 | 1268 | mwReadyFlag = true; |
1222 | 1269 | |
| 1270 | + // Once we have run all the queued functions |
| 1271 | + mw.loader.runModuleLoadQueue(); |
| 1272 | + |
1223 | 1273 | } |
1224 | 1274 | |
1225 | 1275 | |
1226 | 1276 | /** |
1227 | | - * Wrapper for jQuery getScript, |
1228 | | - * Uses the scriptLoader if enabled |
1229 | | - * |
1230 | | - * |
1231 | | - * @param {String} scriptRequest The requested path or resourceNames for the scriptLoader |
1232 | | - * @param {Function} callback Function to call once script is loaded |
1233 | | - */ |
| 1277 | + * Wrapper for jQuery getScript, Uses the scriptLoader if enabled |
| 1278 | + * |
| 1279 | + * |
| 1280 | + * @param {String} |
| 1281 | + * scriptRequest The requested path or resourceNames for the |
| 1282 | + * scriptLoader |
| 1283 | + * @param {Function} |
| 1284 | + * callback Function to call once script is loaded |
| 1285 | + */ |
1234 | 1286 | mw.getScript = function( scriptRequest, callback ) { |
1235 | | - //mw.log( "mw.getScript::" + scriptRequest ); |
1236 | | - // Setup the local scope callback instace |
| 1287 | + // mw.log( "mw.getScript::" + scriptRequest ); |
| 1288 | + // Setup the local scope callback instace |
1237 | 1289 | var myCallback = function(){ |
1238 | 1290 | if( callback ) { |
1239 | 1291 | callback( scriptRequest ); |
1240 | 1292 | } |
1241 | 1293 | } |
1242 | | - // Set the base url based scriptLoader availability & type of scriptRequest |
1243 | | - // ( presently script loader only handles "classes" not relative urls: |
| 1294 | + // Set the base url based scriptLoader availability & type of |
| 1295 | + // scriptRequest |
| 1296 | + // ( presently script loader only handles "classes" not relative urls: |
1244 | 1297 | var scriptLoaderPath = mw.getResourceLoaderPath(); |
1245 | 1298 | |
1246 | | - // Check if its a resource name, ( ie does not start with "/" and does not include :// |
| 1299 | + // Check if its a resource name, ( ie does not start with "/" and does |
| 1300 | + // not include :// |
1247 | 1301 | var isResourceName = ( scriptRequest.indexOf('://') == -1 && scriptRequest.indexOf('/') !== 0 )? true : false; |
1248 | 1302 | |
1249 | 1303 | var ext = scriptRequest.substr( scriptRequest.lastIndexOf( '.' ), 4 ).toLowerCase(); |
— | — | @@ -1265,8 +1319,8 @@ |
1266 | 1320 | mw.log( 'mw.getScript: ' + url ); |
1267 | 1321 | } |
1268 | 1322 | |
1269 | | - // If jQuery is available and debug is off load the scirpt via jQuery |
1270 | | - //( will use XHR if on same domain ) |
| 1323 | + // If jQuery is available and debug is off load the scirpt via jQuery |
| 1324 | + // ( will use XHR if on same domain ) |
1271 | 1325 | if( mw.isset( 'window.jQuery' ) |
1272 | 1326 | && mw.getConfig( 'debug' ) === false |
1273 | 1327 | && typeof $j != 'undefined' |
— | — | @@ -1277,14 +1331,9 @@ |
1278 | 1332 | } |
1279 | 1333 | |
1280 | 1334 | /** |
1281 | | - * No jQuery |
1282 | | - * OR |
1283 | | - * In debug mode |
1284 | | - * OR |
1285 | | - * Is css file |
1286 | | - * |
1287 | | - * :: inject the script instead of doing an XHR eval |
1288 | | - */ |
| 1335 | + * No jQuery OR In debug mode OR Is css file |
| 1336 | + * :: inject the script instead of doing an XHR eval |
| 1337 | + */ |
1289 | 1338 | |
1290 | 1339 | // load style sheet directly if requested loading css |
1291 | 1340 | if( isCssFile ){ |
— | — | @@ -1292,28 +1341,31 @@ |
1293 | 1342 | return ; |
1294 | 1343 | } |
1295 | 1344 | |
1296 | | - // Load and bind manually: ( copied from jQuery ajax function ) |
| 1345 | + // Load and bind manually: ( copied from jQuery ajax function ) |
1297 | 1346 | var head = document.getElementsByTagName("head")[ 0 ]; |
1298 | 1347 | var script = document.createElement("script"); |
1299 | 1348 | script.setAttribute( 'src', url ); |
1300 | 1349 | |
1301 | | - // Attach handlers ( if using script loader it issues onDone callback as well ) |
| 1350 | + // Attach handlers ( if using script loader it issues onDone callback as |
| 1351 | + // well ) |
1302 | 1352 | script.onload = script.onreadystatechange = function() { |
1303 | 1353 | if (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") { |
1304 | 1354 | myCallback(); |
1305 | 1355 | } |
1306 | 1356 | }; |
1307 | | - //mw.log(" append script: " + script.src ); |
| 1357 | + // mw.log(" append script: " + script.src ); |
1308 | 1358 | // Append the script to the DOM: |
1309 | 1359 | head.appendChild( script ); |
1310 | 1360 | }; |
1311 | 1361 | |
1312 | 1362 | /** |
1313 | | - * Add a style sheet string to the document head |
1314 | | - * |
1315 | | - * @param {String} cssResourceName Name of style sheet that has been defined |
1316 | | - * @param {String} cssString Css Payload to be added to head of document |
1317 | | - */ |
| 1363 | + * Add a style sheet string to the document head |
| 1364 | + * |
| 1365 | + * @param {String} |
| 1366 | + * cssResourceName Name of style sheet that has been defined |
| 1367 | + * @param {String} |
| 1368 | + * cssString Css Payload to be added to head of document |
| 1369 | + */ |
1318 | 1370 | mw.addStyleString = function( cssResourceName, cssString ) { |
1319 | 1371 | if( mw.style[ cssResourceName ] ) { |
1320 | 1372 | mw.log(" Style: ( " + cssResourceName + ' ) already set' ); |
— | — | @@ -1321,11 +1373,12 @@ |
1322 | 1374 | } |
1323 | 1375 | // Set the style to true ( to not request it again ) |
1324 | 1376 | mw.style[ cssResourceName ] = true; |
1325 | | - // Add the spinner directly ( without jQuery in case we have to dynamically load jQuery ) |
| 1377 | + // Add the spinner directly ( without jQuery in case we have to |
| 1378 | + // dynamically load jQuery ) |
1326 | 1379 | mw.log( 'Adding style:' + cssResourceName + " to dom " ); |
1327 | 1380 | var styleNode = document.createElement('style'); |
1328 | 1381 | styleNode.type = "text/css"; |
1329 | | - // Use cssText or createTextNode depending on browser: |
| 1382 | + // Use cssText or createTextNode depending on browser: |
1330 | 1383 | if( ( window.attachEvent && !window.opera ) ) { |
1331 | 1384 | styleNode.styleSheet.cssText = cssString; |
1332 | 1385 | } else { |
— | — | @@ -1337,12 +1390,12 @@ |
1338 | 1391 | }; |
1339 | 1392 | |
1340 | 1393 | /** |
1341 | | - * Get a style sheet and append the style sheet to the DOM |
1342 | | - * |
1343 | | - * @param {Mixed} |
1344 | | - * {String} url Url of the style sheet to be loaded |
1345 | | - * {Function} callback Function called once sheet is ready |
1346 | | - */ |
| 1394 | + * Get a style sheet and append the style sheet to the DOM |
| 1395 | + * |
| 1396 | + * @param {Mixed} |
| 1397 | + * {String} url Url of the style sheet to be loaded {Function} |
| 1398 | + * callback Function called once sheet is ready |
| 1399 | + */ |
1347 | 1400 | mw.getStyleSheet = function( url , callback) { |
1348 | 1401 | // Add URL params ( if not already included ) |
1349 | 1402 | if ( url.indexOf( '?' ) == -1 ) { |
— | — | @@ -1355,9 +1408,9 @@ |
1356 | 1409 | var currentSheet = $j( this) .attr( 'href' ); |
1357 | 1410 | var sheetParts = currentSheet.split('?'); |
1358 | 1411 | var urlParts = url.split('?'); |
1359 | | - //if the base url's match check the parameters: |
| 1412 | + // if the base url's match check the parameters: |
1360 | 1413 | if( sheetParts[0] == urlParts[0] && sheetParts[1]) { |
1361 | | - //Check if url params match ( sort to do string compare ) |
| 1414 | + // Check if url params match ( sort to do string compare ) |
1362 | 1415 | if( sheetParts[1].split( '&' ).sort().join('') == |
1363 | 1416 | urlParts[1].split('&').sort().join('') ) { |
1364 | 1417 | foundSheet = true; |
— | — | @@ -1380,8 +1433,9 @@ |
1381 | 1434 | 'href' : url |
1382 | 1435 | } ) |
1383 | 1436 | ); |
1384 | | - // No easy way to check css "onLoad" attribute |
1385 | | - // In production sheets are loaded via resource loader and fire the onDone function call. |
| 1437 | + // No easy way to check css "onLoad" attribute |
| 1438 | + // In production sheets are loaded via resource loader and fire the |
| 1439 | + // onDone function call. |
1386 | 1440 | if( callback ) { |
1387 | 1441 | callback(); |
1388 | 1442 | } |
— | — | @@ -1392,8 +1446,8 @@ |
1393 | 1447 | var mwEmbedPath = null; |
1394 | 1448 | |
1395 | 1449 | /** |
1396 | | - * Get the path to the mwEmbed folder |
1397 | | - */ |
| 1450 | + * Get the path to the mwEmbed folder |
| 1451 | + */ |
1398 | 1452 | mw.getMwEmbedPath = function() { |
1399 | 1453 | if ( mwEmbedPath ) { |
1400 | 1454 | return mwEmbedPath; |
— | — | @@ -1408,9 +1462,10 @@ |
1409 | 1463 | mwpath = src.substr( 0, src.indexOf( 'mwEmbed.js' ) ); |
1410 | 1464 | } |
1411 | 1465 | |
1412 | | - // Check for scriptLoader include of mwEmbed: |
| 1466 | + // Check for scriptLoader include of mwEmbed: |
1413 | 1467 | if ( src.indexOf( 'mwResourceLoader.php' ) !== -1 ) { |
1414 | | - // Script loader is in the root of MediaWiki, Include the default mwEmbed extension path: |
| 1468 | + // Script loader is in the root of MediaWiki, Include the default |
| 1469 | + // mwEmbed extension path: |
1415 | 1470 | mwpath = src.substr( 0, src.indexOf( 'mwResourceLoader.php' ) ) + mw.getConfig( 'mediaWikiEmbedPath' ); |
1416 | 1471 | } |
1417 | 1472 | |
— | — | @@ -1430,18 +1485,17 @@ |
1431 | 1486 | return ; |
1432 | 1487 | } |
1433 | 1488 | |
1434 | | - // Update the cached var with the absolute path: |
| 1489 | + // Update the cached var with the absolute path: |
1435 | 1490 | mwEmbedPath = mw.absoluteUrl( mwpath ) ; |
1436 | 1491 | return mwEmbedPath; |
1437 | 1492 | } |
1438 | 1493 | |
1439 | 1494 | /** |
1440 | | - * Get Script loader path |
1441 | | - * |
1442 | | - * @returns {String}|{Boolean} |
1443 | | - * Url of the scriptLodaer |
1444 | | - * false if the scriptLoader is not used |
1445 | | - */ |
| 1495 | + * Get Script loader path |
| 1496 | + * |
| 1497 | + * @returns {String}|{Boolean} Url of the scriptLodaer false if the |
| 1498 | + * scriptLoader is not used |
| 1499 | + */ |
1446 | 1500 | mw.getResourceLoaderPath = function( ) { |
1447 | 1501 | var src = mw.getMwEmbedSrc(); |
1448 | 1502 | if ( src.indexOf( 'mwResourceLoader.php' ) !== -1 || |
— | — | @@ -1454,12 +1508,14 @@ |
1455 | 1509 | } |
1456 | 1510 | |
1457 | 1511 | /** |
1458 | | - * Given a float number of seconds, returns npt format response. |
1459 | | - * ( ignore days for now ) |
1460 | | - * |
1461 | | - * @param {Float} sec Seconds |
1462 | | - * @param {Boolean} show_ms If milliseconds should be displayed. |
1463 | | - * @return {Float} String npt format |
| 1512 | + * Given a float number of seconds, returns npt format response. ( ignore |
| 1513 | + * days for now ) |
| 1514 | + * |
| 1515 | + * @param {Float} |
| 1516 | + * sec Seconds |
| 1517 | + * @param {Boolean} |
| 1518 | + * show_ms If milliseconds should be displayed. |
| 1519 | + * @return {Float} String npt format |
1464 | 1520 | */ |
1465 | 1521 | mw.seconds2npt = function( sec, show_ms ) { |
1466 | 1522 | if ( isNaN( sec ) ) { |
— | — | @@ -1469,7 +1525,8 @@ |
1470 | 1526 | |
1471 | 1527 | var tm = mw.seconds2Measurements( sec ) |
1472 | 1528 | |
1473 | | - // Round the number of seconds to the required number of significant digits |
| 1529 | + // Round the number of seconds to the required number of significant |
| 1530 | + // digits |
1474 | 1531 | if ( show_ms ) { |
1475 | 1532 | tm.seconds = Math.round( tm.seconds * 1000 ) / 1000; |
1476 | 1533 | } else { |
— | — | @@ -1484,8 +1541,10 @@ |
1485 | 1542 | } |
1486 | 1543 | |
1487 | 1544 | /** |
1488 | | - * Given seconds return array with 'days', 'hours', 'min', 'seconds' |
1489 | | - * @param {float} sec Seconds to be converted into time measurements |
| 1545 | + * Given seconds return array with 'days', 'hours', 'min', 'seconds' |
| 1546 | + * |
| 1547 | + * @param {float} |
| 1548 | + * sec Seconds to be converted into time measurements |
1490 | 1549 | */ |
1491 | 1550 | mw.seconds2Measurements = function ( sec ){ |
1492 | 1551 | var tm = {}; |
— | — | @@ -1497,17 +1556,18 @@ |
1498 | 1557 | } |
1499 | 1558 | |
1500 | 1559 | /** |
1501 | | - * Take hh:mm:ss,ms or hh:mm:ss.ms input, return the number of seconds |
1502 | | - * |
1503 | | - * @param {String} npt_str NPT time string |
1504 | | - * @return {Float} Number of seconds |
1505 | | - */ |
| 1560 | + * Take hh:mm:ss,ms or hh:mm:ss.ms input, return the number of seconds |
| 1561 | + * |
| 1562 | + * @param {String} |
| 1563 | + * npt_str NPT time string |
| 1564 | + * @return {Float} Number of seconds |
| 1565 | + */ |
1506 | 1566 | mw.npt2seconds = function ( npt_str ) { |
1507 | 1567 | if ( !npt_str ) { |
1508 | 1568 | // mw.log('npt2seconds:not valid ntp:'+ntp); |
1509 | 1569 | return false; |
1510 | 1570 | } |
1511 | | - // Strip {npt:}01:02:20 or 32{s} from time if present |
| 1571 | + // Strip {npt:}01:02:20 or 32{s} from time if present |
1512 | 1572 | npt_str = npt_str.replace( /npt:|s/g, '' ); |
1513 | 1573 | |
1514 | 1574 | var hour = 0; |
— | — | @@ -1535,8 +1595,8 @@ |
1536 | 1596 | var mwEmbedSrc = null; |
1537 | 1597 | |
1538 | 1598 | /** |
1539 | | - * Gets the mwEmbed script src attribute |
1540 | | - */ |
| 1599 | + * Gets the mwEmbed script src attribute |
| 1600 | + */ |
1541 | 1601 | mw.getMwEmbedSrc = function() { |
1542 | 1602 | if ( mwEmbedSrc ) { |
1543 | 1603 | return mwEmbedSrc; |
— | — | @@ -1548,9 +1608,9 @@ |
1549 | 1609 | // Check for mwEmbed.js and/or script loader |
1550 | 1610 | var src = js_elements[i].getAttribute( "src" ); |
1551 | 1611 | if ( src ) { |
1552 | | - if ( // Check for mwEmbed.js ( debug mode ) |
| 1612 | + if ( // Check for mwEmbed.js ( debug mode ) |
1553 | 1613 | ( src.indexOf( 'mwEmbed.js' ) !== -1 && src.indexOf( 'MediaWiki:Gadget') == -1 ) |
1554 | | - || // Check for resource loader |
| 1614 | + || // Check for resource loader |
1555 | 1615 | ( |
1556 | 1616 | ( src.indexOf( 'mwResourceLoader.php' ) !== -1 || src.indexOf( 'ResourceLoader.php' ) !== -1 ) |
1557 | 1617 | && |
— | — | @@ -1572,8 +1632,8 @@ |
1573 | 1633 | var mwUrlParam = null; |
1574 | 1634 | |
1575 | 1635 | /** |
1576 | | - * Get URL Parameters per parameters in the host script include |
1577 | | - */ |
| 1636 | + * Get URL Parameters per parameters in the host script include |
| 1637 | + */ |
1578 | 1638 | mw.getUrlParam = function() { |
1579 | 1639 | if ( mwUrlParam ) { |
1580 | 1640 | return mwUrlParam; |
— | — | @@ -1585,14 +1645,15 @@ |
1586 | 1646 | // If we already have a URI, add it to the param request: |
1587 | 1647 | var urid = mw.parseUri( mwEmbedSrc ).queryKey['urid'] |
1588 | 1648 | |
1589 | | - // If we're in debug mode, get a fresh unique request key and pass on "debug" param |
| 1649 | + // If we're in debug mode, get a fresh unique request key and pass on |
| 1650 | + // "debug" param |
1590 | 1651 | if ( mw.parseUri( mwEmbedSrc ).queryKey['debug'] == 'true' ) { |
1591 | 1652 | mw.setConfig( 'debug', true ); |
1592 | 1653 | var d = new Date(); |
1593 | 1654 | req_param += 'urid=' + d.getTime() + '&debug=true'; |
1594 | 1655 | |
1595 | 1656 | } else if ( urid ) { |
1596 | | - // Just pass on the existing urid: |
| 1657 | + // Just pass on the existing urid: |
1597 | 1658 | req_param += 'urid=' + urid; |
1598 | 1659 | } else { |
1599 | 1660 | // Otherwise, Use the mwEmbed version |
— | — | @@ -1604,19 +1665,20 @@ |
1605 | 1666 | if ( langKey ) |
1606 | 1667 | req_param += '&uselang=' + langKey; |
1607 | 1668 | |
1608 | | - // Update the local cache and return the value |
| 1669 | + // Update the local cache and return the value |
1609 | 1670 | mwUrlParam = req_param; |
1610 | 1671 | return mwUrlParam; |
1611 | 1672 | } |
1612 | 1673 | |
1613 | | - /** |
1614 | | - * Replace url parameters via newParams key value pairs |
1615 | | - * |
1616 | | - * @param {String} url Source url to be updated |
1617 | | - * @param {Object} newParams key, value paris to swap in |
1618 | | - * @return {String} |
1619 | | - * the updated url |
1620 | | - */ |
| 1674 | + /** |
| 1675 | + * Replace url parameters via newParams key value pairs |
| 1676 | + * |
| 1677 | + * @param {String} |
| 1678 | + * url Source url to be updated |
| 1679 | + * @param {Object} |
| 1680 | + * newParams key, value paris to swap in |
| 1681 | + * @return {String} the updated url |
| 1682 | + */ |
1621 | 1683 | mw.replaceUrlParams = function( url, newParams ) { |
1622 | 1684 | var parsedUrl = mw.parseUri( url ); |
1623 | 1685 | |
— | — | @@ -1626,7 +1688,7 @@ |
1627 | 1689 | var new_url = parsedUrl.path + '?'; |
1628 | 1690 | } |
1629 | 1691 | |
1630 | | - // Merge new params: |
| 1692 | + // Merge new params: |
1631 | 1693 | for( var key in newParams ) { |
1632 | 1694 | parsedUrl.queryKey[ key ] = newParams[ key ]; |
1633 | 1695 | } |
— | — | @@ -1642,10 +1704,8 @@ |
1643 | 1705 | } |
1644 | 1706 | |
1645 | 1707 | /** |
1646 | | - * parseUri 1.2.2 |
1647 | | - * (c) Steven Levithan <stevenlevithan.com> |
1648 | | - * MIT License |
1649 | | - */ |
| 1708 | + * parseUri 1.2.2 (c) Steven Levithan <stevenlevithan.com> MIT License |
| 1709 | + */ |
1650 | 1710 | mw.parseUri = function (str) { |
1651 | 1711 | var o = mw.parseUri.options, |
1652 | 1712 | m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), |
— | — | @@ -1663,11 +1723,11 @@ |
1664 | 1724 | }; |
1665 | 1725 | |
1666 | 1726 | /** |
1667 | | - * Parse URI function |
1668 | | - * |
1669 | | - * For documentation on its usage see: |
1670 | | - * http://stevenlevithan.com/demo/parseuri/js/ |
1671 | | - */ |
| 1727 | + * Parse URI function |
| 1728 | + * |
| 1729 | + * For documentation on its usage see: |
| 1730 | + * http://stevenlevithan.com/demo/parseuri/js/ |
| 1731 | + */ |
1672 | 1732 | mw.parseUri.options = { |
1673 | 1733 | strictMode: false, |
1674 | 1734 | key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", |
— | — | @@ -1683,11 +1743,13 @@ |
1684 | 1744 | }; |
1685 | 1745 | |
1686 | 1746 | /** |
1687 | | - * getAbsoluteUrl takes a src and returns the absolute location given the document.URL |
1688 | | - * |
1689 | | - * @param {String} src path or url |
1690 | | - * @return {String} absolute url |
1691 | | - */ |
| 1747 | + * getAbsoluteUrl takes a src and returns the absolute location given the |
| 1748 | + * document.URL |
| 1749 | + * |
| 1750 | + * @param {String} |
| 1751 | + * src path or url |
| 1752 | + * @return {String} absolute url |
| 1753 | + */ |
1692 | 1754 | mw.absoluteUrl = function( src, contextUrl ) { |
1693 | 1755 | var parsedSrc = mw.parseUri( src ); |
1694 | 1756 | // Source is already absolute return: |
— | — | @@ -1695,14 +1757,14 @@ |
1696 | 1758 | return src; |
1697 | 1759 | } |
1698 | 1760 | |
1699 | | - // Get parent Url location the context URL |
| 1761 | + // Get parent Url location the context URL |
1700 | 1762 | if( contextUrl) { |
1701 | 1763 | var parsedUrl = mw.parseUri( contextUrl ); |
1702 | 1764 | } else { |
1703 | 1765 | var parsedUrl = mw.parseUri( document.URL ); |
1704 | 1766 | } |
1705 | 1767 | |
1706 | | - // Check for leading slash: |
| 1768 | + // Check for leading slash: |
1707 | 1769 | if( src.indexOf( '/' ) === 0 ) { |
1708 | 1770 | return parsedUrl.protocol + '://' + parsedUrl.authority + src; |
1709 | 1771 | }else{ |
— | — | @@ -1712,9 +1774,10 @@ |
1713 | 1775 | |
1714 | 1776 | /** |
1715 | 1777 | * Escape quotes in a text string |
1716 | | - * @param {String} text String to be escaped |
1717 | | - * @return {string} |
1718 | | - * escaped text string |
| 1778 | + * |
| 1779 | + * @param {String} |
| 1780 | + * text String to be escaped |
| 1781 | + * @return {string} escaped text string |
1719 | 1782 | */ |
1720 | 1783 | mw.escapeQuotes = function( text ) { |
1721 | 1784 | var re = new RegExp("'","g"); |
— | — | @@ -1726,9 +1789,10 @@ |
1727 | 1790 | |
1728 | 1791 | /** |
1729 | 1792 | * Escape an HTML text string |
1730 | | - * @param {String} text String to be escaped |
1731 | | - * @return {string} |
1732 | | - * escaped text html string |
| 1793 | + * |
| 1794 | + * @param {String} |
| 1795 | + * text String to be escaped |
| 1796 | + * @return {string} escaped text html string |
1733 | 1797 | */ |
1734 | 1798 | mw.escapeQuotesHTML = function( text ) { |
1735 | 1799 | var re = new RegExp('&',"g"); |
— | — | @@ -1747,32 +1811,32 @@ |
1748 | 1812 | var mwSetupFunctions = []; |
1749 | 1813 | |
1750 | 1814 | /** |
1751 | | - * Add a function to be run during setup ( prior to mw.ready) |
1752 | | - * this is useful for building out interfaces that |
1753 | | - * should be ready before mw.ready is called. |
1754 | | - * |
1755 | | - * @param {callback} Function Callback function must |
1756 | | - * accept a ready function callback to be called once |
1757 | | - * setup is done |
1758 | | - */ |
| 1815 | + * Add a function to be run during setup ( prior to mw.ready) this is useful |
| 1816 | + * for building out interfaces that should be ready before mw.ready is |
| 1817 | + * called. |
| 1818 | + * |
| 1819 | + * @param {callback} |
| 1820 | + * Function Callback function must accept a ready function |
| 1821 | + * callback to be called once setup is done |
| 1822 | + */ |
1759 | 1823 | mw.addSetupHook = function( callback ) { |
1760 | 1824 | mwSetupFunctions.push ( callback ) ; |
1761 | 1825 | }; |
1762 | 1826 | |
1763 | 1827 | /** |
1764 | | - * One time "setup" for mwEmbed |
1765 | | - * run onDomReady ( so calls to setConfg apply to setup ) |
1766 | | - */ |
| 1828 | + * One time "setup" for mwEmbed run onDomReady ( so calls to setConfg apply |
| 1829 | + * to setup ) |
| 1830 | + */ |
1767 | 1831 | // Flag to ensure setup is only run once: |
1768 | 1832 | var mwSetupFlag = false; |
1769 | 1833 | mw.setupMwEmbed = function ( ) { |
1770 | | - // Only run the setup once: |
| 1834 | + // Only run the setup once: |
1771 | 1835 | if( mwSetupFlag ) { |
1772 | 1836 | return ; |
1773 | 1837 | } |
1774 | 1838 | mwSetupFlag = true; |
1775 | 1839 | |
1776 | | - // Apply any pre-setup config: |
| 1840 | + // Apply any pre-setup config: |
1777 | 1841 | mw.setConfig( preMwEmbedConfig ); |
1778 | 1842 | |
1779 | 1843 | |
— | — | @@ -1780,16 +1844,16 @@ |
1781 | 1845 | |
1782 | 1846 | // Check core mwEmbed loader.js file ( to get configuration and paths ) |
1783 | 1847 | mw.checkCoreLoaderFile( function(){ |
1784 | | - // Make sure we have jQuery |
| 1848 | + // Make sure we have jQuery |
1785 | 1849 | mw.load( 'window.jQuery', function() { |
1786 | 1850 | |
1787 | | - // Add jQuery to $j var. |
| 1851 | + // Add jQuery to $j var. |
1788 | 1852 | if ( ! window[ '$j' ] ) { |
1789 | 1853 | window[ '$j' ] = jQuery.noConflict(); |
1790 | 1854 | } |
1791 | 1855 | |
1792 | | - // Get module loader.js, and language files |
1793 | | - // ( will hit callback directly if set via resource loader ) |
| 1856 | + // Get module loader.js, and language files |
| 1857 | + // ( will hit callback directly if set via resource loader ) |
1794 | 1858 | mw.checkModuleLoaderFiles( function() { |
1795 | 1859 | |
1796 | 1860 | // Set the User language |
— | — | @@ -1803,7 +1867,7 @@ |
1804 | 1868 | } |
1805 | 1869 | } |
1806 | 1870 | |
1807 | | - // Update the image path |
| 1871 | + // Update the image path |
1808 | 1872 | mw.setConfig( 'imagesPath', mw.getMwEmbedPath() + 'skins/common/images/' ); |
1809 | 1873 | |
1810 | 1874 | // Set up AJAX to not send dynamic URLs for loading scripts |
— | — | @@ -1811,27 +1875,30 @@ |
1812 | 1876 | cache: true |
1813 | 1877 | } ); |
1814 | 1878 | |
1815 | | - // Update the magic keywords |
| 1879 | + // Update the magic keywords |
1816 | 1880 | mw.Language.magicSetup(); |
1817 | 1881 | |
1818 | 1882 | // Set up mvEmbed utility jQuery bindings |
1819 | 1883 | mw.dojQueryBindings(); |
1820 | 1884 | |
1821 | 1885 | |
1822 | | - // Special Hack for conditional jquery ui inclusion ( once Usability extension |
1823 | | - // registers the jquery.ui skin in mw.style this won't be needed ) |
| 1886 | + // Special Hack for conditional jquery ui inclusion ( once |
| 1887 | + // Usability extension |
| 1888 | + // registers the jquery.ui skin in mw.style this won't be |
| 1889 | + // needed ) |
1824 | 1890 | if( mw.hasJQueryUiCss() ){ |
1825 | 1891 | mw.style[ 'ui_' + mw.getConfig( 'jQueryUISkin' ) ] = true; |
1826 | 1892 | } |
1827 | 1893 | |
1828 | 1894 | |
1829 | | - // Make sure style sheets are loaded: |
| 1895 | + // Make sure style sheets are loaded: |
1830 | 1896 | mw.load( ['mw.style.mwCommon'] , function(){ |
1831 | | - // Run all the setup function hooks |
1832 | | - // NOTE: setup functions are added via addSetupHook calls |
| 1897 | + // Run all the setup function hooks |
| 1898 | + // NOTE: setup functions are added via addSetupHook |
| 1899 | + // calls |
1833 | 1900 | // and must include a callback. |
1834 | 1901 | // |
1835 | | - // Once complete we can run .ready() queued functions |
| 1902 | + // Once complete we can run .ready() queued functions |
1836 | 1903 | function runSetupFunctions() { |
1837 | 1904 | if( mwSetupFunctions.length ) { |
1838 | 1905 | mwSetupFunctions.shift()( function() { |
— | — | @@ -1850,12 +1917,12 @@ |
1851 | 1918 | }; |
1852 | 1919 | |
1853 | 1920 | /** |
1854 | | - * Checks for jquery ui css by name jquery-ui-1.7.2.css |
1855 | | - * NOTE: this is a hack for usability jquery-ui |
1856 | | - * in the future usability should register a resource in mw.skin |
1857 | | - * |
1858 | | - * @return true if found, return false if not found |
1859 | | - */ |
| 1921 | + * Checks for jquery ui css by name jquery-ui-1.7.2.css NOTE: this is a hack |
| 1922 | + * for usability jquery-ui in the future usability should register a |
| 1923 | + * resource in mw.skin |
| 1924 | + * |
| 1925 | + * @return true if found, return false if not found |
| 1926 | + */ |
1860 | 1927 | mw.hasJQueryUiCss = function(){ |
1861 | 1928 | var hasUiCss = false; |
1862 | 1929 | // Load the jQuery ui skin if usability skin not set |
— | — | @@ -1868,38 +1935,41 @@ |
1869 | 1936 | return hasUiCss; |
1870 | 1937 | } |
1871 | 1938 | |
1872 | | - /** |
| 1939 | + /** |
1873 | 1940 | * Loads the core mwEmbed "loader.js" file config |
1874 | | - * |
1875 | | - * NOTE: if using the ScriptLoader all the loaders and localization converters |
1876 | | - * are included automatically |
1877 | | - * |
1878 | | - * @param {Function} callback Function called once core loader file is loaded |
| 1941 | + * |
| 1942 | + * NOTE: if using the ScriptLoader all the loaders and localization |
| 1943 | + * converters are included automatically |
| 1944 | + * |
| 1945 | + * @param {Function} |
| 1946 | + * callback Function called once core loader file is loaded |
1879 | 1947 | */ |
1880 | 1948 | mw.checkCoreLoaderFile = function( callback ) { |
1881 | | - // Check if we are using scriptloader ( handles loader include automatically ) |
| 1949 | + // Check if we are using scriptloader ( handles loader include |
| 1950 | + // automatically ) |
1882 | 1951 | if( mw.getResourceLoaderPath() ) { |
1883 | 1952 | callback(); |
1884 | 1953 | return ; |
1885 | 1954 | } |
1886 | 1955 | |
1887 | | - // Check if we are using a static package ( mwEmbed path includes -static ) |
| 1956 | + // Check if we are using a static package ( mwEmbed path includes |
| 1957 | + // -static ) |
1888 | 1958 | if( mw.isStaticPackge() ){ |
1889 | 1959 | callback(); |
1890 | 1960 | return ; |
1891 | 1961 | } |
1892 | 1962 | |
1893 | 1963 | // Add the Core loader to the request |
1894 | | - // The follow code is ONLY RUN in debug / raw file mode |
| 1964 | + // The follow code is ONLY RUN in debug / raw file mode |
1895 | 1965 | mw.load( 'loader.js', callback ); |
1896 | 1966 | } |
1897 | 1967 | |
1898 | 1968 | /** |
1899 | | - * Checks if the javascript is a static package ( not using resource loader ) |
1900 | | - * @return {boolean} |
1901 | | - * true the included script is static |
1902 | | - * false the included script |
1903 | | - */ |
| 1969 | + * Checks if the javascript is a static package ( not using resource loader ) |
| 1970 | + * |
| 1971 | + * @return {boolean} true the included script is static false the included |
| 1972 | + * script |
| 1973 | + */ |
1904 | 1974 | mw.isStaticPackge = function(){ |
1905 | 1975 | var src = mw.getMwEmbedSrc(); |
1906 | 1976 | if( src.indexOf('-static') !== -1 ){ |
— | — | @@ -1909,26 +1979,28 @@ |
1910 | 1980 | } |
1911 | 1981 | |
1912 | 1982 | /** |
1913 | | - * Check for resource loader module loaders, and localization files |
1914 | | - * |
1915 | | - * NOTE: if using the ScriptLoader all the loaders and localization converters |
1916 | | - * are included automatically. |
1917 | | - */ |
| 1983 | + * Check for resource loader module loaders, and localization files |
| 1984 | + * |
| 1985 | + * NOTE: if using the ScriptLoader all the loaders and localization |
| 1986 | + * converters are included automatically. |
| 1987 | + */ |
1918 | 1988 | mw.checkModuleLoaderFiles = function( callback ) { |
1919 | 1989 | mw.log( 'doLoaderCheck::' ); |
1920 | 1990 | |
1921 | | - // Check if we are using scriptloader ( handles loader include automatically ) |
1922 | | - // Or if mwEmbed is a static package ( all resources are already loaded ) |
| 1991 | + // Check if we are using scriptloader ( handles loader include |
| 1992 | + // automatically ) |
| 1993 | + // Or if mwEmbed is a static package ( all resources are already loaded |
| 1994 | + // ) |
1923 | 1995 | if( mw.getResourceLoaderPath() || mw.isStaticPackge() ) { |
1924 | 1996 | callback(); |
1925 | 1997 | return ; |
1926 | 1998 | } |
1927 | 1999 | |
1928 | 2000 | // Load the configured modules / components |
1929 | | - // The follow code is ONLY RUN in debug / raw file mode |
| 2001 | + // The follow code is ONLY RUN in debug / raw file mode |
1930 | 2002 | var loaderRequest = []; |
1931 | 2003 | |
1932 | | - //Load enabled components |
| 2004 | + // Load enabled components |
1933 | 2005 | var enabledComponents = mw.getConfig( 'coreComponents' ); |
1934 | 2006 | function loadEnabledComponents( enabledComponents ){ |
1935 | 2007 | if( ! enabledComponents.length ){ |
— | — | @@ -1947,7 +2019,7 @@ |
1948 | 2020 | loadEnabledComponents( enabledComponents ); |
1949 | 2021 | |
1950 | 2022 | |
1951 | | - // Set the loader context and get each loader individually |
| 2023 | + // Set the loader context and get each loader individually |
1952 | 2024 | function loadEnabledModules( enabledModules ){ |
1953 | 2025 | if( ! enabledModules.length ){ |
1954 | 2026 | // If no more modules left load the LanguageFile |
— | — | @@ -1968,7 +2040,7 @@ |
1969 | 2041 | if( mw.getConfig( 'userLanguage' ) ) { |
1970 | 2042 | var langCode = mw.getConfig( 'userLanguage' ); |
1971 | 2043 | |
1972 | | - // Load the language resource if not default 'en' |
| 2044 | + // Load the language resource if not default 'en' |
1973 | 2045 | var transformKey = mw.getLangTransformKey( langCode ); |
1974 | 2046 | if( transformKey != 'en' ){ |
1975 | 2047 | // Upper case the first letter: |
— | — | @@ -1995,21 +2067,20 @@ |
1996 | 2068 | } |
1997 | 2069 | |
1998 | 2070 | /** |
1999 | | - * Checks if a css style rule exists |
2000 | | - * |
2001 | | - * On a page with lots of rules it can take some time |
2002 | | - * so avoid calling this function where possible and |
2003 | | - * cache its result |
2004 | | - * |
2005 | | - * NOTE: this only works for style sheets on the same domain :( |
2006 | | - * |
2007 | | - * @param {String} styleRule Style rule name to check |
2008 | | - * @return {Boolean} |
2009 | | - * true if the rule exists |
2010 | | - * false if the rule does not exist |
2011 | | - */ |
| 2071 | + * Checks if a css style rule exists |
| 2072 | + * |
| 2073 | + * On a page with lots of rules it can take some time so avoid calling this |
| 2074 | + * function where possible and cache its result |
| 2075 | + * |
| 2076 | + * NOTE: this only works for style sheets on the same domain :( |
| 2077 | + * |
| 2078 | + * @param {String} |
| 2079 | + * styleRule Style rule name to check |
| 2080 | + * @return {Boolean} true if the rule exists false if the rule does not |
| 2081 | + * exist |
| 2082 | + */ |
2012 | 2083 | mw.styleRuleExists = function ( styleRule ) { |
2013 | | - // Set up the skin paths configuration |
| 2084 | + // Set up the skin paths configuration |
2014 | 2085 | for( var i=0 ; i < document.styleSheets.length ; i++ ) { |
2015 | 2086 | var rules = null; |
2016 | 2087 | try{ |
— | — | @@ -2037,9 +2108,9 @@ |
2038 | 2109 | var mwModuleLoaderCheckFlag = false; |
2039 | 2110 | |
2040 | 2111 | /** |
2041 | | - * This will get called when the DOM is ready |
2042 | | - * Will check configuration and issue a mw.setupMwEmbed call if needed |
2043 | | - */ |
| 2112 | + * This will get called when the DOM is ready Will check configuration and |
| 2113 | + * issue a mw.setupMwEmbed call if needed |
| 2114 | + */ |
2044 | 2115 | mw.domReady = function ( ) { |
2045 | 2116 | if( mwDomReadyFlag ) { |
2046 | 2117 | return ; |
— | — | @@ -2048,28 +2119,30 @@ |
2049 | 2120 | // Set the onDomReady Flag |
2050 | 2121 | mwDomReadyFlag = true; |
2051 | 2122 | |
2052 | | - // Give us a chance to get to the bottom of the script. |
2053 | | - // When loading mwEmbed asynchronously the dom ready gets called |
2054 | | - // directly and in some browsers beets the $j = jQuery.noConflict(); call |
2055 | | - // and causes symbol undefined errors. |
| 2123 | + // Give us a chance to get to the bottom of the script. |
| 2124 | + // When loading mwEmbed asynchronously the dom ready gets called |
| 2125 | + // directly and in some browsers beets the $j = jQuery.noConflict(); |
| 2126 | + // call |
| 2127 | + // and causes symbol undefined errors. |
2056 | 2128 | setTimeout(function(){ |
2057 | 2129 | mw.setupMwEmbed(); |
2058 | 2130 | },1); |
2059 | 2131 | } |
2060 | 2132 | |
2061 | 2133 | /** |
2062 | | - * A version comparison utility function |
2063 | | - * Handles version of types {Major}.{MinorN}.{Patch} |
2064 | | - * |
2065 | | - * Note this just handles version numbers not patch letters. |
2066 | | - * |
2067 | | - * @param {String} minVersion Minnium version needed |
2068 | | - * @param {String} clientVersion Client version to be checked |
2069 | | - |
2070 | | - * @return |
2071 | | - * true if the version is at least of minVersion |
2072 | | - * false if the version is less than minVersion |
2073 | | - */ |
| 2134 | + * A version comparison utility function Handles version of types |
| 2135 | + * {Major}.{MinorN}.{Patch} |
| 2136 | + * |
| 2137 | + * Note this just handles version numbers not patch letters. |
| 2138 | + * |
| 2139 | + * @param {String} |
| 2140 | + * minVersion Minnium version needed |
| 2141 | + * @param {String} |
| 2142 | + * clientVersion Client version to be checked |
| 2143 | + * |
| 2144 | + * @return true if the version is at least of minVersion false if the |
| 2145 | + * version is less than minVersion |
| 2146 | + */ |
2074 | 2147 | mw.versionIsAtLeast = function( minVersion, clientVersion ) { |
2075 | 2148 | var minVersionParts = minVersion.split('.') |
2076 | 2149 | var clientVersionParts = clientVersion.split('.'); |
— | — | @@ -2088,20 +2161,23 @@ |
2089 | 2162 | /** |
2090 | 2163 | * Runs all the triggers on a given object with a single "callback" |
2091 | 2164 | * |
2092 | | - * Normal tirgger calls will run the callback directly multiple times |
2093 | | - * for every binded function. |
| 2165 | + * Normal tirgger calls will run the callback directly multiple times for |
| 2166 | + * every binded function. |
2094 | 2167 | * |
2095 | | - * With runTriggersCallback() callback is not called until all the |
2096 | | - * binded events have been run. |
| 2168 | + * With runTriggersCallback() callback is not called until all the binded |
| 2169 | + * events have been run. |
2097 | 2170 | * |
2098 | | - * @param {object} targetObject Target object to run triggers on |
2099 | | - * @param {string} triggerName Name of trigger to be run |
2100 | | - * @param {function} callback Function called once all triggers have been run |
| 2171 | + * @param {object} |
| 2172 | + * targetObject Target object to run triggers on |
| 2173 | + * @param {string} |
| 2174 | + * triggerName Name of trigger to be run |
| 2175 | + * @param {function} |
| 2176 | + * callback Function called once all triggers have been run |
2101 | 2177 | * |
2102 | 2178 | */ |
2103 | 2179 | mw.runTriggersCallback = function( targetObject, triggerName, callback ){ |
2104 | 2180 | mw.log( ' runTriggersCallback:: ' + triggerName ); |
2105 | | - // If events are not present directly run callback |
| 2181 | + // If events are not present directly run callback |
2106 | 2182 | if( ! $j( targetObject ).data( 'events' ) || |
2107 | 2183 | ! $j( targetObject ).data( 'events' )[ triggerName ] ) { |
2108 | 2184 | mw.log( ' trigger name not found: ' + triggerName ); |
— | — | @@ -2129,16 +2205,15 @@ |
2130 | 2206 | } ); |
2131 | 2207 | } |
2132 | 2208 | /** |
2133 | | - * Utility jQuery bindings |
2134 | | - * Setup after jQuery is available ). |
| 2209 | + * Utility jQuery bindings Setup after jQuery is available ). |
2135 | 2210 | */ |
2136 | 2211 | mw.dojQueryBindings = function() { |
2137 | 2212 | mw.log( 'mw.dojQueryBindings' ); |
2138 | 2213 | ( function( $ ) { |
2139 | 2214 | |
2140 | 2215 | /** |
2141 | | - * Set a given selector html to the loading spinner: |
2142 | | - */ |
| 2216 | + * Set a given selector html to the loading spinner: |
| 2217 | + */ |
2143 | 2218 | $.fn.loadingSpinner = function( ) { |
2144 | 2219 | if ( this ) { |
2145 | 2220 | $j( this ).html( |
— | — | @@ -2146,38 +2221,28 @@ |
2147 | 2222 | .addClass( "loadingSpinner" ) |
2148 | 2223 | ); |
2149 | 2224 | } |
2150 | | - /* |
2151 | | - //var csstransforms = false; |
2152 | | - if ( Modernizr.csstransforms ) { |
2153 | | - var barNumber = 7; |
2154 | | - var barContent = ''; |
2155 | | - var barSpacingDegrees = 360 / barNumber; |
2156 | | - var barOpacityDelta = 1 / (barNumber); |
2157 | | - for (i = 1; i < barNumber+1; i++) { |
2158 | | - barContent += '<div class="bar' + i + '" style="-moz-transform:rotate(' + (i-1) * barSpacingDegrees + 'deg) translate(0, -40px);-webkit-transform:rotate(' + (i-1) * barSpacingDegrees + 'deg) translate(0, -40px);opacity:' + (i) * barOpacityDelta + '; background:#000"/>'; |
2159 | | - } |
2160 | | - $j( this ).html( |
2161 | | - $j( '<div />' ) |
2162 | | - .addClass( "cssLoadingSpinner" ) |
2163 | | - .html( barContent ) |
2164 | | - ); |
2165 | | - var rotations = 0; |
2166 | | - setInterval( function ( ) { |
2167 | | - $j('.cssLoadingSpinner') |
2168 | | - .css('-moz-transform','rotate('+rotations+'deg)') |
2169 | | - .css('-webkit-transform','rotate('+rotations+'deg)'); |
2170 | | - if( rotations == 360 ) { |
2171 | | - rotations = 0; |
2172 | | - } |
2173 | | - rotations += 5; |
2174 | | - }, 25); |
2175 | | - } |
2176 | | - */ |
| 2225 | + /* |
| 2226 | + * //var csstransforms = false; if ( Modernizr.csstransforms ) { |
| 2227 | + * var barNumber = 7; var barContent = ''; var barSpacingDegrees = |
| 2228 | + * 360 / barNumber; var barOpacityDelta = 1 / (barNumber); for |
| 2229 | + * (i = 1; i < barNumber+1; i++) { barContent += '<div |
| 2230 | + * class="bar' + i + '" style="-moz-transform:rotate(' + (i-1) * |
| 2231 | + * barSpacingDegrees + 'deg) translate(0, |
| 2232 | + * -40px);-webkit-transform:rotate(' + (i-1) * barSpacingDegrees + |
| 2233 | + * 'deg) translate(0, -40px);opacity:' + (i) * barOpacityDelta + '; |
| 2234 | + * background:#000"/>'; } $j( this ).html( $j( '<div />' ) |
| 2235 | + * .addClass( "cssLoadingSpinner" ) .html( barContent ) ); var |
| 2236 | + * rotations = 0; setInterval( function ( ) { |
| 2237 | + * $j('.cssLoadingSpinner') |
| 2238 | + * .css('-moz-transform','rotate('+rotations+'deg)') |
| 2239 | + * .css('-webkit-transform','rotate('+rotations+'deg)'); if( |
| 2240 | + * rotations == 360 ) { rotations = 0; } rotations += 5; }, 25); } |
| 2241 | + */ |
2177 | 2242 | return this; |
2178 | 2243 | } |
2179 | 2244 | /** |
2180 | | - * Add an absolute overlay spinner useful for cases where the element |
2181 | | - * does not display child elements, ( images, video ) |
| 2245 | + * Add an absolute overlay spinner useful for cases where the |
| 2246 | + * element does not display child elements, ( images, video ) |
2182 | 2247 | */ |
2183 | 2248 | $.fn.getAbsoluteOverlaySpinner = function(){ |
2184 | 2249 | var pos = $j( this ).offset(); |
— | — | @@ -2203,8 +2268,8 @@ |
2204 | 2269 | } |
2205 | 2270 | |
2206 | 2271 | /** |
2207 | | - * dragDrop file loader |
2208 | | - */ |
| 2272 | + * dragDrop file loader |
| 2273 | + */ |
2209 | 2274 | $.fn.dragFileUpload = function ( conf ) { |
2210 | 2275 | if ( this.selector ) { |
2211 | 2276 | var _this = this; |
— | — | @@ -2216,8 +2281,8 @@ |
2217 | 2282 | } |
2218 | 2283 | |
2219 | 2284 | /** |
2220 | | - * Shortcut to a themed button |
2221 | | - * Should be depreciated for $.button bellow |
| 2285 | + * Shortcut to a themed button Should be depreciated for $.button |
| 2286 | + * bellow |
2222 | 2287 | */ |
2223 | 2288 | $.btnHtml = function( msg, styleClass, iconId, opt ) { |
2224 | 2289 | if ( !opt ) |
— | — | @@ -2231,7 +2296,8 @@ |
2232 | 2297 | '<span class="btnText">' + msg + '</span></a>'; |
2233 | 2298 | }; |
2234 | 2299 | |
2235 | | - // Shortcut to jQuery button ( should replace all btnHtml with button ) |
| 2300 | + // Shortcut to jQuery button ( should replace all btnHtml with |
| 2301 | + // button ) |
2236 | 2302 | var mw_default_button_options = { |
2237 | 2303 | // The class name for the button link |
2238 | 2304 | 'class' : '', |
— | — | @@ -2249,11 +2315,11 @@ |
2250 | 2316 | $.button = function( options ) { |
2251 | 2317 | var options = $j.extend( mw_default_button_options, options); |
2252 | 2318 | |
2253 | | - // Button: |
| 2319 | + // Button: |
2254 | 2320 | var $btn = $j('<a />') |
2255 | 2321 | .attr('href', '#') |
2256 | 2322 | .addClass( 'ui-state-default ui-corner-all ui-icon_link' ); |
2257 | | - // Add css if set: |
| 2323 | + // Add css if set: |
2258 | 2324 | if( options.css ) { |
2259 | 2325 | $btn.css( options.css ) |
2260 | 2326 | } |
— | — | @@ -2284,9 +2350,11 @@ |
2285 | 2351 | }; |
2286 | 2352 | |
2287 | 2353 | /** |
2288 | | - * Resize a dialog to fit the window |
2289 | | - * @param {Object} options horizontal and vertical space ( default 50 ) |
2290 | | - */ |
| 2354 | + * Resize a dialog to fit the window |
| 2355 | + * |
| 2356 | + * @param {Object} |
| 2357 | + * options horizontal and vertical space ( default 50 ) |
| 2358 | + */ |
2291 | 2359 | $.fn.dialogFitWindow = function( options ) { |
2292 | 2360 | var opt_default = { 'hspace':50, 'vspace':50 }; |
2293 | 2361 | if ( !options ) |
— | — | @@ -2295,7 +2363,8 @@ |
2296 | 2364 | $j( this.selector ).dialog( 'option', 'width', $j( window ).width() - options.hspace ); |
2297 | 2365 | $j( this.selector ).dialog( 'option', 'height', $j( window ).height() - options.vspace ); |
2298 | 2366 | $j( this.selector ).dialog( 'option', 'position', 'center' ); |
2299 | | - // update the child position: (some of this should be pushed up-stream via dialog config options |
| 2367 | + // update the child position: (some of this should be pushed |
| 2368 | + // up-stream via dialog config options |
2300 | 2369 | $j( this.selector + '~ .ui-dialog-buttonpane' ).css( { |
2301 | 2370 | 'position':'absolute', |
2302 | 2371 | 'left':'0px', |
— | — | @@ -2311,13 +2380,11 @@ |
2312 | 2381 | |
2313 | 2382 | |
2314 | 2383 | /** |
2315 | | -* Set DOM-ready call |
2316 | | -* We copy jQuery( document ).ready here since sometimes |
2317 | | -* mwEmbed.js is included without jQuery |
2318 | | -* and we need our own "ready" system so that |
2319 | | -* mwEmbed interfaces can support async built out |
2320 | | -* and the inclution of jQuery. |
2321 | | -*/ |
| 2384 | + * Set DOM-ready call We copy jQuery( document ).ready here since sometimes |
| 2385 | + * mwEmbed.js is included without jQuery and we need our own "ready" system so |
| 2386 | + * that mwEmbed interfaces can support async built out and the inclution of |
| 2387 | + * jQuery. |
| 2388 | + */ |
2322 | 2389 | var mwDomIsReady = false; |
2323 | 2390 | function runMwDomReady(){ |
2324 | 2391 | mwDomIsReady = true; |
— | — | @@ -2325,7 +2392,7 @@ |
2326 | 2393 | mw.domReady() |
2327 | 2394 | } |
2328 | 2395 | } |
2329 | | -// Check if already ready: |
| 2396 | +// Check if already ready: |
2330 | 2397 | if ( document.readyState === "complete" ) { |
2331 | 2398 | runMwDomReady(); |
2332 | 2399 | } |
— | — | @@ -2339,7 +2406,8 @@ |
2340 | 2407 | |
2341 | 2408 | } else if ( document.attachEvent ) { |
2342 | 2409 | DOMContentLoaded = function() { |
2343 | | - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). |
| 2410 | + // Make sure body exists, at least, in case IE gets a little overzealous |
| 2411 | + // (ticket #5443). |
2344 | 2412 | if ( document.readyState === "complete" ) { |
2345 | 2413 | document.detachEvent( "onreadystatechange", DOMContentLoaded ); |
2346 | 2414 | runMwDomReady(); |
— | — | @@ -2395,8 +2463,9 @@ |
2396 | 2464 | } |
2397 | 2465 | |
2398 | 2466 | |
2399 | | -// If using the resource loader and jQuery has not been set give a warning to the user: |
2400 | | -// (this is needed because packaged loader.js files could refrence jQuery ) |
| 2467 | +// If using the resource loader and jQuery has not been set give a warning to |
| 2468 | +// the user: |
| 2469 | +// (this is needed because packaged loader.js files could refrence jQuery ) |
2401 | 2470 | if( mw.getResourceLoaderPath() && !window.jQuery ) { |
2402 | 2471 | mw.log( 'Error: jQuery is required for mwEmbed, please update your resource loader request' ); |
2403 | 2472 | } |
— | — | @@ -2406,14 +2475,13 @@ |
2407 | 2476 | } |
2408 | 2477 | |
2409 | 2478 | /** |
2410 | | - * Hack to keep jQuery in $ when its |
2411 | | - * already there, but also use noConflict to get $j = jQuery |
| 2479 | + * Hack to keep jQuery in $ when its already there, but also use noConflict to |
| 2480 | + * get $j = jQuery |
2412 | 2481 | * |
2413 | | - * This way sites that use $ for jQuery continue to work after |
2414 | | - * including mwEmbed javascript. |
| 2482 | + * This way sites that use $ for jQuery continue to work after including mwEmbed |
| 2483 | + * javascript. |
2415 | 2484 | * |
2416 | | - * Also if jQuery is included prior to mwEmbed we ensure |
2417 | | - * $j is set |
| 2485 | + * Also if jQuery is included prior to mwEmbed we ensure $j is set |
2418 | 2486 | */ |
2419 | 2487 | |
2420 | 2488 | if( window.jQuery ){ |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilBody.js |
— | — | @@ -49,12 +49,8 @@ |
50 | 50 | var _this = this; |
51 | 51 | if( !$node.attr('id') |
52 | 52 | && !$node.attr( 'xml:id' ) |
53 | | - && ( |
54 | | - _this.getNodeSmilType( $node ) == 'ref' |
55 | | - || _this.getNodeSmilType( $node ) == 'smilText' |
56 | | - ) |
57 | 53 | ){ |
58 | | - $node.attr('id', _this.smil.embedPlayer.id + '_ref_' + _this.idIndex ); |
| 54 | + $node.attr('id', _this.getNodeSmilType( $node ) + '_' + _this.idIndex ); |
59 | 55 | mw.log('SmilBody:: gave: ' + $node.get(0).nodeName + ' id: ' + $node.attr('id') ); |
60 | 56 | _this.idIndex++; |
61 | 57 | } |
— | — | @@ -248,16 +244,28 @@ |
249 | 245 | }, |
250 | 246 | |
251 | 247 | /** |
252 | | - * getElementsForTimeRecurse |
253 | | - * @param {Object} $node Node to recursively search for elements in the given time range |
254 | | - */ |
| 248 | + * get the sequence elements from a given par node if no node is provied assume root |
| 249 | + * @param {element=} $parNode Optional parNode to list all sequence timelines |
| 250 | + */ |
| 251 | + getSeqElements: function( $node ){ |
| 252 | + if( ! $node ){ |
| 253 | + $node = this.$dom; |
| 254 | + } |
| 255 | + return $node.find('seq'); |
| 256 | + }, |
255 | 257 | |
| 258 | + |
256 | 259 | /** |
257 | 260 | * Recurse over all body elements, issues a callback on all ref and smilText nodes |
258 | 261 | * adds startOffset info for easy timeline checks. |
| 262 | + * @param {Object} $node Node Starting point |
259 | 263 | */ |
260 | 264 | getRefElementsRecurse: function( $node, startOffset, callback ){ |
261 | 265 | var _this = this; |
| 266 | + |
| 267 | + // Make sure $node is wrapped in jQuery object |
| 268 | + $node = $j( $node ); |
| 269 | + |
262 | 270 | // Setup local pointers: |
263 | 271 | var nodeType = this.getNodeSmilType( $node ); |
264 | 272 | |
— | — | @@ -301,8 +309,8 @@ |
302 | 310 | * Returns the smil body duration |
303 | 311 | * ( wraps getDurationRecurse to get top level node duration ) |
304 | 312 | */ |
305 | | - getDuration: function(){ |
306 | | - this.duration = this.getNodeDuration( this.$dom ); |
| 313 | + getDuration: function( forceRefresh ){ |
| 314 | + this.duration = this.getNodeDuration( this.$dom , forceRefresh); |
307 | 315 | mw.log("smilBody:: getDuration: " + this.duration ); |
308 | 316 | return this.duration; |
309 | 317 | }, |
— | — | @@ -318,6 +326,11 @@ |
319 | 327 | ) { |
320 | 328 | return $node.data('computedDuration'); |
321 | 329 | } |
| 330 | + if( forceRefresh ){ |
| 331 | + //clear out implictDuration |
| 332 | + $node.data( 'implictDuration', false ); |
| 333 | + $node.data( 'computedDuration', false ); |
| 334 | + } |
322 | 335 | |
323 | 336 | var _this = this; |
324 | 337 | var duration = 0; |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/loader.js |
— | — | @@ -1,4 +1,4 @@ |
2 | | -/* |
| 2 | +/** |
3 | 3 | * Loader for smilPlayer |
4 | 4 | */ |
5 | 5 | // Wrap in mw to not pollute global namespace |
— | — | @@ -47,7 +47,7 @@ |
48 | 48 | /** |
49 | 49 | * Check if a video tag element has a smil source |
50 | 50 | */ |
51 | | - mw.CheckElementForSMIL = function( element ){ |
| 51 | + mw.CheckElementForSMIL = function( element ){ |
52 | 52 | if( $j( element ) .attr('type' ) == 'application/smil' || |
53 | 53 | ( $j( element ).attr('src' ) && |
54 | 54 | $j( element ).attr('src' ).substr( -4) == 'smil' ) ) |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.Smil.js |
— | — | @@ -1,378 +1,394 @@ |
2 | 2 | /** |
3 | | - * The Smil object |
4 | | - * |
| 3 | + * The Smil object |
| 4 | + * |
5 | 5 | * @copyright kaltura |
6 | | - * @author: Michael Dale mdale@wikimedia.org |
| 6 | + * @author: Michael Dale mdale@wikimedia.org |
7 | 7 | * @license GPL2 |
8 | 8 | * |
9 | 9 | * Sequence player wraps smil into the video tag |
10 | 10 | * |
11 | | - * Provides an html5 video tag like api to a smil document. |
12 | | - * |
13 | | - * Supports frame by frame rendering of "smil" |
14 | | - * Supports "drop frame" realtime playback of "smil" |
| 11 | + * Provides an html5 video tag like api to a smil document. |
15 | 12 | * |
16 | | - * Extends the "embedPlayer" and represents the playlist as a single video stream |
| 13 | + * Supports frame by frame rendering of "smil" Supports "drop frame" realtime |
| 14 | + * playback of "smil" |
17 | 15 | * |
| 16 | + * Extends the "embedPlayer" and represents the playlist as a single video |
| 17 | + * stream |
| 18 | + * |
18 | 19 | */ |
19 | | - |
| 20 | + |
20 | 21 | /* Add the hooks needed for playback */ |
21 | | -mw.Smil = function( options ){ |
22 | | - return this.init( options ); |
| 22 | +mw.Smil = function(options) { |
| 23 | + return this.init(options); |
23 | 24 | } |
24 | 25 | mw.Smil.prototype = { |
25 | | - |
26 | | - // Store the mw.SmilLayout object |
| 26 | + |
| 27 | + // Store the mw.SmilLayout object |
27 | 28 | layout : null, |
28 | | - |
| 29 | + |
29 | 30 | // Stores the mw.SmilBody object |
30 | 31 | body : null, |
31 | | - |
| 32 | + |
32 | 33 | // Stores the mw.SmilBuffer object |
33 | | - buffer: null, |
34 | | - |
35 | | - // Stores the mw.SmilAnimate object |
36 | | - animate: null, |
37 | | - |
| 34 | + buffer : null, |
| 35 | + |
| 36 | + // Stores the mw.SmilAnimate object |
| 37 | + animate : null, |
| 38 | + |
38 | 39 | // Stores the mw.SmilTransisions object |
39 | | - transitions: null, |
40 | | - |
41 | | - // Stores the smil document for this object ( for relative image paths ) |
42 | | - smilUrl: null, |
43 | | - |
44 | | - // The abstract embed player parent |
45 | | - embedPlayer: null, |
46 | | - |
47 | | - /** |
48 | | - * Constructor |
49 | | - * @param {Object} embedPlayer Reference to the embedPlayer driving the smil object |
50 | | - */ |
51 | | - init: function( embedPlayer ) { |
52 | | - mw.log(" Smil:: init with player: " + embedPlayer.id ); |
| 40 | + transitions : null, |
| 41 | + |
| 42 | + // Stores the smil document for this object ( for relative image paths ) |
| 43 | + smilUrl : null, |
| 44 | + |
| 45 | + // The abstract embed player parent |
| 46 | + embedPlayer : null, |
| 47 | + |
| 48 | + /** |
| 49 | + * Constructor |
| 50 | + * |
| 51 | + * @param {Object} |
| 52 | + * embedPlayer Reference to the embedPlayer driving the smil |
| 53 | + * object |
| 54 | + */ |
| 55 | + init : function(embedPlayer) { |
| 56 | + mw.log(" Smil:: init with player: " + embedPlayer.id); |
53 | 57 | this.embedPlayer = embedPlayer; |
54 | 58 | }, |
55 | | - |
56 | | - /** |
57 | | - * Load smil into this object from a url |
58 | | - * @parm {string} url Source url of smil XML |
59 | | - * @param {function} callback Function to call once smil is loaded and ready |
60 | | - */ |
61 | | - loadFromUrl: function( url , callback ) { |
| 59 | + |
| 60 | + /** |
| 61 | + * Load smil into this object from a url |
| 62 | + * |
| 63 | + * @parm {string} url Source url of smil XML |
| 64 | + * @param {function} |
| 65 | + * callback Function to call once smil is loaded and ready |
| 66 | + */ |
| 67 | + loadFromUrl : function(url, callback) { |
62 | 68 | var _this = this; |
63 | | - this.smilUrl = url; |
64 | | - mw.log( 'Smil::loadFromUrl : ' + url ); |
65 | | - |
66 | | - // Try for direct load ( api cross domain loading is handled outside of SmilInterface |
67 | | - $j.get( url, function( data ) { |
68 | | - _this.loadFromString( data ); |
| 69 | + this.smilUrl = url; |
| 70 | + mw.log('Smil::loadFromUrl : ' + url); |
| 71 | + |
| 72 | + // Try for direct load ( api cross domain loading is handled outside of |
| 73 | + // SmilInterface |
| 74 | + $j.get(url, function(data) { |
| 75 | + _this.loadFromString(data); |
69 | 76 | // XXX check success or failure |
70 | | - callback(); |
71 | | - }); |
| 77 | + callback(); |
| 78 | + }); |
72 | 79 | }, |
73 | | - |
| 80 | + |
74 | 81 | /** |
75 | | - * Set smil from xml string |
76 | | - * @param {string} SmilXmlString Xml string of smil to be processed |
77 | | - */ |
78 | | - loadFromString: function ( smilXmlString ){ |
| 82 | + * Set smil from xml string |
| 83 | + * |
| 84 | + * @param {string} |
| 85 | + * SmilXmlString Xml string of smil to be processed |
| 86 | + */ |
| 87 | + loadFromString : function(smilXmlString) { |
79 | 88 | // Load the parsed string into the local "dom" |
80 | | - this.$dom = $j( smilXmlString ); |
81 | | - |
82 | | - mw.log( "Smil::loadFromString: loaded smil dom: " + this.$dom ); |
83 | | - |
| 89 | + this.$dom = $j(smilXmlString); |
| 90 | + |
| 91 | + mw.log("Smil::loadFromString: loaded smil dom: " + this.$dom); |
| 92 | + |
84 | 93 | // Clear out the layout |
85 | 94 | this.layout = null; |
86 | | - |
87 | | - // Clear out the body |
| 95 | + |
| 96 | + // Clear out the body |
88 | 97 | this.body = null; |
89 | | - |
| 98 | + |
90 | 99 | // Clear out the top level duration |
91 | 100 | this.duration = null; |
92 | | - |
| 101 | + |
93 | 102 | // Clear out the "buffer" object |
94 | 103 | this.buffer = null; |
95 | 104 | }, |
96 | | - |
| 105 | + |
97 | 106 | /** |
98 | | - * Internal function to get the jQuery smil dom |
99 | | - */ |
100 | | - getDom: function() { |
101 | | - if( this.$dom ) { |
| 107 | + * Internal function to get the jQuery smil dom |
| 108 | + */ |
| 109 | + getDom : function() { |
| 110 | + if (this.$dom) { |
102 | 111 | return this.$dom; |
103 | 112 | } |
104 | | - mw.log( "Error SMIL Dom not available" ) ; |
105 | | - return ; |
| 113 | + mw.log("Error SMIL Dom not available"); |
| 114 | + return; |
106 | 115 | }, |
107 | | - |
| 116 | + |
108 | 117 | /** |
109 | 118 | * Render a specific time |
110 | 119 | */ |
111 | | - renderTime: function( time, callback ) { |
112 | | - // Setup the layout if not already setup: |
113 | | - this.getLayout().setupLayout( this.embedPlayer.getRenderTarget() ); |
114 | | - |
| 120 | + renderTime : function(time, callback) { |
| 121 | + // Setup the layout if not already setup: |
| 122 | + this.getLayout().setupLayout(this.embedPlayer.getRenderTarget()); |
| 123 | + |
115 | 124 | // Update the render target with bodyElements for the requested time |
116 | | - this.getBody().renderTime( time ); |
117 | | - |
| 125 | + this.getBody().renderTime(time); |
| 126 | + |
118 | 127 | // Wait until buffer is ready and run the callback |
119 | | - this.getBuffer().addAssetsReadyCallback( callback ); |
| 128 | + this.getBuffer().addAssetsReadyCallback(callback); |
120 | 129 | }, |
121 | | - |
122 | | - |
| 130 | + |
123 | 131 | /** |
124 | | - * We use animateTime instead of a tight framerate loop |
125 | | - * so that we can optimize with css transformations |
126 | | - * |
127 | | - */ |
128 | | - animateTime: function( time, timeDelta ){ |
129 | | - //mw.log("Smil::animateTime: " + time + ' delta: ' + timeDelta ); |
130 | | - this.getBody().renderTime( time, timeDelta ); |
| 132 | + * We use animateTime instead of a tight framerate loop so that we can |
| 133 | + * optimize with css transformations |
| 134 | + * |
| 135 | + */ |
| 136 | + animateTime : function(time, timeDelta) { |
| 137 | + // mw.log("Smil::animateTime: " + time + ' delta: ' + timeDelta ); |
| 138 | + this.getBody().renderTime(time, timeDelta); |
131 | 139 | }, |
132 | | - |
| 140 | + |
133 | 141 | /** |
134 | 142 | * Pause all animations and playback |
135 | 143 | */ |
136 | | - pause: function( currentTime ){ |
137 | | - this.getBody().pause( currentTime ); |
| 144 | + pause : function(currentTime) { |
| 145 | + this.getBody().pause(currentTime); |
138 | 146 | }, |
139 | | - |
| 147 | + |
140 | 148 | /** |
141 | | - * Checks if the playback is in sync with the current time |
142 | | - * @return {boolean} |
143 | | - * true if playback is insync, |
144 | | - * false if not in sync with all animation elements ( video tag for now ) |
| 149 | + * Checks if the playback is in sync with the current time |
| 150 | + * |
| 151 | + * @return {boolean} true if playback is insync, false if not in sync with |
| 152 | + * all animation elements ( video tag for now ) |
145 | 153 | */ |
146 | | - getPlaybackSyncDelta: function( currentTime ){ |
147 | | - return this.getAnimate().getPlaybackSyncDelta( currentTime ); |
| 154 | + getPlaybackSyncDelta : function(currentTime) { |
| 155 | + return this.getAnimate().getPlaybackSyncDelta(currentTime); |
148 | 156 | }, |
149 | | - |
150 | | - getBufferedPercent: function(){ |
| 157 | + |
| 158 | + getBufferedPercent : function() { |
151 | 159 | // Get the clip buffered percent |
152 | 160 | return this.getBuffer().getBufferedPercent(); |
153 | 161 | }, |
154 | | - |
| 162 | + |
155 | 163 | /** |
156 | | - * Get the set of audio ranges for flattening. |
| 164 | + * Get the set of audio ranges for flattening. |
157 | 165 | */ |
158 | | - getAudioTimeSet: function(){ |
| 166 | + getAudioTimeSet : function() { |
159 | 167 | return this.getBody().getFlatAudioTimeLine(); |
160 | 168 | }, |
161 | | - |
| 169 | + |
162 | 170 | /** |
163 | | - * Pass on the request to start buffering the entire sequence of clips |
| 171 | + * Pass on the request to start buffering the entire sequence of clips |
164 | 172 | */ |
165 | | - startBuffer: function(){ |
| 173 | + startBuffer : function() { |
166 | 174 | this.getBuffer().startBuffer(); |
167 | 175 | }, |
168 | | - |
| 176 | + |
169 | 177 | /** |
170 | | - * Get the smil buffer object |
171 | | - */ |
172 | | - getBuffer: function(){ |
173 | | - if( ! this.buffer ) { |
174 | | - this.buffer = new mw.SmilBuffer( this ) ; |
| 178 | + * Get the smil buffer object |
| 179 | + */ |
| 180 | + getBuffer : function() { |
| 181 | + if (!this.buffer) { |
| 182 | + this.buffer = new mw.SmilBuffer(this); |
175 | 183 | } |
176 | | - return this.buffer; |
| 184 | + return this.buffer; |
177 | 185 | }, |
178 | | - |
| 186 | + |
179 | 187 | /** |
180 | | - * Get the animate object |
181 | | - */ |
182 | | - getAnimate: function(){ |
183 | | - if( ! this.animate ){ |
184 | | - this.animate = new mw.SmilAnimate( this ); |
| 188 | + * Get the animate object |
| 189 | + */ |
| 190 | + getAnimate : function() { |
| 191 | + if (!this.animate) { |
| 192 | + this.animate = new mw.SmilAnimate(this); |
185 | 193 | } |
186 | 194 | return this.animate; |
187 | 195 | }, |
188 | | - |
| 196 | + |
189 | 197 | /** |
190 | | - * Get the smil layout object, with reference to the body |
| 198 | + * Get the smil layout object, with reference to the body |
191 | 199 | */ |
192 | | - getLayout: function() { |
193 | | - if( !this.layout ) { |
194 | | - this.layout = new mw.SmilLayout( this ); |
| 200 | + getLayout : function() { |
| 201 | + if (!this.layout) { |
| 202 | + this.layout = new mw.SmilLayout(this); |
195 | 203 | } |
196 | 204 | return this.layout; |
197 | 205 | }, |
198 | | - |
| 206 | + |
199 | 207 | /** |
200 | 208 | * Get the smil body object |
201 | 209 | */ |
202 | | - getBody: function(){ |
203 | | - if( !this.body ){ |
204 | | - this.body = new mw.SmilBody( this ); |
| 210 | + getBody : function() { |
| 211 | + if (!this.body) { |
| 212 | + this.body = new mw.SmilBody(this); |
205 | 213 | } |
206 | 214 | return this.body; |
207 | 215 | }, |
208 | 216 | /** |
209 | 217 | * Get the transitions object |
210 | 218 | */ |
211 | | - getTransitions: function(){ |
212 | | - if( !this.transitions ){ |
213 | | - this.transitions = new mw.SmilTransitions( this ); |
| 219 | + getTransitions : function() { |
| 220 | + if (!this.transitions) { |
| 221 | + this.transitions = new mw.SmilTransitions(this); |
214 | 222 | } |
215 | 223 | return this.transitions; |
216 | 224 | }, |
217 | | - |
218 | | - /** |
219 | | - * Function called continuously to keep sync smil "in sync" |
220 | | - * Checks buffer states... |
| 225 | + |
| 226 | + /** |
| 227 | + * Function called continuously to keep sync smil "in sync" Checks buffer |
| 228 | + * states... |
221 | 229 | */ |
222 | | - syncWithTime: function( time ){ |
| 230 | + syncWithTime : function(time) { |
223 | 231 | /* .. not yet implementd ... */ |
224 | | - mw.log( 'smil sync: ' + time); |
| 232 | + mw.log('smil sync: ' + time); |
225 | 233 | }, |
226 | | - |
227 | | - |
| 234 | + |
228 | 235 | /** |
229 | 236 | * Get the duration form the smil body |
230 | 237 | */ |
231 | | - getDuration: function(){ |
| 238 | + getDuration : function( forceRefresh ) { |
232 | 239 | // return 0 while we don't have the $dom loaded |
233 | | - if( !this.$dom ){ |
| 240 | + if (!this.$dom) { |
234 | 241 | return 0; |
235 | 242 | } |
236 | | - |
237 | | - if( !this.duration ){ |
238 | | - this.duration = this.getBody().getDuration(); |
| 243 | + |
| 244 | + if (!this.duration || forceRefresh ) { |
| 245 | + this.duration = this.getBody().getDuration( forceRefresh ); |
239 | 246 | } |
240 | | - return this.duration; |
| 247 | + return this.duration; |
241 | 248 | }, |
| 249 | + removeById: function ( smilElementId ) { |
| 250 | + var $smilElement = this.$dom.find( '#' + smilElementId ); |
| 251 | + |
| 252 | + // Remove from layout |
| 253 | + this.getLayout().getRootLayout().find( '#' + this.getAssetId( $smilElement ) ) |
| 254 | + .remove(); |
242 | 255 | |
| 256 | + // remove from dom |
| 257 | + $smilElement.remove(); |
| 258 | + |
| 259 | + // xxx todo invalidate dom duration cache |
| 260 | + }, |
243 | 261 | /** |
244 | 262 | * Some Smil Utility functions |
245 | | - */ |
246 | | - |
| 263 | + */ |
| 264 | + |
247 | 265 | /** |
248 | | - * maps a smil element id to a html 'safer' id |
249 | | - * as a decedent subname of the embedPlayer parent |
250 | | - * |
251 | | - * @param {Object} smilElement Element to get id for |
252 | | - */ |
253 | | - getAssetId: function( smilElement ){ |
254 | | - if(! $j( smilElement ).attr('id') ) { |
255 | | - mw.log("Error: getAssetId smilElement missing id " ) ; |
256 | | - return false; |
| 266 | + * maps a smil element id to a html 'safer' id as a decedent subname of the |
| 267 | + * embedPlayer parent |
| 268 | + * |
| 269 | + * @param {Object} |
| 270 | + * smilElement Element to get id for |
| 271 | + */ |
| 272 | + getAssetId : function(smilElement) { |
| 273 | + if (!$j(smilElement).attr('id')) { |
| 274 | + mw.log("Error: getAssetId smilElement missing id "); |
| 275 | + return false; |
257 | 276 | } |
258 | | - if( ! this.embedPlayer || ! this.embedPlayer.id ) { |
| 277 | + if (!this.embedPlayer || !this.embedPlayer.id) { |
259 | 278 | mw.log("Error: getAssetId missing parent embedPlayer"); |
260 | 279 | return false; |
261 | 280 | } |
262 | | - return this.embedPlayer.id + '_' + $j( smilElement ).attr('id'); |
| 281 | + return this.embedPlayer.id + '_' + $j(smilElement).attr('id'); |
263 | 282 | }, |
264 | | - |
| 283 | + |
265 | 284 | /** |
266 | | - * Get an absolute path to asset based on the smil URL |
267 | | - * @param {string} assetPath Path to asset to be transformed into url |
268 | | - */ |
269 | | - getAssetUrl: function( assetPath ){ |
270 | | - // Context url is the smil document url: |
271 | | - var contextUrl = mw.absoluteUrl( this.smilUrl ); |
272 | | - return mw.absoluteUrl( assetPath, contextUrl ); |
| 285 | + * Get an absolute path to asset based on the smil URL |
| 286 | + * |
| 287 | + * @param {string} |
| 288 | + * assetPath Path to asset to be transformed into url |
| 289 | + */ |
| 290 | + getAssetUrl : function(assetPath) { |
| 291 | + // Context url is the smil document url: |
| 292 | + var contextUrl = mw.absoluteUrl(this.smilUrl); |
| 293 | + return mw.absoluteUrl(assetPath, contextUrl); |
273 | 294 | }, |
274 | | - |
| 295 | + |
275 | 296 | /** |
276 | 297 | * Get the smil resource type based on nodeName and type attribute |
277 | 298 | */ |
278 | | - getRefType: function( smilElement ) { |
279 | | - if( $j( smilElement ).length == 0 ){ |
| 299 | + getRefType : function(smilElement) { |
| 300 | + if ($j(smilElement).length == 0) { |
280 | 301 | mw.log('Error: Smil::getRefType on empty smilElement'); |
281 | 302 | return; |
282 | 303 | } |
283 | 304 | // Get the smil type |
284 | | - var smilType = $j( smilElement ).get(0).nodeName.toLowerCase(); |
285 | | - |
286 | | - if( this.getBody().smilBlockTypeMap[ smilType ] != 'ref' ){ |
287 | | - mw.log("Error: trying to get ref type of node that is not a ref" + smilType); |
288 | | - return null; |
| 305 | + var smilType = $j(smilElement).get(0).nodeName.toLowerCase(); |
| 306 | + |
| 307 | + if (this.getBody().smilBlockTypeMap[smilType] != 'ref') { |
| 308 | + mw.log("Error: trying to get ref type of node that is not a ref" |
| 309 | + + smilType); |
| 310 | + return null; |
289 | 311 | } |
290 | | - |
| 312 | + |
291 | 313 | // If the smilType is ref, check for a content type |
292 | | - if( smilType == 'ref' ){ |
293 | | - switch( $j( smilElement ).attr( 'type' ) ) { |
294 | | - case 'text/html': |
295 | | - smilType = 'cdata_html'; |
| 314 | + if (smilType == 'ref') { |
| 315 | + switch ($j(smilElement).attr('type')) { |
| 316 | + case 'text/html': |
| 317 | + smilType = 'cdata_html'; |
296 | 318 | break; |
297 | | - case 'video/ogg': |
298 | | - case 'video/h.264': |
299 | | - case 'video/webm': |
300 | | - smilType = 'video'; |
| 319 | + case 'video/ogg': |
| 320 | + case 'video/h.264': |
| 321 | + case 'video/webm': |
| 322 | + smilType = 'video'; |
301 | 323 | break; |
302 | | - case 'audio/ogg': |
303 | | - smilType = 'audio'; |
| 324 | + case 'audio/ogg': |
| 325 | + smilType = 'audio'; |
304 | 326 | break; |
305 | 327 | } |
306 | 328 | } |
307 | 329 | return smilType; |
308 | 330 | }, |
309 | | - |
310 | | - /** |
| 331 | + |
| 332 | + /** |
311 | 333 | * Parse smil time function |
312 | 334 | * http://www.w3.org/TR/SMIL3/smil-timing.html#Timing-ClockValueSyntax |
313 | 335 | * |
314 | | - * Smil time has the following structure: |
315 | | - * |
316 | | - * Clock-value ::= ( Full-clock-value | Partial-clock-value | Timecount-value ) |
317 | | - * Full-clock-value ::= Hours ":" Minutes ":" Seconds ("." Fraction)? |
318 | | - * Partial-clock-value ::= Minutes ":" Seconds ("." Fraction)? |
319 | | - * Timecount-value ::= Timecount ("." Fraction)? (Metric)? |
320 | | - * Metric ::= "h" | "min" | "s" | "ms" |
321 | | - * Hours ::= DIGIT+ // any positive number |
322 | | - * Minutes ::= 2DIGIT // range from 00 to 59 |
323 | | - * Seconds ::= 2DIGIT // range from 00 to 59 |
324 | | - * Fraction ::= DIGIT+ |
325 | | - * Timecount ::= DIGIT+ |
326 | | - * 2DIGIT ::= DIGIT DIGIT |
327 | | - * DIGIT ::= [0-9] |
| 336 | + * Smil time has the following structure: |
328 | 337 | * |
329 | | - * @param {mixed} timeValue time value of smil structure |
330 | | - * @return {float} Seconds from time value, if timeValue is empty or null return 0 |
| 338 | + * Clock-value ::= ( Full-clock-value | Partial-clock-value | |
| 339 | + * Timecount-value ) Full-clock-value ::= Hours ":" Minutes ":" Seconds ("." |
| 340 | + * Fraction)? Partial-clock-value ::= Minutes ":" Seconds ("." Fraction)? |
| 341 | + * Timecount-value ::= Timecount ("." Fraction)? (Metric)? Metric ::= "h" | |
| 342 | + * "min" | "s" | "ms" Hours ::= DIGIT+ // any positive number Minutes ::= |
| 343 | + * 2DIGIT // range from 00 to 59 Seconds ::= 2DIGIT // range from 00 to 59 |
| 344 | + * Fraction ::= DIGIT+ Timecount ::= DIGIT+ 2DIGIT ::= DIGIT DIGIT DIGIT ::= |
| 345 | + * [0-9] |
| 346 | + * |
| 347 | + * @param {mixed} |
| 348 | + * timeValue time value of smil structure |
| 349 | + * @return {float} Seconds from time value, if timeValue is empty or null |
| 350 | + * return 0 |
331 | 351 | */ |
332 | | - parseTime : function( timeValue ){ |
333 | | - if( !timeValue ) |
| 352 | + parseTime : function(timeValue) { |
| 353 | + if (!timeValue) |
334 | 354 | return 0; |
335 | | - |
336 | | - // If timeValue is already a clean number of seconds, return seconds: |
337 | | - if( ! isNaN( timeValue ) ){ |
338 | | - return parseFloat( timeValue ); |
339 | | - } |
340 | | - // Trim whitespace if empty return zero |
341 | | - timeValue = $j.trim( timeValue ); |
342 | | - if( timeValue == '' ){ |
343 | | - return 0; |
344 | | - } |
345 | | - |
346 | | - // First check for hh:mm:ss time: |
347 | | - if ( timeValue.split( ':' ).length == 3 || timeValue.split( ':' ).length == 2 ) { |
348 | | - return mw.npt2seconds( timeValue ); |
349 | | - } |
350 | | - |
351 | | - var timeFactor = null |
352 | | - // Check for metric hours |
353 | | - if( timeValue.substr( -1 ) == 'h' ){ |
354 | | - timeFactor = 3600 ; |
355 | | - } |
356 | | - // Min metric |
357 | | - if( timeValue.substr( -3 ) == 'min' ){ |
358 | | - timeFactor = 60; |
359 | | - } |
360 | | - // Seconds |
361 | | - if( timeValue.substr( -1 ) == 's'){ |
362 | | - timeFactor = 1; |
363 | | - } |
364 | | - // Millaseconds |
365 | | - if( timeValue.substr( -2 ) == 'ms'){ |
366 | | - timeFactor = .001; |
367 | | - } |
368 | | - |
369 | | - if( timeFactor){ |
370 | | - return parseFloat( parseFloat( timeValue ) * timeFactor ); |
371 | | - } |
372 | | - mw.log("Error could not parse time: " + timeValue); |
| 355 | + |
| 356 | + // If timeValue is already a clean number of seconds, return seconds: |
| 357 | + if (!isNaN(timeValue)) { |
| 358 | + return parseFloat(timeValue); |
| 359 | + } |
| 360 | + // Trim whitespace if empty return zero |
| 361 | + timeValue = $j.trim(timeValue); |
| 362 | + if (timeValue == '') { |
373 | 363 | return 0; |
374 | 364 | } |
375 | | -} |
376 | 365 | |
| 366 | + // First check for hh:mm:ss time: |
| 367 | + if (timeValue.split(':').length == 3 || timeValue.split(':').length == 2) { |
| 368 | + return mw.npt2seconds(timeValue); |
| 369 | + } |
377 | 370 | |
| 371 | + var timeFactor = null |
| 372 | + // Check for metric hours |
| 373 | + if (timeValue.substr(-1) == 'h') { |
| 374 | + timeFactor = 3600; |
| 375 | + } |
| 376 | + // Min metric |
| 377 | + if (timeValue.substr(-3) == 'min') { |
| 378 | + timeFactor = 60; |
| 379 | + } |
| 380 | + // Seconds |
| 381 | + if (timeValue.substr(-1) == 's') { |
| 382 | + timeFactor = 1; |
| 383 | + } |
| 384 | + // Millaseconds |
| 385 | + if (timeValue.substr(-2) == 'ms') { |
| 386 | + timeFactor = .001; |
| 387 | + } |
378 | 388 | |
379 | | - |
\ No newline at end of file |
| 389 | + if (timeFactor) { |
| 390 | + return parseFloat(parseFloat(timeValue) * timeFactor); |
| 391 | + } |
| 392 | + mw.log("Error could not parse time: " + timeValue); |
| 393 | + return 0; |
| 394 | +} |
| 395 | +} |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/tests/VideoCrossFade.html |
— | — | @@ -26,7 +26,7 @@ |
27 | 27 | 'statusTarget': '#targetFoggStatus' |
28 | 28 | }); |
29 | 29 | if( foggRender.doRender() ){ |
30 | | - $j('#renderToFile').text('Stop Render').click(function(){ |
| 30 | + $j('#renderToFile').text('Stop Render').unbind().click(function(){ |
31 | 31 | foggRender.stopRender(); |
32 | 32 | }); |
33 | 33 | } |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/tests/VideoClipBegin.html |
— | — | @@ -26,7 +26,7 @@ |
27 | 27 | 'statusTarget': '#targetFoggStatus' |
28 | 28 | }); |
29 | 29 | if( foggRender.doRender() ){ |
30 | | - $j('#renderToFile').text('Stop Render').click(function(){ |
| 30 | + $j('#renderToFile').text('Stop Render').unbind().click(function(){ |
31 | 31 | foggRender.stopRender(); |
32 | 32 | }); |
33 | 33 | } |
— | — | @@ -42,17 +42,21 @@ |
43 | 43 | <tr> |
44 | 44 | <td> |
45 | 45 | |
46 | | -<video id="videoClipBegin" type="application/smil" src="VideoClipBeginSmil.xml" width="400" height="300"></video> |
| 46 | +<video id="videoClipBegin" width="400" height="300"> |
| 47 | + <source type="application/smil" src="VideoClipBeginSmil.xml" /> |
| 48 | +</video> |
47 | 49 | <p></p>seek to <input id="seekInputTime" size="4" value = "6"></input><span id="seekInProgress" style="display: none"> Seeking<blink>...</blink></span> |
48 | 50 | <br/> |
49 | 51 | <a id="startBuffer" href="#">Start buffering</a> <br> |
50 | 52 | <a id="renderToFile" href="#">Render to file</a> <span id="targetFoggStatus"></span> |
51 | 53 | </td> |
52 | 54 | <td valign="top"> |
53 | | -Sample playlist code: |
| 55 | +Sample Smil Embed code: |
54 | 56 | <div style="clear:both"></div> |
55 | 57 | <textarea style="width:500px;"> |
56 | | -<video id="videoClipBegin" type="application/smil" src="VideoClipBeginSmil.xml" width="400" height="300"></video> |
| 58 | +<video id="videoClipBegin" width="400" height="300"> |
| 59 | + <source type="application/smil" src="VideoClipBeginSmil.xml" /> |
| 60 | +</video> |
57 | 61 | </textarea> |
58 | 62 | <div style="clear:both"></div> |
59 | 63 | |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/tests/VideoClipBeginSmil.xml |
— | — | @@ -40,7 +40,7 @@ |
41 | 41 | |
42 | 42 | <video src="http://upload.wikimedia.org/wikipedia/commons/8/8b/Yochai_Benkler_-_On_Autonomy%2C_Control_and_Cultural_Experience.ogg" |
43 | 43 | transIn="fromBlack" |
44 | | - dur="10" |
| 44 | + dur="0:3:43" |
45 | 45 | clipBegin = "0:3:43" |
46 | 46 | /> |
47 | 47 | |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilHooks.js |
— | — | @@ -1,19 +1,25 @@ |
2 | 2 | |
3 | 3 | // Define the SmilHooks object |
4 | | -mw.SmilHooks = {}; |
| 4 | +mw.SmilHooks = { |
| 5 | + addSmilPlayer: function(){ |
| 6 | + // Check if the smil player has already been added: |
| 7 | + if( mw.EmbedTypes.players.defaultPlayers[ 'application/smil' ] ) |
| 8 | + return ; |
| 9 | + |
| 10 | + // Add the swarmTransport playerType |
| 11 | + mw.EmbedTypes.players.defaultPlayers[ 'application/smil' ] = [ 'Smil' ]; |
| 12 | + |
| 13 | + // Build the swarm Transport "player" |
| 14 | + var smilMediaPlayer = new mediaPlayer( 'smilPlayer', [ 'application/smil' ], 'Smil' ); |
| 15 | + |
| 16 | + // Add the swarmTransport "player" |
| 17 | + mw.EmbedTypes.players.addPlayer( smilMediaPlayer ); |
| 18 | + } |
| 19 | +}; |
5 | 20 | |
6 | 21 | // Add the smil player to available player types: |
7 | 22 | $j( mw ).bind( 'EmbedPlayerManagerReady', function( event ) { |
8 | | - |
9 | | - // Add the swarmTransport playerType |
10 | | - mw.EmbedTypes.players.defaultPlayers[ 'application/smil' ] = [ 'Smil' ]; |
11 | | - |
12 | | - // Build the swarm Transport "player" |
13 | | - var smilMediaPlayer = new mediaPlayer( 'smilPlayer', [ 'application/smil' ], 'Smil' ); |
14 | | - |
15 | | - // Add the swarmTransport "player" |
16 | | - mw.EmbedTypes.players.addPlayer( smilMediaPlayer ); |
17 | | - |
| 23 | + mw.SmilHooks.addSmilPlayer(); |
18 | 24 | } ); |
19 | 25 | |
20 | 26 | // Tell embedPlayer not to wait for height / width metadata in cases of smil documents |
— | — | @@ -28,18 +34,27 @@ |
29 | 35 | $j( mw ).bind( 'newEmbedPlayerEvent', function( event, swapedPlayerId ) { |
30 | 36 | // Setup local reference to embedPlayer interface |
31 | 37 | var embedPlayer = $j( '#' + swapedPlayerId ).get(0); |
| 38 | + // Add the smil player ( in case we were dynamically loaded and EmbedPlayerManagerReady has already been called ) |
| 39 | + mw.SmilHooks.addSmilPlayer(); |
32 | 40 | |
33 | 41 | // Setup the "embedCode" binding to swap in an updated url |
34 | 42 | $j( embedPlayer ).bind( 'checkPlayerSourcesEvent', function( event, callback ) { |
35 | | - mw.log( " smil enter checkPlayerSources" ); |
36 | | - // Get the first smil source: |
37 | | - mw.log( "Source is: " + embedPlayer.mediaElement.getSources( 'application/smil' )[0].getSrc() ); |
38 | | - embedPlayer.smil = new mw.Smil( embedPlayer ); |
39 | | - |
40 | | - // Load the smil url as part of "source check" |
41 | | - embedPlayer.smil.loadFromUrl( embedPlayer.mediaElement.getSources( 'application/smil' )[0].getSrc(), function(){ |
42 | | - callback(); |
43 | | - }); |
| 43 | + mw.log( "SmilHooks::checkPlayerSources" ); |
| 44 | + // Make sure there is a smil source: |
| 45 | + if( embedPlayer.mediaElement.getSources( 'application/smil' ).length ){ |
| 46 | + // Get the first smil source: |
| 47 | + mw.log( "Source is: " + embedPlayer.mediaElement.getSources( 'application/smil' )[0].getSrc() ); |
| 48 | + |
| 49 | + // Add the smil engine to the embed player: |
| 50 | + embedPlayer.smil = new mw.Smil( embedPlayer ); |
| 51 | + |
| 52 | + // Load the smil url as part of "source check" |
| 53 | + embedPlayer.smil.loadFromUrl( embedPlayer.mediaElement.getSources( 'application/smil' )[0].getSrc(), function(){ |
| 54 | + callback(); |
| 55 | + }); |
| 56 | + } else { |
| 57 | + callback(); |
| 58 | + } |
44 | 59 | } ); |
45 | 60 | }); |
46 | 61 | |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.EmbedPlayerSmil.js |
— | — | @@ -68,11 +68,8 @@ |
69 | 69 | setCurrentTime: function( time, callback ) { |
70 | 70 | //mw.log('EmbedPlayerSmil::setCurrentTime: ' + time ); |
71 | 71 | // Set "loading" spinner here) |
72 | | - $j( this ).append( |
73 | | - $j( '<div />') |
74 | | - .attr('id', 'loadingSpinner_' + this.id ) |
75 | | - .loadingSpinner() |
76 | | - ); |
| 72 | + $j( this ).getAbsoluteOverlaySpinner() |
| 73 | + .attr('id', 'loadingSpinner_' + this.id ) |
77 | 74 | // Start seek |
78 | 75 | this.controlBuilder.onSeek(); |
79 | 76 | this.smilPlayTime = time; |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilBuffer.js |
— | — | @@ -131,7 +131,7 @@ |
132 | 132 | } |
133 | 133 | // get the percentage buffered, translated into buffer time and call continueBufferLoad with a timeout |
134 | 134 | var timeBuffered = _this.getBufferedPercent() * _this.smil.getDuration(); |
135 | | - mw.log( 'ContinueBufferLoad::Timed buffered: ' + timeBuffered ); |
| 135 | + //mw.log( 'ContinueBufferLoad::Timed buffered: ' + timeBuffered ); |
136 | 136 | _this.continueBufferLoad( timeBuffered ); |
137 | 137 | }, this.smil.embedPlayer.monitorRate * 2 ); |
138 | 138 | |
— | — | @@ -156,7 +156,6 @@ |
157 | 157 | // but in theory we could set something up with large images |
158 | 158 | switch( this.smil.getRefType( smilElement ) ){ |
159 | 159 | case 'video': |
160 | | - // xxx "seek" to support offsets |
161 | 160 | var vid = $j( '#' + this.smil.getAssetId( smilElement ) ).get(0); |
162 | 161 | |
163 | 162 | // The load request does not work very well instead .play() then .pause() and seek when on display |
— | — | @@ -167,6 +166,9 @@ |
168 | 167 | // Issue the load / play request |
169 | 168 | vid.play(); |
170 | 169 | vid.volume = 0; |
| 170 | + |
| 171 | + // XXX seek to clipBegin if provided ( we don't need to load before that point ) |
| 172 | + |
171 | 173 | } else { |
172 | 174 | // else we have some percentage loaded pause playback |
173 | 175 | //( should continue to load the asset ) |
— | — | @@ -285,6 +287,27 @@ |
286 | 288 | }, |
287 | 289 | |
288 | 290 | /** |
| 291 | + * Clip ready for grabbing a frame such as a canvas thumb |
| 292 | + */ |
| 293 | + canGrabRelativeTime: function( smilElement, relativeTime, callback ){ |
| 294 | + var absoluteTime = relativeTime; |
| 295 | + if( $j( smilElement ).attr('clipBegin') ){ |
| 296 | + absoluteTime += this.smil.parseTime( $j( smilElement ).attr('clipBegin') ); |
| 297 | + } |
| 298 | + switch( this.smil.getRefType( smilElement ) ){ |
| 299 | + case 'video': |
| 300 | + this.videoBufferSeek( smilElement, absoluteTime, callback ) |
| 301 | + break; |
| 302 | + case 'image': |
| 303 | + this.loadImageCallback( smilElement, callback ); |
| 304 | + break; |
| 305 | + default: |
| 306 | + // Assume other formats are directly displayed |
| 307 | + break; |
| 308 | + } |
| 309 | + }, |
| 310 | + |
| 311 | + /** |
289 | 312 | * Check if we can play a given time |
290 | 313 | * @return {boolean} True if the time can be played, false if we need to buffer |
291 | 314 | */ |
— | — | @@ -331,25 +354,6 @@ |
332 | 355 | }, |
333 | 356 | |
334 | 357 | /** |
335 | | - * Manage seek listeners |
336 | | - */ |
337 | | - runSeekCallback: function(assetId, time, callback){ |
338 | | - var _this = this; |
339 | | - |
340 | | - // Get the video target: |
341 | | - var vid = $j ( '#' + assetId).get(0); |
342 | | - |
343 | | - if( this.videoListeners[ assetId ] ){ |
344 | | - this.videoListeners[ assetId ] = true; |
345 | | - vid.addEventListener( 'seeked', function(){ |
346 | | - |
347 | | - }); |
348 | | - } |
349 | | - |
350 | | - this.videoListeners[ assetId ] = callback; |
351 | | - }, |
352 | | - |
353 | | - /** |
354 | 358 | * Abstract the seeked Listener so we don't have stacking bindings |
355 | 359 | */ |
356 | 360 | registerVideoSeekListener: function( assetId ){ |
— | — | @@ -363,10 +367,23 @@ |
364 | 368 | }, false); |
365 | 369 | }, |
366 | 370 | |
| 371 | + loadImageCallback: function ( smilElement, callback ){ |
| 372 | + var assetId = this.smil.getAssetId( smilElement ); |
| 373 | + // Make sure the image is in the dom ( load it ) |
| 374 | + this.loadElement( smilElement ); |
| 375 | + // add the jQuery "loaded" callback |
| 376 | + $j( '#' + assetId).loaded( callback ); |
| 377 | + }, |
| 378 | + |
367 | 379 | videoBufferSeek: function ( smilElement, seekTime, callback ){ |
368 | 380 | var _this = this; |
369 | | - // Get the video target: |
| 381 | + |
| 382 | + // Get the asset target: |
370 | 383 | var assetId = this.smil.getAssetId( smilElement ); |
| 384 | + |
| 385 | + // make sure the target video is in the dom: |
| 386 | + this.loadElement( smilElement ); |
| 387 | + |
371 | 388 | var $vid = $j ( '#' + assetId); |
372 | 389 | var vid = $vid.get(0); |
373 | 390 | // Add the asset to the loading set |
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayer.js |
— | — | @@ -165,7 +165,7 @@ |
166 | 166 | |
167 | 167 | // If the player controls should be overlaid |
168 | 168 | //( Global default via config EmbedPlayer.OverlayControls in module loader.js) |
169 | | - "EmbedPlayer.OverlayControls" : true, |
| 169 | + "overlayControls" : true, |
170 | 170 | |
171 | 171 | // ROE url ( for xml based metadata ) |
172 | 172 | // also see: http://wiki.xiph.org/ROE |
— | — | @@ -421,7 +421,7 @@ |
422 | 422 | if( ranPlayerSwapFlag ){ |
423 | 423 | return ; |
424 | 424 | } |
425 | | - mw.log("runPlayerSwap::" + $j( playerElement ).attr('id') ); |
| 425 | + mw.log("mwEmbedPlayer::runPlayerSwap::" + $j( playerElement ).attr('id') ); |
426 | 426 | ranPlayerSwapFlag = true; |
427 | 427 | var playerInterface = new mw.EmbedPlayer( playerElement , attributes); |
428 | 428 | |
— | — | @@ -429,7 +429,7 @@ |
430 | 430 | |
431 | 431 | |
432 | 432 | // Pass the id to any hook that needs to interface prior to checkPlayerSources |
433 | | - mw.log("addElement :: trigger :: newEmbedPlayerEvent"); |
| 433 | + mw.log("mwEmbedPlayer::addElement :trigger :: newEmbedPlayerEvent"); |
434 | 434 | $j( mw ).trigger ( 'newEmbedPlayerEvent', playerInterface.id ); |
435 | 435 | |
436 | 436 | // Issue the checkPlayerSources call to the new player interface: |
— | — | @@ -438,7 +438,7 @@ |
439 | 439 | } |
440 | 440 | |
441 | 441 | if( waitForMeta ) { |
442 | | - mw.log('DO WaitForMeta ( video missing height (' + $j( playerElement ).attr('height') + '), width (' + $j( playerElement ).attr('width') + ') or duration' ); |
| 442 | + mw.log('mwEmbedPlayer::WaitForMeta ( video missing height (' + $j( playerElement ).attr('height') + '), width (' + $j( playerElement ).attr('width') + ') or duration' ); |
443 | 443 | playerElement.removeEventListener( "loadedmetadata", runPlayerSwap, true ); |
444 | 444 | playerElement.addEventListener( "loadedmetadata", runPlayerSwap, true ); |
445 | 445 | |
— | — | @@ -1465,55 +1465,68 @@ |
1466 | 1466 | */ |
1467 | 1467 | setPlayerSize: function( element ) { |
1468 | 1468 | |
1469 | | - this['height'] = parseInt( $j(element).css( 'height' ) ); |
1470 | | - this['width'] = parseInt( $j(element).css( 'width' ) ); |
| 1469 | + this.height = parseInt( $j(element).css( 'height' ) ); |
| 1470 | + this.width = parseInt( $j(element).css( 'width' ) ); |
1471 | 1471 | |
1472 | | - if( !this['height'] && !this['width'] ) { |
1473 | | - this['height'] = parseInt( $j(element).attr( 'height' ) ); |
1474 | | - this['width'] = parseInt( $j(element).attr( 'width' ) ); |
| 1472 | + if( !this.height && !this.width ) { |
| 1473 | + this.height = parseInt( $j(element).attr( 'height' ) ); |
| 1474 | + this.width = parseInt( $j(element).attr( 'width' ) ); |
1475 | 1475 | } |
1476 | 1476 | |
1477 | 1477 | // Special case for audio |
1478 | 1478 | // Firefox sets audio height to "0px" while webkit uses 32px .. force zero: |
1479 | | - if( element.tagName.toLowerCase() == 'audio' && this['height'] == '32') { |
1480 | | - this['height'] = 0; |
| 1479 | + if( element.tagName.toLowerCase() == 'audio' && this.height == '32' ) { |
| 1480 | + this.height = 0; |
1481 | 1481 | } |
1482 | 1482 | |
1483 | 1483 | // Use default aspect ration to get height or width ( if rewriting a non-audio player ) |
1484 | | - if( element.tagName.toLowerCase() != 'audio' ) { |
1485 | | - if( this['height'] && !this['width'] && this.videoAspect ) { |
1486 | | - var aspect = this.videoAspect.split( ':' ); |
1487 | | - this['width'] = parseInt( this.height * ( aspect[0] / aspect[1] ) ); |
| 1484 | + if( element.tagName.toLowerCase() != 'audio' && this.videoAspect ) { |
| 1485 | + var aspect = this.videoAspect.split( ':' ); |
| 1486 | + if( this.height && !this.width ) { |
| 1487 | + this.width = parseInt( this.height * ( aspect[0] / aspect[1] ) ); |
| 1488 | + } |
| 1489 | + if( this.width && !this.height ) { |
| 1490 | + var apectRatio = ( aspect[1] / aspect[0] ); |
| 1491 | + this.height = parseInt( this.width * ( aspect[1] / aspect[0] ) ); |
1488 | 1492 | } |
1489 | | - |
1490 | | - if( this['width'] && !this['height'] && this.videoAspect ) { |
1491 | | - var aspect = this.videoAspect.split( ':' ); |
1492 | | - this['height'] = parseInt( this.width * ( aspect[1] / aspect[0] ) ); |
1493 | | - } |
1494 | 1493 | } |
1495 | 1494 | |
1496 | 1495 | // On load sometimes attr is temporally -1 as we don't have video metadata yet. |
1497 | 1496 | // or in IE we get NaN for width height |
1498 | 1497 | // |
1499 | 1498 | // NOTE: browsers that do support height width should set "waitForMeta" flag in addElement |
1500 | | - if( ( isNaN( this['height'] ) && isNaN( this['width'] ) ) || |
1501 | | - ( this['height'] == -1 || this['width'] == -1 ) || |
| 1499 | + if( ( isNaN( this.height ) && isNaN( this.width ) ) || |
| 1500 | + ( this.height == -1 || this.width == -1 ) || |
1502 | 1501 | // Check for firefox defaults |
1503 | 1502 | // Note: ideally firefox would not do random guesses at css values |
1504 | 1503 | ( (this.height == 150 || this.height == 64 ) && this.width == 300 ) |
1505 | 1504 | ) { |
1506 | 1505 | var defaultSize = mw.getConfig( 'EmbedPlayer.DefaultSize' ).split( 'x' ); |
1507 | | - this['width'] = defaultSize[0]; |
| 1506 | + this.width = defaultSize[0]; |
1508 | 1507 | |
1509 | 1508 | // Special height default for audio tag ( if not set ) |
1510 | 1509 | if( element.tagName.toLowerCase() == 'audio' ) { |
1511 | | - this['height'] = 0; |
| 1510 | + this.height = 0; |
1512 | 1511 | }else{ |
1513 | | - this['height'] = defaultSize[1]; |
| 1512 | + this.height = defaultSize[1]; |
1514 | 1513 | } |
1515 | 1514 | } |
1516 | 1515 | |
1517 | 1516 | }, |
| 1517 | + /** |
| 1518 | + * Resize the player to a new size |
| 1519 | + */ |
| 1520 | + resizePlayer: function( size , animate){ |
| 1521 | + this.width = size.width; |
| 1522 | + this.hegith = size.height; |
| 1523 | + if( animate ){ |
| 1524 | + $j(this).animate(size); |
| 1525 | + this.$interface.animate( size ); |
| 1526 | + }else{ |
| 1527 | + $j(this).css(size); |
| 1528 | + this.$interface.css( size ); |
| 1529 | + } |
| 1530 | + }, |
1518 | 1531 | |
1519 | 1532 | /** |
1520 | 1533 | * Get the player pixel width not including controls |
— | — | @@ -1812,7 +1825,7 @@ |
1813 | 1826 | * |
1814 | 1827 | * @return start_npt and end_npt time if present |
1815 | 1828 | */ |
1816 | | - getTimeRange: function() { |
| 1829 | + getTimeRange: function() { |
1817 | 1830 | var end_time = (this.controlBuilder.longTimeDisp)? '/' + mw.seconds2npt( this.getDuration() ) : ''; |
1818 | 1831 | var default_time_range = '0:00:00' + end_time; |
1819 | 1832 | if ( !this.mediaElement ) |
— | — | @@ -2720,6 +2733,7 @@ |
2721 | 2734 | if ( this.thumbnail_disp ) { |
2722 | 2735 | // already in stooped state |
2723 | 2736 | mw.log( 'already in stopped state' ); |
| 2737 | + this.controlBuilder.setStatus( this.getTimeRange() ); |
2724 | 2738 | } else { |
2725 | 2739 | // rewrite the html to thumbnail disp |
2726 | 2740 | this.showThumbnail(); |
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/mw.PlayerControlBuilder.js |
— | — | @@ -634,15 +634,17 @@ |
635 | 635 | if( ! this.embedPlayer.supports['overlays'] ){ |
636 | 636 | return false; |
637 | 637 | } |
638 | | - // If the config is false |
639 | | - if( mw.getConfig( 'EmbedPlayer.OverlayControls' ) == false){ |
640 | | - return false; |
641 | | - } |
642 | 638 | |
643 | 639 | // If disabled via the player |
644 | 640 | if( this.embedPlayer.overlayControls === false ){ |
645 | 641 | return false; |
646 | 642 | } |
| 643 | + |
| 644 | + // If the config is false |
| 645 | + if( mw.getConfig( 'EmbedPlayer.OverlayControls' ) == false){ |
| 646 | + return false; |
| 647 | + } |
| 648 | + |
647 | 649 | // don't hide controls when content "height" is 0 ( audio tags ) |
648 | 650 | if( this.embedPlayer.getPlayerHeight() == 0 ){ |
649 | 651 | return false; |
Index: branches/MwEmbedStandAlone/modules/SequenceEdit/loader.js |
— | — | @@ -0,0 +1,69 @@ |
| 2 | +/** |
| 3 | +* SequenceEdit loader |
| 4 | +*/ |
| 5 | + |
| 6 | +// Wrap in mw to not pollute global namespace |
| 7 | +( function( mw ) { |
| 8 | + mw.addResourcePaths( { |
| 9 | + |
| 10 | + "mw.SequenceEdit" : "mw.SequenceEdit.js", |
| 11 | + "mw.style.SequenceEdit" : "mw.style.SequenceEdit.css", |
| 12 | + "mw.SequenceEditPlayer" : "mw.SequenceEditPlayer.js", |
| 13 | + "mw.SequenceEditTimeline" : "mw.SequenceEditTimeline.js", |
| 14 | + "mw.SequenceEditKeyBindings" : "mw.SequenceEditKeyBindings.js", |
| 15 | + |
| 16 | + "mw.FirefoggRender" : "mw.FirefoggRender.js", |
| 17 | + "$j.fn.layout" : "ui.layout/ui.layout-1.2.0.js", |
| 18 | + |
| 19 | + "RemoteMwSequencer" : "remotes/RemoteMwSequencer.js", |
| 20 | + |
| 21 | + "mw.style.SequenceEdit" : "css/mw.style.SequenceEdit.css", |
| 22 | + |
| 23 | + "playlistEmbed" : "playlistEmbed.js" |
| 24 | + } ); |
| 25 | + |
| 26 | + /** |
| 27 | + * The FirefoggRender sub module |
| 28 | + */ |
| 29 | + mw.addModuleLoader( 'FirefoggRender', |
| 30 | + [ |
| 31 | + 'mw.Firefogg', |
| 32 | + 'mw.FirefoggRender', |
| 33 | + 'mw.UploadInterface' |
| 34 | + ] |
| 35 | + ); |
| 36 | + |
| 37 | + // SequenceEditor module loader |
| 38 | + mw.addModuleLoader( 'SequenceEdit', function( ) { |
| 39 | + // Make sure we have the required mwEmbed libs: |
| 40 | + return [ |
| 41 | + [ // Load the EmbedPlayer Module ( includes lots of dependent classes ) |
| 42 | + 'EmbedPlayer' |
| 43 | + ], |
| 44 | + [ |
| 45 | + '$j.contextMenu', |
| 46 | + 'mw.SequenceEdit', |
| 47 | + 'mw.SequenceEditPlayer', |
| 48 | + 'mw.SequenceEditTimeline', |
| 49 | + 'mw.SequenceEditKeyBindings', |
| 50 | + |
| 51 | + 'mw.style.SequenceEdit' |
| 52 | + ], |
| 53 | + [ |
| 54 | + '$j.fn.layout', |
| 55 | + // UI components used in the sequencer interface: |
| 56 | + '$j.ui.accordion', |
| 57 | + '$j.ui.dialog', |
| 58 | + '$j.ui.droppable', |
| 59 | + '$j.ui.draggable', |
| 60 | + '$j.ui.progressbar', |
| 61 | + '$j.ui.sortable', |
| 62 | + '$j.ui.resizable', |
| 63 | + '$j.ui.slider', |
| 64 | + '$j.ui.tabs' |
| 65 | + ] |
| 66 | + ]; |
| 67 | + }); |
| 68 | + |
| 69 | +} )( window.mw ); |
| 70 | + |
\ No newline at end of file |
Index: branches/MwEmbedStandAlone/modules/SequenceEdit/SequenceEdit.i18n.php |
— | — | @@ -0,0 +1,1219 @@ |
| 2 | +<?php |
| 3 | +/* |
| 4 | + * Internationalisation for SequenceEdit |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + */ |
| 9 | + |
| 10 | +$messages = array(); |
| 11 | +$messages['en'] = array( |
| 12 | + 'mwe-sequenceedit-loading_timeline' => 'Loading timeline ...', |
| 13 | + 'mwe-sequenceedit-loading_player' => 'Loading player...', |
| 14 | + 'mwe-sequenceedit-loading_edit' => 'Loading edit...', |
| 15 | + 'mwe-sequenceedit-no-sequence-start-new' => 'Empty sequence, [$1 browser for assets] to create a new sequence', |
| 16 | + 'mwe-sequenceedit-video-track' => 'Video track', |
| 17 | + 'mwe-sequenceedit-audio-track' => 'Audio track', |
| 18 | + |
| 19 | + 'mwe-sequenceedit-transition_in' => 'Transition in', |
| 20 | + 'mwe-sequenceedit-transition_out' => 'Transition out', |
| 21 | + 'mwe-sequenceedit-effects' => 'Effects stack', |
| 22 | + 'mwe-sequenceedit-remove_transition' => 'Remove transition', |
| 23 | + 'mwe-sequenceedit-edit_transin' => 'Edit transition into clip', |
| 24 | + 'mwe-sequenceedit-edit_transout' => 'Edit transition out of clip', |
| 25 | + 'mwe-sequenceedit-add-transition' => 'Add a transition', |
| 26 | + 'mwe-sequenceedit-menu_clipedit' => 'Edit media', |
| 27 | + 'mwe-sequenceedit-menu_transition' => 'Transitions and effects', |
| 28 | + 'mwe-sequenceedit-menu_cliplib' => 'Add media', |
| 29 | + 'mwe-sequenceedit-menu_resource_overview' => 'Resource overview', |
| 30 | + 'mwe-sequenceedit-menu_options' => 'Options', |
| 31 | + 'mwe-sequenceedit-loading_user_rights' => 'Loading user rights ...', |
| 32 | + 'mwe-sequenceedit-no_edit_permissions' => 'You do not have permissions to save changes to this sequence', |
| 33 | + 'mwe-sequenceedit-edit_clip' => 'Edit clip', |
| 34 | + 'mwe-sequenceedit-edit_save' => 'Save sequence changes', |
| 35 | + 'mwe-sequenceedit-saving_wait' => 'Save in progress (please wait)', |
| 36 | + 'mwe-sequenceedit-save_done' => 'Save complete', |
| 37 | + 'mwe-sequenceedit-edit_cancel' => 'Cancel sequence edit', |
| 38 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Are you sure you want to cancel your edit? Changes will be lost.', |
| 39 | + 'mwe-sequenceedit-zoom_in' => 'Zoom in', |
| 40 | + 'mwe-sequenceedit-zoom_out' => 'Zoom out', |
| 41 | + 'mwe-sequenceedit-cut_clip' => 'Cut clips', |
| 42 | + 'mwe-sequenceedit-expand_track' => 'Expand track', |
| 43 | + 'mwe-sequenceedit-collapse_track' => 'Collapse track', |
| 44 | + 'mwe-sequenceedit-play_from_position' => 'Play from playline position', |
| 45 | + 'mwe-sequenceedit-pixle2sec' => 'pixels to seconds', |
| 46 | + 'mwe-sequenceedit-rmclip' => 'Remove clip', |
| 47 | + 'mwe-sequenceedit-clip_in' => 'clip in', |
| 48 | + 'mwe-sequenceedit-clip_out' => 'clip out', |
| 49 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>No resource selected</h3> Select a clip to enable editing.', |
| 50 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Multiple resources selected</h3> Select a single clip to edit it.', |
| 51 | + 'mwe-sequenceedit-editor_options' => 'Editor options', |
| 52 | + 'mwe-sequenceedit-editor_mode' => 'Editor mode', |
| 53 | + 'mwe-sequenceedit-simple_editor_desc' => 'simple editor (iMovie style)', |
| 54 | + 'mwe-sequenceedit-advanced_editor_desc' => 'advanced editor (Final Cut style)', |
| 55 | + 'mwe-sequenceedit-other_options' => 'Other options', |
| 56 | + 'mwe-sequenceedit-contextmenu_opt' => 'Enable context menus', |
| 57 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Developed by [$1 Kaltura, Inc] in partnership with the [$1 Wikimedia Foundation]', |
| 58 | + 'mwe-sequenceedit-sequence-create-one' => 'Nostart a sequence', |
| 59 | +); |
| 60 | +$messages['af'] = array( |
| 61 | + 'mwe-sequenceedit-menu_options' => 'Opsies', |
| 62 | + 'mwe-sequenceedit-other_options' => 'Ander opsies', |
| 63 | +); |
| 64 | +$messages['ar'] = array( |
| 65 | + 'mwe-sequenceedit-remove_transition' => 'أزل الترجمة', |
| 66 | + 'mwe-sequenceedit-edit_transin' => 'عدّل الترجمة في المقطع', |
| 67 | + 'mwe-sequenceedit-edit_transout' => 'عدّل الترجمة خارج المقطع', |
| 68 | + 'mwe-sequenceedit-menu_clipedit' => 'حرّر الوسيط', |
| 69 | + 'mwe-sequenceedit-menu_transition' => 'ترجمات ومؤثرات', |
| 70 | + 'mwe-sequenceedit-menu_cliplib' => 'أضف وسيطًا', |
| 71 | + 'mwe-sequenceedit-menu_options' => 'خيارات', |
| 72 | + 'mwe-sequenceedit-loading_timeline' => 'يحمل الشريط الزمني...', |
| 73 | + 'mwe-sequenceedit-loading_user_rights' => 'يحمل صلاحيات المستخدم...', |
| 74 | + 'mwe-sequenceedit-edit_clip' => 'حرّر المقطع', |
| 75 | + 'mwe-sequenceedit-saving_wait' => 'الحفظ قيد التنفيذ (من فضلك انتظر)', |
| 76 | + 'mwe-sequenceedit-save_done' => 'اكتمل الحفظ', |
| 77 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'أمتأكد من أنك تريد إلغاء تعديلك؟ سوف تضيع التعديلات.', |
| 78 | + 'mwe-sequenceedit-zoom_in' => 'قرّب', |
| 79 | + 'mwe-sequenceedit-zoom_out' => 'بعّد', |
| 80 | + 'mwe-sequenceedit-expand_track' => 'وسّع المقطوعة', |
| 81 | + 'mwe-sequenceedit-collapse_track' => 'اطوِ المقطوعة', |
| 82 | + 'mwe-sequenceedit-rmclip' => 'أزل المقطع', |
| 83 | + 'mwe-sequenceedit-editor_options' => 'خيارات المحرر', |
| 84 | + 'mwe-sequenceedit-editor_mode' => 'وضع المحرّر', |
| 85 | + 'mwe-sequenceedit-simple_editor_desc' => 'مُحرّر بسيط (على نمط iMovie)', |
| 86 | + 'mwe-sequenceedit-other_options' => 'خيارات أخرى', |
| 87 | +); |
| 88 | +$messages['be-tarask'] = array( |
| 89 | + 'mwe-sequenceedit-transition_in' => 'Пераход у', |
| 90 | + 'mwe-sequenceedit-transition_out' => 'Пераход з', |
| 91 | + 'mwe-sequenceedit-effects' => 'Набор эфэктаў', |
| 92 | + 'mwe-sequenceedit-remove_transition' => 'Выдаліць пераход', |
| 93 | + 'mwe-sequenceedit-edit_transin' => 'Рэдагаваць пераход у частку файла', |
| 94 | + 'mwe-sequenceedit-edit_transout' => 'Рэдагаваць пераход з часткі файла', |
| 95 | + 'mwe-sequenceedit-add-transition' => 'Дадаць пераход', |
| 96 | + 'mwe-sequenceedit-menu_clipedit' => 'Рэдагаваць мэдыя', |
| 97 | + 'mwe-sequenceedit-menu_transition' => 'Пераходы і эфэкты', |
| 98 | + 'mwe-sequenceedit-menu_cliplib' => 'Дадаць мэдыя', |
| 99 | + 'mwe-sequenceedit-menu_resource_overview' => 'Агляд рэсурсаў', |
| 100 | + 'mwe-sequenceedit-menu_options' => 'Устаноўкі', |
| 101 | + 'mwe-sequenceedit-loading_timeline' => 'Загрузка шкалы часу ...', |
| 102 | + 'mwe-sequenceedit-loading_user_rights' => 'Загрузка правоў удзельніка ...', |
| 103 | + 'mwe-sequenceedit-no_edit_permissions' => 'Вы ня маеце правоў для захаваньня зьменаў у гэтай пасьлядоўнасьці', |
| 104 | + 'mwe-sequenceedit-edit_clip' => 'Рэдагаваць частку файла', |
| 105 | + 'mwe-sequenceedit-edit_save' => 'Захаваць зьмены пасьлядоўнасьці', |
| 106 | + 'mwe-sequenceedit-saving_wait' => 'Захаваньне зьдзяйсьняецца (калі ласка, пачакайце)', |
| 107 | + 'mwe-sequenceedit-save_done' => 'Захаваньне скончанае', |
| 108 | + 'mwe-sequenceedit-edit_cancel' => 'Адмяніць рэдагаваньне пасьлядоўнасьці', |
| 109 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Вы ўпэўнены, што жадаеце адмяніць Вашае рэдагаваньне? Зьмены будуць страчаныя.', |
| 110 | + 'mwe-sequenceedit-zoom_in' => 'Павялічыць', |
| 111 | + 'mwe-sequenceedit-zoom_out' => 'Паменшыць', |
| 112 | + 'mwe-sequenceedit-cut_clip' => 'Кадраваньне кліпаў', |
| 113 | + 'mwe-sequenceedit-expand_track' => 'Павялічыць сьцежку', |
| 114 | + 'mwe-sequenceedit-collapse_track' => 'Паменшыць сьцежку', |
| 115 | + 'mwe-sequenceedit-play_from_position' => 'Прайграваць з цяперашняй пазыцыі', |
| 116 | + 'mwe-sequenceedit-pixle2sec' => 'піксэлі ў сэкундах', |
| 117 | + 'mwe-sequenceedit-rmclip' => 'Выдаліць частку файла', |
| 118 | + 'mwe-sequenceedit-clip_in' => 'дадаць кліп', |
| 119 | + 'mwe-sequenceedit-clip_out' => 'выдаліць кліп', |
| 120 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Рэсурс не выбраны</h3> Выберыце частку файла для уключэньня рэдагаваньня.', |
| 121 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Выбраныя некалькі рэсурсаў</h3> Выберыце адну частку файла для яе рэдагаваньня.', |
| 122 | + 'mwe-sequenceedit-editor_options' => 'Устаноўкі рэдактара', |
| 123 | + 'mwe-sequenceedit-editor_mode' => 'Рэжым рэдактара', |
| 124 | + 'mwe-sequenceedit-simple_editor_desc' => 'просты рэдактар (стыль iMovie)', |
| 125 | + 'mwe-sequenceedit-advanced_editor_desc' => 'палепшаны рэдактар (стыль Final Cut)', |
| 126 | + 'mwe-sequenceedit-other_options' => 'Іншыя ўстаноўкі', |
| 127 | + 'mwe-sequenceedit-contextmenu_opt' => 'Дазволіць кантэкстныя мэню', |
| 128 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Распрацавана <a href="http://kaltura.com">Kaltura, Inc.</a> у садружнасьці з <a href="http://wikimediafoundation.org/wiki/Home">фундацыяй «Вікімэдыя»</a> (<a href="#">падрабязнасьці </a>).', |
| 129 | +); |
| 130 | +$messages['br'] = array( |
| 131 | + 'mwe-sequenceedit-menu_clipedit' => 'Aozañ ar media', |
| 132 | + 'mwe-sequenceedit-menu_cliplib' => 'Ouzhpennañ ur media', |
| 133 | + 'mwe-sequenceedit-menu_options' => 'Dibarzhioù', |
| 134 | + 'mwe-sequenceedit-edit_clip' => 'Aozañ ar c\'hlip', |
| 135 | + 'mwe-sequenceedit-save_done' => 'Echu eo an enrollañ', |
| 136 | + 'mwe-sequenceedit-zoom_in' => 'Zoumiñ', |
| 137 | + 'mwe-sequenceedit-zoom_out' => 'Dizoumiñ', |
| 138 | + 'mwe-sequenceedit-rmclip' => 'Dilemel ar c\'hlip', |
| 139 | + 'mwe-sequenceedit-editor_options' => 'Dibarzhioù an aozer', |
| 140 | + 'mwe-sequenceedit-simple_editor_desc' => 'aozer eeun (stil iMovie)', |
| 141 | + 'mwe-sequenceedit-other_options' => 'Dibarzhioù all', |
| 142 | +); |
| 143 | +$messages['bs'] = array( |
| 144 | + 'mwe-sequenceedit-remove_transition' => 'Ukloni prelazak', |
| 145 | + 'mwe-sequenceedit-add-transition' => 'Dodaj prijelaz', |
| 146 | + 'mwe-sequenceedit-menu_clipedit' => 'Uredi mediju', |
| 147 | + 'mwe-sequenceedit-menu_transition' => 'Prijelazi i efekti', |
| 148 | + 'mwe-sequenceedit-menu_cliplib' => 'Dodaj mediju', |
| 149 | + 'mwe-sequenceedit-menu_resource_overview' => 'Pregled resursa', |
| 150 | + 'mwe-sequenceedit-menu_options' => 'Opcije', |
| 151 | + 'mwe-sequenceedit-loading_timeline' => 'Učitavanje vremenske linije ...', |
| 152 | + 'mwe-sequenceedit-loading_user_rights' => 'Učitavanje korisničkih prava ...', |
| 153 | + 'mwe-sequenceedit-no_edit_permissions' => 'Nemate dopuštenja da spremite izmjene ove sekvence', |
| 154 | + 'mwe-sequenceedit-edit_clip' => 'Uredi isječak', |
| 155 | + 'mwe-sequenceedit-edit_save' => 'Spremi izmjene sekvence', |
| 156 | + 'mwe-sequenceedit-saving_wait' => 'Spremanje u toku (molimo pričekajte)', |
| 157 | + 'mwe-sequenceedit-save_done' => 'Spremanje završeno', |
| 158 | + 'mwe-sequenceedit-edit_cancel' => 'Odustani od uređivanja sekvence', |
| 159 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Da li ste sigurni da želite odustati od Vašeg uređivanja? Izmjene će biti izgubljene.', |
| 160 | + 'mwe-sequenceedit-zoom_in' => 'Približi', |
| 161 | + 'mwe-sequenceedit-zoom_out' => 'Udalji', |
| 162 | + 'mwe-sequenceedit-cut_clip' => 'Rezanje isječaka', |
| 163 | + 'mwe-sequenceedit-expand_track' => 'Proširi traku', |
| 164 | + 'mwe-sequenceedit-collapse_track' => 'Smanji traku', |
| 165 | + 'mwe-sequenceedit-pixle2sec' => 'pikseli u sekunde', |
| 166 | + 'mwe-sequenceedit-rmclip' => 'Ukloni isječak', |
| 167 | + 'mwe-sequenceedit-editor_options' => 'Opcije uređivača', |
| 168 | + 'mwe-sequenceedit-editor_mode' => 'Način uređivanja', |
| 169 | + 'mwe-sequenceedit-simple_editor_desc' => 'jednostavni uređivač (iMovie stil)', |
| 170 | + 'mwe-sequenceedit-advanced_editor_desc' => 'napredni uređivač (Final Cut stil)', |
| 171 | + 'mwe-sequenceedit-other_options' => 'Ostale opcije', |
| 172 | + 'mwe-sequenceedit-contextmenu_opt' => 'Omogući kontekstne menije', |
| 173 | +); |
| 174 | +$messages['de'] = array( |
| 175 | + 'mwe-sequenceedit-transition_in' => 'Übergang ein', |
| 176 | + 'mwe-sequenceedit-transition_out' => 'Übergang aus', |
| 177 | + 'mwe-sequenceedit-remove_transition' => 'Übergang entfernen', |
| 178 | + 'mwe-sequenceedit-menu_transition' => 'Übergänge und Effekte', |
| 179 | + 'mwe-sequenceedit-menu_resource_overview' => 'Quellübersicht', |
| 180 | + 'mwe-sequenceedit-menu_options' => 'Optionen', |
| 181 | + 'mwe-sequenceedit-loading_timeline' => 'Lade Zeitleiste …', |
| 182 | + 'mwe-sequenceedit-loading_user_rights' => 'Lade Benutzerrechte …', |
| 183 | + 'mwe-sequenceedit-no_edit_permissions' => 'Du hast keine Berechtigungen, Änderungen zu dieser Sequenz zu speichern', |
| 184 | + 'mwe-sequenceedit-edit_clip' => 'Clip bearbeiten', |
| 185 | + 'mwe-sequenceedit-edit_save' => 'Sequenzänderungen speichern', |
| 186 | + 'mwe-sequenceedit-saving_wait' => 'Speichere (bitte warten)', |
| 187 | + 'mwe-sequenceedit-save_done' => 'Speicherung fertig', |
| 188 | + 'mwe-sequenceedit-edit_cancel' => 'Sequenzbearbeitung abbrechen', |
| 189 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Bist du sicher, dass du deine Bearbeitung abbrechen willst? Änderungen gehen verloren.', |
| 190 | + 'mwe-sequenceedit-zoom_in' => 'Vergrößern', |
| 191 | + 'mwe-sequenceedit-zoom_out' => 'Verkleinern', |
| 192 | + 'mwe-sequenceedit-cut_clip' => 'Clips schneiden', |
| 193 | + 'mwe-sequenceedit-expand_track' => 'Spur ausklappen', |
| 194 | + 'mwe-sequenceedit-collapse_track' => 'Spur einklappen', |
| 195 | + 'mwe-sequenceedit-play_from_position' => 'Abspielen ab Playline-Position', |
| 196 | + 'mwe-sequenceedit-rmclip' => 'Clip entfernen', |
| 197 | + 'mwe-sequenceedit-clip_in' => 'Clip hinzufügen', |
| 198 | + 'mwe-sequenceedit-clip_out' => 'Clip entfernen', |
| 199 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Keine Quelle ausgewählt</h3> Wähle einen Clip aus, um das Bearbeiten zu aktivieren.', |
| 200 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Mehrere Quellen ausgewählt</h3> Wähle nur einen Clip aus, um ihn zu bearbeiten.', |
| 201 | + 'mwe-sequenceedit-editor_options' => 'Editoroptionen', |
| 202 | + 'mwe-sequenceedit-editor_mode' => 'Editormodus', |
| 203 | + 'mwe-sequenceedit-simple_editor_desc' => 'einfacher Editor (iMovie-Stil)', |
| 204 | + 'mwe-sequenceedit-advanced_editor_desc' => 'erweiterter Editor (Final-Cut-Stil)', |
| 205 | + 'mwe-sequenceedit-other_options' => 'Andere Optionen', |
| 206 | + 'mwe-sequenceedit-contextmenu_opt' => 'Kontextmenüs aktivieren', |
| 207 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Entwickelt von <a href="http://kaltura.com">Kaltura, Inc.</a> in Zusammenarbeit mit der <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">mehr Informationen</a>).', |
| 208 | +); |
| 209 | +$messages['diq'] = array( |
| 210 | + 'mwe-sequenceedit-transition_in' => 'dekewtış', |
| 211 | + 'mwe-sequenceedit-transition_out' => 'teber kewtış', |
| 212 | + 'mwe-sequenceedit-effects' => 'loda (kopê) efekti', |
| 213 | + 'mwe-sequenceedit-remove_transition' => 'raviyertış wedar/werad', |
| 214 | + 'mwe-sequenceedit-edit_transin' => 'şiyayişê klibi bıvurn', |
| 215 | + 'mwe-sequenceedit-edit_transout' => 'klip ra şliyayiş bıvurn', |
| 216 | + 'mwe-sequenceedit-add-transition' => 'Yew çarnayiş de bike', |
| 217 | + 'mwe-sequenceedit-menu_clipedit' => 'medya bıvurn', |
| 218 | + 'mwe-sequenceedit-menu_transition' => 'efekt u raviyertışi', |
| 219 | + 'mwe-sequenceedit-menu_cliplib' => 'medya têarê ker', |
| 220 | + 'mwe-sequenceedit-menu_resource_overview' => 'Resource overview', |
| 221 | + 'mwe-sequenceedit-menu_options' => 'tercihi', |
| 222 | + 'mwe-sequenceedit-loading_timeline' => 'Loading timeline ...', |
| 223 | + 'mwe-sequenceedit-loading_user_rights' => 'heqê karberi bar bêni', |
| 224 | + 'mwe-sequenceedit-no_edit_permissions' => 'şıma nêşkeni vuriyayişan no rêzkerdışi re qeyd bıkeri', |
| 225 | + 'mwe-sequenceedit-edit_clip' => 'klib bıvurn', |
| 226 | + 'mwe-sequenceedit-edit_save' => 'vuriyayişanê rêzkerdışan qeyd bıker', |
| 227 | + 'mwe-sequenceedit-saving_wait' => 'qeyd kerdış dewam keno ( kerem kerê vınderê)', |
| 228 | + 'mwe-sequenceedit-save_done' => 'qeyd kerdış temam bı', |
| 229 | + 'mwe-sequenceedit-edit_cancel' => 'vuriyayişê rêzbiyayişi iptal bıker', |
| 230 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'şıma raşta wazeni vurnayişanê xo iptal ker? vuriyayişi vindibeni', |
| 231 | + 'mwe-sequenceedit-zoom_in' => 'biyar nızdi (zoom ker)', |
| 232 | + 'mwe-sequenceedit-zoom_out' => 'dûr ker (zoom meker)', |
| 233 | + 'mwe-sequenceedit-cut_clip' => 'kliban bıqesn', |
| 234 | + 'mwe-sequenceedit-expand_track' => 'reç hêra ker', |
| 235 | + 'mwe-sequenceedit-collapse_track' => 'reç teng ker', |
| 236 | + 'mwe-sequenceedit-play_from_position' => 'bı serê xetê kaydayiş ra bıd\' kaydayış', |
| 237 | + 'mwe-sequenceedit-pixle2sec' => 'piksel re saniye', |
| 238 | + 'mwe-sequenceedit-rmclip' => 'klib wedar/werad', |
| 239 | + 'mwe-sequenceedit-clip_in' => 'zerre re klib', |
| 240 | + 'mwe-sequenceedit-clip_out' => 'teber re klib', |
| 241 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>çı çıme nêvıciya</h3> qey aktifkerdışê vurnayişi yew klib bıvıcinê.', |
| 242 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>yew ra zêd çıme vıciya</h3> qey vurnayişi yew klib bıvıcinê.', |
| 243 | + 'mwe-sequenceedit-editor_options' => 'tercihê editori', |
| 244 | + 'mwe-sequenceedit-editor_mode' => 'modê editori', |
| 245 | + 'mwe-sequenceedit-simple_editor_desc' => 'editoro basit (bı stilê imovie\'yi)', |
| 246 | + 'mwe-sequenceedit-advanced_editor_desc' => 'editoro dewlemend (bı stilê final cut\'i)', |
| 247 | + 'mwe-sequenceedit-other_options' => 'tercihê bini', |
| 248 | + 'mwe-sequenceedit-contextmenu_opt' => 'menuyê muhtewayan aktif bıker', |
| 249 | + 'mwe-sequenceedit-sequencer_credit_line' => 'hetê <a href="http://kaltura.com">Kaltura, Inc.</a>yi ra pê ortaxiyê <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">qey malumato zêd</a>)yi dewlemend biyo.', |
| 250 | +); |
| 251 | +$messages['dsb'] = array( |
| 252 | + 'mwe-sequenceedit-transition_in' => 'Zablendowanje', |
| 253 | + 'mwe-sequenceedit-transition_out' => 'Wublendowanje', |
| 254 | + 'mwe-sequenceedit-effects' => 'Skład efektow', |
| 255 | + 'mwe-sequenceedit-remove_transition' => 'Pśechad wótpóraś', |
| 256 | + 'mwe-sequenceedit-edit_transin' => 'Zablendowanje do klipa wobźěłaś', |
| 257 | + 'mwe-sequenceedit-edit_transout' => 'Wublendowanje z klipa wobźěłaś', |
| 258 | + 'mwe-sequenceedit-add-transition' => 'Pśechad pśidaś', |
| 259 | + 'mwe-sequenceedit-menu_clipedit' => 'Medije wobźěłaś', |
| 260 | + 'mwe-sequenceedit-menu_transition' => 'Pśechady a efekty', |
| 261 | + 'mwe-sequenceedit-menu_cliplib' => 'Medije pśidaś', |
| 262 | + 'mwe-sequenceedit-menu_resource_overview' => 'Pśeglěd resursow', |
| 263 | + 'mwe-sequenceedit-menu_options' => 'Opcije', |
| 264 | + 'mwe-sequenceedit-loading_timeline' => 'Casowu ceru zacytaś ...', |
| 265 | + 'mwe-sequenceedit-loading_user_rights' => 'Wužywarske pšawa se zacytuju ...', |
| 266 | + 'mwe-sequenceedit-no_edit_permissions' => 'Njamaš pšawa, aby změny na toś tej sekwency składował.', |
| 267 | + 'mwe-sequenceedit-edit_clip' => 'Klip wobźěłaś', |
| 268 | + 'mwe-sequenceedit-edit_save' => 'Sekwencowe změny składowaś', |
| 269 | + 'mwe-sequenceedit-saving_wait' => 'Składujo se rowno (pšosym cakaj)', |
| 270 | + 'mwe-sequenceedit-save_done' => 'Składowanje dokóńcone', |
| 271 | + 'mwe-sequenceedit-edit_cancel' => 'Wobźěłanje sekwence pśetergnuś', |
| 272 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Coš napšawdu swójo wobźěłanje pśetergnuś? Změny se zgubiju.', |
| 273 | + 'mwe-sequenceedit-zoom_in' => 'Pówětšyś', |
| 274 | + 'mwe-sequenceedit-zoom_out' => 'Pómjeńšyś', |
| 275 | + 'mwe-sequenceedit-cut_clip' => 'Klipy stśigaś', |
| 276 | + 'mwe-sequenceedit-expand_track' => 'Ceru wuklapnuś', |
| 277 | + 'mwe-sequenceedit-collapse_track' => 'Ceru złožyś', |
| 278 | + 'mwe-sequenceedit-play_from_position' => 'Wót pozicije wótegraś', |
| 279 | + 'mwe-sequenceedit-pixle2sec' => 'piksele do sekundow', |
| 280 | + 'mwe-sequenceedit-rmclip' => 'Klip wótpóraś', |
| 281 | + 'mwe-sequenceedit-clip_in' => 'Klip pśidaś', |
| 282 | + 'mwe-sequenceedit-clip_out' => 'Klip wótpóraś', |
| 283 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Žedna resursa wubrana</h3> Wubjeŕ klip, aby zmóžnił wobźěłowanje.', |
| 284 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Někotare resurse wubrane</h3> Wubjeŕ jadnotliwy klip, aby jen wobźěłał.', |
| 285 | + 'mwe-sequenceedit-editor_options' => 'Editorowe opcije', |
| 286 | + 'mwe-sequenceedit-editor_mode' => 'Editorowy modus', |
| 287 | + 'mwe-sequenceedit-simple_editor_desc' => 'jadnory editor (stil iMovie)', |
| 288 | + 'mwe-sequenceedit-advanced_editor_desc' => 'rozšyrjony editor (stil Final Cut)', |
| 289 | + 'mwe-sequenceedit-other_options' => 'Druge opcije', |
| 290 | + 'mwe-sequenceedit-contextmenu_opt' => 'Kontekstowe menije zmóžniś', |
| 291 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Wuwity wót <a href="http://kaltura.com">Kaltura, Inc.</a> gromaźe ze załožbu <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">dalšne informacije</a>).', |
| 292 | +); |
| 293 | +$messages['el'] = array( |
| 294 | + 'mwe-sequenceedit-transition_in' => 'Ταχύτητα μέσα', |
| 295 | + 'mwe-sequenceedit-transition_out' => 'Ταχύτητα έξω', |
| 296 | + 'mwe-sequenceedit-remove_transition' => 'Αφαίρεση ταχύτητας', |
| 297 | + 'mwe-sequenceedit-menu_clipedit' => 'Επεξεργασία μέσου', |
| 298 | + 'mwe-sequenceedit-menu_cliplib' => 'Προσθήκη μέσου', |
| 299 | + 'mwe-sequenceedit-menu_resource_overview' => 'Επισκόπηση πηγής', |
| 300 | + 'mwe-sequenceedit-menu_options' => 'Επιλογές', |
| 301 | + 'mwe-sequenceedit-loading_timeline' => 'Φορτώνει η χρονολογία ...', |
| 302 | + 'mwe-sequenceedit-loading_user_rights' => 'Φορτώνουν τα δικαιώματα χρήστη ...', |
| 303 | + 'mwe-sequenceedit-edit_clip' => 'Επεξεργασία κλιπ', |
| 304 | + 'mwe-sequenceedit-edit_save' => 'Αποθήκευση αλλαγών ακολουθίας', |
| 305 | + 'mwe-sequenceedit-saving_wait' => 'Αποθήκευση σε εξέλιξη (παρακαλώ περιμένετε)', |
| 306 | + 'mwe-sequenceedit-save_done' => 'Η αποθήκευση ολοκληρώθηκε', |
| 307 | + 'mwe-sequenceedit-edit_cancel' => 'Ακύρωση επεξεργασίας ακολουθίας', |
| 308 | + 'mwe-sequenceedit-zoom_in' => 'Μεγέθυνση', |
| 309 | + 'mwe-sequenceedit-zoom_out' => 'Σμίκρυνση', |
| 310 | + 'mwe-sequenceedit-pixle2sec' => 'πίξελ ανά δευτερόλεπτα', |
| 311 | + 'mwe-sequenceedit-rmclip' => 'Αφαίρεση κλιπ', |
| 312 | + 'mwe-sequenceedit-editor_options' => 'Επιλογές επεξεργαστή', |
| 313 | + 'mwe-sequenceedit-editor_mode' => 'Λειτουργία επεξεργαστή', |
| 314 | + 'mwe-sequenceedit-simple_editor_desc' => 'απλός επεξεργαστής (iMovie στυλ)', |
| 315 | + 'mwe-sequenceedit-advanced_editor_desc' => 'προχωρημένος επεξεργαστής (Final Cut στυλ)', |
| 316 | + 'mwe-sequenceedit-other_options' => 'Άλλες επιλογές', |
| 317 | +); |
| 318 | +$messages['eo'] = array( |
| 319 | + 'mwe-sequenceedit-menu_options' => 'Agordoj', |
| 320 | + 'mwe-sequenceedit-zoom_in' => 'Zomi', |
| 321 | + 'mwe-sequenceedit-zoom_out' => 'Malzomi', |
| 322 | + 'mwe-sequenceedit-editor_options' => 'Opcioj por redaktilo', |
| 323 | + 'mwe-sequenceedit-editor_mode' => 'Redakta reĝimo', |
| 324 | + 'mwe-sequenceedit-other_options' => 'Aliaj agordoj', |
| 325 | +); |
| 326 | +$messages['es'] = array( |
| 327 | + 'mwe-sequenceedit-transition_in' => 'Transición de entrada', |
| 328 | + 'mwe-sequenceedit-transition_out' => 'Transición de salida', |
| 329 | + 'mwe-sequenceedit-effects' => 'Pila de efectos', |
| 330 | + 'mwe-sequenceedit-remove_transition' => 'Remover transición', |
| 331 | + 'mwe-sequenceedit-edit_transin' => 'Editar la transición en el clip', |
| 332 | + 'mwe-sequenceedit-edit_transout' => 'Editar la transición fuera del clip', |
| 333 | + 'mwe-sequenceedit-add-transition' => 'Añadir una transición', |
| 334 | + 'mwe-sequenceedit-menu_clipedit' => 'Editar medios', |
| 335 | + 'mwe-sequenceedit-menu_transition' => 'Transiciones y efectos', |
| 336 | + 'mwe-sequenceedit-menu_cliplib' => 'Agregar medios', |
| 337 | + 'mwe-sequenceedit-menu_options' => 'Opciones', |
| 338 | + 'mwe-sequenceedit-loading_timeline' => 'Cargando línea temporal...', |
| 339 | + 'mwe-sequenceedit-loading_user_rights' => 'Cargando derechos de usuario...', |
| 340 | + 'mwe-sequenceedit-no_edit_permissions' => 'No tienes permisos para grabar cambios a esta secuencia', |
| 341 | + 'mwe-sequenceedit-edit_clip' => 'Editar clip', |
| 342 | + 'mwe-sequenceedit-edit_save' => 'Grabar cambios de secuencia', |
| 343 | + 'mwe-sequenceedit-saving_wait' => 'Grabado en proceso (por favor espere)', |
| 344 | + 'mwe-sequenceedit-save_done' => 'Grabar completo', |
| 345 | + 'mwe-sequenceedit-edit_cancel' => 'Cancelar edición de secuencia', |
| 346 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Estás seguro que deseas cancelar tu edición? Los cambios se perderán.', |
| 347 | + 'mwe-sequenceedit-zoom_in' => 'Agrandar', |
| 348 | + 'mwe-sequenceedit-zoom_out' => 'Achicar', |
| 349 | + 'mwe-sequenceedit-cut_clip' => 'Cortar clips', |
| 350 | + 'mwe-sequenceedit-expand_track' => 'Expandir la pista', |
| 351 | + 'mwe-sequenceedit-collapse_track' => 'Contraer la pista', |
| 352 | + 'mwe-sequenceedit-pixle2sec' => 'píxeles a segundos', |
| 353 | + 'mwe-sequenceedit-rmclip' => 'Remover clip', |
| 354 | + 'mwe-sequenceedit-editor_options' => 'Opciones de editor', |
| 355 | + 'mwe-sequenceedit-editor_mode' => 'Modo editor', |
| 356 | + 'mwe-sequenceedit-simple_editor_desc' => 'editor simple(estilo iMovie)', |
| 357 | + 'mwe-sequenceedit-advanced_editor_desc' => 'editor avanzado (estilo Final Cut)', |
| 358 | + 'mwe-sequenceedit-other_options' => 'Otras opciones', |
| 359 | + 'mwe-sequenceedit-contextmenu_opt' => 'Habilitar menúes contextuales', |
| 360 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Desarrollado por <a href="http://kaltura.com">Kaltura, Inc.</a> en asociación con <a href="http://wikimediafoundation.org/wiki/Home">Fundación Wikimedia</a> (<a href="#">más información</a>).', |
| 361 | +); |
| 362 | +$messages['fi'] = array( |
| 363 | + 'mwe-sequenceedit-menu_options' => 'Asetukset', |
| 364 | + 'mwe-sequenceedit-simple_editor_desc' => 'yksinkertainen editori (iMovie-tyyli)', |
| 365 | + 'mwe-sequenceedit-other_options' => 'Muut valinnat', |
| 366 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Kehittänyt <a href="http://kaltura.com">Kaltura, Inc.</a> yhteistyössä <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundationin</a> kanssa (<a href="#">lisätietoja</a>).', |
| 367 | +); |
| 368 | +$messages['fr'] = array( |
| 369 | + 'mwe-sequenceedit-transition_in' => 'Transition entrante', |
| 370 | + 'mwe-sequenceedit-transition_out' => 'Transition sortante', |
| 371 | + 'mwe-sequenceedit-effects' => 'Pile d\'effets', |
| 372 | + 'mwe-sequenceedit-remove_transition' => 'Supprimer la transition', |
| 373 | + 'mwe-sequenceedit-edit_transin' => 'Modifier la transition vers le clip', |
| 374 | + 'mwe-sequenceedit-edit_transout' => 'Modifier la transition hors du clip', |
| 375 | + 'mwe-sequenceedit-add-transition' => 'Ajouter une traduction', |
| 376 | + 'mwe-sequenceedit-menu_clipedit' => 'Modifier le media', |
| 377 | + 'mwe-sequenceedit-menu_transition' => 'Transitions et effets', |
| 378 | + 'mwe-sequenceedit-menu_cliplib' => 'Ajouter un media', |
| 379 | + 'mwe-sequenceedit-menu_resource_overview' => 'Vue d\'ensemble de la ressource', |
| 380 | + 'mwe-sequenceedit-menu_options' => 'Options', |
| 381 | + 'mwe-sequenceedit-loading_timeline' => 'Chargement de la chronologie ...', |
| 382 | + 'mwe-sequenceedit-loading_user_rights' => 'Chargement des droits d\'utilisateur ...', |
| 383 | + 'mwe-sequenceedit-no_edit_permissions' => 'Vous n\'avez pas l\'autorisation de sauvegarder les changements apportés à cette séquence', |
| 384 | + 'mwe-sequenceedit-edit_clip' => 'Modifier le clip', |
| 385 | + 'mwe-sequenceedit-edit_save' => 'Sauvegarder les modifications de la séquence', |
| 386 | + 'mwe-sequenceedit-saving_wait' => 'Sauvegarde en cours (veuillez patienter)', |
| 387 | + 'mwe-sequenceedit-save_done' => 'Sauvegarde terminée', |
| 388 | + 'mwe-sequenceedit-edit_cancel' => 'Annuler la modification de la séquence', |
| 389 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Êtes-vous sûr de vouloir annuler votre modification ? Les changements seront perdus.', |
| 390 | + 'mwe-sequenceedit-zoom_in' => 'Zoom avant', |
| 391 | + 'mwe-sequenceedit-zoom_out' => 'Zoom arrière', |
| 392 | + 'mwe-sequenceedit-cut_clip' => 'Couper les clips', |
| 393 | + 'mwe-sequenceedit-expand_track' => 'Étendre la piste', |
| 394 | + 'mwe-sequenceedit-collapse_track' => 'Réduire la piste', |
| 395 | + 'mwe-sequenceedit-play_from_position' => 'Lire à partir de la position de lecture', |
| 396 | + 'mwe-sequenceedit-pixle2sec' => 'pixels vers secondes', |
| 397 | + 'mwe-sequenceedit-rmclip' => 'Supprimer le clip', |
| 398 | + 'mwe-sequenceedit-clip_in' => 'attacher', |
| 399 | + 'mwe-sequenceedit-clip_out' => 'détacher', |
| 400 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Aucune ressource sélectionnée</h3> Sélectionnez un clip pour activer l\'édition', |
| 401 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Plusieurs ressources sélectionnées</h3> Sélectionnez un seul clip pour le modifier', |
| 402 | + 'mwe-sequenceedit-editor_options' => 'Options de l\'éditeur', |
| 403 | + 'mwe-sequenceedit-editor_mode' => 'Mode de l\'éditeur', |
| 404 | + 'mwe-sequenceedit-simple_editor_desc' => 'éditeur simple (style iMovie)', |
| 405 | + 'mwe-sequenceedit-advanced_editor_desc' => 'éditeur avancé (style Final Cut)', |
| 406 | + 'mwe-sequenceedit-other_options' => 'Autres options', |
| 407 | + 'mwe-sequenceedit-contextmenu_opt' => 'Activer les menus contextuels', |
| 408 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Développé par <a href="http://kaltura.com">Kaltura, Inc.</a> en partenariat avec la <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">plus d\'information</a>).', |
| 409 | +); |
| 410 | +$messages['gl'] = array( |
| 411 | + 'mwe-sequenceedit-transition_in' => 'Transición de entrada', |
| 412 | + 'mwe-sequenceedit-transition_out' => 'Transición de saída', |
| 413 | + 'mwe-sequenceedit-effects' => 'Pila de efectos', |
| 414 | + 'mwe-sequenceedit-remove_transition' => 'Eliminar a transición', |
| 415 | + 'mwe-sequenceedit-edit_transin' => 'Editar a transición no vídeo', |
| 416 | + 'mwe-sequenceedit-edit_transout' => 'Editar a transición fóra do vídeo', |
| 417 | + 'mwe-sequenceedit-add-transition' => 'Engadir unha transición', |
| 418 | + 'mwe-sequenceedit-menu_clipedit' => 'Editar o soporte', |
| 419 | + 'mwe-sequenceedit-menu_transition' => 'Transicións e efectos', |
| 420 | + 'mwe-sequenceedit-menu_cliplib' => 'Engadir un soporte', |
| 421 | + 'mwe-sequenceedit-menu_resource_overview' => 'Vista xeral dos recursos', |
| 422 | + 'mwe-sequenceedit-menu_options' => 'Opcións', |
| 423 | + 'mwe-sequenceedit-loading_timeline' => 'Cargando a liña do tempo...', |
| 424 | + 'mwe-sequenceedit-loading_user_rights' => 'Cargando os dereitos de usuario...', |
| 425 | + 'mwe-sequenceedit-no_edit_permissions' => 'Non ten os permisos necesarios para gardar os cambios feitos nesta secuencia', |
| 426 | + 'mwe-sequenceedit-edit_clip' => 'Editar o vídeo', |
| 427 | + 'mwe-sequenceedit-edit_save' => 'Gardar os cambios feitos na secuencia', |
| 428 | + 'mwe-sequenceedit-saving_wait' => 'Gardando (por favor, espere)', |
| 429 | + 'mwe-sequenceedit-save_done' => 'Gardado', |
| 430 | + 'mwe-sequenceedit-edit_cancel' => 'Cancelar a edición da secuencia', |
| 431 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Está seguro de querer cancelar a súa edición? Perderanse todos os cambios feitos.', |
| 432 | + 'mwe-sequenceedit-zoom_in' => 'Ampliar', |
| 433 | + 'mwe-sequenceedit-zoom_out' => 'Reducir', |
| 434 | + 'mwe-sequenceedit-cut_clip' => 'Cortar os vídeos', |
| 435 | + 'mwe-sequenceedit-expand_track' => 'Expandir a pista', |
| 436 | + 'mwe-sequenceedit-collapse_track' => 'Contraer a pista', |
| 437 | + 'mwe-sequenceedit-play_from_position' => 'Reproducir desde a posición de lectura', |
| 438 | + 'mwe-sequenceedit-pixle2sec' => 'píxeles a segundos', |
| 439 | + 'mwe-sequenceedit-rmclip' => 'Eliminar o vídeo', |
| 440 | + 'mwe-sequenceedit-clip_in' => 'achegar', |
| 441 | + 'mwe-sequenceedit-clip_out' => 'separar', |
| 442 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Non se seleccionou ningún recurso</h3> Seleccione un vídeo para permitir a edición.', |
| 443 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Seleccionáronse varios recursos</h3> Seleccione soamente un vídeo para editalo.', |
| 444 | + 'mwe-sequenceedit-editor_options' => 'Opcións do editor', |
| 445 | + 'mwe-sequenceedit-editor_mode' => 'Modo do editor', |
| 446 | + 'mwe-sequenceedit-simple_editor_desc' => 'editor simple (estilo iMovie)', |
| 447 | + 'mwe-sequenceedit-advanced_editor_desc' => 'editor avanzado (estilo Final Cut)', |
| 448 | + 'mwe-sequenceedit-other_options' => 'Outras opcións', |
| 449 | + 'mwe-sequenceedit-contextmenu_opt' => 'Activar os menús contextuais', |
| 450 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Desenvolvido por <a href="http://kaltura.com">Kaltura, Inc.</a> en colaboración coa <a href="http://wikimediafoundation.org/wiki/Portada_galega">Fundación Wikimedia</a> (<a href="#">máis información</a>).', |
| 451 | +); |
| 452 | +$messages['gsw'] = array( |
| 453 | + 'mwe-sequenceedit-transition_in' => 'Ibergang aa', |
| 454 | + 'mwe-sequenceedit-transition_out' => 'Ibergang ab', |
| 455 | + 'mwe-sequenceedit-effects' => 'Effäkt-Stacks', |
| 456 | + 'mwe-sequenceedit-remove_transition' => 'Ibergang useneh', |
| 457 | + 'mwe-sequenceedit-edit_transin' => 'Ibergang im Clip bearbeite', |
| 458 | + 'mwe-sequenceedit-edit_transout' => 'Ibergang usserhalb vum Clip bearbeite', |
| 459 | + 'mwe-sequenceedit-add-transition' => 'Ibergang zuefiege', |
| 460 | + 'mwe-sequenceedit-menu_clipedit' => 'Medie bearbeite', |
| 461 | + 'mwe-sequenceedit-menu_transition' => 'Ibergäng un Effäkt', |
| 462 | + 'mwe-sequenceedit-menu_cliplib' => 'Medie zuefiege', |
| 463 | + 'mwe-sequenceedit-menu_resource_overview' => 'Quälleibersicht', |
| 464 | + 'mwe-sequenceedit-menu_options' => 'Optione', |
| 465 | + 'mwe-sequenceedit-loading_timeline' => 'Am Lade vun ere Zytzylete ...', |
| 466 | + 'mwe-sequenceedit-loading_user_rights' => 'Am Lade vu Benutzerrächt ...', |
| 467 | + 'mwe-sequenceedit-no_edit_permissions' => 'Du derfsch Änderige in däm Abschnitt nit spychere', |
| 468 | + 'mwe-sequenceedit-edit_clip' => 'Clip bearbeite', |
| 469 | + 'mwe-sequenceedit-edit_save' => 'Änderige am Abschnitt spychere', |
| 470 | + 'mwe-sequenceedit-saving_wait' => 'Grad am Spychere (bitte wart no)', |
| 471 | + 'mwe-sequenceedit-save_done' => 'Spychere fertig', |
| 472 | + 'mwe-sequenceedit-edit_cancel' => 'Bearbeitig vu däm Abschnitt abbräche', |
| 473 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Bisch sicher, ass Du Dyni bearbeitig witt abbräche? Alli Änderige gehn derno verlore.', |
| 474 | + 'mwe-sequenceedit-zoom_in' => 'Vergreßere', |
| 475 | + 'mwe-sequenceedit-zoom_out' => 'Verchleinere', |
| 476 | + 'mwe-sequenceedit-cut_clip' => 'Clips uusschnitte', |
| 477 | + 'mwe-sequenceedit-expand_track' => 'Spur uusklappe', |
| 478 | + 'mwe-sequenceedit-collapse_track' => 'Spur yyklappe', |
| 479 | + 'mwe-sequenceedit-play_from_position' => 'Abspile ab dr Playline-Position', |
| 480 | + 'mwe-sequenceedit-pixle2sec' => 'Pixel je Sekund', |
| 481 | + 'mwe-sequenceedit-rmclip' => 'Clip uuseneh', |
| 482 | + 'mwe-sequenceedit-clip_in' => 'Clip zuefiege', |
| 483 | + 'mwe-sequenceedit-clip_out' => 'Clip uuseneh', |
| 484 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Kei Quälle uusgwehlt</h3> Wehl e Clip uus go s Bearbeite meglig mache.', |
| 485 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Meh wie ei Quälle uusgwehlt</h3> Wehl ei einzige Clip zuem Bearbeite uus.', |
| 486 | + 'mwe-sequenceedit-editor_options' => 'Yystellige zum Bearbeite', |
| 487 | + 'mwe-sequenceedit-editor_mode' => 'Bearbeitigsmodus', |
| 488 | + 'mwe-sequenceedit-simple_editor_desc' => 'Eifachi Bearbeitig (iMovie-Stil)', |
| 489 | + 'mwe-sequenceedit-advanced_editor_desc' => 'Fortgschritteni Bearbeitig (Final Cut-Stil)', |
| 490 | + 'mwe-sequenceedit-other_options' => 'Anderi Optione', |
| 491 | + 'mwe-sequenceedit-contextmenu_opt' => 'Kontext-Menüs zueloo', |
| 492 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Entwicklet dur <a href="http://kaltura.com">Kaltura, Inc.</a> zämme mit dr <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">meh Informatione</a>).', |
| 493 | +); |
| 494 | +$messages['he'] = array( |
| 495 | + 'mwe-sequenceedit-transition_in' => 'מעברון כניסה', |
| 496 | + 'mwe-sequenceedit-transition_out' => 'מעברון יציאה', |
| 497 | + 'mwe-sequenceedit-effects' => 'מכלול האפקטים', |
| 498 | + 'mwe-sequenceedit-remove_transition' => 'הסרת המעברון', |
| 499 | + 'mwe-sequenceedit-edit_transin' => 'עריכת המעברון אל תוך הסרטון', |
| 500 | + 'mwe-sequenceedit-edit_transout' => 'עריכת המעברון אל מחוץ לסרטון', |
| 501 | + 'mwe-sequenceedit-menu_clipedit' => 'עריכת המדיה', |
| 502 | + 'mwe-sequenceedit-menu_transition' => 'מעברונים ואפקטים', |
| 503 | + 'mwe-sequenceedit-menu_cliplib' => 'הוספת מדיה', |
| 504 | + 'mwe-sequenceedit-menu_resource_overview' => 'סקירת המשאבים', |
| 505 | + 'mwe-sequenceedit-menu_options' => 'אפשרויות', |
| 506 | + 'mwe-sequenceedit-loading_timeline' => 'מתבצעת טעינת ציר הזמן ...', |
| 507 | + 'mwe-sequenceedit-loading_user_rights' => 'מתבצעת טעינת הרשאות המשתמש ...', |
| 508 | + 'mwe-sequenceedit-no_edit_permissions' => 'אין לכם הרשאות לשמור את השינויים לרצף זה', |
| 509 | + 'mwe-sequenceedit-edit_clip' => 'עריכת הסרטון', |
| 510 | + 'mwe-sequenceedit-edit_save' => 'שמירת השינויים ברצף', |
| 511 | + 'mwe-sequenceedit-saving_wait' => 'השמירה מתבצעת (נא להמתין)', |
| 512 | + 'mwe-sequenceedit-save_done' => 'השמירה הושלמה', |
| 513 | + 'mwe-sequenceedit-edit_cancel' => 'ביטול עריכת הרצף', |
| 514 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'האם אתם בטוחים שברצונם לבטל את עריכתכם? השינויים יאבדו.', |
| 515 | + 'mwe-sequenceedit-zoom_in' => 'התקרבות', |
| 516 | + 'mwe-sequenceedit-zoom_out' => 'התרחקות', |
| 517 | + 'mwe-sequenceedit-cut_clip' => 'גזירת סרטונים', |
| 518 | + 'mwe-sequenceedit-expand_track' => 'הרחבת הרצועה', |
| 519 | + 'mwe-sequenceedit-collapse_track' => 'צמצום הרצועה', |
| 520 | + 'mwe-sequenceedit-play_from_position' => 'נגינה מהמיקום בשורת הנגינה', |
| 521 | + 'mwe-sequenceedit-pixle2sec' => 'פיקסלים לשניות', |
| 522 | + 'mwe-sequenceedit-rmclip' => 'הסרת סרטון', |
| 523 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>לא נבחר משאב</h3> יש לבחור סרטון כדי לאפשר עריכה.', |
| 524 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>נבחרו מספר מקורות</h3> יש לבחור בקטע בודד כדי לערוך אותו.', |
| 525 | + 'mwe-sequenceedit-editor_options' => 'אפשרויות העורך', |
| 526 | + 'mwe-sequenceedit-editor_mode' => 'מצב עורך', |
| 527 | + 'mwe-sequenceedit-simple_editor_desc' => 'עורך פשוט (בסגנון iMovie)', |
| 528 | + 'mwe-sequenceedit-advanced_editor_desc' => 'עורך מתקדם (בסגנון Final Cut)', |
| 529 | + 'mwe-sequenceedit-other_options' => 'אפשרויות אחרות', |
| 530 | + 'mwe-sequenceedit-contextmenu_opt' => 'הפעלת תפריטי ההקשר', |
| 531 | + 'mwe-sequenceedit-sequencer_credit_line' => 'פותח על ידי <a href="http://kaltura.com">Kaltura בע"מ</a> בשיתוף עם <a href="http://wikimediafoundation.org/wiki/Home">קרן ויקימדיה</a> (<a href="#">למידע נוסף</a>).', |
| 532 | +); |
| 533 | +$messages['hsb'] = array( |
| 534 | + 'mwe-sequenceedit-transition_in' => 'Zablendować', |
| 535 | + 'mwe-sequenceedit-transition_out' => 'Wublendować', |
| 536 | + 'mwe-sequenceedit-effects' => 'Stapl efektow', |
| 537 | + 'mwe-sequenceedit-remove_transition' => 'Přechad wotstronić', |
| 538 | + 'mwe-sequenceedit-edit_transin' => 'Přechod do klipa wobdźěłać', |
| 539 | + 'mwe-sequenceedit-edit_transout' => 'Přechod z klipa wobdźěłać', |
| 540 | + 'mwe-sequenceedit-add-transition' => 'Přechad přidać', |
| 541 | + 'mwe-sequenceedit-menu_clipedit' => 'Medije wobdźěłać', |
| 542 | + 'mwe-sequenceedit-menu_transition' => 'Přechady a efekty', |
| 543 | + 'mwe-sequenceedit-menu_cliplib' => 'Medije přidać', |
| 544 | + 'mwe-sequenceedit-menu_resource_overview' => 'Resursowy přehlad', |
| 545 | + 'mwe-sequenceedit-menu_options' => 'Opcije', |
| 546 | + 'mwe-sequenceedit-loading_timeline' => 'Časowa lajsta ...', |
| 547 | + 'mwe-sequenceedit-loading_user_rights' => 'Wužiwarske prawa so začituja ...', |
| 548 | + 'mwe-sequenceedit-no_edit_permissions' => 'Nimaš prawa, zo by změny na tutej sekwency składował', |
| 549 | + 'mwe-sequenceedit-edit_clip' => 'Klip wobdźěłać', |
| 550 | + 'mwe-sequenceedit-edit_save' => 'Změny sekwency składować', |
| 551 | + 'mwe-sequenceedit-saving_wait' => 'Składuje so runje (prošu čakać)', |
| 552 | + 'mwe-sequenceedit-save_done' => 'Składowanje zakónčene', |
| 553 | + 'mwe-sequenceedit-edit_cancel' => 'Wobdźěłowanje sekwency přetorhnyć', |
| 554 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Chceš woprawdźe swoje wobdźěłanje zaćisnyć? Změny so zhubja.', |
| 555 | + 'mwe-sequenceedit-zoom_in' => 'Powjetšić', |
| 556 | + 'mwe-sequenceedit-zoom_out' => 'Pomjeńšić', |
| 557 | + 'mwe-sequenceedit-cut_clip' => 'Klipy třihać', |
| 558 | + 'mwe-sequenceedit-expand_track' => 'Ćěr rozfałdować', |
| 559 | + 'mwe-sequenceedit-collapse_track' => 'Ćěr fałdować', |
| 560 | + 'mwe-sequenceedit-play_from_position' => 'Wot aktuelneje pozicije wohtrać', |
| 561 | + 'mwe-sequenceedit-pixle2sec' => 'piksele do sekundow', |
| 562 | + 'mwe-sequenceedit-rmclip' => 'Klip wotstronić', |
| 563 | + 'mwe-sequenceedit-clip_in' => 'klip přidać', |
| 564 | + 'mwe-sequenceedit-clip_out' => 'klip wotstronić', |
| 565 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Žana resursa wubrana</h3> Wubjer klip, zo by wobdźěłowanje zmóžnił.', |
| 566 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Wjacore resursy wubrane</h3> Wubjer jednotliwy klip za wobdźěłanje.', |
| 567 | + 'mwe-sequenceedit-editor_options' => 'Editorowe opcije', |
| 568 | + 'mwe-sequenceedit-editor_mode' => 'Editorowy modus', |
| 569 | + 'mwe-sequenceedit-simple_editor_desc' => 'jednory editor (stil iMovie)', |
| 570 | + 'mwe-sequenceedit-advanced_editor_desc' => 'rozšěrjeny editor (stil Final Cut)', |
| 571 | + 'mwe-sequenceedit-other_options' => 'Druhe opcije', |
| 572 | + 'mwe-sequenceedit-contextmenu_opt' => 'Kontekstowe menije zmóžnić', |
| 573 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Wuwity wot <a href="http://kaltura.com">Kaltura, Inc.</a> w partnerstwje ze załožbu <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">dalše informacije</a>).', |
| 574 | +); |
| 575 | +$messages['hu'] = array( |
| 576 | + 'mwe-sequenceedit-transition_in' => 'Áttűnés kezdete', |
| 577 | + 'mwe-sequenceedit-transition_out' => 'Áttűnés vége', |
| 578 | + 'mwe-sequenceedit-effects' => 'Effektverem', |
| 579 | + 'mwe-sequenceedit-remove_transition' => 'Áttűnés eltávolítása', |
| 580 | + 'mwe-sequenceedit-edit_transin' => 'Kezdő átmenet szerkesztése', |
| 581 | + 'mwe-sequenceedit-edit_transout' => 'Klip végi átmenet szerkesztése', |
| 582 | + 'mwe-sequenceedit-add-transition' => 'Átmenet hozzáadása', |
| 583 | + 'mwe-sequenceedit-menu_clipedit' => 'Média szerkesztése', |
| 584 | + 'mwe-sequenceedit-menu_transition' => 'Áttűnések és effektek', |
| 585 | + 'mwe-sequenceedit-menu_cliplib' => 'Média hozzáadása', |
| 586 | + 'mwe-sequenceedit-menu_resource_overview' => 'Erőforrás áttekintés', |
| 587 | + 'mwe-sequenceedit-menu_options' => 'Beállítások', |
| 588 | + 'mwe-sequenceedit-loading_timeline' => 'Idővonal betöltése…', |
| 589 | + 'mwe-sequenceedit-loading_user_rights' => 'Felhasználói jogosultságok betöltése…', |
| 590 | + 'mwe-sequenceedit-no_edit_permissions' => 'Nincs jogosultságod a változtatások elmentéséhez a jelenetbe', |
| 591 | + 'mwe-sequenceedit-edit_clip' => 'Klip szerkesztése', |
| 592 | + 'mwe-sequenceedit-edit_save' => 'Jelenet változásainak mentése', |
| 593 | + 'mwe-sequenceedit-saving_wait' => 'Mentés folyamatban (kérlek várj)', |
| 594 | + 'mwe-sequenceedit-save_done' => 'Mentés kész', |
| 595 | + 'mwe-sequenceedit-edit_cancel' => 'Jelenet szerkesztésének eldobása', |
| 596 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Biztos vagy benne, hogy megszakítod a szerkesztést? A változtatások elvesznek.', |
| 597 | + 'mwe-sequenceedit-zoom_in' => 'Nagyítás', |
| 598 | + 'mwe-sequenceedit-zoom_out' => 'Kicsinyítés', |
| 599 | + 'mwe-sequenceedit-cut_clip' => 'Klipek vágása', |
| 600 | + 'mwe-sequenceedit-expand_track' => 'Sáv kibontása', |
| 601 | + 'mwe-sequenceedit-collapse_track' => 'Sáv összecsukása', |
| 602 | + 'mwe-sequenceedit-play_from_position' => 'Lejátszás a lejátszó pozíciójától', |
| 603 | + 'mwe-sequenceedit-pixle2sec' => 'képpontokat másodpercekké', |
| 604 | + 'mwe-sequenceedit-rmclip' => 'Klip eltávolítása', |
| 605 | + 'mwe-sequenceedit-clip_in' => 'klip eleji', |
| 606 | + 'mwe-sequenceedit-clip_out' => 'klip végi', |
| 607 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Nincs kiválasztott erőforrás</h3> Válassz egy klipet a szerkesztéshez.', |
| 608 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Több erőforrás kiválasztva</h3> Egy klipet válassz a szerkesztéséhez.', |
| 609 | + 'mwe-sequenceedit-editor_options' => 'Szerkesztő beállításai', |
| 610 | + 'mwe-sequenceedit-editor_mode' => 'Szerkesztői mód', |
| 611 | + 'mwe-sequenceedit-simple_editor_desc' => 'egyszerű szerkesztő (iMovie stílusban)', |
| 612 | + 'mwe-sequenceedit-advanced_editor_desc' => 'haladó szerkesztő (Final Cut stílusban)', |
| 613 | + 'mwe-sequenceedit-other_options' => 'Egyéb beállítások', |
| 614 | + 'mwe-sequenceedit-contextmenu_opt' => 'Helyi menük engedélyezése', |
| 615 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Fejlesztette a <a href="http://kaltura.com">Kaltura, Inc.</a> együttműködésben a <a href="http://wikimediafoundation.org/wiki/Home">Wikimédia Alapítvánnyal</a> (<a href="#">további információk</a>)', |
| 616 | +); |
| 617 | +$messages['ia'] = array( |
| 618 | + 'mwe-sequenceedit-transition_in' => 'Transition entrante', |
| 619 | + 'mwe-sequenceedit-transition_out' => 'Transition sortiente', |
| 620 | + 'mwe-sequenceedit-effects' => 'Pila de effectos', |
| 621 | + 'mwe-sequenceedit-remove_transition' => 'Remover transition', |
| 622 | + 'mwe-sequenceedit-edit_transin' => 'Inserer transition in clip', |
| 623 | + 'mwe-sequenceedit-edit_transout' => 'Remover transition del clip', |
| 624 | + 'mwe-sequenceedit-add-transition' => 'Adder un transition', |
| 625 | + 'mwe-sequenceedit-menu_clipedit' => 'Modificar multimedia', |
| 626 | + 'mwe-sequenceedit-menu_transition' => 'Transitiones e effectos', |
| 627 | + 'mwe-sequenceedit-menu_cliplib' => 'Adder multimedia', |
| 628 | + 'mwe-sequenceedit-menu_resource_overview' => 'Summario de ressources', |
| 629 | + 'mwe-sequenceedit-menu_options' => 'Optiones', |
| 630 | + 'mwe-sequenceedit-loading_timeline' => 'Carga chronologia ...', |
| 631 | + 'mwe-sequenceedit-loading_user_rights' => 'Carga derectos de usator ...', |
| 632 | + 'mwe-sequenceedit-no_edit_permissions' => 'Tu non ha le permission de immagazinar modificationes a iste sequentia', |
| 633 | + 'mwe-sequenceedit-edit_clip' => 'Modificar clip', |
| 634 | + 'mwe-sequenceedit-edit_save' => 'Immagazinar modificationes del sequentia', |
| 635 | + 'mwe-sequenceedit-saving_wait' => 'Immagazinage in curso (per favor attende)', |
| 636 | + 'mwe-sequenceedit-save_done' => 'Immagazinage complete', |
| 637 | + 'mwe-sequenceedit-edit_cancel' => 'Cancellar modification del sequentia', |
| 638 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Es tu secur de voler cancellar tu modification? Le cambiamentos essera perdite.', |
| 639 | + 'mwe-sequenceedit-zoom_in' => 'Zoom avante', |
| 640 | + 'mwe-sequenceedit-zoom_out' => 'Zoom retro', |
| 641 | + 'mwe-sequenceedit-cut_clip' => 'Trenchar clips', |
| 642 | + 'mwe-sequenceedit-expand_track' => 'Expander tracia', |
| 643 | + 'mwe-sequenceedit-collapse_track' => 'Contraher tracia', |
| 644 | + 'mwe-sequenceedit-play_from_position' => 'Reproducer a partir del position de lectura', |
| 645 | + 'mwe-sequenceedit-pixle2sec' => 'pixeles a secundas', |
| 646 | + 'mwe-sequenceedit-rmclip' => 'Remover clip', |
| 647 | + 'mwe-sequenceedit-clip_in' => 'attachar', |
| 648 | + 'mwe-sequenceedit-clip_out' => 'distachar', |
| 649 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Nulle ressource seligite</h3> Selige un clip pro activar le modification.', |
| 650 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Plure ressources seligite</h3> Selige un sol clip pro modificar lo.', |
| 651 | + 'mwe-sequenceedit-editor_options' => 'Optiones de editor', |
| 652 | + 'mwe-sequenceedit-editor_mode' => 'Modo de editor', |
| 653 | + 'mwe-sequenceedit-simple_editor_desc' => 'editor simple (stilo iMovie)', |
| 654 | + 'mwe-sequenceedit-advanced_editor_desc' => 'editor avantiate (stilo Final Cut)', |
| 655 | + 'mwe-sequenceedit-other_options' => 'Altere optiones', |
| 656 | + 'mwe-sequenceedit-contextmenu_opt' => 'Activar menus contextual', |
| 657 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Disveloppate per <a href="http://kaltura.com">Kaltura, Inc.</a> in association con le <a href="http://wikimediafoundation.org/wiki/Home">Fundation Wikimedia</a> (<a href="#">plus information</a>).', |
| 658 | +); |
| 659 | +$messages['id'] = array( |
| 660 | + 'mwe-sequenceedit-transition_in' => 'Transisi masuk', |
| 661 | + 'mwe-sequenceedit-transition_out' => 'Transisi keluar', |
| 662 | + 'mwe-sequenceedit-effects' => 'Tumpuk efek', |
| 663 | + 'mwe-sequenceedit-remove_transition' => 'Singkirkan transisi', |
| 664 | + 'mwe-sequenceedit-edit_transin' => 'Sunting transisi masuk klip', |
| 665 | + 'mwe-sequenceedit-edit_transout' => 'Sunting transisi keluar klip', |
| 666 | + 'mwe-sequenceedit-add-transition' => 'Tambahkan transisi', |
| 667 | + 'mwe-sequenceedit-menu_clipedit' => 'Sunting media', |
| 668 | + 'mwe-sequenceedit-menu_transition' => 'Transisi dan efek', |
| 669 | + 'mwe-sequenceedit-menu_cliplib' => 'Tambah media', |
| 670 | + 'mwe-sequenceedit-menu_resource_overview' => 'Tinjauan sumber daya', |
| 671 | + 'mwe-sequenceedit-menu_options' => 'Pilihan', |
| 672 | + 'mwe-sequenceedit-loading_timeline' => 'Memuat garis waktu ...', |
| 673 | + 'mwe-sequenceedit-loading_user_rights' => 'Memuat hak pengguna ...', |
| 674 | + 'mwe-sequenceedit-no_edit_permissions' => 'Anda tidak memiliki hak untuk menyimpan perubahan pada bagian ini', |
| 675 | + 'mwe-sequenceedit-edit_clip' => 'Sunting klip', |
| 676 | + 'mwe-sequenceedit-edit_save' => 'Simpan perubahan urutan', |
| 677 | + 'mwe-sequenceedit-saving_wait' => 'Penyimpanan dalam proses (mohoon tunggu)', |
| 678 | + 'mwe-sequenceedit-save_done' => 'Menyimpanan lengkap', |
| 679 | + 'mwe-sequenceedit-edit_cancel' => 'Batalkan suntingan urutan', |
| 680 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Apakan anda yakin akan membatalkan suntingan anda? Perubahan akan hilang.', |
| 681 | + 'mwe-sequenceedit-zoom_in' => 'Zum masuk', |
| 682 | + 'mwe-sequenceedit-zoom_out' => 'Zum keluar', |
| 683 | + 'mwe-sequenceedit-cut_clip' => 'Potong klip', |
| 684 | + 'mwe-sequenceedit-expand_track' => 'Kembangkan trek', |
| 685 | + 'mwe-sequenceedit-collapse_track' => 'Ciutkan trek', |
| 686 | + 'mwe-sequenceedit-play_from_position' => 'Putar dari posisi playline', |
| 687 | + 'mwe-sequenceedit-pixle2sec' => 'piksel ke detik', |
| 688 | + 'mwe-sequenceedit-rmclip' => 'Hapus klip', |
| 689 | + 'mwe-sequenceedit-clip_in' => 'klip masuk', |
| 690 | + 'mwe-sequenceedit-clip_out' => 'klip keluar', |
| 691 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Tidak ada sumber dipilih</h3> Pilih klip untuk mengaktifkan suntingan.', |
| 692 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Beberapa sumber telah dipilih</h3> Pilih satu klip untuk disunting.', |
| 693 | + 'mwe-sequenceedit-editor_options' => 'Pilihan penyunting', |
| 694 | + 'mwe-sequenceedit-editor_mode' => 'Modus sunting', |
| 695 | + 'mwe-sequenceedit-simple_editor_desc' => 'suntingan sederhana (gaya iMovie)', |
| 696 | + 'mwe-sequenceedit-advanced_editor_desc' => 'suntingan lanjutan (gaya potongan akhir)', |
| 697 | + 'mwe-sequenceedit-other_options' => 'Pilihan lain', |
| 698 | + 'mwe-sequenceedit-contextmenu_opt' => 'Aktifkan menu konteks', |
| 699 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Dikembangkan oleh <a href="http://kaltura.com">Kaltura, Inc</a> bekerja sama dengan <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">informasi lebih lanjut</a>).', |
| 700 | +); |
| 701 | +$messages['it'] = array( |
| 702 | + 'mwe-sequenceedit-menu_options' => 'Opzioni', |
| 703 | + 'mwe-sequenceedit-other_options' => 'Altre opzioni', |
| 704 | + 'mwe-sequenceedit-contextmenu_opt' => 'Attiva i menu contestuali', |
| 705 | +); |
| 706 | +$messages['ja'] = array( |
| 707 | + 'mwe-sequenceedit-transition_in' => 'トランジション・イン', |
| 708 | + 'mwe-sequenceedit-transition_out' => 'トランジション・アウト', |
| 709 | + 'mwe-sequenceedit-effects' => 'エフェクト棚', |
| 710 | + 'mwe-sequenceedit-remove_transition' => 'トランジションを除去', |
| 711 | + 'mwe-sequenceedit-edit_transin' => 'クリップのトランジション・インを編集', |
| 712 | + 'mwe-sequenceedit-edit_transout' => 'クリップのトランジション・アウトを編集', |
| 713 | + 'mwe-sequenceedit-add-transition' => 'トランジションを追加', |
| 714 | + 'mwe-sequenceedit-menu_clipedit' => 'メディアを編集', |
| 715 | + 'mwe-sequenceedit-menu_transition' => 'トランジションとエフェクト', |
| 716 | + 'mwe-sequenceedit-menu_cliplib' => 'メディアを追加', |
| 717 | + 'mwe-sequenceedit-menu_resource_overview' => 'リソース概観', |
| 718 | + 'mwe-sequenceedit-menu_options' => 'オプション', |
| 719 | + 'mwe-sequenceedit-loading_timeline' => 'タイムラインを読み込み中 …', |
| 720 | + 'mwe-sequenceedit-loading_user_rights' => '利用者権限を読み込み中 …', |
| 721 | + 'mwe-sequenceedit-no_edit_permissions' => 'あなたはこのシーケンスに変更を加える許可がありません', |
| 722 | + 'mwe-sequenceedit-edit_clip' => 'クリップを編集', |
| 723 | + 'mwe-sequenceedit-edit_save' => 'シーケンスの変更を保存', |
| 724 | + 'mwe-sequenceedit-saving_wait' => '保存処理中 (お待ちください)', |
| 725 | + 'mwe-sequenceedit-save_done' => '保存完了', |
| 726 | + 'mwe-sequenceedit-edit_cancel' => 'シーケンスの編集を中止', |
| 727 | + 'mwe-sequenceedit-edit_cancel_confirm' => '本当に編集を中止しますか?変更は失われます。', |
| 728 | + 'mwe-sequenceedit-zoom_in' => '拡大', |
| 729 | + 'mwe-sequenceedit-zoom_out' => '縮小', |
| 730 | + 'mwe-sequenceedit-cut_clip' => 'クリップを切り抜く', |
| 731 | + 'mwe-sequenceedit-expand_track' => 'トラックを展開', |
| 732 | + 'mwe-sequenceedit-collapse_track' => 'トラックを折り畳む', |
| 733 | + 'mwe-sequenceedit-play_from_position' => '再生開始位置から再生', |
| 734 | + 'mwe-sequenceedit-pixle2sec' => 'ピクセルから秒へ', |
| 735 | + 'mwe-sequenceedit-rmclip' => 'クリップを削除', |
| 736 | + 'mwe-sequenceedit-clip_in' => '添付する', |
| 737 | + 'mwe-sequenceedit-clip_out' => '除去する', |
| 738 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>素材が選択されていません</h3>編集を行うにはクリップを選択してください。', |
| 739 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>複数の素材が選択されています</h3> 編集するにはクリップを1つだけ選択してください。', |
| 740 | + 'mwe-sequenceedit-editor_options' => '編集オプション', |
| 741 | + 'mwe-sequenceedit-editor_mode' => '編集モード', |
| 742 | + 'mwe-sequenceedit-simple_editor_desc' => '単純なエディター (iMovie 風)', |
| 743 | + 'mwe-sequenceedit-advanced_editor_desc' => '高度なエディター (Final Cut 風)', |
| 744 | + 'mwe-sequenceedit-other_options' => '他のオプション', |
| 745 | + 'mwe-sequenceedit-contextmenu_opt' => 'コンテキストメニューを有効化', |
| 746 | + 'mwe-sequenceedit-sequencer_credit_line' => '本機能は<a href="http://kaltura.com">Kaltura, Inc.</a> が <a href="http://wikimediafoundation.org/wiki/Home">ウィキメディア財団</a>の協力のもと開発しました (<a href="#">詳細情報</a>)。', |
| 747 | +); |
| 748 | +$messages['ko'] = array( |
| 749 | + 'mwe-sequenceedit-menu_options' => '설정', |
| 750 | + 'mwe-sequenceedit-zoom_in' => '확대', |
| 751 | + 'mwe-sequenceedit-zoom_out' => '축소', |
| 752 | + 'mwe-sequenceedit-editor_options' => '에디터 설정', |
| 753 | + 'mwe-sequenceedit-other_options' => '다른 설정', |
| 754 | +); |
| 755 | +$messages['ksh'] = array( |
| 756 | + 'mwe-sequenceedit-transition_in' => 'Övverjang en', |
| 757 | + 'mwe-sequenceedit-transition_out' => 'Övverjang uß', |
| 758 | + 'mwe-sequenceedit-effects' => 'Dä Pöngel met dä Effäkte', |
| 759 | + 'mwe-sequenceedit-remove_transition' => 'Dä Övverjang fott nämme', |
| 760 | + 'mwe-sequenceedit-edit_transin' => 'Donn dä Övverjang en dä Ußschnett eren bränge', |
| 761 | + 'mwe-sequenceedit-edit_transout' => 'Donn dä Övverjang uß däm Ußschned eruß bränge', |
| 762 | + 'mwe-sequenceedit-add-transition' => 'Donn ene Övverjang dobei', |
| 763 | + 'mwe-sequenceedit-menu_clipedit' => 'Meedije Ändere', |
| 764 | + 'mwe-sequenceedit-menu_transition' => 'Övverjäng un besönder Effäkte', |
| 765 | + 'mwe-sequenceedit-menu_cliplib' => 'Alle Meedije', |
| 766 | + 'mwe-sequenceedit-menu_resource_overview' => 'Övverseesch', |
| 767 | + 'mwe-sequenceedit-menu_options' => 'Ußwahle', |
| 768 | + 'mwe-sequenceedit-loading_timeline' => 'En Zick-Reih aam Laade …', |
| 769 | + 'mwe-sequenceedit-loading_user_rights' => 'Metmaacher-Rääschte aam Laade …', |
| 770 | + 'mwe-sequenceedit-no_edit_permissions' => 'Do häs nit dat Rääsch, Änderunge aan heh dä Afshpellleß afzeshpeishere', |
| 771 | + 'mwe-sequenceedit-edit_clip' => 'Ußschnett ändere', |
| 772 | + 'mwe-sequenceedit-edit_save' => 'Änderunge aan dä Afshpellleß afshpeishere', |
| 773 | + 'mwe-sequenceedit-saving_wait' => 'Et Afsheijshere es noch em Jang, donn noch jät waade.', |
| 774 | + 'mwe-sequenceedit-save_done' => 'Fäädesch afjeshpeishert', |
| 775 | + 'mwe-sequenceedit-edit_cancel' => 'Et Ändere vun dä Afshpellleß afbreshe', |
| 776 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Bes De sescher, dat De et Ändere afbräsche wells? All Ding Werrek beß jäz jeiht verschött!', |
| 777 | + 'mwe-sequenceedit-zoom_in' => 'Eraan zoome', |
| 778 | + 'mwe-sequenceedit-zoom_out' => 'Fott zoome', |
| 779 | + 'mwe-sequenceedit-cut_clip' => 'Ußschnedde ußschnigge', |
| 780 | + 'mwe-sequenceedit-expand_track' => 'Shpoor opklappe', |
| 781 | + 'mwe-sequenceedit-collapse_track' => 'Shpoor ennklappe', |
| 782 | + 'mwe-sequenceedit-play_from_position' => 'Vun dä Linnesch aan afschpelle', |
| 783 | + 'mwe-sequenceedit-pixle2sec' => 'Pixele pro Sekund', |
| 784 | + 'mwe-sequenceedit-rmclip' => 'Ußschnett fott schmiiße', |
| 785 | + 'mwe-sequenceedit-clip_in' => 'Ußschnett en', |
| 786 | + 'mwe-sequenceedit-clip_out' => 'Ußschnett uß', |
| 787 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Nix ußjesöhk</h3>Söhk ene Ußschnett uß, öm et Ändere müjjelesch ze maache.', |
| 788 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Mieh wie ein Denge ußjesöhk</h3>Söhk ene einzel Ußschnett uß, öm et Ändere müjjelesch ze maache.', |
| 789 | + 'mwe-sequenceedit-editor_options' => 'Enshtällunge för et Ändere', |
| 790 | + 'mwe-sequenceedit-editor_mode' => 'Aat vum Beärbeide', |
| 791 | + 'mwe-sequenceedit-simple_editor_desc' => 'Eijfach Beärbeide (em Shtil vun <i lang="en">iMovie</i>)', |
| 792 | + 'mwe-sequenceedit-advanced_editor_desc' => 'Beärbeide met alle Schikaane (em Shtil vun <i lang="en">Final Cut</i>)', |
| 793 | + 'mwe-sequenceedit-other_options' => 'Ander Müjjeleshkeite', |
| 794 | + 'mwe-sequenceedit-contextmenu_opt' => 'Donn de Kontex-Menühß zohlohße', |
| 795 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Äntweckelt vun dä Ferma <i lang="en"><a href="http://kaltura.com">Kaltura, Inc.</a></i> em Zosammewerke met dä <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Shtefftung</a> (<a href="#">mieh Enfommazjohne</a>).', |
| 796 | +); |
| 797 | +$messages['lb'] = array( |
| 798 | + 'mwe-sequenceedit-transition_in' => 'Iwwergang fir eran', |
| 799 | + 'mwe-sequenceedit-transition_out' => 'Iwwergang fir eraus', |
| 800 | + 'mwe-sequenceedit-remove_transition' => 'Iwwergang ewechhuelen', |
| 801 | + 'mwe-sequenceedit-add-transition' => 'En Iwwergang derbäisetzen', |
| 802 | + 'mwe-sequenceedit-menu_transition' => 'Iwwergäng an Effekter', |
| 803 | + 'mwe-sequenceedit-menu_cliplib' => 'E Medium derbäi setzen', |
| 804 | + 'mwe-sequenceedit-menu_resource_overview' => 'Iwwersiicht iwwer d\'Ressourcen', |
| 805 | + 'mwe-sequenceedit-menu_options' => 'Optiounen', |
| 806 | + 'mwe-sequenceedit-loading_timeline' => 'Zäitläischt lueden ...', |
| 807 | + 'mwe-sequenceedit-loading_user_rights' => 'Benotzerrechter lueden ...', |
| 808 | + 'mwe-sequenceedit-no_edit_permissions' => 'Dir hutt net d\'Rechter fir Ännerungen un dëser Sequenz', |
| 809 | + 'mwe-sequenceedit-edit_clip' => 'Clip änneren', |
| 810 | + 'mwe-sequenceedit-edit_save' => 'D\'Ännerunge vun der Sequenz späicheren', |
| 811 | + 'mwe-sequenceedit-saving_wait' => 'Späicheren amgaang (waard w.e.g.)', |
| 812 | + 'mwe-sequenceedit-save_done' => 'Späicheren ofgeschloss', |
| 813 | + 'mwe-sequenceedit-edit_cancel' => 'Ännerung vun der Sequenz ofbriechen', |
| 814 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Sidd Dir sécher datt dir Är Ännerung ofbrieche wëllt? D\'Ännerunge gi verluer.', |
| 815 | + 'mwe-sequenceedit-zoom_in' => 'Era zoomen', |
| 816 | + 'mwe-sequenceedit-cut_clip' => 'Clippe schneiden', |
| 817 | + 'mwe-sequenceedit-pixle2sec' => 'Pixelen op Sekonnen', |
| 818 | + 'mwe-sequenceedit-rmclip' => 'Clip ewechhuelen', |
| 819 | + 'mwe-sequenceedit-clip_in' => 'Clip derbäisetzen', |
| 820 | + 'mwe-sequenceedit-clip_out' => 'Clip ewechhuelen', |
| 821 | + 'mwe-sequenceedit-other_options' => 'Aner Optiounen', |
| 822 | + 'mwe-sequenceedit-contextmenu_opt' => 'Kontextmenüen aktivéieren', |
| 823 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Entwéckelt vu <a href="http://kaltura.com">Kaltura, Inc.</a> an zesummenaarbecht mat der <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">méi Informatiounen</a>).', |
| 824 | +); |
| 825 | +$messages['ml'] = array( |
| 826 | + 'mwe-sequenceedit-menu_clipedit' => 'മീഡിയ തിരുത്തുക', |
| 827 | + 'mwe-sequenceedit-menu_cliplib' => 'മീഡിയ കൂട്ടിച്ചേർക്കുക', |
| 828 | + 'mwe-sequenceedit-menu_resource_overview' => 'സ്രോതസ്സ് അവലോകനം', |
| 829 | + 'mwe-sequenceedit-menu_options' => 'ഐച്ഛികങ്ങൾ', |
| 830 | + 'mwe-sequenceedit-loading_timeline' => 'സമയരേഖ ശേഖരിക്കുന്നു ...', |
| 831 | + 'mwe-sequenceedit-loading_user_rights' => 'ഉപയോക്തൃ അവകാശങ്ങൾ ശേഖരിക്കുന്നു ...', |
| 832 | + 'mwe-sequenceedit-no_edit_permissions' => 'ഈ അനുവർത്തനത്തിൽ മാറ്റങ്ങൾ സേവ് ചെയ്യാനുള്ള അനുമതി താങ്കൾക്കില്ല', |
| 833 | + 'mwe-sequenceedit-edit_clip' => 'ചലച്ചിത്രശകലം തിരുത്തുക', |
| 834 | + 'mwe-sequenceedit-edit_save' => 'അനുവർത്തനത്തിലെ മാറ്റങ്ങൾ സേവ് ചെയ്യുക', |
| 835 | + 'mwe-sequenceedit-saving_wait' => 'സേവ് ചെയ്യൽ പുരോഗമിക്കുന്നു (ദയവായി കാത്തിരിക്കുക)', |
| 836 | + 'mwe-sequenceedit-save_done' => 'പൂർണ്ണമായത് സേവ് ചെയ്യുക', |
| 837 | + 'mwe-sequenceedit-edit_cancel' => 'അനുവർത്തനത്തിലെ തിരുത്തൽ റദ്ദാക്കുക', |
| 838 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'താങ്കളുടെ തിരുത്തൽ റദ്ദാക്കണം എന്നതിൽ താങ്കൾ ഉറച്ചു നിൽക്കുന്നുവോ? മാറ്റങ്ങൾ നഷ്ടമാവുന്നതാണ്.', |
| 839 | + 'mwe-sequenceedit-zoom_in' => 'വലുതാക്കുക', |
| 840 | + 'mwe-sequenceedit-zoom_out' => 'ചെറുതാക്കുക', |
| 841 | + 'mwe-sequenceedit-cut_clip' => 'ചലച്ചിത്രശകലം മുറിയ്ക്കുക', |
| 842 | + 'mwe-sequenceedit-rmclip' => 'ചലച്ചിത്രശകലം നീക്കംചെയ്യുക', |
| 843 | + 'mwe-sequenceedit-clip_in' => 'ചലച്ചിത്രശകലം ഉൾപ്പെടുത്തുക', |
| 844 | + 'mwe-sequenceedit-clip_out' => 'ചലച്ചിത്രശകലം പുറംതള്ളുക', |
| 845 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>ഒരു സ്രോതസ്സും തിരഞ്ഞെടുത്തിട്ടില്ല</h3> മാറ്റംവരുത്തുവാൻ ഒരു ചലച്ചിത്രശകലം തിരഞ്ഞെടുക്കുക.', |
| 846 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>നിരവധി സ്രോതസ്സുകൾ തിരഞ്ഞെടുത്തിരിക്കുന്നു</h3> മാറ്റംവരുത്തുവാനായി ഒരു ചലച്ചിത്രശകലം തിരഞ്ഞെടുക്കുക.', |
| 847 | + 'mwe-sequenceedit-editor_options' => 'തിരുത്തലുപകരണ ഐച്ഛികങ്ങൾ', |
| 848 | + 'mwe-sequenceedit-editor_mode' => 'തിരുത്തലുപകരണ സമ്പ്രദായം', |
| 849 | + 'mwe-sequenceedit-simple_editor_desc' => 'ലളിതമായ തിരുത്തലുപകരണം (iMovie രീതി)', |
| 850 | + 'mwe-sequenceedit-advanced_editor_desc' => 'വിപുലമായ തിരുത്തലുപകരണം (ഫൈനൽ കട്ട് രീതി)', |
| 851 | + 'mwe-sequenceedit-other_options' => 'മറ്റ് ഐച്ഛികങ്ങൾ', |
| 852 | + 'mwe-sequenceedit-sequencer_credit_line' => '<a href="http://kaltura.com">Kaltura, Inc.</a>, <a href="http://wikimediafoundation.org/wiki/Home">വിക്കിമീഡിയ ഫൗണ്ടേഷന്റെ</a> പങ്കാളിത്തത്തോടു കൂടി വികസിപ്പിച്ചെടുത്തത് (<a href="#">കൂടുതൽ വിവരങ്ങൾ</a>).', |
| 853 | +); |
| 854 | +$messages['nl'] = array( |
| 855 | + 'mwe-sequenceedit-transition_in' => 'Overgangen', |
| 856 | + 'mwe-sequenceedit-transition_out' => 'Overgang einde', |
| 857 | + 'mwe-sequenceedit-effects' => 'Effecten', |
| 858 | + 'mwe-sequenceedit-remove_transition' => 'Overgang verwijderen', |
| 859 | + 'mwe-sequenceedit-edit_transin' => 'Overgang in clip bewerken', |
| 860 | + 'mwe-sequenceedit-edit_transout' => 'Overgang uit clip verwijderen', |
| 861 | + 'mwe-sequenceedit-add-transition' => 'Overgang toevoegen', |
| 862 | + 'mwe-sequenceedit-menu_clipedit' => 'Media bewerken', |
| 863 | + 'mwe-sequenceedit-menu_transition' => 'Overgangseffecten', |
| 864 | + 'mwe-sequenceedit-menu_cliplib' => 'Media toevoegen', |
| 865 | + 'mwe-sequenceedit-menu_resource_overview' => 'Bronnenoverzicht', |
| 866 | + 'mwe-sequenceedit-menu_options' => 'Instellingen', |
| 867 | + 'mwe-sequenceedit-loading_timeline' => 'Bezig met het laden van de tijdlijn ...', |
| 868 | + 'mwe-sequenceedit-loading_user_rights' => 'Bezig met laden van gebruikersrechten ...', |
| 869 | + 'mwe-sequenceedit-no_edit_permissions' => 'U hebt geen rechten om wijzigingen aan deze reeks op te slaan', |
| 870 | + 'mwe-sequenceedit-edit_clip' => 'Clip bewerken', |
| 871 | + 'mwe-sequenceedit-edit_save' => 'Wijzigingen aan de reeks opslaan', |
| 872 | + 'mwe-sequenceedit-saving_wait' => 'Bezig met opslaan. Even geduld, alstublieft.', |
| 873 | + 'mwe-sequenceedit-save_done' => 'Opslaan voltooid.', |
| 874 | + 'mwe-sequenceedit-edit_cancel' => 'Bewerken van de reeks annuleren', |
| 875 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Weet u zeker dat u uw bewerking wilt afbreken? Alle wijzigingen worden ongedaan gemaakt.', |
| 876 | + 'mwe-sequenceedit-zoom_in' => 'Vergroten', |
| 877 | + 'mwe-sequenceedit-zoom_out' => 'Verkleinen', |
| 878 | + 'mwe-sequenceedit-cut_clip' => 'Clips uitsnijden', |
| 879 | + 'mwe-sequenceedit-expand_track' => 'Spoor uitklappen', |
| 880 | + 'mwe-sequenceedit-collapse_track' => 'Spoor inklappen', |
| 881 | + 'mwe-sequenceedit-play_from_position' => 'Afspelen vanaf positie', |
| 882 | + 'mwe-sequenceedit-pixle2sec' => 'pixels naar seconden', |
| 883 | + 'mwe-sequenceedit-rmclip' => 'Clip verwijderen', |
| 884 | + 'mwe-sequenceedit-clip_in' => 'clip toevoegen', |
| 885 | + 'mwe-sequenceedit-clip_out' => 'clip verwijderen', |
| 886 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Er is geen bestand geselecteerd</h3> |
| 887 | +Selecteer een te bewerken clip.', |
| 888 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Er zijn meerdere bestanden geselecteerd</h3> |
| 889 | +Selecteer één te bewerken clip.', |
| 890 | + 'mwe-sequenceedit-editor_options' => 'Editorinstellingen', |
| 891 | + 'mwe-sequenceedit-editor_mode' => 'Bewerkingsmodus', |
| 892 | + 'mwe-sequenceedit-simple_editor_desc' => 'eenvoudige editor (iMovie-stijl)', |
| 893 | + 'mwe-sequenceedit-advanced_editor_desc' => 'uitgebreide editor (Final Cut-stijl)', |
| 894 | + 'mwe-sequenceedit-other_options' => 'Ander opsies', |
| 895 | + 'mwe-sequenceedit-contextmenu_opt' => 'Contextafhankelijke menu\'s inschakelen', |
| 896 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Ontwikkeld door <a href="http://kaltura.com">Kaltura, Inc.</a> in samenwerking met de <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">meer informatie</a>).', |
| 897 | +); |
| 898 | +$messages['oc'] = array( |
| 899 | + 'mwe-sequenceedit-transition_in' => 'Transicion entranta', |
| 900 | + 'mwe-sequenceedit-transition_out' => 'Transicion sortenta', |
| 901 | + 'mwe-sequenceedit-effects' => 'Pila d\'efièches', |
| 902 | + 'mwe-sequenceedit-remove_transition' => 'Suprimir la transicion', |
| 903 | + 'mwe-sequenceedit-edit_transin' => 'Modificar la transicion cap al clip', |
| 904 | + 'mwe-sequenceedit-edit_transout' => 'Modificar la transicion en defòta del clip', |
| 905 | + 'mwe-sequenceedit-menu_clipedit' => 'Modificar lo mèdia', |
| 906 | + 'mwe-sequenceedit-menu_transition' => 'Transicions e efièches', |
| 907 | + 'mwe-sequenceedit-menu_cliplib' => 'Apondre un mèdia', |
| 908 | + 'mwe-sequenceedit-menu_resource_overview' => 'Vista d\'ensemble de la ressorsa', |
| 909 | + 'mwe-sequenceedit-menu_options' => 'Opcions', |
| 910 | + 'mwe-sequenceedit-loading_timeline' => 'Cargament de la cronologia ...', |
| 911 | + 'mwe-sequenceedit-loading_user_rights' => 'Cargament dels dreches d\'utilizaire ...', |
| 912 | + 'mwe-sequenceedit-no_edit_permissions' => 'Avètz pas l\'autorizacion de salvar los cambiaments aportats a aquesta sequéncia', |
| 913 | + 'mwe-sequenceedit-edit_clip' => 'Modificar lo clip', |
| 914 | + 'mwe-sequenceedit-edit_save' => 'Salvar las modificacions de la sequéncia', |
| 915 | + 'mwe-sequenceedit-saving_wait' => 'Salvament en cors (pacientatz)', |
| 916 | + 'mwe-sequenceedit-save_done' => 'Salvament acabat', |
| 917 | + 'mwe-sequenceedit-edit_cancel' => 'Anullar la modificacion de la sequéncia', |
| 918 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Sètz segur que volètz anullar vòstra modificacion ? Los cambiaments seràn perduts.', |
| 919 | + 'mwe-sequenceedit-zoom_in' => 'Agrandir', |
| 920 | + 'mwe-sequenceedit-zoom_out' => 'Reduire', |
| 921 | + 'mwe-sequenceedit-cut_clip' => 'Copar los clips', |
| 922 | + 'mwe-sequenceedit-expand_track' => 'Espandir la pista', |
| 923 | + 'mwe-sequenceedit-collapse_track' => 'Reduire la pista', |
| 924 | + 'mwe-sequenceedit-play_from_position' => 'Legir a partir de la posicion de lectura', |
| 925 | + 'mwe-sequenceedit-pixle2sec' => 'pixèls cap a segondas', |
| 926 | + 'mwe-sequenceedit-rmclip' => 'Suprimir lo clip', |
| 927 | + 'mwe-sequenceedit-clip_in' => 'estacar', |
| 928 | + 'mwe-sequenceedit-clip_out' => 'destacar', |
| 929 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Cap de ressorsa pas seleccionada</h3> Seleccionatz un clip per activar l\'edicion', |
| 930 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Mantuna ressorsa seleccionada</h3> Seleccionatz un sol clip per lo modificar', |
| 931 | + 'mwe-sequenceedit-editor_options' => 'Opcions de l\'editor', |
| 932 | + 'mwe-sequenceedit-editor_mode' => 'Mòde de l\'editor', |
| 933 | + 'mwe-sequenceedit-simple_editor_desc' => 'editor simple (estil iMovie)', |
| 934 | + 'mwe-sequenceedit-advanced_editor_desc' => 'editor avançat (estil Final Cut)', |
| 935 | + 'mwe-sequenceedit-other_options' => 'Autras opcions', |
| 936 | + 'mwe-sequenceedit-contextmenu_opt' => 'Activar los menuts contextuals', |
| 937 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Desvolopat per <a href="http://kaltura.com">Kaltura, Inc.</a> en partenariat amb la <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">mai d\'entresenhas</a>).', |
| 938 | +); |
| 939 | +$messages['pl'] = array( |
| 940 | + 'mwe-sequenceedit-transition_in' => 'Wejście', |
| 941 | + 'mwe-sequenceedit-transition_out' => 'Wyjście', |
| 942 | + 'mwe-sequenceedit-effects' => 'Stos efektów', |
| 943 | + 'mwe-sequenceedit-remove_transition' => 'Usuń przejście', |
| 944 | + 'mwe-sequenceedit-edit_transin' => 'Edytuj przejście do klipu', |
| 945 | + 'mwe-sequenceedit-edit_transout' => 'Edytuj przejście zakończenia klipu', |
| 946 | + 'mwe-sequenceedit-menu_clipedit' => 'Edytuj multimeda', |
| 947 | + 'mwe-sequenceedit-menu_transition' => 'Przejścia i efekty', |
| 948 | + 'mwe-sequenceedit-menu_cliplib' => 'Dodaj media', |
| 949 | + 'mwe-sequenceedit-menu_resource_overview' => 'Przegląd zasobów', |
| 950 | + 'mwe-sequenceedit-menu_options' => 'Opcje', |
| 951 | + 'mwe-sequenceedit-loading_timeline' => 'Ładowanie osi czasu ...', |
| 952 | + 'mwe-sequenceedit-loading_user_rights' => 'Ładowanie praw użytkowników ...', |
| 953 | + 'mwe-sequenceedit-no_edit_permissions' => 'Nie masz uprawnień, aby zapisać zmiany w tej kolejności', |
| 954 | + 'mwe-sequenceedit-edit_clip' => 'Edytuj klip', |
| 955 | + 'mwe-sequenceedit-edit_save' => 'Zapisz sekwencję zmian', |
| 956 | + 'mwe-sequenceedit-saving_wait' => 'Zapisywanie trwa (proszę czekać)', |
| 957 | + 'mwe-sequenceedit-save_done' => 'Zapisano', |
| 958 | + 'mwe-sequenceedit-edit_cancel' => 'Anuluj sekwencję zmian', |
| 959 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Czy na pewno chcesz anulować edycję? Zmiany zostaną utracone.', |
| 960 | + 'mwe-sequenceedit-zoom_in' => 'Powiększ', |
| 961 | + 'mwe-sequenceedit-zoom_out' => 'Pomniejsz', |
| 962 | + 'mwe-sequenceedit-cut_clip' => 'Przytnij klipy', |
| 963 | + 'mwe-sequenceedit-rmclip' => 'Usuń klip', |
| 964 | + 'mwe-sequenceedit-clip_in' => 'początek klipu', |
| 965 | + 'mwe-sequenceedit-clip_out' => 'koniec klipu', |
| 966 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Nie wybrano zasobu</h3> Wybierz klip, jeśli chcesz edytować.', |
| 967 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Wybrano wiele zasobów</h3> Wybierz jeden klip, jeśli chcesz edytować.', |
| 968 | + 'mwe-sequenceedit-editor_options' => 'Opcje edytora', |
| 969 | + 'mwe-sequenceedit-editor_mode' => 'Tryb pracy edytora', |
| 970 | + 'mwe-sequenceedit-simple_editor_desc' => 'prosty edytor tekstu (w stylu iMovie)', |
| 971 | + 'mwe-sequenceedit-advanced_editor_desc' => 'zaawansowany edytor (w stylu Final Cut)', |
| 972 | + 'mwe-sequenceedit-other_options' => 'Inne opcje', |
| 973 | + 'mwe-sequenceedit-contextmenu_opt' => 'Włącz menu kontekstowe', |
| 974 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Wykonane przez <a href="http://kaltura.com">Kaltura, Inc,</a> we współpracy z <a href="http://wikimediafoundation.org/wiki/Home">Fundacją Wikimedia</a> (<a href="#">więcej informacji</a>).', |
| 975 | +); |
| 976 | +$messages['pt'] = array( |
| 977 | + 'mwe-sequenceedit-transition_in' => 'Entrada da transição', |
| 978 | + 'mwe-sequenceedit-transition_out' => 'Saída da transição', |
| 979 | + 'mwe-sequenceedit-effects' => 'Pilha de efeitos', |
| 980 | + 'mwe-sequenceedit-remove_transition' => 'Remover transição', |
| 981 | + 'mwe-sequenceedit-edit_transin' => 'Inserir transição no clipe', |
| 982 | + 'mwe-sequenceedit-edit_transout' => 'Remover transição do clipe', |
| 983 | + 'mwe-sequenceedit-add-transition' => 'Adicionar uma transição', |
| 984 | + 'mwe-sequenceedit-menu_clipedit' => 'Editar multimédia', |
| 985 | + 'mwe-sequenceedit-menu_transition' => 'Transições e efeitos', |
| 986 | + 'mwe-sequenceedit-menu_cliplib' => 'Adicionar multimédia', |
| 987 | + 'mwe-sequenceedit-menu_resource_overview' => 'Visão geral dos recursos', |
| 988 | + 'mwe-sequenceedit-menu_options' => 'Opções', |
| 989 | + 'mwe-sequenceedit-loading_timeline' => 'A carregar linha do tempo ...', |
| 990 | + 'mwe-sequenceedit-loading_user_rights' => 'A carregar os direitos do utilizador ...', |
| 991 | + 'mwe-sequenceedit-no_edit_permissions' => 'Não tem permissões para gravar alterações a esta sequência', |
| 992 | + 'mwe-sequenceedit-edit_clip' => 'Editar clipe', |
| 993 | + 'mwe-sequenceedit-edit_save' => 'Gravar mudanças na sequência', |
| 994 | + 'mwe-sequenceedit-saving_wait' => 'Gravação em progresso (por favor, aguarde)', |
| 995 | + 'mwe-sequenceedit-save_done' => 'Gravação completa', |
| 996 | + 'mwe-sequenceedit-edit_cancel' => 'Cancelar edição da sequência', |
| 997 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Tem a certeza de que quer cancelar a edição? As alterações serão perdidas.', |
| 998 | + 'mwe-sequenceedit-zoom_in' => 'Aproximar', |
| 999 | + 'mwe-sequenceedit-zoom_out' => 'Afastar', |
| 1000 | + 'mwe-sequenceedit-cut_clip' => 'Cortar clipes', |
| 1001 | + 'mwe-sequenceedit-expand_track' => 'Expandir faixa', |
| 1002 | + 'mwe-sequenceedit-collapse_track' => 'Colapsar faixa', |
| 1003 | + 'mwe-sequenceedit-play_from_position' => 'Começar a partir da posicão na linha', |
| 1004 | + 'mwe-sequenceedit-pixle2sec' => 'pixels para segundos', |
| 1005 | + 'mwe-sequenceedit-rmclip' => 'Remover clipe', |
| 1006 | + 'mwe-sequenceedit-clip_in' => 'entrada do clipe', |
| 1007 | + 'mwe-sequenceedit-clip_out' => 'saída do clipe', |
| 1008 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Nenhum recurso seleccionado</h3> Seleccione um clip para possibilitar edição.', |
| 1009 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Vários recursos seleccionados</h3> Seleccione um único clipe para editá-lo.', |
| 1010 | + 'mwe-sequenceedit-editor_options' => 'Opções do editor', |
| 1011 | + 'mwe-sequenceedit-editor_mode' => 'Modo editor', |
| 1012 | + 'mwe-sequenceedit-simple_editor_desc' => 'editor simples (estilo iMovie)', |
| 1013 | + 'mwe-sequenceedit-advanced_editor_desc' => 'editor avançado (estilo Final Cut)', |
| 1014 | + 'mwe-sequenceedit-other_options' => 'Outras opções', |
| 1015 | + 'mwe-sequenceedit-contextmenu_opt' => 'Possibilitar menus de contexto', |
| 1016 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Desenvolvido por <a href="http://kaltura.com">Kaltura, Inc.</a> em parceria com a <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">mais informações</a>).', |
| 1017 | +); |
| 1018 | +$messages['pt-br'] = array( |
| 1019 | + 'mwe-sequenceedit-menu_options' => 'Opções', |
| 1020 | + 'mwe-sequenceedit-loading_user_rights' => 'A carregar direitos de usuário ...', |
| 1021 | + 'mwe-sequenceedit-other_options' => 'Outras opções', |
| 1022 | + 'mwe-sequenceedit-contextmenu_opt' => 'Habilitar menus de contexto', |
| 1023 | +); |
| 1024 | +$messages['ru'] = array( |
| 1025 | + 'mwe-sequenceedit-transition_in' => 'Переход в', |
| 1026 | + 'mwe-sequenceedit-transition_out' => 'Переход из', |
| 1027 | + 'mwe-sequenceedit-effects' => 'Набор эффектов', |
| 1028 | + 'mwe-sequenceedit-remove_transition' => 'Удалить переход', |
| 1029 | + 'mwe-sequenceedit-edit_transin' => 'Изменить переход в клипе', |
| 1030 | + 'mwe-sequenceedit-edit_transout' => 'Изменить переход-выход в клипе', |
| 1031 | + 'mwe-sequenceedit-add-transition' => 'Добавить переход', |
| 1032 | + 'mwe-sequenceedit-menu_clipedit' => 'Изменить медиа', |
| 1033 | + 'mwe-sequenceedit-menu_transition' => 'Переходы и эффекты', |
| 1034 | + 'mwe-sequenceedit-menu_cliplib' => 'Добавить медиа', |
| 1035 | + 'mwe-sequenceedit-menu_resource_overview' => 'Обзор ресурсов', |
| 1036 | + 'mwe-sequenceedit-menu_options' => 'Настройки', |
| 1037 | + 'mwe-sequenceedit-loading_timeline' => 'Загружается хронология …', |
| 1038 | + 'mwe-sequenceedit-loading_user_rights' => 'Загружаются права участников …', |
| 1039 | + 'mwe-sequenceedit-no_edit_permissions' => 'У вас нет разрешения сохранять изменения последовательности', |
| 1040 | + 'mwe-sequenceedit-edit_clip' => 'Редактировать клип', |
| 1041 | + 'mwe-sequenceedit-edit_save' => 'Сохранить изменения последовательности', |
| 1042 | + 'mwe-sequenceedit-saving_wait' => 'Идёт сохранение (пожалуйста, подождите)', |
| 1043 | + 'mwe-sequenceedit-save_done' => 'Сохранение завершено', |
| 1044 | + 'mwe-sequenceedit-edit_cancel' => 'Отменить правку последовательности', |
| 1045 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Вы уверены, что хотите отменить Вашу правку? Изменения будут потеряны.', |
| 1046 | + 'mwe-sequenceedit-zoom_in' => 'Увеличить', |
| 1047 | + 'mwe-sequenceedit-zoom_out' => 'Уменьшить', |
| 1048 | + 'mwe-sequenceedit-cut_clip' => 'Кадрирование клипов', |
| 1049 | + 'mwe-sequenceedit-expand_track' => 'Развернуть трек', |
| 1050 | + 'mwe-sequenceedit-collapse_track' => 'Свернуть трек', |
| 1051 | + 'mwe-sequenceedit-play_from_position' => 'Проигрывать с позиции линии воспроизведения', |
| 1052 | + 'mwe-sequenceedit-pixle2sec' => 'пикселов в секунду', |
| 1053 | + 'mwe-sequenceedit-rmclip' => 'Удалить клип', |
| 1054 | + 'mwe-sequenceedit-clip_in' => 'добавить клип', |
| 1055 | + 'mwe-sequenceedit-clip_out' => 'убрать клип', |
| 1056 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Не выбран ресурс</h3>Выберите клип для редактирования.', |
| 1057 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Выбрано несколько ресурсов</h3> Выберите один клип для редактирования.', |
| 1058 | + 'mwe-sequenceedit-editor_options' => 'Настройки редактора', |
| 1059 | + 'mwe-sequenceedit-editor_mode' => 'Режим редактора', |
| 1060 | + 'mwe-sequenceedit-simple_editor_desc' => 'простой редактор (стиль iMovie)', |
| 1061 | + 'mwe-sequenceedit-advanced_editor_desc' => 'улучшенный редактор (стиль Final Cut)', |
| 1062 | + 'mwe-sequenceedit-other_options' => 'Другие настройки', |
| 1063 | + 'mwe-sequenceedit-contextmenu_opt' => 'Включить контекстные меню', |
| 1064 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Разработано <a href="http://kaltura.com">Kaltura, Inc</a> в сотрудничестве с <a href="http://wikimediafoundation.org/wiki/Home">Фондом Викимедиа</a> (<a href="#">подробнее</a>).', |
| 1065 | +); |
| 1066 | +$messages['sah'] = array( |
| 1067 | + 'mwe-sequenceedit-menu_options' => 'Туруоруулар', |
| 1068 | + 'mwe-sequenceedit-edit_clip' => 'Клибы уларытыы', |
| 1069 | + 'mwe-sequenceedit-zoom_in' => 'Улаатыннар', |
| 1070 | + 'mwe-sequenceedit-zoom_out' => 'Кыччат', |
| 1071 | +); |
| 1072 | +$messages['sk'] = array( |
| 1073 | + 'mwe-sequenceedit-transition_in' => 'Prechod do', |
| 1074 | + 'mwe-sequenceedit-transition_out' => 'Prechod z', |
| 1075 | + 'mwe-sequenceedit-effects' => 'Zásobník efektov', |
| 1076 | + 'mwe-sequenceedit-remove_transition' => 'Odstrániť prechod', |
| 1077 | + 'mwe-sequenceedit-edit_transin' => 'Upraviť prechod do klipu', |
| 1078 | + 'mwe-sequenceedit-edit_transout' => 'Upraviť prechod z klipu', |
| 1079 | + 'mwe-sequenceedit-menu_clipedit' => 'Upraviť multimédiá', |
| 1080 | + 'mwe-sequenceedit-menu_transition' => 'Prechody a efekty', |
| 1081 | + 'mwe-sequenceedit-menu_cliplib' => 'Pridať multimédiá', |
| 1082 | + 'mwe-sequenceedit-menu_resource_overview' => 'Prehľad zdroja', |
| 1083 | + 'mwe-sequenceedit-menu_options' => 'Možnosti', |
| 1084 | + 'mwe-sequenceedit-loading_timeline' => 'Načítava sa časová os ...', |
| 1085 | + 'mwe-sequenceedit-loading_user_rights' => 'Načítavajú sa oprávnenia používateľov ...', |
| 1086 | + 'mwe-sequenceedit-no_edit_permissions' => 'Nemáte oprávnenie ukladať zmenu tejto sekvencie', |
| 1087 | + 'mwe-sequenceedit-edit_clip' => 'Upraviť klip', |
| 1088 | + 'mwe-sequenceedit-edit_save' => 'Uložiť zmeny sekvencie', |
| 1089 | + 'mwe-sequenceedit-saving_wait' => 'Prebieha ukladanie (prosím, čakajte)', |
| 1090 | + 'mwe-sequenceedit-save_done' => 'Ukladanie dokončené', |
| 1091 | + 'mwe-sequenceedit-edit_cancel' => 'Zrušiť úpravu sekvencie', |
| 1092 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Ste si istý, že chcete zrušiť svoje úpravy? Zmeny sa stratia.', |
| 1093 | + 'mwe-sequenceedit-zoom_in' => 'Priblížiť', |
| 1094 | + 'mwe-sequenceedit-zoom_out' => 'Oddialiť', |
| 1095 | + 'mwe-sequenceedit-cut_clip' => 'Strih klipov', |
| 1096 | + 'mwe-sequenceedit-expand_track' => 'Rozšíriť stopu', |
| 1097 | + 'mwe-sequenceedit-collapse_track' => 'Zmrštiť stopu', |
| 1098 | + 'mwe-sequenceedit-play_from_position' => 'Prehrať od značky', |
| 1099 | + 'mwe-sequenceedit-pixle2sec' => 'pixle na sekundy', |
| 1100 | + 'mwe-sequenceedit-rmclip' => 'Odstrániť klip', |
| 1101 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Nebol vybraný žiadny zdroj</h3> Úpravu začnete vybraním klipu.', |
| 1102 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Boli vybrané viaceré zdroje</h3> Úpravu začnete vybraním jediného klipu.', |
| 1103 | + 'mwe-sequenceedit-editor_options' => 'Možnosti editora', |
| 1104 | + 'mwe-sequenceedit-editor_mode' => 'Režim editora', |
| 1105 | + 'mwe-sequenceedit-simple_editor_desc' => 'jednoduchý editor (v štýle iMovie)', |
| 1106 | + 'mwe-sequenceedit-advanced_editor_desc' => 'pokročilý editor (v štýle Final Cut)', |
| 1107 | + 'mwe-sequenceedit-other_options' => 'Ďalšie možnosti', |
| 1108 | + 'mwe-sequenceedit-contextmenu_opt' => 'Zapnúť kontextové menu', |
| 1109 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Vyvinula <a href="http://kaltura.com">Kaltura, Inc.</a> v spolupráci s <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">ďalšie informácie</a>).', |
| 1110 | +); |
| 1111 | +$messages['sv'] = array( |
| 1112 | + 'mwe-sequenceedit-menu_clipedit' => 'Redigera media', |
| 1113 | + 'mwe-sequenceedit-menu_cliplib' => 'Lägg till media', |
| 1114 | + 'mwe-sequenceedit-menu_options' => 'Alternativ', |
| 1115 | + 'mwe-sequenceedit-loading_timeline' => 'Laddar tidslinje...', |
| 1116 | + 'mwe-sequenceedit-loading_user_rights' => 'Laddar användarrättigheter...', |
| 1117 | + 'mwe-sequenceedit-zoom_in' => 'Zooma in', |
| 1118 | + 'mwe-sequenceedit-zoom_out' => 'Zooma ut', |
| 1119 | + 'mwe-sequenceedit-pixle2sec' => 'Pixlar till sekunder', |
| 1120 | + 'mwe-sequenceedit-other_options' => 'Andra alternativ', |
| 1121 | +); |
| 1122 | +$messages['te'] = array( |
| 1123 | + 'mwe-sequenceedit-menu_options' => 'ఎంపికలు', |
| 1124 | + 'mwe-sequenceedit-saving_wait' => 'భద్రపరడం జరుగుతూంది (దయచేసి వేచివుండండి)', |
| 1125 | + 'mwe-sequenceedit-save_done' => 'భద్రపరచడం పూర్తయ్యింది', |
| 1126 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'మీరు నిజంగానే మీ మార్పుని రద్దుచేయాలనుకుంటున్నారా? మార్పులు పోతాయి.', |
| 1127 | + 'mwe-sequenceedit-editor_options' => 'కూర్పరి ఎంపికలు', |
| 1128 | + 'mwe-sequenceedit-other_options' => 'ఇతర ఎంపికలు', |
| 1129 | +); |
| 1130 | +$messages['tr'] = array( |
| 1131 | + 'mwe-sequenceedit-transition_in' => 'İçe geçiş', |
| 1132 | + 'mwe-sequenceedit-transition_out' => 'Dışa geçiş', |
| 1133 | + 'mwe-sequenceedit-effects' => 'Efekt yığını', |
| 1134 | + 'mwe-sequenceedit-remove_transition' => 'Geçişi kaldır', |
| 1135 | + 'mwe-sequenceedit-edit_transin' => 'Klibe geçişi değiştir', |
| 1136 | + 'mwe-sequenceedit-edit_transout' => 'Klipten geçişi değiştir', |
| 1137 | + 'mwe-sequenceedit-add-transition' => 'Geçiş ekle', |
| 1138 | + 'mwe-sequenceedit-menu_clipedit' => 'Ortamı değiştir', |
| 1139 | + 'mwe-sequenceedit-menu_transition' => 'Geçişler ve efektler', |
| 1140 | + 'mwe-sequenceedit-menu_cliplib' => 'Ortam ekle', |
| 1141 | + 'mwe-sequenceedit-menu_resource_overview' => 'Kaynak genel bakışı', |
| 1142 | + 'mwe-sequenceedit-menu_options' => 'Seçenekler', |
| 1143 | + 'mwe-sequenceedit-loading_timeline' => 'Zaman çizelgesi yükleniyor ...', |
| 1144 | + 'mwe-sequenceedit-loading_user_rights' => 'Kullanıcı hakları yükleniyor ...', |
| 1145 | + 'mwe-sequenceedit-no_edit_permissions' => 'Bu dizilişe değişiklikleri kaydetme izniniz yok', |
| 1146 | + 'mwe-sequenceedit-edit_clip' => 'Klibi değiştir', |
| 1147 | + 'mwe-sequenceedit-edit_save' => 'Diziliş değişikliklerini kaydet', |
| 1148 | + 'mwe-sequenceedit-saving_wait' => 'Kaydetme sürüyor (lütfen bekleyin)', |
| 1149 | + 'mwe-sequenceedit-save_done' => 'Kaydetme tamamlandı', |
| 1150 | + 'mwe-sequenceedit-edit_cancel' => 'Diziliş değişikliğini iptal et', |
| 1151 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Değişikliğinizi iptal etmek istediğinize emin misiniz? Değişiklikler kaybolacaktır.', |
| 1152 | + 'mwe-sequenceedit-zoom_in' => 'Yakınlaştır', |
| 1153 | + 'mwe-sequenceedit-zoom_out' => 'Uzaklaştır', |
| 1154 | + 'mwe-sequenceedit-cut_clip' => 'Klipleri kes', |
| 1155 | + 'mwe-sequenceedit-expand_track' => 'İzi genişlet', |
| 1156 | + 'mwe-sequenceedit-collapse_track' => 'İzi daralt', |
| 1157 | + 'mwe-sequenceedit-play_from_position' => 'Oynatma çizgisi konumundan oynat', |
| 1158 | + 'mwe-sequenceedit-pixle2sec' => 'piksele saniye', |
| 1159 | + 'mwe-sequenceedit-rmclip' => 'Klibi kaldır', |
| 1160 | + 'mwe-sequenceedit-clip_in' => 'içe klip', |
| 1161 | + 'mwe-sequenceedit-clip_out' => 'dışa klip', |
| 1162 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Hiç kaynak seçilmedi</h3> Değiştirmeyi etkinleştirmek için bir klip seçin.', |
| 1163 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Birden fazla kaynak seçildi</h3> Değiştirmek için tek klip seçin.', |
| 1164 | + 'mwe-sequenceedit-editor_options' => 'Düzenleyici seçenekleri', |
| 1165 | + 'mwe-sequenceedit-editor_mode' => 'Düzenleyici kipi', |
| 1166 | + 'mwe-sequenceedit-simple_editor_desc' => 'basit düzenleyici (iMovie tarzı)', |
| 1167 | + 'mwe-sequenceedit-advanced_editor_desc' => 'gelişmiş düzenleyici (Final Cut tarzı)', |
| 1168 | + 'mwe-sequenceedit-other_options' => 'Diğer seçenekler', |
| 1169 | + 'mwe-sequenceedit-contextmenu_opt' => 'İçerik menülerini etkinleştir', |
| 1170 | + 'mwe-sequenceedit-sequencer_credit_line' => '<a href="http://kaltura.com">Kaltura, Inc.</a> tarafından, <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">daha fazla bilgi</a>) ortaklığında geliştirilmiştir.', |
| 1171 | +); |
| 1172 | +$messages['vec'] = array( |
| 1173 | + 'mwe-sequenceedit-menu_options' => 'Opzioni', |
| 1174 | + 'mwe-sequenceedit-saving_wait' => 'So\' drio salvar (speta n\'atimo, par piaser)', |
| 1175 | + 'mwe-sequenceedit-save_done' => 'Salvatajo conpleto', |
| 1176 | + 'mwe-sequenceedit-zoom_in' => 'Strenzi zoom', |
| 1177 | + 'mwe-sequenceedit-zoom_out' => 'Slarga zoom', |
| 1178 | +); |
| 1179 | +$messages['vep'] = array( |
| 1180 | + 'mwe-sequenceedit-menu_cliplib' => 'Ližata medijad', |
| 1181 | + 'mwe-sequenceedit-rmclip' => 'Heitta klip poiš', |
| 1182 | +); |
| 1183 | +$messages['vi'] = array( |
| 1184 | + 'mwe-sequenceedit-transition_in' => 'Chuyển tiếp vào', |
| 1185 | + 'mwe-sequenceedit-transition_out' => 'Chuyển tiếp ra', |
| 1186 | + 'mwe-sequenceedit-effects' => 'Đống hiệu ứng', |
| 1187 | + 'mwe-sequenceedit-remove_transition' => 'Xóa chuyển tiếp', |
| 1188 | + 'mwe-sequenceedit-edit_transin' => 'Sửa chuyển tiếp vào clip', |
| 1189 | + 'mwe-sequenceedit-edit_transout' => 'Sửa chuyển tiếp ra khỏi clip', |
| 1190 | + 'mwe-sequenceedit-menu_clipedit' => 'Sửa tập tin nghe nhìn', |
| 1191 | + 'mwe-sequenceedit-menu_transition' => 'Điểm chuyển và hiệu ứng', |
| 1192 | + 'mwe-sequenceedit-menu_cliplib' => 'Thêm phương tiện', |
| 1193 | + 'mwe-sequenceedit-menu_resource_overview' => 'Tổng quát tài nguyên', |
| 1194 | + 'mwe-sequenceedit-menu_options' => 'Tùy chọn', |
| 1195 | + 'mwe-sequenceedit-loading_timeline' => 'Đang tải dòng thời gian ...', |
| 1196 | + 'mwe-sequenceedit-loading_user_rights' => 'Đang tải quyền thành viên ...', |
| 1197 | + 'mwe-sequenceedit-no_edit_permissions' => 'Bạn không quyền lưu thay đổi vào cảnh này', |
| 1198 | + 'mwe-sequenceedit-edit_clip' => 'Sửa clip', |
| 1199 | + 'mwe-sequenceedit-edit_save' => 'Lưu thay đổi trong cảnh', |
| 1200 | + 'mwe-sequenceedit-saving_wait' => 'Đang lưu (xin chờ)', |
| 1201 | + 'mwe-sequenceedit-save_done' => 'Đã lưu', |
| 1202 | + 'mwe-sequenceedit-edit_cancel' => 'Hủy sửa cảnh', |
| 1203 | + 'mwe-sequenceedit-edit_cancel_confirm' => 'Bạn có chắc là mình muốn hủy sửa đổi không? Các thay đổi sẽ bị mất.', |
| 1204 | + 'mwe-sequenceedit-zoom_in' => 'Phóng to', |
| 1205 | + 'mwe-sequenceedit-zoom_out' => 'Thu nhỏ', |
| 1206 | + 'mwe-sequenceedit-cut_clip' => 'Cắt clip', |
| 1207 | + 'mwe-sequenceedit-expand_track' => 'Bung track', |
| 1208 | + 'mwe-sequenceedit-collapse_track' => 'Thu nhỏ track', |
| 1209 | + 'mwe-sequenceedit-play_from_position' => 'Chơi từ vị trí playline', |
| 1210 | + 'mwe-sequenceedit-pixle2sec' => 'pixel sang giây', |
| 1211 | + 'mwe-sequenceedit-rmclip' => 'Xóa clip', |
| 1212 | + 'mwe-sequenceedit-no_selected_resource' => '<h3>Chưa chọn tài nguyên</h3> Hãy chọn clip để sửa đổi.', |
| 1213 | + 'mwe-sequenceedit-error_edit_multiple' => '<h3>Đã chọn hơn một tài nguyên</h3> Hãy chỉ chọn một clip để sửa đổi nó.', |
| 1214 | + 'mwe-sequenceedit-editor_options' => 'Tùy chọn sửa đổi', |
| 1215 | + 'mwe-sequenceedit-editor_mode' => 'Chế độ sửa đổi', |
| 1216 | + 'mwe-sequenceedit-simple_editor_desc' => 'bộ sửa đổi đơn giản (kiểu iMovie)', |
| 1217 | + 'mwe-sequenceedit-advanced_editor_desc' => 'bộ sửa đổi nâng cấp (kiểu Final Cut)', |
| 1218 | + 'mwe-sequenceedit-other_options' => 'Tùy chọn khác', |
| 1219 | + 'mwe-sequenceedit-sequencer_credit_line' => 'Do <a href="http://kaltura.com">Kaltura, Inc.</a> phát triển với sự hỗ trợ của <a href="http://wikimediafoundation.org/wiki/Trang_chủ?uselang=vi">Quỹ Wikimedia</a> (<a href="#">chi tiết</a>).', |
| 1220 | +); |
Index: branches/MwEmbedStandAlone/modules/SequenceEdit/mw.SequenceEditKeyBindings.js |
— | — | @@ -0,0 +1,91 @@ |
| 2 | +/** |
| 3 | +* Stores the key bindings |
| 4 | +*/ |
| 5 | + |
| 6 | +mw.SequenceEditKeyBindings = function( sequenceEdit ) { |
| 7 | + return this.init( sequenceEdit ); |
| 8 | +}; |
| 9 | +mw.SequenceEditKeyBindings.prototype = { |
| 10 | + // set of key flags: |
| 11 | + shiftDown: false, |
| 12 | + ctrlDown: false, |
| 13 | + |
| 14 | + init: function( sequenceEdit ){ |
| 15 | + this.sequenceEdit = sequenceEdit; |
| 16 | + this.setupKeyBindigs() |
| 17 | + }, |
| 18 | + |
| 19 | + bindEvent: function( eventType, callback){ |
| 20 | + if( typeof eventType == 'object' ){ |
| 21 | + for( var i in eventType ){ |
| 22 | + this.bindEvent( i, eventType[i] ); |
| 23 | + } |
| 24 | + } |
| 25 | + switch( eventType ){ |
| 26 | + case 'copy': |
| 27 | + this.copyEvent = callback; |
| 28 | + break; |
| 29 | + case 'cut': |
| 30 | + this.cutEvent = callback; |
| 31 | + break; |
| 32 | + case 'paste' : |
| 33 | + this.pasteEvent = callback; |
| 34 | + break; |
| 35 | + case 'escape' : |
| 36 | + this.escapeEvent = callback; |
| 37 | + break; |
| 38 | + case 'delete': |
| 39 | + this.deleteEvent = callback; |
| 40 | + break; |
| 41 | + } |
| 42 | + return this; |
| 43 | + }, |
| 44 | + onInputFocus: function( ){ |
| 45 | + _this.inputFocus = true; |
| 46 | + }, |
| 47 | + onInputBlur: function(){ |
| 48 | + _this.inputFocus = false; |
| 49 | + }, |
| 50 | + setupKeyBindigs: function(){ |
| 51 | + var _this = this; |
| 52 | + // Set up key bindings |
| 53 | + $j( window ).keydown( function( e ) { |
| 54 | + mw.log( 'SequenceEditKeyBindings::pushed down on:' + e.which ); |
| 55 | + if ( e.which == 16 ) |
| 56 | + _this.shiftDown = true; |
| 57 | + |
| 58 | + if ( e.which == 17 ) |
| 59 | + _this.ctrlDown = true; |
| 60 | + |
| 61 | + if ( ( e.which == 67 && _this.ctrlDown ) && !_this.inputFocus ) |
| 62 | + _this.copyEvent(); |
| 63 | + |
| 64 | + if ( ( e.which == 88 && _this.ctrlDown ) && !_this.inputFocus ) |
| 65 | + _this.cutEvent(); |
| 66 | + |
| 67 | + // Paste cips on v + ctrl while not focused on a text area: |
| 68 | + if ( ( e.which == 86 && _this.ctrlDown ) && !_this.inputFocus ) |
| 69 | + _this.pasteEvent(); |
| 70 | + |
| 71 | + } ); |
| 72 | + $j( window ).keyup( function( e ) { |
| 73 | + mw.log( 'SequenceEditKeyBindings::key up on ' + e.which ); |
| 74 | + // User let go of "shift" turn off multi-select |
| 75 | + if ( e.which == 16 ) |
| 76 | + _this.shiftDown = false; |
| 77 | + |
| 78 | + if ( e.which == 17 ) |
| 79 | + _this.ctrlDown = false; |
| 80 | + |
| 81 | + // Escape key ( deselect ) |
| 82 | + if ( e.which == 27 ) |
| 83 | + _this.escapeEvent(); |
| 84 | + |
| 85 | + |
| 86 | + // Backspace or Delete key while not focused on a text area: |
| 87 | + if ( ( e.which == 8 || e.which == 46 ) && !_this.inputFocus ) |
| 88 | + _this.deleteEvent(); |
| 89 | + } ); |
| 90 | + } |
| 91 | + |
| 92 | +} |
\ No newline at end of file |
Index: branches/MwEmbedStandAlone/modules/SequenceEdit/mw.SequenceEditTimeline.js |
— | — | @@ -0,0 +1,347 @@ |
| 2 | + |
| 3 | +//Wrap in mw closure to avoid global leakage |
| 4 | +( function( mw ) { |
| 5 | + |
| 6 | +mw.SequenceEditTimeline = function( sequenceEdit ) { |
| 7 | + return this.init( sequenceEdit ); |
| 8 | +}; |
| 9 | + |
| 10 | +// Set up the mvSequencer object |
| 11 | +mw.SequenceEditTimeline.prototype = { |
| 12 | + // Lazy init $timelineTracksContainer |
| 13 | + $timelineTracksContainer : null, |
| 14 | + |
| 15 | + // store a pointer to the track layout |
| 16 | + trackLayout: null, |
| 17 | + |
| 18 | + //Default height width of timeline clip: |
| 19 | + timelineThumbSize: { |
| 20 | + 'height': 90, |
| 21 | + 'width' : 120 |
| 22 | + }, |
| 23 | + |
| 24 | + init: function( sequenceEdit ){ |
| 25 | + this.sequenceEdit = sequenceEdit; |
| 26 | + }, |
| 27 | + |
| 28 | + getTimelineContainer: function(){ |
| 29 | + return this.sequenceEdit.getContainer().find('.mwseq-timeline'); |
| 30 | + }, |
| 31 | + |
| 32 | + getTracksContainer: function(){ |
| 33 | + if( ! this.$timelineTracksContainer ){ |
| 34 | + // getTimelineContainer |
| 35 | + this.getTimelineContainer().append( |
| 36 | + $j('<div />') |
| 37 | + .addClass('timelineTrackContainer') |
| 38 | + .append( |
| 39 | + $j('<div />') |
| 40 | + .addClass( 'ui-layout-west trackNamesContainer'), |
| 41 | + |
| 42 | + $j('<div />') |
| 43 | + .addClass( 'ui-layout-center trackClipsContainer') |
| 44 | + ) |
| 45 | + ) |
| 46 | + // Apply layout control to track name / trackClips division |
| 47 | + this.$timelineTracksContainer = this.getTimelineContainer().find( '.timelineTrackContainer'); |
| 48 | + this.trackLayout = this.$timelineTracksContainer |
| 49 | + .layout( { |
| 50 | + 'applyDefaultStyles': true, |
| 51 | + 'west__size' : 150, |
| 52 | + 'west__minSize' : 100, |
| 53 | + 'west__maxSize' : 300 |
| 54 | + } ); |
| 55 | + } |
| 56 | + return this.$timelineTracksContainer; |
| 57 | + }, |
| 58 | + resizeTimeline: function(){ |
| 59 | + if( this.trackLayout ){ |
| 60 | + this.trackLayout.resizeAll(); |
| 61 | + } |
| 62 | + }, |
| 63 | + //draw the timeline |
| 64 | + drawTimeline: function(){ |
| 65 | + // Empty the timeline container |
| 66 | + this.getTimelineContainer().empty(); |
| 67 | + |
| 68 | + // Get the top level sequence tracks |
| 69 | + var seqTracks = this.sequenceEdit.getSmil().getBody().getSeqElements(); |
| 70 | + var trackType = 'video'; |
| 71 | + // for now just two tracks first is video second is audio |
| 72 | + for( var trackIndex=0; trackIndex < seqTracks.length; trackIndex++){ |
| 73 | + |
| 74 | + if( trackType == 'audio' ){ |
| 75 | + mw.log("SequenceEditTimeline::Error only two tracks presently suppoted"); |
| 76 | + break; |
| 77 | + } |
| 78 | + // Draw the sequence track |
| 79 | + this.drawSequenceTrack( trackIndex, seqTracks[ trackIndex ], trackType); |
| 80 | + trackType = 'audio'; |
| 81 | + } |
| 82 | + }, |
| 83 | + |
| 84 | + drawSequenceTrack: function( trackIndex, sequenceNode, trackType ){ |
| 85 | + mw.log(" drawSequenceTrack: Track inx: " + trackIndex + ' trackType:' + trackType ); |
| 86 | + // Check if we already have a container for this track set |
| 87 | + |
| 88 | + // Add a sequence track Name |
| 89 | + this.getTracksContainer().find('.trackNamesContainer').append( |
| 90 | + this.getTrackNameInterface( trackIndex, sequenceNode, trackType ) |
| 91 | + ) |
| 92 | + |
| 93 | + // Add Sequence clips |
| 94 | + this.getTracksContainer().find('.trackClipsContainer').append( |
| 95 | + this.getTrackClipInterface( trackIndex ,sequenceNode , trackType ) |
| 96 | + ) |
| 97 | + // Load and display all clip thumbnails |
| 98 | + }, |
| 99 | + |
| 100 | + /** |
| 101 | + * Get Track Clip Interface |
| 102 | + */ |
| 103 | + getTrackClipInterface: function( trackIndex, sequenceNode, trackType ){ |
| 104 | + var _this = this; |
| 105 | + // setup a local pointer to the smil engine: |
| 106 | + var smil = this.sequenceEdit.getSmil(); |
| 107 | + // Get all the refs that are children of the sequenceNode with associated offsets and durations |
| 108 | + // for now assume all tracks start at zero: |
| 109 | + var startOffset = 0; |
| 110 | + var $trackClips = |
| 111 | + $j('<div />') |
| 112 | + .attr('id', this.sequenceEdit.getId() + '_trackClips_' + trackIndex ) |
| 113 | + .addClass('trackClips ui-corner-all'); |
| 114 | + |
| 115 | + smil.getBody().getRefElementsRecurse( sequenceNode, startOffset, function( $node ){ |
| 116 | + // Draw the node onto the timeline: |
| 117 | + |
| 118 | + // xxx would be good to support both "storyboard" and "timeline" view modes. |
| 119 | + // for now just "storyboard" |
| 120 | + |
| 121 | + // add a clip float left box container |
| 122 | + $trackClips.append( |
| 123 | + $j('<div />') |
| 124 | + .attr('id', _this.getTimelineClipId( $node ) ) |
| 125 | + .data('smilId', $node.attr('id')) |
| 126 | + .addClass('timelineClip ui-corner-all') |
| 127 | + .css( _this.timelineThumbSize ) |
| 128 | + .loadingSpinner() |
| 129 | + .click(function(){ |
| 130 | + //Add clip to selection |
| 131 | + _this.handleMultiSelect( this ); |
| 132 | + }) |
| 133 | + .draggable( { |
| 134 | + axis:'x', |
| 135 | + containment:'#' + _this.sequenceEdit.getId() + '_trackClips_' + trackIndex, |
| 136 | + opacity:50, |
| 137 | + //handle: ":not(.clip_control)", |
| 138 | + scroll:true, |
| 139 | + drag:function( e, ui ) { |
| 140 | + // debugger; |
| 141 | + //insert_key = _this.clipDragUpdate( ui, this ); |
| 142 | + }, |
| 143 | + start:function( e, ui ) { |
| 144 | + mw.log( 'start drag:' + this.id ); |
| 145 | + // make sure we are ontop |
| 146 | + $j( this ).css( { top:'0px', zindex:10 } ); |
| 147 | + }, |
| 148 | + stop:function( e, ui ) { |
| 149 | + mw.log("stop drag"); |
| 150 | + $j( this ).css( { top:'0px', zindex:0 } ); |
| 151 | + // switch dom order |
| 152 | + } |
| 153 | + } ) |
| 154 | + ) |
| 155 | + |
| 156 | + |
| 157 | + // Check Buffer for when the first frame of the smilNode can be grabbed: |
| 158 | + smil.getBuffer().canGrabRelativeTime( $node, 0, function(){ |
| 159 | + mw.log("getTrackClipInterface::canGrabRelativeTime for " + smil.getAssetId( $node )); |
| 160 | + _this.drawClipThumb( $node , 0); |
| 161 | + }); |
| 162 | + }) |
| 163 | + |
| 164 | + // Add global TrackClipInterface bindings: |
| 165 | + var keyBindings = this.sequenceEdit.getKeyBindings(); |
| 166 | + keyBindings.bindEvent({ |
| 167 | + 'escape': function(){ |
| 168 | + _this.getTimelineContainer().find( '.selectedClip' ).removeClass( 'selectedClip' ); |
| 169 | + }, |
| 170 | + 'delete': function(){ |
| 171 | + _this.removeSelectedClips(); |
| 172 | + } |
| 173 | + }) |
| 174 | + return $trackClips; |
| 175 | + }, |
| 176 | + |
| 177 | + /** |
| 178 | + * Remove selected clips and update the smil player |
| 179 | + */ |
| 180 | + removeSelectedClips: function(){ |
| 181 | + var smil = this.sequenceEdit.getSmil(); |
| 182 | + // modify the smil.dom and rebuild |
| 183 | + this.getTimelineContainer().find( '.selectedClip' ).each(function( inx, selectedClip ){ |
| 184 | + // Remove from smil dom: |
| 185 | + smil.removeById( $j(selectedClip).data('smilId') ); |
| 186 | + // Remove from timeline dom: |
| 187 | + $j( selectedClip ).remove(); |
| 188 | + }) |
| 189 | + // Invalidate embedPlayer duration |
| 190 | + this.sequenceEdit.getEmbedPlayer().duration = null; |
| 191 | + // Rebuild the smil duration: |
| 192 | + smil.getDuration( true ); |
| 193 | + // Update the time display / stop playback if playing |
| 194 | + this.sequenceEdit.getEmbedPlayer().stop(); |
| 195 | + }, |
| 196 | + |
| 197 | + /** |
| 198 | + * Handle multiple selections based on what clips was just "cliked" |
| 199 | + */ |
| 200 | + handleMultiSelect: function( clickClip ){ |
| 201 | + var keyBindings = this.sequenceEdit.getKeyBindings(); |
| 202 | + var $target = this.getTimelineContainer(); |
| 203 | + var smil = this.sequenceEdit.getSmil(); |
| 204 | + var embedPlayer = this.sequenceEdit.getEmbedPlayer(); |
| 205 | + |
| 206 | + |
| 207 | + // Add the selectedClip class to the clickClip |
| 208 | + if( $j( clickClip ).hasClass( 'selectedClip') && $target.find( '.selectedClip' ).length == 1 ){ |
| 209 | + $j( clickClip ).removeClass( 'selectedClip' ); |
| 210 | + }else { |
| 211 | + $j( clickClip ).addClass( 'selectedClip' ); |
| 212 | + } |
| 213 | + |
| 214 | + // If not in multi select mode remove all existing selections except for clickClip |
| 215 | + mw.log( ' HandleMultiSelect::' + keyBindings.shiftDown + ' ctrl_down:' + keyBindings.ctrlDown ); |
| 216 | + |
| 217 | + if ( ! keyBindings.shiftDown && ! keyBindings.ctrlDown ) { |
| 218 | + $target.find( '.selectedClip' ).each( function( inx, selectedClip ) { |
| 219 | + if( $j( clickClip ).attr('id') != $j( selectedClip ).attr('id') ){ |
| 220 | + $j( selectedClip ).removeClass('selectedClip'); |
| 221 | + } |
| 222 | + } ); |
| 223 | + } |
| 224 | + // Seek to the current clip time ( startOffset of current ) |
| 225 | + var seekTime = smil.$dom.find('#' + $j( clickClip ).data('smilId') ).data( 'startOffset' ) |
| 226 | + embedPlayer.setCurrentTime( seekTime, function(){ |
| 227 | + mw.log("handleMultiSelect::seek done") |
| 228 | + }); |
| 229 | + |
| 230 | + // if shift select is down select the in-between clips |
| 231 | + if( keyBindings.shiftDown ){ |
| 232 | + // get the min max of current selection (within the current track) |
| 233 | + var max_order = 0; |
| 234 | + var min_order = 999999999; |
| 235 | + $target.find( '.timelineClip' ).each( function( inx, curClip) { |
| 236 | + if( $j(curClip).hasClass('selectedClip') ){ |
| 237 | + // Set min max |
| 238 | + if ( inx < min_order ) |
| 239 | + min_order = inx; |
| 240 | + if ( inx > max_order ) |
| 241 | + max_order = inx; |
| 242 | + } |
| 243 | + } ); |
| 244 | + // select all non-selected between max or min |
| 245 | + $target.find( '.timelineClip' ).each( function( inx, curClip) { |
| 246 | + if( inx > min_order && inx < max_order ){ |
| 247 | + $j(curClip).addClass( 'selectedClip') |
| 248 | + } |
| 249 | + }); |
| 250 | + } |
| 251 | + }, |
| 252 | + |
| 253 | + getTimelineClipId: function( $node ){ |
| 254 | + return this.sequenceEdit.getSmil().getAssetId( $node ) + '_timelineClip'; |
| 255 | + }, |
| 256 | + |
| 257 | + // Draw a clip thumb into the timeline clip target |
| 258 | + drawClipThumb: function ( $node , relativeTime ){ |
| 259 | + var _this = this; |
| 260 | + var smil = this.sequenceEdit.getSmil(); |
| 261 | + // Check the display type: |
| 262 | + smil.getBuffer().canGrabRelativeTime( $node, relativeTime, function(){ |
| 263 | + mw.log("drawClipThumb:: canGrabRelativeTime:" + _this.getTimelineClipId( $node )); |
| 264 | + |
| 265 | + var naturaSize = {}; |
| 266 | + |
| 267 | + var drawElement = $j( '#' + smil.getAssetId( $node ) ).get(0); |
| 268 | + |
| 269 | + if( drawElement.nodeName.toLowerCase() == 'img' ){ |
| 270 | + naturaSize.height = drawElement.naturalHeight; |
| 271 | + naturaSize.width = drawElement.naturalWidth; |
| 272 | + } else if( drawElement.nodeName.toLowerCase() == 'video' ){ |
| 273 | + naturaSize.height = drawElement.videoHeight; |
| 274 | + naturaSize.width = drawElement.videoWidth; |
| 275 | + } |
| 276 | + |
| 277 | + // Draw the thumb via canvas grab |
| 278 | + // NOTE I attempted to scale down the image using canvas but failed |
| 279 | + // xxx should revisit thumb size issue: |
| 280 | + $j( '#' + _this.getTimelineClipId( $node ) ).html( |
| 281 | + $j('<canvas />') |
| 282 | + .attr({ |
| 283 | + height: naturaSize.height, |
| 284 | + width : naturaSize.width |
| 285 | + }).css( { |
| 286 | + height:'100%', |
| 287 | + widht:'100%' |
| 288 | + }) |
| 289 | + .addClass("ui-corner-all") |
| 290 | + ) |
| 291 | + .find( 'canvas') |
| 292 | + .get(0) |
| 293 | + .getContext('2d') |
| 294 | + .drawImage( $j( '#' + smil.getAssetId( $node ) ).get(0), 0, 0) |
| 295 | + }) |
| 296 | + }, |
| 297 | + /** |
| 298 | + * Gets an sequence track control interface |
| 299 | + * features to add :: expand collapse, hide, mute etc. |
| 300 | + * for now just audio or video with icon |
| 301 | + */ |
| 302 | + getTrackNameInterface: function( trackIndex, sequenceNode, trackType ){ |
| 303 | + var $trackNameInterface = |
| 304 | + $j('<a />') |
| 305 | + .attr('href','#') |
| 306 | + .addClass( "ui-icon_link" ); |
| 307 | + if( trackType == 'video'){ |
| 308 | + $trackNameInterface.append( |
| 309 | + $j('<span />').addClass( 'ui-icon ui-icon-video'), |
| 310 | + $j('<span />').text( gM( 'mwe-sequenceedit-video-track' ) ) |
| 311 | + ) |
| 312 | + } else { |
| 313 | + $trackNameInterface.append( |
| 314 | + $j('<span />').addClass( 'ui-icon ui-icon-volume-on'), |
| 315 | + $j('<span />').text( gM( 'mwe-sequenceedit-audio-track' ) ) |
| 316 | + ) |
| 317 | + } |
| 318 | + // Wrap the track name in a box that matches the trackNames |
| 319 | + return $j('<div />') |
| 320 | + .attr('id', this.sequenceEdit.getId() + '_trackName_' + trackIndex) |
| 321 | + .addClass('trackNames ui-corner-all') |
| 322 | + .append( |
| 323 | + $trackNameInterface |
| 324 | + ) |
| 325 | + }, |
| 326 | + |
| 327 | + getSequenceTrackTitle: function( sequenceNode ){ |
| 328 | + if( $j( sequenceNode).attr('title') ){ |
| 329 | + return $j( sequenceNode).attr('title'); |
| 330 | + } |
| 331 | + // Else return an empty string ( for now ) |
| 332 | + return '' |
| 333 | + }, |
| 334 | + |
| 335 | + getSequenceTrackId: function( index, sequenceNode ){ |
| 336 | + if( ! $j( sequenceNode ).data('id') ){ |
| 337 | + $j( sequenceNode ).data('id', this.sequenceEdit.getId() + '_sequenceTrack_' + index ); |
| 338 | + } |
| 339 | + return $j( sequenceNode ).data('id'); |
| 340 | + } |
| 341 | +} |
| 342 | + |
| 343 | + |
| 344 | + |
| 345 | + |
| 346 | + |
| 347 | + |
| 348 | +} )( window.mw ); |
\ No newline at end of file |
Index: branches/MwEmbedStandAlone/modules/SequenceEdit/tests/Sequence_Editor.html |
— | — | @@ -0,0 +1,41 @@ |
| 2 | +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
| 3 | +"http://www.w3.org/TR/html4/loose.dtd"> |
| 4 | +<html> |
| 5 | +<head> |
| 6 | + <title>SMIL Sequence Editor example</title> |
| 7 | + <script type="text/javascript" src="../../../mwEmbed.js?debug=true"></script> |
| 8 | + <script type="text/javascript"> |
| 9 | + mw.ready( function(){ |
| 10 | + mw.load( 'SequenceEdit', function(){ |
| 11 | + $j('#seqContainer').sequenceEdit({ |
| 12 | + 'smilSource' : 'SampleEditorSequenceSmil.xml', |
| 13 | + //set the add media wizard to only include commons: |
| 14 | + 'AddMediaConf':{ |
| 15 | + 'enabled_providers':[ 'wiki_commons', 'kaltura', 'archive_org', 'flickr', 'metavid' ], |
| 16 | + 'import_url_mode' : 'remote_link', |
| 17 | + 'default_query' : 'fish' |
| 18 | + } |
| 19 | + }); |
| 20 | + }); |
| 21 | + }); |
| 22 | + </script> |
| 23 | +<style> |
| 24 | + body { |
| 25 | + font: x-small sans-serif; |
| 26 | + color: black; |
| 27 | + margin: 0; |
| 28 | + padding: 0; |
| 29 | + } |
| 30 | + img { |
| 31 | + border:medium none; |
| 32 | + } |
| 33 | +</style> |
| 34 | + |
| 35 | +</head> |
| 36 | +<body> |
| 37 | + <div id="seqContainer" style="position:absolute;top:5px;bottom:10px;left:10px;right:10px;"> |
| 38 | + Loading sequence editor ... |
| 39 | + </div> |
| 40 | + </body> |
| 41 | +</html> |
| 42 | + |
Index: branches/MwEmbedStandAlone/modules/SequenceEdit/tests/SampleEditorSequenceSmil.xml |
— | — | @@ -0,0 +1,52 @@ |
| 2 | +<?xml version="1.0" encoding="UTF-8"?> |
| 3 | +<smil baseProfile="Language" version="3.0" xmlns="http://www.w3.org/ns/SMIL"> |
| 4 | + <head> |
| 5 | + <meta name="title" content="Simple Crossfading Example"/> |
| 6 | + |
| 7 | + <transition id="" |
| 8 | + type="fade" |
| 9 | + subtype="fadeFromColor" |
| 10 | + fadeColor="#000" |
| 11 | + dur="4s"/> |
| 12 | + |
| 13 | + </head> |
| 14 | + <body> |
| 15 | + <seq> |
| 16 | + |
| 17 | + <video src="http://upload.wikimedia.org/wikipedia/commons/9/94/Folgers.ogv" |
| 18 | + dur="5s" |
| 19 | + clipBegin = "17s" |
| 20 | + /> |
| 21 | + |
| 22 | + <video src="http://upload.wikimedia.org/wikipedia/commons/1/14/Independence_Day%2C_1940_Promotion.ogv" |
| 23 | + dur="1s" |
| 24 | + /> |
| 25 | + |
| 26 | + <video src="http://upload.wikimedia.org/wikipedia/commons/1/14/Independence_Day%2C_1940_Promotion.ogv" |
| 27 | + transIn="fromBlack" |
| 28 | + dur="2s" |
| 29 | + clipBegin = "16s" |
| 30 | + /> |
| 31 | + |
| 32 | + <video src="http://upload.wikimedia.org/wikipedia/commons/9/94/Folgers.ogv" |
| 33 | + dur="3s" |
| 34 | + clipBegin = "16s" |
| 35 | + /> |
| 36 | + |
| 37 | + <video src="http://upload.wikimedia.org/wikipedia/commons/1/14/Independence_Day%2C_1940_Promotion.ogv" |
| 38 | + dur="2" |
| 39 | + clipBegin = "18" |
| 40 | + /> |
| 41 | + |
| 42 | + <video src="http://upload.wikimedia.org/wikipedia/commons/8/8b/Yochai_Benkler_-_On_Autonomy%2C_Control_and_Cultural_Experience.ogg" |
| 43 | + transIn="fromBlack" |
| 44 | + dur="10" |
| 45 | + clipBegin = "0:3:43" |
| 46 | + /> |
| 47 | + |
| 48 | + </seq> |
| 49 | + |
| 50 | + </body> |
| 51 | +</smil> |
| 52 | + |
| 53 | + |
Index: branches/MwEmbedStandAlone/modules/SequenceEdit/tests/VideoRender.xml |
— | — | @@ -0,0 +1,89 @@ |
| 2 | +<?xml version="1.0" encoding="UTF-8"?> |
| 3 | +<smil baseProfile="Language" version="3.0" xmlns="http://www.w3.org/ns/SMIL"> |
| 4 | + <head> |
| 5 | + <meta name="title" content="Simple Rendering Example"/> |
| 6 | + |
| 7 | + <transition id="fromBlack" |
| 8 | + type="fade" |
| 9 | + subtype="fadeFromColor" |
| 10 | + fadeColor="#000" |
| 11 | + dur="4s"/> |
| 12 | + |
| 13 | + <transition id="fromGreen" |
| 14 | + type="fade" |
| 15 | + subtype="fadeFromColor" |
| 16 | + fadeColor="#87CF87" |
| 17 | + dur="4s"/> |
| 18 | + |
| 19 | + <transition id="xFade" |
| 20 | + type="fade" |
| 21 | + subtype="crossfade" |
| 22 | + dur="4s"/> |
| 23 | + |
| 24 | + <layout>
|
| 25 | + <root-layout backgroundColor="green" height="800" width="500"/>
|
| 26 | + <region backgroundColor="green" height="700" top="50" left="50" width="400" xml:id="image_region"/>
|
| 27 | + <region xml:id="Title" height="25" width="300" left="100" top="10"/>
|
| 28 | + <region xml:id="Captions" height="70" width="300" left="100" top="510"/>
|
| 29 | + <region id="audio_region" soundLevel="100%"/>
|
| 30 | + </layout>
|
| 31 | + |
| 32 | + </head> |
| 33 | + <body> |
| 34 | + <par> |
| 35 | + |
| 36 | + <video src="media/raw_media/cats_of_ulthar_lovecraft_jp.ogg" |
| 37 | + begin="1s" |
| 38 | + dur="1000s" |
| 39 | + /> |
| 40 | + |
| 41 | + <video src="media/raw_media/le_voyage_dans_la_lune_edit_1.ogv" |
| 42 | + transIn="fromBlack" |
| 43 | + type="video/ogg" |
| 44 | + fill="transition" |
| 45 | + dur="1000s" |
| 46 | + /> |
| 47 | + |
| 48 | + <video src="media/raw_media/MoviePowderPresentsPlan9FromOuterSpace.ogv" |
| 49 | + begin="15s" |
| 50 | + transIn="xFade" |
| 51 | + |
| 52 | + fill="transition" |
| 53 | + dur="1000s" |
| 54 | + durationHint="70" |
| 55 | + type="video/ogg" |
| 56 | + /> |
| 57 | + |
| 58 | + <img src="media/raw_media/fruitStand.jpg" |
| 59 | + dur="25s" |
| 60 | + fill="freeze" |
| 61 | + fit="meet" |
| 62 | + id="image" |
| 63 | + panZoom="0,0,100%,100%" |
| 64 | + region="image_region" |
| 65 | + > |
| 66 | + |
| 67 | + <animate attributeName="panZoom" begin="2.0" |
| 68 | + dur="1.5s" fill="freeze" values="-1,4,99%,99%;511,509,47%,14%"/> |
| 69 | + |
| 70 | + <animate attributeName="panZoom" begin="5.0" |
| 71 | + dur="1.5s" fill="freeze" values="511,509,47%,14%;418,-3,34%,13%"/> |
| 72 | + |
| 73 | + <animate attributeName="panZoom" begin="9.0" |
| 74 | + dur="1.5s" fill="freeze" values="418,-3,34%,13%;9,1115,41%,20%"/> |
| 75 | + |
| 76 | + <animate attributeName="panZoom" begin="13.0" |
| 77 | + dur="1.5s" fill="freeze" values="9,1115,41%,20%;573,2073,64%,17%"/> |
| 78 | + |
| 79 | + <animate attributeName="panZoom" begin="16.0" |
| 80 | + dur="1.5s" fill="freeze" values="573,2073,64%,17%;1118,1365,14%,8%"/> |
| 81 | + |
| 82 | + <animate attributeName="panZoom" begin="18.0" |
| 83 | + dur="1.5s" fill="freeze" values="1118,1365,14%,8%;0,0,100%,100%"/> |
| 84 | + </img> |
| 85 | + |
| 86 | +</par> |
| 87 | +</body> |
| 88 | +</smil> |
| 89 | + |
| 90 | + |
Index: branches/MwEmbedStandAlone/modules/SequenceEdit/tests/VideoRender.html |
— | — | @@ -0,0 +1,72 @@ |
| 2 | +<!doctype html> |
| 3 | +<html> |
| 4 | +<head> |
| 5 | + <title>Video CrossFade Example</title> |
| 6 | + <script type="text/javascript" src="../../../mwEmbed.js?debug=true"></script> |
| 7 | + <!-- <script type="text/javascript" src="../../ResourceLoader.php?class=window.jQuery,mwEmbed&debug=true"></script> --> |
| 8 | + <script type="text/javascript"> |
| 9 | + mw.setConfig( 'EmbedPlayer.OverlayControls', false ); |
| 10 | + mw.ready(function(){ |
| 11 | + $j( "#seekInputTime" ).blur( function(){ |
| 12 | + var smilVid = $j('#videoCrossfade').get(0); |
| 13 | + $j('#seekInProgress').show(); |
| 14 | + smilVid.setCurrentTime( parseFloat( $j(this).val() ), function() { |
| 15 | + $j('#seekInProgress').hide(); |
| 16 | + }); |
| 17 | + }); |
| 18 | + $j('#startBuffer').click( function(){ |
| 19 | + $j('#videoCrossfade').get(0).load(); |
| 20 | + return false; |
| 21 | + }); |
| 22 | + $j('#renderToFile').click(function(){ |
| 23 | + $j(this).empty().unbind().after( |
| 24 | + $j('<span />').text( ' ' ), |
| 25 | + $j('<span />').attr('id', 'targetFoggStatus' ) |
| 26 | + ); |
| 27 | + |
| 28 | + // xxx for local rendering 'AddMedia.firefogg' is overkill |
| 29 | + // but will have to clean up modularity later |
| 30 | + |
| 31 | + mw.load( ['AddMedia.firefogg','mw.FirefoggRender'],function(){ |
| 32 | + var foggRender = $j('#videoCrossfade').firefoggRender({ |
| 33 | + 'statusTarget': '#targetFoggStatus' |
| 34 | + }); |
| 35 | + foggRender.doRender(); |
| 36 | + |
| 37 | + $j('#renderToFile').text('Stop Render').click(function(){ |
| 38 | + foggRender.stopRender(); |
| 39 | + }); |
| 40 | + }) |
| 41 | + return false; |
| 42 | + }); |
| 43 | + }); |
| 44 | + </script> |
| 45 | +</head> |
| 46 | +<body> |
| 47 | +<h3>Sample Video CrossFade</h3> |
| 48 | +<table> |
| 49 | +<tr> |
| 50 | +<td> |
| 51 | + |
| 52 | +<video id="videoCrossfade" type="application/smil" src="VideoRender.xml" width="400" height="300"></video> |
| 53 | +<p></p>seek to <input id="seekInputTime" size="4" value = "6"></input><span id="seekInProgress" style="display: none"> Seeking<blink>...</blink></span> |
| 54 | +<br/> |
| 55 | +<a id="startBuffer" href="#">Start buffering</a> <br> |
| 56 | +<a id="renderToFile" href="#">Render to file</a> |
| 57 | +</td> |
| 58 | +<td valign="top"> |
| 59 | +Sample playlist code: |
| 60 | +<div style="clear:both"></div> |
| 61 | +<textarea style="width:500px;"> |
| 62 | +<video id="videoCrossfade" type="application/smil" src="VideoRender.xml" width="400" height="300"></video> |
| 63 | +</textarea> |
| 64 | +<div style="clear:both"></div> |
| 65 | + |
| 66 | +SMIL Source: |
| 67 | +<div style="clear:both"></div> |
| 68 | +<iframe style="width:500px;height:300px" src="VideoRender.xml"></iframe> |
| 69 | +</td> |
| 70 | +</tr> |
| 71 | +</table> |
| 72 | +</body> |
| 73 | +</html> |
Index: branches/MwEmbedStandAlone/modules/SequenceEdit/mw.FirefoggRender.js |
— | — | @@ -0,0 +1,187 @@ |
| 2 | +/* |
| 3 | +* Handles driving the firefogg render system |
| 4 | +*/ |
| 5 | + |
| 6 | +/* |
| 7 | +* Set the jQuery bindings: |
| 8 | +*/ |
| 9 | +( function( $ ) { |
| 10 | + $.fn.firefoggRender = function( options, callback ) { |
| 11 | + if(!options) |
| 12 | + options = {}; |
| 13 | + options.playerTarget = this.selector; |
| 14 | + var myFogg = new mw.FirefoggRender( options ); |
| 15 | + return myFogg; |
| 16 | + } |
| 17 | +} )( jQuery ); |
| 18 | + |
| 19 | + |
| 20 | +mw.FirefoggRender = function( options ) { |
| 21 | + return this.init( options ); |
| 22 | +}; |
| 23 | +// Set up the mvPlaylist object |
| 24 | +mw.FirefoggRender.prototype = { |
| 25 | + |
| 26 | + // Default render options: |
| 27 | + renderOptions: { |
| 28 | + "videoQuality" : 8, |
| 29 | + "framerate" : 30 |
| 30 | + }, |
| 31 | + |
| 32 | + // Render time |
| 33 | + renderTime: null, |
| 34 | + |
| 35 | + // The interval time ( set via requested framerate) |
| 36 | + interval: null, |
| 37 | + |
| 38 | + // Continue rendering |
| 39 | + continueRendering:false, |
| 40 | + |
| 41 | + // Start time for rendering |
| 42 | + startTime: 0, |
| 43 | + |
| 44 | + // Constructor |
| 45 | + init:function( options ) { |
| 46 | + var _this = this; |
| 47 | + |
| 48 | + // Grab the mvFirefogg object to do basic tests |
| 49 | + this.myFogg = new mw.Firefogg( { |
| 50 | + 'only_fogg':true |
| 51 | + }); |
| 52 | + |
| 53 | + // Check for firefogg: |
| 54 | + if ( this.myFogg.getFirefogg() ) { |
| 55 | + this.enabled = true; |
| 56 | + } else { |
| 57 | + this.enabled = false; |
| 58 | + mw.log('Error firefogg not installed'); |
| 59 | + return this; |
| 60 | + } |
| 61 | + |
| 62 | + // Setup local fogg pointer: |
| 63 | + this.fogg = this.myFogg.fogg; |
| 64 | + |
| 65 | + // Setup player instance |
| 66 | + this.playerTarget = options.playerTarget; |
| 67 | + |
| 68 | + // Extend the render options with any provided details |
| 69 | + if( options['renderOptions'] ){ |
| 70 | + this.renderOptions = $j.extend( this.renderOptions, options['renderOptions'] ); |
| 71 | + } |
| 72 | + |
| 73 | + if( options ['statusTarget']){ |
| 74 | + this.statusTarget = options ['statusTarget']; |
| 75 | + } |
| 76 | + |
| 77 | + // If no height width provided use target DOM width/height |
| 78 | + if( !this.renderOptions.width && !this.renderOptions.height ) { |
| 79 | + this.renderOptions.width = $j(this.playerTarget).width(); |
| 80 | + this.renderOptions.height = $j(this.playerTarget).height(); |
| 81 | + } |
| 82 | + |
| 83 | + |
| 84 | + }, |
| 85 | + getPlayer: function(){ |
| 86 | + return $j( this.playerTarget ).get( 0 ); |
| 87 | + }, |
| 88 | + // Start rendering |
| 89 | + doRender: function() { |
| 90 | + var _this = this; |
| 91 | + // Make sure we get a target destination |
| 92 | + if( !_this.fogg.saveVideoAs() ){ |
| 93 | + return false; |
| 94 | + } |
| 95 | + // Set the render time to "startTime" of the render request |
| 96 | + this.renderTime = this.startTime; |
| 97 | + |
| 98 | + // Get the interval from renderOptions framerate |
| 99 | + this.interval = 1 / this.renderOptions.framerate |
| 100 | + |
| 101 | + // Set the continue rendering flag to true: |
| 102 | + this.continueRendering = true; |
| 103 | + |
| 104 | + // Set a target file: |
| 105 | + mw.log( "Firefogg Render Settings:" + JSON.stringify( _this.renderOptions ) ); |
| 106 | + this.fogg.initRender( JSON.stringify( _this.renderOptions ), 'foggRender.ogv' ); |
| 107 | + |
| 108 | + // Add audio if we had any: |
| 109 | + var audioSet = this.getPlayer().getAudioTimeSet(); |
| 110 | + var previusAudioTime = 0; |
| 111 | + for( var i=0; i < audioSet.length ; i++) { |
| 112 | + var currentAudio = audioSet[i]; |
| 113 | + // Check if we need to add silence |
| 114 | + if( currentAudio.startTime > previusAudioTime ){ |
| 115 | + mw.log("FirefoggRender::addSilence " + ( currentAudio.startTime - previusAudioTime )); |
| 116 | + this.fogg.addSilence( currentAudio.startTime - previusAudioTime ); |
| 117 | + } |
| 118 | + // Add the block of audio from the url |
| 119 | + mw.log("FirefoggRender::addAudioUrl " + currentAudio.src + |
| 120 | + ', ' + currentAudio.offset + ', ' + currentAudio.duration ); |
| 121 | + this.fogg.addAudioUrl( currentAudio.src, currentAudio.offset, currentAudio.duration ); |
| 122 | + |
| 123 | + // Update previusAudioTime |
| 124 | + previusAudioTime = currentAudio.startTime + currentAudio.duration; |
| 125 | + } |
| 126 | + // Now issue the save video as call |
| 127 | + _this.doNextFrame(); |
| 128 | + return true; |
| 129 | + }, |
| 130 | + |
| 131 | + /** |
| 132 | + * Do the next frame in the render target |
| 133 | + */ |
| 134 | + doNextFrame: function() { |
| 135 | + var _this = this; |
| 136 | + // internal function to handle updates: |
| 137 | + /*mw.log( "FirefoggRender::doNextFrame: on " + ( Math.round( _this.renderTime * 10 ) / 10 ) + " of " + |
| 138 | + ( Math.round( _this.player.getDuration() * 10 ) / 10 ) ); |
| 139 | + */ |
| 140 | + |
| 141 | + _this.getPlayer().setCurrentTime( _this.renderTime, function() { |
| 142 | + |
| 143 | + _this.fogg.addFrame( $j( _this.playerTarget ).attr( 'id' ) ); |
| 144 | + $j( _this.statusTarget ).text( "AddFrame::" + ( Math.round( _this.renderTime * 1000 ) / 1000 ) ); |
| 145 | + |
| 146 | + _this.renderTime += _this.interval; |
| 147 | + |
| 148 | + if ( _this.renderTime >= _this.getPlayer().getDuration() || ! _this.continueRendering ) { |
| 149 | + _this.doFinalRender(); |
| 150 | + } else { |
| 151 | + // Don't block on render requests |
| 152 | + setTimeout(function(){ |
| 153 | + _this.doNextFrame(); |
| 154 | + },1 ) |
| 155 | + } |
| 156 | + } ); |
| 157 | + }, |
| 158 | + |
| 159 | + /** |
| 160 | + * Stop the current render process on the next frame |
| 161 | + */ |
| 162 | + stopRender: function() { |
| 163 | + this.continueRendering = false; |
| 164 | + }, |
| 165 | + |
| 166 | + /** |
| 167 | + * Issue the call to firefogg to render out the ogg video |
| 168 | + */ |
| 169 | + doFinalRender: function() { |
| 170 | + mw.log("FirefoggRender:: doFinalRenderr" ); |
| 171 | + this.fogg.render(); |
| 172 | + this.updateStatus(); |
| 173 | + }, |
| 174 | + |
| 175 | + /** |
| 176 | + * Update the render status |
| 177 | + */ |
| 178 | + updateStatus: function() { |
| 179 | + var _this = this; |
| 180 | + var rstatus = _this.fogg.renderstatus(); |
| 181 | + $j( _this.statusTarget ).text( rstatus ); |
| 182 | + if ( rstatus != 'done' && rstatus != 'rendering failed' ) { |
| 183 | + setTimeout( function() { |
| 184 | + _this.updateStatus(); |
| 185 | + }, 100 ); |
| 186 | + } |
| 187 | + } |
| 188 | +} |
\ No newline at end of file |
Property changes on: branches/MwEmbedStandAlone/modules/SequenceEdit/mw.FirefoggRender.js |
___________________________________________________________________ |
Added: svn:mergeinfo |
1 | 189 | Merged /branches/REL1_15/phase3/js2/mwEmbed/libSequencer/mvFirefoggRender.js:r51646 |
2 | 190 | Merged /branches/sqlite/js2/mwEmbed/libSequencer/mvFirefoggRender.js:r58211-58321 |
Added: svn:eol-style |
3 | 191 | + native |
Index: branches/MwEmbedStandAlone/modules/SequenceEdit/css/mw.style.SequenceEdit.css |
— | — | @@ -0,0 +1,48 @@ |
| 2 | + |
| 3 | + |
| 4 | +.mwe-sequence-edit .timelineTrackContainer{ |
| 5 | + position: absolute; |
| 6 | + border: solid thin #999; |
| 7 | + top: 4px; |
| 8 | + left:4px; |
| 9 | + right: 4px; |
| 10 | + bottom: 4px; |
| 11 | +} |
| 12 | + |
| 13 | +.mwe-sequence-edit .trackNameContainer{ |
| 14 | + overflow:hidden; |
| 15 | +} |
| 16 | +.mwe-sequence-edit .trackClipsContainer{ |
| 17 | + overflow-x: scroll; |
| 18 | +} |
| 19 | + |
| 20 | +.mwe-sequence-edit .trackClips{ |
| 21 | + height: 100px; |
| 22 | + background-color: #EEE; |
| 23 | + border: solid thin #999; |
| 24 | +} |
| 25 | + |
| 26 | +.mwe-sequence-edit .trackNames{ |
| 27 | + height: 100px; |
| 28 | + background-color: #EEE; |
| 29 | + border: solid thin #999; |
| 30 | +} |
| 31 | + |
| 32 | + |
| 33 | +.mwe-sequence-edit .timelineClip{ |
| 34 | + float: left; |
| 35 | + margin: 5px; |
| 36 | + background-color: #FFF; |
| 37 | + border: 2px solid #555; |
| 38 | + overflow: hidden; |
| 39 | +} |
| 40 | +.mwe-sequence-edit .timelineClip:hover{ |
| 41 | + border: 2px solid #66F; |
| 42 | +} |
| 43 | +.mwe-sequence-edit .selectedClip{ |
| 44 | + border: 2px solid #F66; |
| 45 | +} |
| 46 | +.mwe-sequence-edit .selectedClip:hover{ |
| 47 | + border: 2px solid #F22; |
| 48 | +} |
| 49 | + |
Index: branches/MwEmbedStandAlone/modules/SequenceEdit/mw.SequenceEditPlayer.js |
— | — | @@ -0,0 +1,103 @@ |
| 2 | + |
| 3 | +//Wrap in mw closure to avoid global leakage |
| 4 | +( function( mw ) { |
| 5 | + |
| 6 | +mw.SequenceEditPlayer = function( sequenceEdit ) { |
| 7 | + return this.init( sequenceEdit ); |
| 8 | +}; |
| 9 | + |
| 10 | +// Set up the mvSequencer object |
| 11 | +mw.SequenceEditPlayer.prototype = { |
| 12 | + // The id of the sequence player |
| 13 | + smilPlayerId: null, // lazy init |
| 14 | + |
| 15 | + init: function( sequenceEdit ){ |
| 16 | + this.sequenceEdit = sequenceEdit; |
| 17 | + }, |
| 18 | + /** |
| 19 | + * Draw a smil player to the screen. |
| 20 | + */ |
| 21 | + drawPlayer: function( callback ){ |
| 22 | + var _this = this; |
| 23 | + var $playerTarget = this.sequenceEdit.getContainer().find( '.mwseq-player' ); |
| 24 | + var smilSource = this.sequenceEdit.getSmilSource() |
| 25 | + if( ! smilSource ){ |
| 26 | + $playerTarget.append( |
| 27 | + gM( 'mwe-sequenceedit-no-sequence-start-new', |
| 28 | + $j('<a />').click(function(){ |
| 29 | + alert( 'Browse for assets / start new sequence' ); |
| 30 | + }) |
| 31 | + ) |
| 32 | + ) |
| 33 | + return ; |
| 34 | + } |
| 35 | + |
| 36 | + // Else add the player |
| 37 | + $playerTarget.html( |
| 38 | + $j('<video />').css( |
| 39 | + this.getPlayerSize() |
| 40 | + ).attr({ |
| 41 | + 'id' : this.getSmilPlayerId() |
| 42 | + }).append( |
| 43 | + $j('<source />').attr({ |
| 44 | + 'type' : 'application/smil', |
| 45 | + 'src' : smilSource |
| 46 | + }) |
| 47 | + ) |
| 48 | + ); |
| 49 | + // Draw the player ( keep the playhead for now ) |
| 50 | + // xxx we will eventually replace the playhead with sequence |
| 51 | + // based playhead interface for doing easy trims. |
| 52 | + $j( '#' + this.getSmilPlayerId() ).embedPlayer({ |
| 53 | + 'overlayControls' : false |
| 54 | + }, function(){ |
| 55 | + // Set the player interface to autoMargin ( need to fix css propagation in embed player) |
| 56 | + $j( '#' + _this.getSmilPlayerId() ).parent('.interface_wrap').css('margin', 'auto'); |
| 57 | + if( callback ){ |
| 58 | + callback(); |
| 59 | + } |
| 60 | + }) |
| 61 | + |
| 62 | + }, |
| 63 | + |
| 64 | + resizePlayer: function(){ |
| 65 | + mw.log("SequenceEditPlayer:: resizePlayer: " + $j('#' + this.getSmilPlayerId() ).length ); |
| 66 | + $j('#' + this.getSmilPlayerId() ).get(0) |
| 67 | + .resizePlayer( |
| 68 | + this.getPlayerSize(), |
| 69 | + true |
| 70 | + ); |
| 71 | + }, |
| 72 | + |
| 73 | + getPlayerSize: function(){ |
| 74 | + var size = {}; |
| 75 | + var $playerContainer = this.sequenceEdit.getContainer().find('.mwseq-player'); |
| 76 | + size.width = $playerContainer.width(); |
| 77 | + if( this.sequenceEdit.videoAspect ){ |
| 78 | + var aspect = this.sequenceEdit.videoAspect.split( ':' ); |
| 79 | + var apectRatio = ( aspect[1] / aspect[0] ); |
| 80 | + size.height = parseInt( size.width * ( aspect[1] / aspect[0] ) ); |
| 81 | + } else { |
| 82 | + size.height = $playerContainer.width(); |
| 83 | + } |
| 84 | + // Check if we exceeded the max height |
| 85 | + if( size.height > $playerContainer.height() ){ |
| 86 | + size.height = $playerContainer.height(); |
| 87 | + size.width = parseInt( size.height * ( aspect[0] / aspect[1] ) ); |
| 88 | + } |
| 89 | + return size; |
| 90 | + }, |
| 91 | + |
| 92 | + /** |
| 93 | + * Get a player id based on |
| 94 | + */ |
| 95 | + getSmilPlayerId: function(){ |
| 96 | + if( !this.smilPlayerId ){ |
| 97 | + this.smilPlayerId = this.sequenceEdit.getId() + '_smilPlayer'; |
| 98 | + } |
| 99 | + return this.smilPlayerId; |
| 100 | + } |
| 101 | +} |
| 102 | + |
| 103 | + |
| 104 | +} )( window.mw ); |
\ No newline at end of file |
Index: branches/MwEmbedStandAlone/modules/SequenceEdit/ui.layout/ui.layout-1.2.0.js |
— | — | @@ -0,0 +1,2507 @@ |
| 2 | +/* |
| 3 | + * jquery.layout 1.2.0 |
| 4 | + * |
| 5 | + * Copyright (c) 2008 |
| 6 | + * Fabrizio Balliano (http://www.fabrizioballiano.net) |
| 7 | + * Kevin Dalman (http://allpro.net) |
| 8 | + * |
| 9 | + * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html) |
| 10 | + * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses. |
| 11 | + * |
| 12 | + * $Date: 2008-12-27 02:17:22 +0100 (sab, 27 dic 2008) $ |
| 13 | + * $Rev: 203 $ |
| 14 | + * |
| 15 | + * NOTE: For best code readability, view this with a fixed-space font and tabs equal to 4-chars |
| 16 | + */ |
| 17 | +(function($) { |
| 18 | + |
| 19 | +$.fn.layout = function (opts) { |
| 20 | + |
| 21 | +/* |
| 22 | + * ########################### |
| 23 | + * WIDGET CONFIG & OPTIONS |
| 24 | + * ########################### |
| 25 | + */ |
| 26 | + |
| 27 | + // DEFAULTS for options |
| 28 | + var |
| 29 | + prefix = "ui-layout-" // prefix for ALL selectors and classNames |
| 30 | + , defaults = { // misc default values |
| 31 | + paneClass: prefix+"pane" // ui-layout-pane |
| 32 | + , resizerClass: prefix+"resizer" // ui-layout-resizer |
| 33 | + , togglerClass: prefix+"toggler" // ui-layout-toggler |
| 34 | + , togglerInnerClass: prefix+"" // ui-layout-open / ui-layout-closed |
| 35 | + , buttonClass: prefix+"button" // ui-layout-button |
| 36 | + , contentSelector: "."+prefix+"content"// ui-layout-content |
| 37 | + , contentIgnoreSelector: "."+prefix+"ignore" // ui-layout-mask |
| 38 | + } |
| 39 | + ; |
| 40 | + |
| 41 | + // DEFAULT PANEL OPTIONS - CHANGE IF DESIRED |
| 42 | + var options = { |
| 43 | + name: "" // FUTURE REFERENCE - not used right now |
| 44 | + , scrollToBookmarkOnLoad: true // after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark) |
| 45 | + , defaults: { // default options for 'all panes' - will be overridden by 'per-pane settings' |
| 46 | + applyDefaultStyles: false // apply basic styles directly to resizers & buttons? If not, then stylesheet must handle it |
| 47 | + , closable: true // pane can open & close |
| 48 | + , resizable: true // when open, pane can be resized |
| 49 | + , slidable: true // when closed, pane can 'slide' open over other panes - closes on mouse-out |
| 50 | + //, paneSelector: [ ] // MUST be pane-specific! |
| 51 | + , contentSelector: defaults.contentSelector // INNER div/element to auto-size so only it scrolls, not the entire pane! |
| 52 | + , contentIgnoreSelector: defaults.contentIgnoreSelector // elem(s) to 'ignore' when measuring 'content' |
| 53 | + , paneClass: defaults.paneClass // border-Pane - default: 'ui-layout-pane' |
| 54 | + , resizerClass: defaults.resizerClass // Resizer Bar - default: 'ui-layout-resizer' |
| 55 | + , togglerClass: defaults.togglerClass // Toggler Button - default: 'ui-layout-toggler' |
| 56 | + , buttonClass: defaults.buttonClass // CUSTOM Buttons - default: 'ui-layout-button-toggle/-open/-close/-pin' |
| 57 | + , resizerDragOpacity: 1 // option for ui.draggable |
| 58 | + //, resizerCursor: "" // MUST be pane-specific - cursor when over resizer-bar |
| 59 | + , maskIframesOnResize: true // true = all iframes OR = iframe-selector(s) - adds masking-div during resizing/dragging |
| 60 | + //, size: 100 // inital size of pane - defaults are set 'per pane' |
| 61 | + , minSize: 0 // when manually resizing a pane |
| 62 | + , maxSize: 0 // ditto, 0 = no limit |
| 63 | + , spacing_open: 6 // space between pane and adjacent panes - when pane is 'open' |
| 64 | + , spacing_closed: 6 // ditto - when pane is 'closed' |
| 65 | + , togglerLength_open: 50 // Length = WIDTH of toggler button on north/south edges - HEIGHT on east/west edges |
| 66 | + , togglerLength_closed: 50 // 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden' |
| 67 | + , togglerAlign_open: "center" // top/left, bottom/right, center, OR... |
| 68 | + , togglerAlign_closed: "center" // 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right |
| 69 | + , togglerTip_open: "Close" // Toggler tool-tip (title) |
| 70 | + , togglerTip_closed: "Open" // ditto |
| 71 | + , resizerTip: "Resize" // Resizer tool-tip (title) |
| 72 | + , sliderTip: "Slide Open" // resizer-bar triggers 'sliding' when pane is closed |
| 73 | + , sliderCursor: "pointer" // cursor when resizer-bar will trigger 'sliding' |
| 74 | + , slideTrigger_open: "click" // click, dblclick, mouseover |
| 75 | + , slideTrigger_close: "mouseout" // click, mouseout |
| 76 | + , hideTogglerOnSlide: false // when pane is slid-open, should the toggler show? |
| 77 | + , togglerContent_open: "" // text or HTML to put INSIDE the toggler |
| 78 | + , togglerContent_closed: "" // ditto |
| 79 | + , showOverflowOnHover: false // will bind allowOverflow() utility to pane.onMouseOver |
| 80 | + , enableCursorHotkey: true // enabled 'cursor' hotkeys |
| 81 | + //, customHotkey: "" // MUST be pane-specific - EITHER a charCode OR a character |
| 82 | + , customHotkeyModifier: "SHIFT" // either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT' |
| 83 | + // NOTE: fxSss_open & fxSss_close options (eg: fxName_open) are auto-generated if not passed |
| 84 | + , fxName: "slide" // ('none' or blank), slide, drop, scale |
| 85 | + , fxSpeed: null // slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration |
| 86 | + , fxSettings: {} // can be passed, eg: { easing: "easeOutBounce", duration: 1500 } |
| 87 | + , initClosed: false // true = init pane as 'closed' |
| 88 | + , initHidden: false // true = init pane as 'hidden' - no resizer or spacing |
| 89 | + |
| 90 | + /* callback options do not have to be set - listed here for reference only |
| 91 | + , onshow_start: "" // CALLBACK when pane STARTS to Show - BEFORE onopen/onhide_start |
| 92 | + , onshow_end: "" // CALLBACK when pane ENDS being Shown - AFTER onopen/onhide_end |
| 93 | + , onhide_start: "" // CALLBACK when pane STARTS to Close - BEFORE onclose_start |
| 94 | + , onhide_end: "" // CALLBACK when pane ENDS being Closed - AFTER onclose_end |
| 95 | + , onopen_start: "" // CALLBACK when pane STARTS to Open |
| 96 | + , onopen_end: "" // CALLBACK when pane ENDS being Opened |
| 97 | + , onclose_start: "" // CALLBACK when pane STARTS to Close |
| 98 | + , onclose_end: "" // CALLBACK when pane ENDS being Closed |
| 99 | + , onresize_start: "" // CALLBACK when pane STARTS to be ***MANUALLY*** Resized |
| 100 | + , onresize_end: "" // CALLBACK when pane ENDS being Resized ***FOR ANY REASON*** |
| 101 | + */ |
| 102 | + } |
| 103 | + , north: { |
| 104 | + paneSelector: "."+prefix+"north" // default = .ui-layout-north |
| 105 | + , size: "auto" |
| 106 | + , resizerCursor: "n-resize" |
| 107 | + } |
| 108 | + , south: { |
| 109 | + paneSelector: "."+prefix+"south" // default = .ui-layout-south |
| 110 | + , size: "auto" |
| 111 | + , resizerCursor: "s-resize" |
| 112 | + } |
| 113 | + , east: { |
| 114 | + paneSelector: "."+prefix+"east" // default = .ui-layout-east |
| 115 | + , size: 200 |
| 116 | + , resizerCursor: "e-resize" |
| 117 | + } |
| 118 | + , west: { |
| 119 | + paneSelector: "."+prefix+"west" // default = .ui-layout-west |
| 120 | + , size: 200 |
| 121 | + , resizerCursor: "w-resize" |
| 122 | + } |
| 123 | + , center: { |
| 124 | + paneSelector: "."+prefix+"center" // default = .ui-layout-center |
| 125 | + } |
| 126 | + |
| 127 | + }; |
| 128 | + |
| 129 | + |
| 130 | + var effects = { // LIST *PREDEFINED EFFECTS* HERE, even if effect has no settings |
| 131 | + slide: { |
| 132 | + all: { duration: "fast" } // eg: duration: 1000, easing: "easeOutBounce" |
| 133 | + , north: { direction: "up" } |
| 134 | + , south: { direction: "down" } |
| 135 | + , east: { direction: "right"} |
| 136 | + , west: { direction: "left" } |
| 137 | + } |
| 138 | + , drop: { |
| 139 | + all: { duration: "slow" } // eg: duration: 1000, easing: "easeOutQuint" |
| 140 | + , north: { direction: "up" } |
| 141 | + , south: { direction: "down" } |
| 142 | + , east: { direction: "right"} |
| 143 | + , west: { direction: "left" } |
| 144 | + } |
| 145 | + , scale: { |
| 146 | + all: { duration: "fast" } |
| 147 | + } |
| 148 | + }; |
| 149 | + |
| 150 | + |
| 151 | + // STATIC, INTERNAL CONFIG - DO NOT CHANGE THIS! |
| 152 | + var config = { |
| 153 | + allPanes: "north,south,east,west,center" |
| 154 | + , borderPanes: "north,south,east,west" |
| 155 | + , zIndex: { // set z-index values here |
| 156 | + resizer_normal: 1 // normal z-index for resizer-bars |
| 157 | + , pane_normal: 2 // normal z-index for panes |
| 158 | + , mask: 4 // overlay div used to mask pane(s) during resizing |
| 159 | + , sliding: 100 // applied to both the pane and its resizer when a pane is 'slid open' |
| 160 | + , resizing: 10000 // applied to the CLONED resizer-bar when being 'dragged' |
| 161 | + , animation: 10000 // applied to the pane when being animated - not applied to the resizer |
| 162 | + } |
| 163 | + , resizers: { |
| 164 | + cssReq: { |
| 165 | + position: "absolute" |
| 166 | + , padding: 0 |
| 167 | + , margin: 0 |
| 168 | + , fontSize: "1px" |
| 169 | + , textAlign: "left" // to counter-act "center" alignment! |
| 170 | + , overflow: "hidden" // keep toggler button from overflowing |
| 171 | + , zIndex: 1 |
| 172 | + } |
| 173 | + , cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true |
| 174 | + background: "#DDD" |
| 175 | + , border: "none" |
| 176 | + } |
| 177 | + } |
| 178 | + , togglers: { |
| 179 | + cssReq: { |
| 180 | + position: "absolute" |
| 181 | + , display: "block" |
| 182 | + , padding: 0 |
| 183 | + , margin: 0 |
| 184 | + , overflow: "hidden" |
| 185 | + , textAlign: "center" |
| 186 | + , fontSize: "1px" |
| 187 | + , cursor: "pointer" |
| 188 | + , zIndex: 1 |
| 189 | + } |
| 190 | + , cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true |
| 191 | + background: "#AAA" |
| 192 | + } |
| 193 | + } |
| 194 | + , content: { |
| 195 | + cssReq: { |
| 196 | + overflow: "auto" |
| 197 | + } |
| 198 | + , cssDef: {} |
| 199 | + } |
| 200 | + , defaults: { // defaults for ALL panes - overridden by 'per-pane settings' below |
| 201 | + cssReq: { |
| 202 | + position: "absolute" |
| 203 | + , margin: 0 |
| 204 | + , zIndex: 2 |
| 205 | + } |
| 206 | + , cssDef: { |
| 207 | + padding: "10px" |
| 208 | + , background: "#FFF" |
| 209 | + , border: "1px solid #BBB" |
| 210 | + , overflow: "auto" |
| 211 | + } |
| 212 | + } |
| 213 | + , north: { |
| 214 | + edge: "top" |
| 215 | + , sizeType: "height" |
| 216 | + , dir: "horz" |
| 217 | + , cssReq: { |
| 218 | + top: 0 |
| 219 | + , bottom: "auto" |
| 220 | + , left: 0 |
| 221 | + , right: 0 |
| 222 | + , width: "auto" |
| 223 | + // height: DYNAMIC |
| 224 | + } |
| 225 | + } |
| 226 | + , south: { |
| 227 | + edge: "bottom" |
| 228 | + , sizeType: "height" |
| 229 | + , dir: "horz" |
| 230 | + , cssReq: { |
| 231 | + top: "auto" |
| 232 | + , bottom: 0 |
| 233 | + , left: 0 |
| 234 | + , right: 0 |
| 235 | + , width: "auto" |
| 236 | + // height: DYNAMIC |
| 237 | + } |
| 238 | + } |
| 239 | + , east: { |
| 240 | + edge: "right" |
| 241 | + , sizeType: "width" |
| 242 | + , dir: "vert" |
| 243 | + , cssReq: { |
| 244 | + left: "auto" |
| 245 | + , right: 0 |
| 246 | + , top: "auto" // DYNAMIC |
| 247 | + , bottom: "auto" // DYNAMIC |
| 248 | + , height: "auto" |
| 249 | + // width: DYNAMIC |
| 250 | + } |
| 251 | + } |
| 252 | + , west: { |
| 253 | + edge: "left" |
| 254 | + , sizeType: "width" |
| 255 | + , dir: "vert" |
| 256 | + , cssReq: { |
| 257 | + left: 0 |
| 258 | + , right: "auto" |
| 259 | + , top: "auto" // DYNAMIC |
| 260 | + , bottom: "auto" // DYNAMIC |
| 261 | + , height: "auto" |
| 262 | + // width: DYNAMIC |
| 263 | + } |
| 264 | + } |
| 265 | + , center: { |
| 266 | + dir: "center" |
| 267 | + , cssReq: { |
| 268 | + left: "auto" // DYNAMIC |
| 269 | + , right: "auto" // DYNAMIC |
| 270 | + , top: "auto" // DYNAMIC |
| 271 | + , bottom: "auto" // DYNAMIC |
| 272 | + , height: "auto" |
| 273 | + , width: "auto" |
| 274 | + } |
| 275 | + } |
| 276 | + }; |
| 277 | + |
| 278 | + |
| 279 | + // DYNAMIC DATA |
| 280 | + var state = { |
| 281 | + // generate random 'ID#' to identify layout - used to create global namespace for timers |
| 282 | + id: Math.floor(Math.random() * 10000) |
| 283 | + , container: {} |
| 284 | + , north: {} |
| 285 | + , south: {} |
| 286 | + , east: {} |
| 287 | + , west: {} |
| 288 | + , center: {} |
| 289 | + }; |
| 290 | + |
| 291 | + |
| 292 | + var |
| 293 | + altEdge = { |
| 294 | + top: "bottom" |
| 295 | + , bottom: "top" |
| 296 | + , left: "right" |
| 297 | + , right: "left" |
| 298 | + } |
| 299 | + , altSide = { |
| 300 | + north: "south" |
| 301 | + , south: "north" |
| 302 | + , east: "west" |
| 303 | + , west: "east" |
| 304 | + } |
| 305 | + ; |
| 306 | + |
| 307 | + |
| 308 | +/* |
| 309 | + * ########################### |
| 310 | + * INTERNAL HELPER FUNCTIONS |
| 311 | + * ########################### |
| 312 | + */ |
| 313 | + |
| 314 | + /** |
| 315 | + * isStr |
| 316 | + * |
| 317 | + * Returns true if passed param is EITHER a simple string OR a 'string object' - otherwise returns false |
| 318 | + */ |
| 319 | + var isStr = function (o) { |
| 320 | + if (typeof o == "string") |
| 321 | + return true; |
| 322 | + else if (typeof o == "object") { |
| 323 | + try { |
| 324 | + var match = o.constructor.toString().match(/string/i); |
| 325 | + return (match !== null); |
| 326 | + } catch (e) {} |
| 327 | + } |
| 328 | + return false; |
| 329 | + }; |
| 330 | + |
| 331 | + /** |
| 332 | + * str |
| 333 | + * |
| 334 | + * Returns a simple string if the passed param is EITHER a simple string OR a 'string object', |
| 335 | + * else returns the original object |
| 336 | + */ |
| 337 | + var str = function (o) { |
| 338 | + if (typeof o == "string" || isStr(o)) return $.trim(o); // trim converts 'String object' to a simple string |
| 339 | + else return o; |
| 340 | + }; |
| 341 | + |
| 342 | + /** |
| 343 | + * min / max |
| 344 | + * |
| 345 | + * Alias for Math.min/.max to simplify coding |
| 346 | + */ |
| 347 | + var min = function (x,y) { return Math.min(x,y); }; |
| 348 | + var max = function (x,y) { return Math.max(x,y); }; |
| 349 | + |
| 350 | + /** |
| 351 | + * transformData |
| 352 | + * |
| 353 | + * Processes the options passed in and transforms them into the format used by layout() |
| 354 | + * Missing keys are added, and converts the data if passed in 'flat-format' (no sub-keys) |
| 355 | + * In flat-format, pane-specific-settings are prefixed like: north__optName (2-underscores) |
| 356 | + * To update effects, options MUST use nested-keys format, with an effects key |
| 357 | + * |
| 358 | + * @callers initOptions() |
| 359 | + * @params JSON d Data/options passed by user - may be a single level or nested levels |
| 360 | + * @returns JSON Creates a data struture that perfectly matches 'options', ready to be imported |
| 361 | + */ |
| 362 | + var transformData = function (d) { |
| 363 | + var json = { defaults:{fxSettings:{}}, north:{fxSettings:{}}, south:{fxSettings:{}}, east:{fxSettings:{}}, west:{fxSettings:{}}, center:{fxSettings:{}} }; |
| 364 | + d = d || {}; |
| 365 | + if (d.effects || d.defaults || d.north || d.south || d.west || d.east || d.center) |
| 366 | + json = $.extend( json, d ); // already in json format - add to base keys |
| 367 | + else |
| 368 | + // convert 'flat' to 'nest-keys' format - also handles 'empty' user-options |
| 369 | + $.each( d, function (key,val) { |
| 370 | + a = key.split("__"); |
| 371 | + json[ a[1] ? a[0] : "defaults" ][ a[1] ? a[1] : a[0] ] = val; |
| 372 | + }); |
| 373 | + return json; |
| 374 | + }; |
| 375 | + |
| 376 | + /** |
| 377 | + * setFlowCallback |
| 378 | + * |
| 379 | + * Set an INTERNAL callback to avoid simultaneous animation |
| 380 | + * Runs only if needed and only if all callbacks are not 'already set'! |
| 381 | + * |
| 382 | + * @param String action Either 'open' or 'close' |
| 383 | + * @pane String pane A valid border-pane name, eg 'west' |
| 384 | + * @pane Boolean param Extra param for callback (optional) |
| 385 | + */ |
| 386 | + var setFlowCallback = function (action, pane, param) { |
| 387 | + var |
| 388 | + cb = action +","+ pane +","+ (param ? 1 : 0) |
| 389 | + , cP, cbPane |
| 390 | + ; |
| 391 | + $.each(c.borderPanes.split(","), function (i,p) { |
| 392 | + if (c[p].isMoving) { |
| 393 | + bindCallback(p); // TRY to bind a callback |
| 394 | + return false; // BREAK |
| 395 | + } |
| 396 | + }); |
| 397 | + |
| 398 | + function bindCallback (p, test) { |
| 399 | + cP = c[p]; |
| 400 | + if (!cP.doCallback) { |
| 401 | + cP.doCallback = true; |
| 402 | + cP.callback = cb; |
| 403 | + } |
| 404 | + else { // try to 'chain' this callback |
| 405 | + cpPane = cP.callback.split(",")[1]; // 2nd param is 'pane' |
| 406 | + if (cpPane != p && cpPane != pane) // callback target NOT 'itself' and NOT 'this pane' |
| 407 | + bindCallback (cpPane, true); // RECURSE |
| 408 | + } |
| 409 | + } |
| 410 | + }; |
| 411 | + |
| 412 | + /** |
| 413 | + * execFlowCallback |
| 414 | + * |
| 415 | + * RUN the INTERNAL callback for this pane - if one exists |
| 416 | + * |
| 417 | + * @param String action Either 'open' or 'close' |
| 418 | + * @pane String pane A valid border-pane name, eg 'west' |
| 419 | + * @pane Boolean param Extra param for callback (optional) |
| 420 | + */ |
| 421 | + var execFlowCallback = function (pane) { |
| 422 | + var cP = c[pane]; |
| 423 | + |
| 424 | + // RESET flow-control flaGs |
| 425 | + c.isLayoutBusy = false; |
| 426 | + delete cP.isMoving; |
| 427 | + if (!cP.doCallback || !cP.callback) return; |
| 428 | + |
| 429 | + cP.doCallback = false; // RESET logic flag |
| 430 | + |
| 431 | + // EXECUTE the callback |
| 432 | + var |
| 433 | + cb = cP.callback.split(",") |
| 434 | + , param = (cb[2] > 0 ? true : false) |
| 435 | + ; |
| 436 | + if (cb[0] == "open") |
| 437 | + open( cb[1], param ); |
| 438 | + else if (cb[0] == "close") |
| 439 | + close( cb[1], param ); |
| 440 | + |
| 441 | + if (!cP.doCallback) cP.callback = null; // RESET - unless callback above enabled it again! |
| 442 | + }; |
| 443 | + |
| 444 | + /** |
| 445 | + * execUserCallback |
| 446 | + * |
| 447 | + * Executes a Callback function after a trigger event, like resize, open or close |
| 448 | + * |
| 449 | + * @param String pane This is passed only so we can pass the 'pane object' to the callback |
| 450 | + * @param String v_fn Accepts a function name, OR a comma-delimited array: [0]=function name, [1]=argument |
| 451 | + */ |
| 452 | + var execUserCallback = function (pane, v_fn) { |
| 453 | + if (!v_fn) return; |
| 454 | + var fn; |
| 455 | + try { |
| 456 | + if (typeof v_fn == "function") |
| 457 | + fn = v_fn; |
| 458 | + else if (typeof v_fn != "string") |
| 459 | + return; |
| 460 | + else if (v_fn.indexOf(",") > 0) { |
| 461 | + // function name cannot contain a comma, so must be a function name AND a 'name' parameter |
| 462 | + var |
| 463 | + args = v_fn.split(",") |
| 464 | + , fn = eval(args[0]) |
| 465 | + ; |
| 466 | + if (typeof fn=="function" && args.length > 1) |
| 467 | + return fn(args[1]); // pass the argument parsed from 'list' |
| 468 | + } |
| 469 | + else // just the name of an external function? |
| 470 | + fn = eval(v_fn); |
| 471 | + |
| 472 | + if (typeof fn=="function") |
| 473 | + // pass data: pane-name, pane-element, pane-state, pane-options, and layout-name |
| 474 | + return fn( pane, $Ps[pane], $.extend({},state[pane]), $.extend({},options[pane]), options.name ); |
| 475 | + } |
| 476 | + catch (ex) {} |
| 477 | + }; |
| 478 | + |
| 479 | + /** |
| 480 | + * cssNum |
| 481 | + * |
| 482 | + * Returns the 'current CSS value' for an element - returns 0 if property does not exist |
| 483 | + * |
| 484 | + * @callers Called by many methods |
| 485 | + * @param jQuery $Elem Must pass a jQuery object - first element is processed |
| 486 | + * @param String property The name of the CSS property, eg: top, width, etc. |
| 487 | + * @returns Variant Usually is used to get an integer value for position (top, left) or size (height, width) |
| 488 | + */ |
| 489 | + var cssNum = function ($E, prop) { |
| 490 | + var |
| 491 | + val = 0 |
| 492 | + , hidden = false |
| 493 | + , visibility = "" |
| 494 | + ; |
| 495 | + if (!$.browser.msie) { // IE CAN read dimensions of 'hidden' elements - FF CANNOT |
| 496 | + if ($.curCSS($E[0], "display", true) == "none") { |
| 497 | + hidden = true; |
| 498 | + visibility = $.curCSS($E[0], "visibility", true); // SAVE current setting |
| 499 | + $E.css({ display: "block", visibility: "hidden" }); // show element 'invisibly' so we can measure it |
| 500 | + } |
| 501 | + } |
| 502 | + |
| 503 | + val = parseInt($.curCSS($E[0], prop, true), 10) || 0; |
| 504 | + |
| 505 | + if (hidden) { // WAS hidden, so put back the way it was |
| 506 | + $E.css({ display: "none" }); |
| 507 | + if (visibility && visibility != "hidden") |
| 508 | + $E.css({ visibility: visibility }); // reset 'visibility' |
| 509 | + } |
| 510 | + |
| 511 | + return val; |
| 512 | + }; |
| 513 | + |
| 514 | + /** |
| 515 | + * cssW / cssH / cssSize |
| 516 | + * |
| 517 | + * Contains logic to check boxModel & browser, and return the correct width/height for the current browser/doctype |
| 518 | + * |
| 519 | + * @callers initPanes(), sizeMidPanes(), initHandles(), sizeHandles() |
| 520 | + * @param Variant elem Can accept a 'pane' (east, west, etc) OR a DOM object OR a jQuery object |
| 521 | + * @param Integer outerWidth/outerHeight (optional) Can pass a width, allowing calculations BEFORE element is resized |
| 522 | + * @returns Integer Returns the innerHeight of the elem by subtracting padding and borders |
| 523 | + * |
| 524 | + * @TODO May need to add additional logic to handle more browser/doctype variations? |
| 525 | + */ |
| 526 | + var cssW = function (e, outerWidth) { |
| 527 | + var $E; |
| 528 | + if (isStr(e)) { |
| 529 | + e = str(e); |
| 530 | + $E = $Ps[e]; |
| 531 | + } |
| 532 | + else |
| 533 | + $E = $(e); |
| 534 | + |
| 535 | + // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed |
| 536 | + if (outerWidth <= 0) |
| 537 | + return 0; |
| 538 | + else if (!(outerWidth>0)) |
| 539 | + outerWidth = isStr(e) ? getPaneSize(e) : $E.outerWidth(); |
| 540 | + |
| 541 | + if (!$.boxModel) |
| 542 | + return outerWidth; |
| 543 | + |
| 544 | + else // strip border and padding size from outerWidth to get CSS Width |
| 545 | + return outerWidth |
| 546 | + - cssNum($E, "paddingLeft") |
| 547 | + - cssNum($E, "paddingRight") |
| 548 | + - ($.curCSS($E[0], "borderLeftStyle", true) == "none" ? 0 : cssNum($E, "borderLeftWidth")) |
| 549 | + - ($.curCSS($E[0], "borderRightStyle", true) == "none" ? 0 : cssNum($E, "borderRightWidth")) |
| 550 | + ; |
| 551 | + }; |
| 552 | + var cssH = function (e, outerHeight) { |
| 553 | + var $E; |
| 554 | + if (isStr(e)) { |
| 555 | + e = str(e); |
| 556 | + $E = $Ps[e]; |
| 557 | + } |
| 558 | + else |
| 559 | + $E = $(e); |
| 560 | + |
| 561 | + // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed |
| 562 | + if (outerHeight <= 0) |
| 563 | + return 0; |
| 564 | + else if (!(outerHeight>0)) |
| 565 | + outerHeight = (isStr(e)) ? getPaneSize(e) : $E.outerHeight(); |
| 566 | + |
| 567 | + if (!$.boxModel) |
| 568 | + return outerHeight; |
| 569 | + |
| 570 | + else // strip border and padding size from outerHeight to get CSS Height |
| 571 | + return outerHeight |
| 572 | + - cssNum($E, "paddingTop") |
| 573 | + - cssNum($E, "paddingBottom") |
| 574 | + - ($.curCSS($E[0], "borderTopStyle", true) == "none" ? 0 : cssNum($E, "borderTopWidth")) |
| 575 | + - ($.curCSS($E[0], "borderBottomStyle", true) == "none" ? 0 : cssNum($E, "borderBottomWidth")) |
| 576 | + ; |
| 577 | + }; |
| 578 | + var cssSize = function (pane, outerSize) { |
| 579 | + if (c[pane].dir=="horz") // pane = north or south |
| 580 | + return cssH(pane, outerSize); |
| 581 | + else // pane = east or west |
| 582 | + return cssW(pane, outerSize); |
| 583 | + }; |
| 584 | + |
| 585 | + /** |
| 586 | + * getPaneSize |
| 587 | + * |
| 588 | + * Calculates the current 'size' (width or height) of a border-pane - optionally with 'pane spacing' added |
| 589 | + * |
| 590 | + * @returns Integer Returns EITHER Width for east/west panes OR Height for north/south panes - adjusted for boxModel & browser |
| 591 | + */ |
| 592 | + var getPaneSize = function (pane, inclSpace) { |
| 593 | + var |
| 594 | + $P = $Ps[pane] |
| 595 | + , o = options[pane] |
| 596 | + , s = state[pane] |
| 597 | + , oSp = (inclSpace ? o.spacing_open : 0) |
| 598 | + , cSp = (inclSpace ? o.spacing_closed : 0) |
| 599 | + ; |
| 600 | + if (!$P || s.isHidden) |
| 601 | + return 0; |
| 602 | + else if (s.isClosed || (s.isSliding && inclSpace)) |
| 603 | + return cSp; |
| 604 | + else if (c[pane].dir == "horz") |
| 605 | + return $P.outerHeight() + oSp; |
| 606 | + else // dir == "vert" |
| 607 | + return $P.outerWidth() + oSp; |
| 608 | + }; |
| 609 | + |
| 610 | + var setPaneMinMaxSizes = function (pane) { |
| 611 | + var |
| 612 | + d = cDims |
| 613 | + , edge = c[pane].edge |
| 614 | + , dir = c[pane].dir |
| 615 | + , o = options[pane] |
| 616 | + , s = state[pane] |
| 617 | + , $P = $Ps[pane] |
| 618 | + , $altPane = $Ps[ altSide[pane] ] |
| 619 | + , paneSpacing = o.spacing_open |
| 620 | + , altPaneSpacing = options[ altSide[pane] ].spacing_open |
| 621 | + , altPaneSize = (!$altPane ? 0 : (dir=="horz" ? $altPane.outerHeight() : $altPane.outerWidth())) |
| 622 | + , containerSize = (dir=="horz" ? d.innerHeight : d.innerWidth) |
| 623 | + // limitSize prevents this pane from 'overlapping' opposite pane - even if opposite pane is currently closed |
| 624 | + , limitSize = containerSize - paneSpacing - altPaneSize - altPaneSpacing |
| 625 | + , minSize = s.minSize || 0 |
| 626 | + , maxSize = Math.min(s.maxSize || 9999, limitSize) |
| 627 | + , minPos, maxPos // used to set resizing limits |
| 628 | + ; |
| 629 | + switch (pane) { |
| 630 | + case "north": minPos = d.offsetTop + minSize; |
| 631 | + maxPos = d.offsetTop + maxSize; |
| 632 | + break; |
| 633 | + case "west": minPos = d.offsetLeft + minSize; |
| 634 | + maxPos = d.offsetLeft + maxSize; |
| 635 | + break; |
| 636 | + case "south": minPos = d.offsetTop + d.innerHeight - maxSize; |
| 637 | + maxPos = d.offsetTop + d.innerHeight - minSize; |
| 638 | + break; |
| 639 | + case "east": minPos = d.offsetLeft + d.innerWidth - maxSize; |
| 640 | + maxPos = d.offsetLeft + d.innerWidth - minSize; |
| 641 | + break; |
| 642 | + } |
| 643 | + // save data to pane-state |
| 644 | + $.extend(s, { minSize: minSize, maxSize: maxSize, minPosition: minPos, maxPosition: maxPos }); |
| 645 | + }; |
| 646 | + |
| 647 | + /** |
| 648 | + * getPaneDims |
| 649 | + * |
| 650 | + * Returns data for setting the size/position of center pane. Date is also used to set Height for east/west panes |
| 651 | + * |
| 652 | + * @returns JSON Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height |
| 653 | + */ |
| 654 | + var getPaneDims = function () { |
| 655 | + var d = { |
| 656 | + top: getPaneSize("north", true) // true = include 'spacing' value for p |
| 657 | + , bottom: getPaneSize("south", true) |
| 658 | + , left: getPaneSize("west", true) |
| 659 | + , right: getPaneSize("east", true) |
| 660 | + , width: 0 |
| 661 | + , height: 0 |
| 662 | + }; |
| 663 | + |
| 664 | + with (d) { |
| 665 | + width = cDims.innerWidth - left - right; |
| 666 | + height = cDims.innerHeight - bottom - top; |
| 667 | + // now add the 'container border/padding' to get final positions - relative to the container |
| 668 | + top += cDims.top; |
| 669 | + bottom += cDims.bottom; |
| 670 | + left += cDims.left; |
| 671 | + right += cDims.right; |
| 672 | + } |
| 673 | + |
| 674 | + return d; |
| 675 | + }; |
| 676 | + |
| 677 | + |
| 678 | + /** |
| 679 | + * getElemDims |
| 680 | + * |
| 681 | + * Returns data for setting size of an element (container or a pane). |
| 682 | + * |
| 683 | + * @callers create(), onWindowResize() for container, plus others for pane |
| 684 | + * @returns JSON Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc |
| 685 | + */ |
| 686 | + var getElemDims = function ($E) { |
| 687 | + var |
| 688 | + d = {} // dimensions hash |
| 689 | + , e, b, p // edge, border, padding |
| 690 | + ; |
| 691 | + |
| 692 | + $.each("Left,Right,Top,Bottom".split(","), function () { |
| 693 | + e = str(this); |
| 694 | + b = d["border" +e] = cssNum($E, "border"+e+"Width"); |
| 695 | + p = d["padding"+e] = cssNum($E, "padding"+e); |
| 696 | + d["offset" +e] = b + p; // total offset of content from outer edge |
| 697 | + // if BOX MODEL, then 'position' = PADDING (ignore borderWidth) |
| 698 | + if ($E == $Container) |
| 699 | + d[e.toLowerCase()] = ($.boxModel ? p : 0); |
| 700 | + }); |
| 701 | + |
| 702 | + d.innerWidth = d.outerWidth = $E.outerWidth(); |
| 703 | + d.innerHeight = d.outerHeight = $E.outerHeight(); |
| 704 | + if ($.boxModel) { |
| 705 | + d.innerWidth -= (d.offsetLeft + d.offsetRight); |
| 706 | + d.innerHeight -= (d.offsetTop + d.offsetBottom); |
| 707 | + } |
| 708 | + |
| 709 | + return d; |
| 710 | + }; |
| 711 | + |
| 712 | + |
| 713 | + var setTimer = function (pane, action, fn, ms) { |
| 714 | + var |
| 715 | + Layout = window.layout = window.layout || {} |
| 716 | + , Timers = Layout.timers = Layout.timers || {} |
| 717 | + , name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action |
| 718 | + ; |
| 719 | + if (Timers[name]) return; // timer already set! |
| 720 | + else Timers[name] = setTimeout(fn, ms); |
| 721 | + }; |
| 722 | + |
| 723 | + var clearTimer = function (pane, action) { |
| 724 | + var |
| 725 | + Layout = window.layout = window.layout || {} |
| 726 | + , Timers = Layout.timers = Layout.timers || {} |
| 727 | + , name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action |
| 728 | + ; |
| 729 | + if (Timers[name]) { |
| 730 | + clearTimeout( Timers[name] ); |
| 731 | + delete Timers[name]; |
| 732 | + return true; |
| 733 | + } |
| 734 | + else |
| 735 | + return false; |
| 736 | + }; |
| 737 | + |
| 738 | + |
| 739 | +/* |
| 740 | + * ########################### |
| 741 | + * INITIALIZATION METHODS |
| 742 | + * ########################### |
| 743 | + */ |
| 744 | + |
| 745 | + /** |
| 746 | + * create |
| 747 | + * |
| 748 | + * Initialize the layout - called automatically whenever an instance of layout is created |
| 749 | + * |
| 750 | + * @callers NEVER explicity called |
| 751 | + * @returns An object pointer to the instance created |
| 752 | + */ |
| 753 | + var create = function () { |
| 754 | + // initialize config/options |
| 755 | + initOptions(); |
| 756 | + |
| 757 | + // initialize all objects |
| 758 | + initContainer(); // set CSS as needed and init state.container dimensions |
| 759 | + initPanes(); // size & position all panes |
| 760 | + initHandles(); // create and position all resize bars & togglers buttons |
| 761 | + initResizable(); // activate resizing on all panes where resizable=true |
| 762 | + sizeContent("all"); // AFTER panes & handles have been initialized, size 'content' divs |
| 763 | + |
| 764 | + if (options.scrollToBookmarkOnLoad) |
| 765 | + with (self.location) if (hash) replace( hash ); // scrollTo Bookmark |
| 766 | + |
| 767 | + // bind hotkey function - keyDown - if required |
| 768 | + initHotkeys(); |
| 769 | + |
| 770 | + // bind resizeAll() for 'this layout instance' to window.resize event |
| 771 | + $(window).resize(function () { |
| 772 | + var timerID = "timerLayout_"+state.id; |
| 773 | + if (window[timerID]) clearTimeout(window[timerID]); |
| 774 | + window[timerID] = null; |
| 775 | + if (true || $.browser.msie) // use a delay for IE because the resize event fires repeatly |
| 776 | + window[timerID] = setTimeout(resizeAll, 100); |
| 777 | + else // most other browsers have a built-in delay before firing the resize event |
| 778 | + resizeAll(); // resize all layout elements NOW! |
| 779 | + }); |
| 780 | + }; |
| 781 | + |
| 782 | + /** |
| 783 | + * initContainer |
| 784 | + * |
| 785 | + * Validate and initialize container CSS and events |
| 786 | + * |
| 787 | + * @callers create() |
| 788 | + */ |
| 789 | + var initContainer = function () { |
| 790 | + try { // format html/body if this is a full page layout |
| 791 | + if ($Container[0].tagName == "BODY") { |
| 792 | + $("html").css({ |
| 793 | + height: "100%" |
| 794 | + , overflow: "hidden" |
| 795 | + }); |
| 796 | + $("body").css({ |
| 797 | + position: "relative" |
| 798 | + , height: "100%" |
| 799 | + , overflow: "hidden" |
| 800 | + , margin: 0 |
| 801 | + , padding: 0 // TODO: test whether body-padding could be handled? |
| 802 | + , border: "none" // a body-border creates problems because it cannot be measured! |
| 803 | + }); |
| 804 | + } |
| 805 | + else { // set required CSS - overflow and position |
| 806 | + var |
| 807 | + CSS = { overflow: "hidden" } // make sure container will not 'scroll' |
| 808 | + , p = $Container.css("position") |
| 809 | + , h = $Container.css("height") |
| 810 | + ; |
| 811 | + // if this is a NESTED layout, then outer-pane ALREADY has position and height |
| 812 | + if (!$Container.hasClass("ui-layout-pane")) { |
| 813 | + if (!p || "fixed,absolute,relative".indexOf(p) < 0) |
| 814 | + CSS.position = "relative"; // container MUST have a 'position' |
| 815 | + if (!h || h=="auto") |
| 816 | + CSS.height = "100%"; // container MUST have a 'height' |
| 817 | + } |
| 818 | + $Container.css( CSS ); |
| 819 | + } |
| 820 | + } catch (ex) {} |
| 821 | + |
| 822 | + // get layout-container dimensions (updated when necessary) |
| 823 | + cDims = state.container = getElemDims( $Container ); // update data-pointer too |
| 824 | + }; |
| 825 | + |
| 826 | + /** |
| 827 | + * initHotkeys |
| 828 | + * |
| 829 | + * Bind layout hotkeys - if options enabled |
| 830 | + * |
| 831 | + * @callers create() |
| 832 | + */ |
| 833 | + var initHotkeys = function () { |
| 834 | + // bind keyDown to capture hotkeys, if option enabled for ANY pane |
| 835 | + $.each(c.borderPanes.split(","), function (i,pane) { |
| 836 | + var o = options[pane]; |
| 837 | + if (o.enableCursorHotkey || o.customHotkey) { |
| 838 | + $(document).keydown( keyDown ); // only need to bind this ONCE |
| 839 | + return false; // BREAK - binding was done |
| 840 | + } |
| 841 | + }); |
| 842 | + }; |
| 843 | + |
| 844 | + /** |
| 845 | + * initOptions |
| 846 | + * |
| 847 | + * Build final CONFIG and OPTIONS data |
| 848 | + * |
| 849 | + * @callers create() |
| 850 | + */ |
| 851 | + var initOptions = function () { |
| 852 | + // simplify logic by making sure passed 'opts' var has basic keys |
| 853 | + opts = transformData( opts ); |
| 854 | + |
| 855 | + // update default effects, if case user passed key |
| 856 | + if (opts.effects) { |
| 857 | + $.extend( effects, opts.effects ); |
| 858 | + delete opts.effects; |
| 859 | + } |
| 860 | + |
| 861 | + // see if any 'global options' were specified |
| 862 | + $.each("name,scrollToBookmarkOnLoad".split(","), function (idx,key) { |
| 863 | + if (opts[key] !== undefined) |
| 864 | + options[key] = opts[key]; |
| 865 | + else if (opts.defaults[key] !== undefined) { |
| 866 | + options[key] = opts.defaults[key]; |
| 867 | + delete opts.defaults[key]; |
| 868 | + } |
| 869 | + }); |
| 870 | + |
| 871 | + // remove any 'defaults' that MUST be set 'per-pane' |
| 872 | + $.each("paneSelector,resizerCursor,customHotkey".split(","), |
| 873 | + function (idx,key) { delete opts.defaults[key]; } // is OK if key does not exist |
| 874 | + ); |
| 875 | + |
| 876 | + // now update options.defaults |
| 877 | + $.extend( options.defaults, opts.defaults ); |
| 878 | + // make sure required sub-keys exist |
| 879 | + //if (typeof options.defaults.fxSettings != "object") options.defaults.fxSettings = {}; |
| 880 | + |
| 881 | + // merge all config & options for the 'center' pane |
| 882 | + c.center = $.extend( true, {}, c.defaults, c.center ); |
| 883 | + $.extend( options.center, opts.center ); |
| 884 | + // Most 'default options' do not apply to 'center', so add only those that DO |
| 885 | + var o_Center = $.extend( true, {}, options.defaults, opts.defaults, options.center ); // TEMP data |
| 886 | + $.each("paneClass,contentSelector,contentIgnoreSelector,applyDefaultStyles,showOverflowOnHover".split(","), |
| 887 | + function (idx,key) { options.center[key] = o_Center[key]; } |
| 888 | + ); |
| 889 | + |
| 890 | + var defs = options.defaults; |
| 891 | + |
| 892 | + // create a COMPLETE set of options for EACH border-pane |
| 893 | + $.each(c.borderPanes.split(","), function(i,pane) { |
| 894 | + // apply 'pane-defaults' to CONFIG.PANE |
| 895 | + c[pane] = $.extend( true, {}, c.defaults, c[pane] ); |
| 896 | + // apply 'pane-defaults' + user-options to OPTIONS.PANE |
| 897 | + o = options[pane] = $.extend( true, {}, options.defaults, options[pane], opts.defaults, opts[pane] ); |
| 898 | + |
| 899 | + // make sure we have base-classes |
| 900 | + if (!o.paneClass) o.paneClass = defaults.paneClass; |
| 901 | + if (!o.resizerClass) o.resizerClass = defaults.resizerClass; |
| 902 | + if (!o.togglerClass) o.togglerClass = defaults.togglerClass; |
| 903 | + |
| 904 | + // create FINAL fx options for each pane, ie: options.PANE.fxName/fxSpeed/fxSettings[_open|_close] |
| 905 | + $.each(["_open","_close",""], function (i,n) { |
| 906 | + var |
| 907 | + sName = "fxName"+n |
| 908 | + , sSpeed = "fxSpeed"+n |
| 909 | + , sSettings = "fxSettings"+n |
| 910 | + ; |
| 911 | + // recalculate fxName according to specificity rules |
| 912 | + o[sName] = |
| 913 | + opts[pane][sName] // opts.west.fxName_open |
| 914 | + || opts[pane].fxName // opts.west.fxName |
| 915 | + || opts.defaults[sName] // opts.defaults.fxName_open |
| 916 | + || opts.defaults.fxName // opts.defaults.fxName |
| 917 | + || o[sName] // options.west.fxName_open |
| 918 | + || o.fxName // options.west.fxName |
| 919 | + || defs[sName] // options.defaults.fxName_open |
| 920 | + || defs.fxName // options.defaults.fxName |
| 921 | + || "none" |
| 922 | + ; |
| 923 | + // validate fxName to be sure is a valid effect |
| 924 | + var fxName = o[sName]; |
| 925 | + if (fxName == "none" || !$.effects || !$.effects[fxName] || (!effects[fxName] && !o[sSettings] && !o.fxSettings)) |
| 926 | + fxName = o[sName] = "none"; // effect not loaded, OR undefined FX AND fxSettings not passed |
| 927 | + // set vars for effects subkeys to simplify logic |
| 928 | + var |
| 929 | + fx = effects[fxName] || {} // effects.slide |
| 930 | + , fx_all = fx.all || {} // effects.slide.all |
| 931 | + , fx_pane = fx[pane] || {} // effects.slide.west |
| 932 | + ; |
| 933 | + // RECREATE the fxSettings[_open|_close] keys using specificity rules |
| 934 | + o[sSettings] = $.extend( |
| 935 | + {} |
| 936 | + , fx_all // effects.slide.all |
| 937 | + , fx_pane // effects.slide.west |
| 938 | + , defs.fxSettings || {} // options.defaults.fxSettings |
| 939 | + , defs[sSettings] || {} // options.defaults.fxSettings_open |
| 940 | + , o.fxSettings // options.west.fxSettings |
| 941 | + , o[sSettings] // options.west.fxSettings_open |
| 942 | + , opts.defaults.fxSettings // opts.defaults.fxSettings |
| 943 | + , opts.defaults[sSettings] || {} // opts.defaults.fxSettings_open |
| 944 | + , opts[pane].fxSettings // opts.west.fxSettings |
| 945 | + , opts[pane][sSettings] || {} // opts.west.fxSettings_open |
| 946 | + ); |
| 947 | + // recalculate fxSpeed according to specificity rules |
| 948 | + o[sSpeed] = |
| 949 | + opts[pane][sSpeed] // opts.west.fxSpeed_open |
| 950 | + || opts[pane].fxSpeed // opts.west.fxSpeed (pane-default) |
| 951 | + || opts.defaults[sSpeed] // opts.defaults.fxSpeed_open |
| 952 | + || opts.defaults.fxSpeed // opts.defaults.fxSpeed |
| 953 | + || o[sSpeed] // options.west.fxSpeed_open |
| 954 | + || o[sSettings].duration // options.west.fxSettings_open.duration |
| 955 | + || o.fxSpeed // options.west.fxSpeed |
| 956 | + || o.fxSettings.duration // options.west.fxSettings.duration |
| 957 | + || defs.fxSpeed // options.defaults.fxSpeed |
| 958 | + || defs.fxSettings.duration// options.defaults.fxSettings.duration |
| 959 | + || fx_pane.duration // effects.slide.west.duration |
| 960 | + || fx_all.duration // effects.slide.all.duration |
| 961 | + || "normal" // DEFAULT |
| 962 | + ; |
| 963 | + // DEBUG: if (pane=="east") debugData( $.extend({}, {speed: o[sSpeed], fxSettings_duration: o[sSettings].duration}, o[sSettings]), pane+"."+sName+" = "+fxName ); |
| 964 | + }); |
| 965 | + }); |
| 966 | + }; |
| 967 | + |
| 968 | + /** |
| 969 | + * initPanes |
| 970 | + * |
| 971 | + * Initialize module objects, styling, size and position for all panes |
| 972 | + * |
| 973 | + * @callers create() |
| 974 | + */ |
| 975 | + var initPanes = function () { |
| 976 | + // NOTE: do north & south FIRST so we can measure their height - do center LAST |
| 977 | + $.each(c.allPanes.split(","), function() { |
| 978 | + var |
| 979 | + pane = str(this) |
| 980 | + , o = options[pane] |
| 981 | + , s = state[pane] |
| 982 | + , fx = s.fx |
| 983 | + , dir = c[pane].dir |
| 984 | + // if o.size is not > 0, then we will use MEASURE the pane and use that as it's 'size' |
| 985 | + , size = o.size=="auto" || isNaN(o.size) ? 0 : o.size |
| 986 | + , minSize = o.minSize || 1 |
| 987 | + , maxSize = o.maxSize || 9999 |
| 988 | + , spacing = o.spacing_open || 0 |
| 989 | + , sel = o.paneSelector |
| 990 | + , isIE6 = ($.browser.msie && $.browser.version < 7) |
| 991 | + , CSS = {} |
| 992 | + , $P, $C |
| 993 | + ; |
| 994 | + $Cs[pane] = false; // init |
| 995 | + |
| 996 | + if (sel.substr(0,1)==="#") // ID selector |
| 997 | + // NOTE: elements selected 'by ID' DO NOT have to be 'children' |
| 998 | + $P = $Ps[pane] = $Container.find(sel+":first"); |
| 999 | + else { // class or other selector |
| 1000 | + $P = $Ps[pane] = $Container.children(sel+":first"); |
| 1001 | + // look for the pane nested inside a 'form' element |
| 1002 | + if (!$P.length) $P = $Ps[pane] = $Container.children("form:first").children(sel+":first"); |
| 1003 | + } |
| 1004 | + |
| 1005 | + if (!$P.length) { |
| 1006 | + $Ps[pane] = false; // logic |
| 1007 | + return true; // SKIP to next |
| 1008 | + } |
| 1009 | + |
| 1010 | + // add basic classes & attributes |
| 1011 | + $P |
| 1012 | + .attr("pane", pane) // add pane-identifier |
| 1013 | + .addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector' |
| 1014 | + ; |
| 1015 | + |
| 1016 | + // init pane-logic vars, etc. |
| 1017 | + if (pane != "center") { |
| 1018 | + s.isClosed = false; // true = pane is closed |
| 1019 | + s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes |
| 1020 | + s.isResizing= false; // true = pane is in process of being resized |
| 1021 | + s.isHidden = false; // true = pane is hidden - no spacing, resizer or toggler is visible! |
| 1022 | + s.noRoom = false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically |
| 1023 | + // create special keys for internal use |
| 1024 | + c[pane].pins = []; // used to track and sync 'pin-buttons' for border-panes |
| 1025 | + } |
| 1026 | + |
| 1027 | + CSS = $.extend({ visibility: "visible", display: "block" }, c.defaults.cssReq, c[pane].cssReq ); |
| 1028 | + if (o.applyDefaultStyles) $.extend( CSS, c.defaults.cssDef, c[pane].cssDef ); // cosmetic defaults |
| 1029 | + $P.css(CSS); // add base-css BEFORE 'measuring' to calc size & position |
| 1030 | + CSS = {}; // reset var |
| 1031 | + |
| 1032 | + // set css-position to account for container borders & padding |
| 1033 | + switch (pane) { |
| 1034 | + case "north": CSS.top = cDims.top; |
| 1035 | + CSS.left = cDims.left; |
| 1036 | + CSS.right = cDims.right; |
| 1037 | + break; |
| 1038 | + case "south": CSS.bottom = cDims.bottom; |
| 1039 | + CSS.left = cDims.left; |
| 1040 | + CSS.right = cDims.right; |
| 1041 | + break; |
| 1042 | + case "west": CSS.left = cDims.left; // top, bottom & height set by sizeMidPanes() |
| 1043 | + break; |
| 1044 | + case "east": CSS.right = cDims.right; // ditto |
| 1045 | + break; |
| 1046 | + case "center": // top, left, width & height set by sizeMidPanes() |
| 1047 | + } |
| 1048 | + |
| 1049 | + if (dir == "horz") { // north or south pane |
| 1050 | + if (size === 0 || size == "auto") { |
| 1051 | + $P.css({ height: "auto" }); |
| 1052 | + size = $P.outerHeight(); |
| 1053 | + } |
| 1054 | + size = max(size, minSize); |
| 1055 | + size = min(size, maxSize); |
| 1056 | + size = min(size, cDims.innerHeight - spacing); |
| 1057 | + CSS.height = max(1, cssH(pane, size)); |
| 1058 | + s.size = size; // update state |
| 1059 | + // make sure minSize is sufficient to avoid errors |
| 1060 | + s.maxSize = maxSize; // init value |
| 1061 | + s.minSize = max(minSize, size - CSS.height + 1); // = pane.outerHeight when css.height = 1px |
| 1062 | + // handle IE6 |
| 1063 | + //if (isIE6) CSS.width = cssW($P, cDims.innerWidth); |
| 1064 | + $P.css(CSS); // apply size & position |
| 1065 | + } |
| 1066 | + else if (dir == "vert") { // east or west pane |
| 1067 | + if (size === 0 || size == "auto") { |
| 1068 | + $P.css({ width: "auto", float: "left" }); // float = FORCE pane to auto-size |
| 1069 | + size = $P.outerWidth(); |
| 1070 | + $P.css({ float: "none" }); // RESET |
| 1071 | + } |
| 1072 | + size = max(size, minSize); |
| 1073 | + size = min(size, maxSize); |
| 1074 | + size = min(size, cDims.innerWidth - spacing); |
| 1075 | + CSS.width = max(1, cssW(pane, size)); |
| 1076 | + s.size = size; // update state |
| 1077 | + s.maxSize = maxSize; // init value |
| 1078 | + // make sure minSize is sufficient to avoid errors |
| 1079 | + s.minSize = max(minSize, size - CSS.width + 1); // = pane.outerWidth when css.width = 1px |
| 1080 | + $P.css(CSS); // apply size - top, bottom & height set by sizeMidPanes |
| 1081 | + sizeMidPanes(pane, null, true); // true = onInit |
| 1082 | + } |
| 1083 | + else if (pane == "center") { |
| 1084 | + $P.css(CSS); // top, left, width & height set by sizeMidPanes... |
| 1085 | + sizeMidPanes("center", null, true); // true = onInit |
| 1086 | + } |
| 1087 | + |
| 1088 | + // close or hide the pane if specified in settings |
| 1089 | + if (o.initClosed && o.closable) { |
| 1090 | + $P.hide().addClass("closed"); |
| 1091 | + s.isClosed = true; |
| 1092 | + } |
| 1093 | + else if (o.initHidden || o.initClosed) { |
| 1094 | + hide(pane, true); // will be completely invisible - no resizer or spacing |
| 1095 | + s.isHidden = true; |
| 1096 | + } |
| 1097 | + else |
| 1098 | + $P.addClass("open"); |
| 1099 | + |
| 1100 | + // check option for auto-handling of pop-ups & drop-downs |
| 1101 | + if (o.showOverflowOnHover) |
| 1102 | + $P.hover( allowOverflow, resetOverflow ); |
| 1103 | + |
| 1104 | + /* |
| 1105 | + * see if this pane has a 'content element' that we need to auto-size |
| 1106 | + */ |
| 1107 | + if (o.contentSelector) { |
| 1108 | + $C = $Cs[pane] = $P.children(o.contentSelector+":first"); // match 1-element only |
| 1109 | + if (!$C.length) { |
| 1110 | + $Cs[pane] = false; |
| 1111 | + return true; // SKIP to next |
| 1112 | + } |
| 1113 | + $C.css( c.content.cssReq ); |
| 1114 | + if (o.applyDefaultStyles) $C.css( c.content.cssDef ); // cosmetic defaults |
| 1115 | + // NO PANE-SCROLLING when there is a content-div |
| 1116 | + $P.css({ overflow: "hidden" }); |
| 1117 | + } |
| 1118 | + }); |
| 1119 | + }; |
| 1120 | + |
| 1121 | + /** |
| 1122 | + * initHandles |
| 1123 | + * |
| 1124 | + * Initialize module objects, styling, size and position for all resize bars and toggler buttons |
| 1125 | + * |
| 1126 | + * @callers create() |
| 1127 | + */ |
| 1128 | + var initHandles = function () { |
| 1129 | + // create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV |
| 1130 | + $.each(c.borderPanes.split(","), function() { |
| 1131 | + var |
| 1132 | + pane = str(this) |
| 1133 | + , o = options[pane] |
| 1134 | + , s = state[pane] |
| 1135 | + , rClass = o.resizerClass |
| 1136 | + , tClass = o.togglerClass |
| 1137 | + , $P = $Ps[pane] |
| 1138 | + ; |
| 1139 | + $Rs[pane] = false; // INIT |
| 1140 | + $Ts[pane] = false; |
| 1141 | + |
| 1142 | + if (!$P || (!o.closable && !o.resizable)) return; // pane does not exist - skip |
| 1143 | + |
| 1144 | + var |
| 1145 | + edge = c[pane].edge |
| 1146 | + , isOpen = $P.is(":visible") |
| 1147 | + , spacing = (isOpen ? o.spacing_open : o.spacing_closed) |
| 1148 | + , _pane = "-"+ pane // used for classNames |
| 1149 | + , _state = (isOpen ? "-open" : "-closed") // used for classNames |
| 1150 | + , $R, $T |
| 1151 | + ; |
| 1152 | + // INIT RESIZER BAR |
| 1153 | + $R = $Rs[pane] = $("<span></span>"); |
| 1154 | + |
| 1155 | + if (isOpen && o.resizable) |
| 1156 | + ; // this is handled by initResizable |
| 1157 | + else if (!isOpen && o.slidable) |
| 1158 | + $R.attr("title", o.sliderTip).css("cursor", o.sliderCursor); |
| 1159 | + |
| 1160 | + $R |
| 1161 | + // if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer" |
| 1162 | + .attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-resizer" : "")) |
| 1163 | + .attr("resizer", pane) // so we can read this from the resizer |
| 1164 | + .css(c.resizers.cssReq) // add base/required styles |
| 1165 | + // POSITION of resizer bar - allow for container border & padding |
| 1166 | + .css(edge, cDims[edge] + getPaneSize(pane)) |
| 1167 | + // ADD CLASSNAMES - eg: class="resizer resizer-west resizer-open" |
| 1168 | + .addClass( rClass +" "+ rClass+_pane +" "+ rClass+_state +" "+ rClass+_pane+_state ) |
| 1169 | + .appendTo($Container) // append DIV to container |
| 1170 | + ; |
| 1171 | + // ADD VISUAL STYLES |
| 1172 | + if (o.applyDefaultStyles) |
| 1173 | + $R.css(c.resizers.cssDef); |
| 1174 | + |
| 1175 | + if (o.closable) { |
| 1176 | + // INIT COLLAPSER BUTTON |
| 1177 | + $T = $Ts[pane] = $("<div></div>"); |
| 1178 | + $T |
| 1179 | + // if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-toggler" |
| 1180 | + .attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-toggler" : "")) |
| 1181 | + .css(c.togglers.cssReq) // add base/required styles |
| 1182 | + .attr("title", (isOpen ? o.togglerTip_open : o.togglerTip_closed)) |
| 1183 | + .click(function(evt){ toggle(pane); evt.stopPropagation(); }) |
| 1184 | + .mouseover(function(evt){ evt.stopPropagation(); }) // prevent resizer event |
| 1185 | + // ADD CLASSNAMES - eg: class="toggler toggler-west toggler-west-open" |
| 1186 | + .addClass( tClass +" "+ tClass+_pane +" "+ tClass+_state +" "+ tClass+_pane+_state ) |
| 1187 | + .appendTo($R) // append SPAN to resizer DIV |
| 1188 | + ; |
| 1189 | + |
| 1190 | + // ADD INNER-SPANS TO TOGGLER |
| 1191 | + if (o.togglerContent_open) // ui-layout-open |
| 1192 | + $("<span>"+ o.togglerContent_open +"</span>") |
| 1193 | + .addClass("content content-open") |
| 1194 | + .css("display", s.isClosed ? "none" : "block") |
| 1195 | + .appendTo( $T ) |
| 1196 | + ; |
| 1197 | + if (o.togglerContent_closed) // ui-layout-closed |
| 1198 | + $("<span>"+ o.togglerContent_closed +"</span>") |
| 1199 | + .addClass("content content-closed") |
| 1200 | + .css("display", s.isClosed ? "block" : "none") |
| 1201 | + .appendTo( $T ) |
| 1202 | + ; |
| 1203 | + |
| 1204 | + // ADD BASIC VISUAL STYLES |
| 1205 | + if (o.applyDefaultStyles) |
| 1206 | + $T.css(c.togglers.cssDef); |
| 1207 | + |
| 1208 | + if (!isOpen) bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true |
| 1209 | + } |
| 1210 | + |
| 1211 | + }); |
| 1212 | + |
| 1213 | + // SET ALL HANDLE SIZES & LENGTHS |
| 1214 | + sizeHandles("all", true); // true = onInit |
| 1215 | + }; |
| 1216 | + |
| 1217 | + /** |
| 1218 | + * initResizable |
| 1219 | + * |
| 1220 | + * Add resize-bars to all panes that specify it in options |
| 1221 | + * |
| 1222 | + * @dependancies $.fn.resizable - will abort if not found |
| 1223 | + * @callers create() |
| 1224 | + */ |
| 1225 | + var initResizable = function () { |
| 1226 | + var |
| 1227 | + draggingAvailable = (typeof $.fn.draggable == "function") |
| 1228 | + , minPosition, maxPosition, edge // set in start() |
| 1229 | + ; |
| 1230 | + |
| 1231 | + $.each(c.borderPanes.split(","), function() { |
| 1232 | + var |
| 1233 | + pane = str(this) |
| 1234 | + , o = options[pane] |
| 1235 | + , s = state[pane] |
| 1236 | + ; |
| 1237 | + if (!draggingAvailable || !$Ps[pane] || !o.resizable) { |
| 1238 | + o.resizable = false; |
| 1239 | + return true; // skip to next |
| 1240 | + } |
| 1241 | + |
| 1242 | + var |
| 1243 | + rClass = o.resizerClass |
| 1244 | + // 'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process |
| 1245 | + , dragClass = rClass+"-drag" // resizer-drag |
| 1246 | + , dragPaneClass = rClass+"-"+pane+"-drag" // resizer-north-drag |
| 1247 | + // 'dragging' class is applied to the CLONED resizer-bar while it is being dragged |
| 1248 | + , draggingClass = rClass+"-dragging" // resizer-dragging |
| 1249 | + , draggingPaneClass = rClass+"-"+pane+"-dragging" // resizer-north-dragging |
| 1250 | + , draggingClassSet = false // logic var |
| 1251 | + , $P = $Ps[pane] |
| 1252 | + , $R = $Rs[pane] |
| 1253 | + ; |
| 1254 | + |
| 1255 | + if (!s.isClosed) |
| 1256 | + $R |
| 1257 | + .attr("title", o.resizerTip) |
| 1258 | + .css("cursor", o.resizerCursor) // n-resize, s-resize, etc |
| 1259 | + ; |
| 1260 | + |
| 1261 | + $R.draggable({ |
| 1262 | + containment: $Container[0] // limit resizing to layout container |
| 1263 | + , axis: (c[pane].dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis |
| 1264 | + , delay: 200 |
| 1265 | + , distance: 1 |
| 1266 | + // basic format for helper - style it using class: .ui-draggable-dragging |
| 1267 | + , helper: "clone" |
| 1268 | + , opacity: o.resizerDragOpacity |
| 1269 | + //, iframeFix: o.draggableIframeFix // TODO: consider using when bug is fixed |
| 1270 | + , zIndex: c.zIndex.resizing |
| 1271 | + |
| 1272 | + , start: function (e, ui) { |
| 1273 | + // onresize_start callback - will CANCEL hide if returns false |
| 1274 | + // TODO: CONFIRM that dragging can be cancelled like this??? |
| 1275 | + if (false === execUserCallback(pane, o.onresize_start)) return false; |
| 1276 | + |
| 1277 | + s.isResizing = true; // prevent pane from closing while resizing |
| 1278 | + clearTimer(pane, "closeSlider"); // just in case already triggered |
| 1279 | + |
| 1280 | + $R.addClass( dragClass +" "+ dragPaneClass ); // add drag classes |
| 1281 | + draggingClassSet = false; // reset logic var - see drag() |
| 1282 | + |
| 1283 | + // SET RESIZING LIMITS - used in drag() |
| 1284 | + var resizerWidth = (pane=="east" || pane=="south" ? o.spacing_open : 0); |
| 1285 | + setPaneMinMaxSizes(pane); // update pane-state |
| 1286 | + s.minPosition -= resizerWidth; |
| 1287 | + s.maxPosition -= resizerWidth; |
| 1288 | + edge = (c[pane].dir=="horz" ? "top" : "left"); |
| 1289 | + |
| 1290 | + // MASK PANES WITH IFRAMES OR OTHER TROUBLESOME ELEMENTS |
| 1291 | + $(o.maskIframesOnResize === true ? "iframe" : o.maskIframesOnResize).each(function() { |
| 1292 | + $('<div class="ui-layout-mask"/>') |
| 1293 | + .css({ |
| 1294 | + background: "#fff" |
| 1295 | + , opacity: "0.001" |
| 1296 | + , zIndex: 9 |
| 1297 | + , position: "absolute" |
| 1298 | + , width: this.offsetWidth+"px" |
| 1299 | + , height: this.offsetHeight+"px" |
| 1300 | + }) |
| 1301 | + .css($(this).offset()) // top & left |
| 1302 | + .appendTo(this.parentNode) // put div INSIDE pane to avoid zIndex issues |
| 1303 | + ; |
| 1304 | + }); |
| 1305 | + } |
| 1306 | + |
| 1307 | + , drag: function (e, ui) { |
| 1308 | + if (!draggingClassSet) { // can only add classes after clone has been added to the DOM |
| 1309 | + $(".ui-draggable-dragging") |
| 1310 | + .addClass( draggingClass +" "+ draggingPaneClass ) // add dragging classes |
| 1311 | + .children().css("visibility","hidden") // hide toggler inside dragged resizer-bar |
| 1312 | + ; |
| 1313 | + draggingClassSet = true; |
| 1314 | + // draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane! |
| 1315 | + if (s.isSliding) $Ps[pane].css("zIndex", c.zIndex.sliding); |
| 1316 | + } |
| 1317 | + // CONTAIN RESIZER-BAR TO RESIZING LIMITS |
| 1318 | + if (ui.position[edge] < s.minPosition) ui.position[edge] = s.minPosition; |
| 1319 | + else if (ui.position[edge] > s.maxPosition) ui.position[edge] = s.maxPosition; |
| 1320 | + } |
| 1321 | + |
| 1322 | + , stop: function (e, ui) { |
| 1323 | + var |
| 1324 | + dragPos = ui.position |
| 1325 | + , resizerPos |
| 1326 | + , newSize |
| 1327 | + ; |
| 1328 | + $R.removeClass( dragClass +" "+ dragPaneClass ); // remove drag classes |
| 1329 | + |
| 1330 | + switch (pane) { |
| 1331 | + case "north": resizerPos = dragPos.top; break; |
| 1332 | + case "west": resizerPos = dragPos.left; break; |
| 1333 | + case "south": resizerPos = cDims.outerHeight - dragPos.top - $R.outerHeight(); break; |
| 1334 | + case "east": resizerPos = cDims.outerWidth - dragPos.left - $R.outerWidth(); break; |
| 1335 | + } |
| 1336 | + // remove container margin from resizer position to get the pane size |
| 1337 | + newSize = resizerPos - cDims[ c[pane].edge ]; |
| 1338 | + |
| 1339 | + sizePane(pane, newSize); |
| 1340 | + |
| 1341 | + // UN-MASK PANES MASKED IN drag.start |
| 1342 | + $("div.ui-layout-mask").remove(); // Remove iframe masks |
| 1343 | + |
| 1344 | + s.isResizing = false; |
| 1345 | + } |
| 1346 | + |
| 1347 | + }); |
| 1348 | + }); |
| 1349 | + }; |
| 1350 | + |
| 1351 | + |
| 1352 | + |
| 1353 | +/* |
| 1354 | + * ########################### |
| 1355 | + * ACTION METHODS |
| 1356 | + * ########################### |
| 1357 | + */ |
| 1358 | + |
| 1359 | + /** |
| 1360 | + * hide / show |
| 1361 | + * |
| 1362 | + * Completely 'hides' a pane, including its spacing - as if it does not exist |
| 1363 | + * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it |
| 1364 | + * |
| 1365 | + * @param String pane The pane being hidden, ie: north, south, east, or west |
| 1366 | + */ |
| 1367 | + var hide = function (pane, onInit) { |
| 1368 | + var |
| 1369 | + o = options[pane] |
| 1370 | + , s = state[pane] |
| 1371 | + , $P = $Ps[pane] |
| 1372 | + , $R = $Rs[pane] |
| 1373 | + ; |
| 1374 | + if (!$P || s.isHidden) return; // pane does not exist OR is already hidden |
| 1375 | + |
| 1376 | + // onhide_start callback - will CANCEL hide if returns false |
| 1377 | + if (false === execUserCallback(pane, o.onhide_start)) return; |
| 1378 | + |
| 1379 | + s.isSliding = false; // just in case |
| 1380 | + |
| 1381 | + // now hide the elements |
| 1382 | + if ($R) $R.hide(); // hide resizer-bar |
| 1383 | + if (onInit || s.isClosed) { |
| 1384 | + s.isClosed = true; // to trigger open-animation on show() |
| 1385 | + s.isHidden = true; |
| 1386 | + $P.hide(); // no animation when loading page |
| 1387 | + sizeMidPanes(c[pane].dir == "horz" ? "all" : "center"); |
| 1388 | + execUserCallback(pane, o.onhide_end || o.onhide); |
| 1389 | + } |
| 1390 | + else { |
| 1391 | + s.isHiding = true; // used by onclose |
| 1392 | + close(pane, false); // adjust all panes to fit |
| 1393 | + //s.isHidden = true; - will be set by close - if not cancelled |
| 1394 | + } |
| 1395 | + }; |
| 1396 | + |
| 1397 | + var show = function (pane, openPane) { |
| 1398 | + var |
| 1399 | + o = options[pane] |
| 1400 | + , s = state[pane] |
| 1401 | + , $P = $Ps[pane] |
| 1402 | + , $R = $Rs[pane] |
| 1403 | + ; |
| 1404 | + if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden |
| 1405 | + |
| 1406 | + // onhide_start callback - will CANCEL hide if returns false |
| 1407 | + if (false === execUserCallback(pane, o.onshow_start)) return; |
| 1408 | + |
| 1409 | + s.isSliding = false; // just in case |
| 1410 | + s.isShowing = true; // used by onopen/onclose |
| 1411 | + //s.isHidden = false; - will be set by open/close - if not cancelled |
| 1412 | + |
| 1413 | + // now show the elements |
| 1414 | + if ($R && o.spacing_open > 0) $R.show(); |
| 1415 | + if (openPane === false) |
| 1416 | + close(pane, true); // true = force |
| 1417 | + else |
| 1418 | + open(pane); // adjust all panes to fit |
| 1419 | + }; |
| 1420 | + |
| 1421 | + |
| 1422 | + /** |
| 1423 | + * toggle |
| 1424 | + * |
| 1425 | + * Toggles a pane open/closed by calling either open or close |
| 1426 | + * |
| 1427 | + * @param String pane The pane being toggled, ie: north, south, east, or west |
| 1428 | + */ |
| 1429 | + var toggle = function (pane) { |
| 1430 | + var s = state[pane]; |
| 1431 | + if (s.isHidden) |
| 1432 | + show(pane); // will call 'open' after unhiding it |
| 1433 | + else if (s.isClosed) |
| 1434 | + open(pane); |
| 1435 | + else |
| 1436 | + close(pane); |
| 1437 | + }; |
| 1438 | + |
| 1439 | + /** |
| 1440 | + * close |
| 1441 | + * |
| 1442 | + * Close the specified pane (animation optional), and resize all other panes as needed |
| 1443 | + * |
| 1444 | + * @param String pane The pane being closed, ie: north, south, east, or west |
| 1445 | + */ |
| 1446 | + var close = function (pane, force, noAnimation) { |
| 1447 | + var |
| 1448 | + $P = $Ps[pane] |
| 1449 | + , $R = $Rs[pane] |
| 1450 | + , $T = $Ts[pane] |
| 1451 | + , o = options[pane] |
| 1452 | + , s = state[pane] |
| 1453 | + , doFX = !noAnimation && !s.isClosed && (o.fxName_close != "none") |
| 1454 | + , edge = c[pane].edge |
| 1455 | + , rClass = o.resizerClass |
| 1456 | + , tClass = o.togglerClass |
| 1457 | + , _pane = "-"+ pane // used for classNames |
| 1458 | + , _open = "-open" |
| 1459 | + , _sliding= "-sliding" |
| 1460 | + , _closed = "-closed" |
| 1461 | + // transfer logic vars to temp vars |
| 1462 | + , isShowing = s.isShowing |
| 1463 | + , isHiding = s.isHiding |
| 1464 | + ; |
| 1465 | + // now clear the logic vars |
| 1466 | + delete s.isShowing; |
| 1467 | + delete s.isHiding; |
| 1468 | + |
| 1469 | + if (!$P || (!o.resizable && !o.closable)) return; // invalid request |
| 1470 | + else if (!force && s.isClosed && !isShowing) return; // already closed |
| 1471 | + |
| 1472 | + if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation |
| 1473 | + setFlowCallback("close", pane, force); // set a callback for this action, if possible |
| 1474 | + return; // ABORT |
| 1475 | + } |
| 1476 | + |
| 1477 | + // onclose_start callback - will CANCEL hide if returns false |
| 1478 | + // SKIP if just 'showing' a hidden pane as 'closed' |
| 1479 | + if (!isShowing && false === execUserCallback(pane, o.onclose_start)) return; |
| 1480 | + |
| 1481 | + // SET flow-control flags |
| 1482 | + c[pane].isMoving = true; |
| 1483 | + c.isLayoutBusy = true; |
| 1484 | + |
| 1485 | + s.isClosed = true; |
| 1486 | + // update isHidden BEFORE sizing panes |
| 1487 | + if (isHiding) s.isHidden = true; |
| 1488 | + else if (isShowing) s.isHidden = false; |
| 1489 | + |
| 1490 | + // sync any 'pin buttons' |
| 1491 | + syncPinBtns(pane, false); |
| 1492 | + |
| 1493 | + // resize panes adjacent to this one |
| 1494 | + if (!s.isSliding) sizeMidPanes(c[pane].dir == "horz" ? "all" : "center"); |
| 1495 | + |
| 1496 | + // if this pane has a resizer bar, move it now |
| 1497 | + if ($R) { |
| 1498 | + $R |
| 1499 | + .css(edge, cDims[edge]) // move the resizer bar |
| 1500 | + .removeClass( rClass+_open +" "+ rClass+_pane+_open ) |
| 1501 | + .removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding ) |
| 1502 | + .addClass( rClass+_closed +" "+ rClass+_pane+_closed ) |
| 1503 | + ; |
| 1504 | + // DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvent |
| 1505 | + if (o.resizable) |
| 1506 | + $R |
| 1507 | + .draggable("disable") |
| 1508 | + .css("cursor", "default") |
| 1509 | + .attr("title","") |
| 1510 | + ; |
| 1511 | + // if pane has a toggler button, adjust that too |
| 1512 | + if ($T) { |
| 1513 | + $T |
| 1514 | + .removeClass( tClass+_open +" "+ tClass+_pane+_open ) |
| 1515 | + .addClass( tClass+_closed +" "+ tClass+_pane+_closed ) |
| 1516 | + .attr("title", o.togglerTip_closed) // may be blank |
| 1517 | + ; |
| 1518 | + } |
| 1519 | + sizeHandles(); // resize 'length' and position togglers for adjacent panes |
| 1520 | + } |
| 1521 | + |
| 1522 | + // ANIMATE 'CLOSE' - if no animation, then was ALREADY shown above |
| 1523 | + if (doFX) { |
| 1524 | + lockPaneForFX(pane, true); // need to set left/top so animation will work |
| 1525 | + $P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () { |
| 1526 | + lockPaneForFX(pane, false); // undo |
| 1527 | + if (!s.isClosed) return; // pane was opened before animation finished! |
| 1528 | + close_2(); |
| 1529 | + }); |
| 1530 | + } |
| 1531 | + else { |
| 1532 | + $P.hide(); // just hide pane NOW |
| 1533 | + close_2(); |
| 1534 | + } |
| 1535 | + |
| 1536 | + // SUBROUTINE |
| 1537 | + function close_2 () { |
| 1538 | + bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true |
| 1539 | + |
| 1540 | + // onclose callback - UNLESS just 'showing' a hidden pane as 'closed' |
| 1541 | + if (!isShowing) execUserCallback(pane, o.onclose_end || o.onclose); |
| 1542 | + // onhide OR onshow callback |
| 1543 | + if (isShowing) execUserCallback(pane, o.onshow_end || o.onshow); |
| 1544 | + if (isHiding) execUserCallback(pane, o.onhide_end || o.onhide); |
| 1545 | + |
| 1546 | + // internal flow-control callback |
| 1547 | + execFlowCallback(pane); |
| 1548 | + } |
| 1549 | + }; |
| 1550 | + |
| 1551 | + /** |
| 1552 | + * open |
| 1553 | + * |
| 1554 | + * Open the specified pane (animation optional), and resize all other panes as needed |
| 1555 | + * |
| 1556 | + * @param String pane The pane being opened, ie: north, south, east, or west |
| 1557 | + */ |
| 1558 | + var open = function (pane, slide, noAnimation) { |
| 1559 | + var |
| 1560 | + $P = $Ps[pane] |
| 1561 | + , $R = $Rs[pane] |
| 1562 | + , $T = $Ts[pane] |
| 1563 | + , o = options[pane] |
| 1564 | + , s = state[pane] |
| 1565 | + , doFX = !noAnimation && s.isClosed && (o.fxName_open != "none") |
| 1566 | + , edge = c[pane].edge |
| 1567 | + , rClass = o.resizerClass |
| 1568 | + , tClass = o.togglerClass |
| 1569 | + , _pane = "-"+ pane // used for classNames |
| 1570 | + , _open = "-open" |
| 1571 | + , _closed = "-closed" |
| 1572 | + , _sliding= "-sliding" |
| 1573 | + // transfer logic var to temp var |
| 1574 | + , isShowing = s.isShowing |
| 1575 | + ; |
| 1576 | + // now clear the logic var |
| 1577 | + delete s.isShowing; |
| 1578 | + |
| 1579 | + if (!$P || (!o.resizable && !o.closable)) return; // invalid request |
| 1580 | + else if (!s.isClosed && !s.isSliding) return; // already open |
| 1581 | + |
| 1582 | + // pane can ALSO be unhidden by just calling show(), so handle this scenario |
| 1583 | + if (s.isHidden && !isShowing) { |
| 1584 | + show(pane, true); |
| 1585 | + return; |
| 1586 | + } |
| 1587 | + |
| 1588 | + if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation |
| 1589 | + setFlowCallback("open", pane, slide); // set a callback for this action, if possible |
| 1590 | + return; // ABORT |
| 1591 | + } |
| 1592 | + |
| 1593 | + // onopen_start callback - will CANCEL hide if returns false |
| 1594 | + if (false === execUserCallback(pane, o.onopen_start)) return; |
| 1595 | + |
| 1596 | + // SET flow-control flags |
| 1597 | + c[pane].isMoving = true; |
| 1598 | + c.isLayoutBusy = true; |
| 1599 | + |
| 1600 | + // 'PIN PANE' - stop sliding |
| 1601 | + if (s.isSliding && !slide) // !slide = 'open pane normally' - NOT sliding |
| 1602 | + bindStopSlidingEvents(pane, false); // will set isSliding=false |
| 1603 | + |
| 1604 | + s.isClosed = false; |
| 1605 | + // update isHidden BEFORE sizing panes |
| 1606 | + if (isShowing) s.isHidden = false; |
| 1607 | + |
| 1608 | + // Container size may have changed - shrink the pane if now 'too big' |
| 1609 | + setPaneMinMaxSizes(pane); // update pane-state |
| 1610 | + if (s.size > s.maxSize) // pane is too big! resize it before opening |
| 1611 | + $P.css( c[pane].sizeType, max(1, cssSize(pane, s.maxSize)) ); |
| 1612 | + |
| 1613 | + bindStartSlidingEvent(pane, false); // remove trigger event from resizer-bar |
| 1614 | + |
| 1615 | + if (doFX) { // ANIMATE |
| 1616 | + lockPaneForFX(pane, true); // need to set left/top so animation will work |
| 1617 | + $P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() { |
| 1618 | + lockPaneForFX(pane, false); // undo |
| 1619 | + if (s.isClosed) return; // pane was closed before animation finished! |
| 1620 | + open_2(); // continue |
| 1621 | + }); |
| 1622 | + } |
| 1623 | + else {// no animation |
| 1624 | + $P.show(); // just show pane and... |
| 1625 | + open_2(); // continue |
| 1626 | + } |
| 1627 | + |
| 1628 | + // SUBROUTINE |
| 1629 | + function open_2 () { |
| 1630 | + // NOTE: if isSliding, then other panes are NOT 'resized' |
| 1631 | + if (!s.isSliding) // resize all panes adjacent to this one |
| 1632 | + sizeMidPanes(c[pane].dir=="vert" ? "center" : "all"); |
| 1633 | + |
| 1634 | + // if this pane has a toggler, move it now |
| 1635 | + if ($R) { |
| 1636 | + $R |
| 1637 | + .css(edge, cDims[edge] + getPaneSize(pane)) // move the toggler |
| 1638 | + .removeClass( rClass+_closed +" "+ rClass+_pane+_closed ) |
| 1639 | + .addClass( rClass+_open +" "+ rClass+_pane+_open ) |
| 1640 | + .addClass( !s.isSliding ? "" : rClass+_sliding +" "+ rClass+_pane+_sliding ) |
| 1641 | + ; |
| 1642 | + if (o.resizable) |
| 1643 | + $R |
| 1644 | + .draggable("enable") |
| 1645 | + .css("cursor", o.resizerCursor) |
| 1646 | + .attr("title", o.resizerTip) |
| 1647 | + ; |
| 1648 | + else |
| 1649 | + $R.css("cursor", "default"); // n-resize, s-resize, etc |
| 1650 | + // if pane also has a toggler button, adjust that too |
| 1651 | + if ($T) { |
| 1652 | + $T |
| 1653 | + .removeClass( tClass+_closed +" "+ tClass+_pane+_closed ) |
| 1654 | + .addClass( tClass+_open +" "+ tClass+_pane+_open ) |
| 1655 | + .attr("title", o.togglerTip_open) // may be blank |
| 1656 | + ; |
| 1657 | + } |
| 1658 | + sizeHandles("all"); // resize resizer & toggler sizes for all panes |
| 1659 | + } |
| 1660 | + |
| 1661 | + // resize content every time pane opens - to be sure |
| 1662 | + sizeContent(pane); |
| 1663 | + |
| 1664 | + // sync any 'pin buttons' |
| 1665 | + syncPinBtns(pane, !s.isSliding); |
| 1666 | + |
| 1667 | + // onopen callback |
| 1668 | + execUserCallback(pane, o.onopen_end || o.onopen); |
| 1669 | + |
| 1670 | + // onshow callback |
| 1671 | + if (isShowing) execUserCallback(pane, o.onshow_end || o.onshow); |
| 1672 | + |
| 1673 | + // internal flow-control callback |
| 1674 | + execFlowCallback(pane); |
| 1675 | + } |
| 1676 | + }; |
| 1677 | + |
| 1678 | + |
| 1679 | + /** |
| 1680 | + * lockPaneForFX |
| 1681 | + * |
| 1682 | + * Must set left/top on East/South panes so animation will work properly |
| 1683 | + * |
| 1684 | + * @param String pane The pane to lock, 'east' or 'south' - any other is ignored! |
| 1685 | + * @param Boolean doLock true = set left/top, false = remove |
| 1686 | + */ |
| 1687 | + var lockPaneForFX = function (pane, doLock) { |
| 1688 | + var $P = $Ps[pane]; |
| 1689 | + if (doLock) { |
| 1690 | + $P.css({ zIndex: c.zIndex.animation }); // overlay all elements during animation |
| 1691 | + if (pane=="south") |
| 1692 | + $P.css({ top: cDims.top + cDims.innerHeight - $P.outerHeight() }); |
| 1693 | + else if (pane=="east") |
| 1694 | + $P.css({ left: cDims.left + cDims.innerWidth - $P.outerWidth() }); |
| 1695 | + } |
| 1696 | + else { |
| 1697 | + if (!state[pane].isSliding) $P.css({ zIndex: c.zIndex.pane_normal }); |
| 1698 | + if (pane=="south") |
| 1699 | + $P.css({ top: "auto" }); |
| 1700 | + else if (pane=="east") |
| 1701 | + $P.css({ left: "auto" }); |
| 1702 | + } |
| 1703 | + }; |
| 1704 | + |
| 1705 | + |
| 1706 | + /** |
| 1707 | + * bindStartSlidingEvent |
| 1708 | + * |
| 1709 | + * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger |
| 1710 | + * |
| 1711 | + * @callers open(), close() |
| 1712 | + * @param String pane The pane to enable/disable, 'north', 'south', etc. |
| 1713 | + * @param Boolean enable Enable or Disable sliding? |
| 1714 | + */ |
| 1715 | + var bindStartSlidingEvent = function (pane, enable) { |
| 1716 | + var |
| 1717 | + o = options[pane] |
| 1718 | + , $R = $Rs[pane] |
| 1719 | + , trigger = o.slideTrigger_open |
| 1720 | + ; |
| 1721 | + if (!$R || !o.slidable) return; |
| 1722 | + // make sure we have a valid event |
| 1723 | + if (trigger != "click" && trigger != "dblclick" && trigger != "mouseover") trigger = "click"; |
| 1724 | + $R |
| 1725 | + // add or remove trigger event |
| 1726 | + [enable ? "bind" : "unbind"](trigger, slideOpen) |
| 1727 | + // set the appropriate cursor & title/tip |
| 1728 | + .css("cursor", (enable ? o.sliderCursor: "default")) |
| 1729 | + .attr("title", (enable ? o.sliderTip : "")) |
| 1730 | + ; |
| 1731 | + }; |
| 1732 | + |
| 1733 | + /** |
| 1734 | + * bindStopSlidingEvents |
| 1735 | + * |
| 1736 | + * Add or remove 'mouseout' events to 'slide close' when pane is 'sliding' open or closed |
| 1737 | + * Also increases zIndex when pane is sliding open |
| 1738 | + * See bindStartSlidingEvent for code to control 'slide open' |
| 1739 | + * |
| 1740 | + * @callers slideOpen(), slideClosed() |
| 1741 | + * @param String pane The pane to process, 'north', 'south', etc. |
| 1742 | + * @param Boolean isOpen Is pane open or closed? |
| 1743 | + */ |
| 1744 | + var bindStopSlidingEvents = function (pane, enable) { |
| 1745 | + var |
| 1746 | + o = options[pane] |
| 1747 | + , s = state[pane] |
| 1748 | + , trigger = o.slideTrigger_close |
| 1749 | + , action = (enable ? "bind" : "unbind") // can't make 'unbind' work! - see disabled code below |
| 1750 | + , $P = $Ps[pane] |
| 1751 | + , $R = $Rs[pane] |
| 1752 | + ; |
| 1753 | + |
| 1754 | + s.isSliding = enable; // logic |
| 1755 | + clearTimer(pane, "closeSlider"); // just in case |
| 1756 | + |
| 1757 | + // raise z-index when sliding |
| 1758 | + $P.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.pane_normal) }); |
| 1759 | + $R.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.resizer_normal) }); |
| 1760 | + |
| 1761 | + // make sure we have a valid event |
| 1762 | + if (trigger != "click" && trigger != "mouseout") trigger = "mouseout"; |
| 1763 | + |
| 1764 | + // when trigger is 'mouseout', must cancel timer when mouse moves between 'pane' and 'resizer' |
| 1765 | + if (enable) { // BIND trigger events |
| 1766 | + $P.bind(trigger, slideClosed ); |
| 1767 | + $R.bind(trigger, slideClosed ); |
| 1768 | + if (trigger = "mouseout") { |
| 1769 | + $P.bind("mouseover", cancelMouseOut ); |
| 1770 | + $R.bind("mouseover", cancelMouseOut ); |
| 1771 | + } |
| 1772 | + } |
| 1773 | + else { // UNBIND trigger events |
| 1774 | + // TODO: why does unbind of a 'single function' not work reliably? |
| 1775 | + //$P[action](trigger, slideClosed ); |
| 1776 | + $P.unbind(trigger); |
| 1777 | + $R.unbind(trigger); |
| 1778 | + if (trigger = "mouseout") { |
| 1779 | + //$P[action]("mouseover", cancelMouseOut ); |
| 1780 | + $P.unbind("mouseover"); |
| 1781 | + $R.unbind("mouseover"); |
| 1782 | + clearTimer(pane, "closeSlider"); |
| 1783 | + } |
| 1784 | + } |
| 1785 | + |
| 1786 | + // SUBROUTINE for mouseout timer clearing |
| 1787 | + function cancelMouseOut (evt) { |
| 1788 | + clearTimer(pane, "closeSlider"); |
| 1789 | + evt.stopPropagation(); |
| 1790 | + } |
| 1791 | + }; |
| 1792 | + |
| 1793 | + var slideOpen = function () { |
| 1794 | + var pane = $(this).attr("resizer"); // attr added by initHandles |
| 1795 | + if (state[pane].isClosed) { // skip if already open! |
| 1796 | + bindStopSlidingEvents(pane, true); // pane is opening, so BIND trigger events to close it |
| 1797 | + open(pane, true); // true = slide - ie, called from here! |
| 1798 | + } |
| 1799 | + }; |
| 1800 | + |
| 1801 | + var slideClosed = function () { |
| 1802 | + var |
| 1803 | + $E = $(this) |
| 1804 | + , pane = $E.attr("pane") || $E.attr("resizer") |
| 1805 | + , o = options[pane] |
| 1806 | + , s = state[pane] |
| 1807 | + ; |
| 1808 | + if (s.isClosed || s.isResizing) |
| 1809 | + return; // skip if already closed OR in process of resizing |
| 1810 | + else if (o.slideTrigger_close == "click") |
| 1811 | + close_NOW(); // close immediately onClick |
| 1812 | + else // trigger = mouseout - use a delay |
| 1813 | + setTimer(pane, "closeSlider", close_NOW, 300); // .3 sec delay |
| 1814 | + |
| 1815 | + // SUBROUTINE for timed close |
| 1816 | + function close_NOW () { |
| 1817 | + bindStopSlidingEvents(pane, false); // pane is being closed, so UNBIND trigger events |
| 1818 | + if (!s.isClosed) close(pane); // skip if already closed! |
| 1819 | + } |
| 1820 | + }; |
| 1821 | + |
| 1822 | + |
| 1823 | + /** |
| 1824 | + * sizePane |
| 1825 | + * |
| 1826 | + * @callers initResizable.stop() |
| 1827 | + * @param String pane The pane being resized - usually west or east, but potentially north or south |
| 1828 | + * @param Integer newSize The new size for this pane - will be validated |
| 1829 | + */ |
| 1830 | + var sizePane = function (pane, size) { |
| 1831 | + // TODO: accept "auto" as size, and size-to-fit pane content |
| 1832 | + var |
| 1833 | + edge = c[pane].edge |
| 1834 | + , dir = c[pane].dir |
| 1835 | + , o = options[pane] |
| 1836 | + , s = state[pane] |
| 1837 | + , $P = $Ps[pane] |
| 1838 | + , $R = $Rs[pane] |
| 1839 | + ; |
| 1840 | + // calculate 'current' min/max sizes |
| 1841 | + setPaneMinMaxSizes(pane); // update pane-state |
| 1842 | + // compare/update calculated min/max to user-options |
| 1843 | + s.minSize = max(s.minSize, o.minSize); |
| 1844 | + if (o.maxSize > 0) s.maxSize = min(s.maxSize, o.maxSize); |
| 1845 | + // validate passed size |
| 1846 | + size = max(size, s.minSize); |
| 1847 | + size = min(size, s.maxSize); |
| 1848 | + s.size = size; // update state |
| 1849 | + |
| 1850 | + // move the resizer bar and resize the pane |
| 1851 | + $R.css( edge, size + cDims[edge] ); |
| 1852 | + $P.css( c[pane].sizeType, max(1, cssSize(pane, size)) ); |
| 1853 | + |
| 1854 | + // resize all the adjacent panes, and adjust their toggler buttons |
| 1855 | + if (!s.isSliding) sizeMidPanes(dir=="horz" ? "all" : "center"); |
| 1856 | + sizeHandles(); |
| 1857 | + sizeContent(pane); |
| 1858 | + execUserCallback(pane, o.onresize_end || o.onresize); |
| 1859 | + }; |
| 1860 | + |
| 1861 | + /** |
| 1862 | + * sizeMidPanes |
| 1863 | + * |
| 1864 | + * @callers create(), open(), close(), onWindowResize() |
| 1865 | + */ |
| 1866 | + var sizeMidPanes = function (panes, overrideDims, onInit) { |
| 1867 | + if (!panes || panes == "all") panes = "east,west,center"; |
| 1868 | + |
| 1869 | + var d = getPaneDims(); |
| 1870 | + if (overrideDims) $.extend( d, overrideDims ); |
| 1871 | + |
| 1872 | + $.each(panes.split(","), function() { |
| 1873 | + if (!$Ps[this]) return; // NO PANE - skip |
| 1874 | + var |
| 1875 | + pane = str(this) |
| 1876 | + , o = options[pane] |
| 1877 | + , s = state[pane] |
| 1878 | + , $P = $Ps[pane] |
| 1879 | + , $R = $Rs[pane] |
| 1880 | + , hasRoom = true |
| 1881 | + , CSS = {} |
| 1882 | + ; |
| 1883 | + |
| 1884 | + if (pane == "center") { |
| 1885 | + d = getPaneDims(); // REFRESH Dims because may have just 'unhidden' East or West pane after a 'resize' |
| 1886 | + CSS = $.extend( {}, d ); // COPY ALL of the paneDims |
| 1887 | + CSS.width = max(1, cssW(pane, CSS.width)); |
| 1888 | + CSS.height = max(1, cssH(pane, CSS.height)); |
| 1889 | + hasRoom = (CSS.width > 1 && CSS.height > 1); |
| 1890 | + /* |
| 1891 | + * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes |
| 1892 | + * Normally these panes have only 'left' & 'right' positions so pane auto-sizes |
| 1893 | + */ |
| 1894 | + if ($.browser.msie && (!$.boxModel || $.browser.version < 7)) { |
| 1895 | + if ($Ps.north) $Ps.north.css({ width: cssW($Ps.north, cDims.innerWidth) }); |
| 1896 | + if ($Ps.south) $Ps.south.css({ width: cssW($Ps.south, cDims.innerWidth) }); |
| 1897 | + } |
| 1898 | + } |
| 1899 | + else { // for east and west, set only the height |
| 1900 | + CSS.top = d.top; |
| 1901 | + CSS.bottom = d.bottom; |
| 1902 | + CSS.height = max(1, cssH(pane, d.height)); |
| 1903 | + hasRoom = (CSS.height > 1); |
| 1904 | + } |
| 1905 | + |
| 1906 | + if (hasRoom) { |
| 1907 | + $P.css(CSS); |
| 1908 | + if (s.noRoom) { |
| 1909 | + s.noRoom = false; |
| 1910 | + if (s.isHidden) return; |
| 1911 | + else show(pane, !s.isClosed); |
| 1912 | + /* OLD CODE - keep until sure line above works right! |
| 1913 | + if (!s.isClosed) $P.show(); // in case was previously hidden due to NOT hasRoom |
| 1914 | + if ($R) $R.show(); |
| 1915 | + */ |
| 1916 | + } |
| 1917 | + if (!onInit) { |
| 1918 | + sizeContent(pane); |
| 1919 | + execUserCallback(pane, o.onresize_end || o.onresize); |
| 1920 | + } |
| 1921 | + } |
| 1922 | + else if (!s.noRoom) { // no room for pane, so just hide it (if not already) |
| 1923 | + s.noRoom = true; // update state |
| 1924 | + if (s.isHidden) return; |
| 1925 | + if (onInit) { // skip onhide callback and other logic onLoad |
| 1926 | + $P.hide(); |
| 1927 | + if ($R) $R.hide(); |
| 1928 | + } |
| 1929 | + else hide(pane); |
| 1930 | + } |
| 1931 | + }); |
| 1932 | + }; |
| 1933 | + |
| 1934 | + |
| 1935 | + var sizeContent = function (panes) { |
| 1936 | + if (!panes || panes == "all") panes = c.allPanes; |
| 1937 | + |
| 1938 | + $.each(panes.split(","), function() { |
| 1939 | + if (!$Cs[this]) return; // NO CONTENT - skip |
| 1940 | + var |
| 1941 | + pane = str(this) |
| 1942 | + , ignore = options[pane].contentIgnoreSelector |
| 1943 | + , $P = $Ps[pane] |
| 1944 | + , $C = $Cs[pane] |
| 1945 | + , e_C = $C[0] // DOM element |
| 1946 | + , height = cssH($P); // init to pane.innerHeight |
| 1947 | + ; |
| 1948 | + $P.children().each(function() { |
| 1949 | + if (this == e_C) return; // Content elem - skip |
| 1950 | + var $E = $(this); |
| 1951 | + if (!ignore || !$E.is(ignore)) |
| 1952 | + height -= $E.outerHeight(); |
| 1953 | + }); |
| 1954 | + if (height > 0) |
| 1955 | + height = cssH($C, height); |
| 1956 | + if (height < 1) |
| 1957 | + $C.hide(); // no room for content! |
| 1958 | + else |
| 1959 | + $C.css({ height: height }).show(); |
| 1960 | + }); |
| 1961 | + }; |
| 1962 | + |
| 1963 | + |
| 1964 | + /** |
| 1965 | + * sizeHandles |
| 1966 | + * |
| 1967 | + * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary |
| 1968 | + * |
| 1969 | + * @callers initHandles(), open(), close(), resizeAll() |
| 1970 | + */ |
| 1971 | + var sizeHandles = function (panes, onInit) { |
| 1972 | + if (!panes || panes == "all") panes = c.borderPanes; |
| 1973 | + |
| 1974 | + $.each(panes.split(","), function() { |
| 1975 | + var |
| 1976 | + pane = str(this) |
| 1977 | + , o = options[pane] |
| 1978 | + , s = state[pane] |
| 1979 | + , $P = $Ps[pane] |
| 1980 | + , $R = $Rs[pane] |
| 1981 | + , $T = $Ts[pane] |
| 1982 | + ; |
| 1983 | + if (!$P || !$R || (!o.resizable && !o.closable)) return; // skip |
| 1984 | + |
| 1985 | + var |
| 1986 | + dir = c[pane].dir |
| 1987 | + , _state = (s.isClosed ? "_closed" : "_open") |
| 1988 | + , spacing = o["spacing"+ _state] |
| 1989 | + , togAlign = o["togglerAlign"+ _state] |
| 1990 | + , togLen = o["togglerLength"+ _state] |
| 1991 | + , paneLen |
| 1992 | + , offset |
| 1993 | + , CSS = {} |
| 1994 | + ; |
| 1995 | + if (spacing == 0) { |
| 1996 | + $R.hide(); |
| 1997 | + return; |
| 1998 | + } |
| 1999 | + else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason |
| 2000 | + $R.show(); // in case was previously hidden |
| 2001 | + |
| 2002 | + // Resizer Bar is ALWAYS same width/height of pane it is attached to |
| 2003 | + if (dir == "horz") { // north/south |
| 2004 | + paneLen = $P.outerWidth(); |
| 2005 | + $R.css({ |
| 2006 | + width: max(1, cssW($R, paneLen)) // account for borders & padding |
| 2007 | + , height: max(1, cssH($R, spacing)) // ditto |
| 2008 | + , left: cssNum($P, "left") |
| 2009 | + }); |
| 2010 | + } |
| 2011 | + else { // east/west |
| 2012 | + paneLen = $P.outerHeight(); |
| 2013 | + $R.css({ |
| 2014 | + height: max(1, cssH($R, paneLen)) // account for borders & padding |
| 2015 | + , width: max(1, cssW($R, spacing)) // ditto |
| 2016 | + , top: cDims.top + getPaneSize("north", true) |
| 2017 | + //, top: cssNum($Ps["center"], "top") |
| 2018 | + }); |
| 2019 | + |
| 2020 | + } |
| 2021 | + |
| 2022 | + if ($T) { |
| 2023 | + if (togLen == 0 || (s.isSliding && o.hideTogglerOnSlide)) { |
| 2024 | + $T.hide(); // always HIDE the toggler when 'sliding' |
| 2025 | + return; |
| 2026 | + } |
| 2027 | + else |
| 2028 | + $T.show(); // in case was previously hidden |
| 2029 | + |
| 2030 | + if (!(togLen > 0) || togLen == "100%" || togLen > paneLen) { |
| 2031 | + togLen = paneLen; |
| 2032 | + offset = 0; |
| 2033 | + } |
| 2034 | + else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed |
| 2035 | + if (typeof togAlign == "string") { |
| 2036 | + switch (togAlign) { |
| 2037 | + case "top": |
| 2038 | + case "left": offset = 0; |
| 2039 | + break; |
| 2040 | + case "bottom": |
| 2041 | + case "right": offset = paneLen - togLen; |
| 2042 | + break; |
| 2043 | + case "middle": |
| 2044 | + case "center": |
| 2045 | + default: offset = Math.floor((paneLen - togLen) / 2); // 'default' catches typos |
| 2046 | + } |
| 2047 | + } |
| 2048 | + else { // togAlign = number |
| 2049 | + var x = parseInt(togAlign); // |
| 2050 | + if (togAlign >= 0) offset = x; |
| 2051 | + else offset = paneLen - togLen + x; // NOTE: x is negative! |
| 2052 | + } |
| 2053 | + } |
| 2054 | + |
| 2055 | + var |
| 2056 | + $TC_o = (o.togglerContent_open ? $T.children(".content-open") : false) |
| 2057 | + , $TC_c = (o.togglerContent_closed ? $T.children(".content-closed") : false) |
| 2058 | + , $TC = (s.isClosed ? $TC_c : $TC_o) |
| 2059 | + ; |
| 2060 | + if ($TC_o) $TC_o.css("display", s.isClosed ? "none" : "block"); |
| 2061 | + if ($TC_c) $TC_c.css("display", s.isClosed ? "block" : "none"); |
| 2062 | + |
| 2063 | + if (dir == "horz") { // north/south |
| 2064 | + var width = cssW($T, togLen); |
| 2065 | + $T.css({ |
| 2066 | + width: max(0, width) // account for borders & padding |
| 2067 | + , height: max(1, cssH($T, spacing)) // ditto |
| 2068 | + , left: offset // TODO: VERIFY that toggler positions correctly for ALL values |
| 2069 | + }); |
| 2070 | + if ($TC) // CENTER the toggler content SPAN |
| 2071 | + $TC.css("marginLeft", Math.floor((width-$TC.outerWidth())/2)); // could be negative |
| 2072 | + } |
| 2073 | + else { // east/west |
| 2074 | + var height = cssH($T, togLen); |
| 2075 | + $T.css({ |
| 2076 | + height: max(0, height) // account for borders & padding |
| 2077 | + , width: max(1, cssW($T, spacing)) // ditto |
| 2078 | + , top: offset // POSITION the toggler |
| 2079 | + }); |
| 2080 | + if ($TC) // CENTER the toggler content SPAN |
| 2081 | + $TC.css("marginTop", Math.floor((height-$TC.outerHeight())/2)); // could be negative |
| 2082 | + } |
| 2083 | + |
| 2084 | + |
| 2085 | + } |
| 2086 | + |
| 2087 | + // DONE measuring and sizing this resizer/toggler, so can be 'hidden' now |
| 2088 | + if (onInit && o.initHidden) { |
| 2089 | + $R.hide(); |
| 2090 | + if ($T) $T.hide(); |
| 2091 | + } |
| 2092 | + }); |
| 2093 | + }; |
| 2094 | + |
| 2095 | + |
| 2096 | + /** |
| 2097 | + * resizeAll |
| 2098 | + * |
| 2099 | + * @callers window.onresize(), callbacks or custom code |
| 2100 | + */ |
| 2101 | + var resizeAll = function () { |
| 2102 | + var |
| 2103 | + oldW = cDims.innerWidth |
| 2104 | + , oldH = cDims.innerHeight |
| 2105 | + ; |
| 2106 | + cDims = state.container = getElemDims($Container); // UPDATE container dimensions |
| 2107 | + |
| 2108 | + var |
| 2109 | + checkH = (cDims.innerHeight < oldH) |
| 2110 | + , checkW = (cDims.innerWidth < oldW) |
| 2111 | + , s, dir |
| 2112 | + ; |
| 2113 | + |
| 2114 | + if (checkH || checkW) |
| 2115 | + // NOTE special order for sizing: S-N-E-W |
| 2116 | + $.each(["south","north","east","west"], function(i,pane) { |
| 2117 | + s = state[pane]; |
| 2118 | + dir = c[pane].dir; |
| 2119 | + if (!s.isClosed && ((checkH && dir=="horz") || (checkW && dir=="vert"))) { |
| 2120 | + setPaneMinMaxSizes(pane); // update pane-state |
| 2121 | + // shrink pane if 'too big' to fit |
| 2122 | + if (s.size > s.maxSize) |
| 2123 | + sizePane(pane, s.maxSize); |
| 2124 | + } |
| 2125 | + }); |
| 2126 | + |
| 2127 | + sizeMidPanes("all"); |
| 2128 | + sizeHandles("all"); // reposition the toggler elements |
| 2129 | + }; |
| 2130 | + |
| 2131 | + |
| 2132 | + /** |
| 2133 | + * keyDown |
| 2134 | + * |
| 2135 | + * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed |
| 2136 | + * |
| 2137 | + * @callers document.keydown() |
| 2138 | + */ |
| 2139 | + function keyDown (evt) { |
| 2140 | + if (!evt) return true; |
| 2141 | + var code = evt.keyCode; |
| 2142 | + if (code < 33) return true; // ignore special keys: ENTER, TAB, etc |
| 2143 | + |
| 2144 | + var |
| 2145 | + PANE = { |
| 2146 | + 38: "north" // Up Cursor |
| 2147 | + , 40: "south" // Down Cursor |
| 2148 | + , 37: "west" // Left Cursor |
| 2149 | + , 39: "east" // Right Cursor |
| 2150 | + } |
| 2151 | + , isCursorKey = (code >= 37 && code <= 40) |
| 2152 | + , ALT = evt.altKey // no worky! |
| 2153 | + , SHIFT = evt.shiftKey |
| 2154 | + , CTRL = evt.ctrlKey |
| 2155 | + , pane = false |
| 2156 | + , s, o, k, m, el |
| 2157 | + ; |
| 2158 | + |
| 2159 | + if (!CTRL && !SHIFT) |
| 2160 | + return true; // no modifier key - abort |
| 2161 | + else if (isCursorKey && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey |
| 2162 | + pane = PANE[code]; |
| 2163 | + else // check to see if this matches a custom-hotkey |
| 2164 | + $.each(c.borderPanes.split(","), function(i,p) { // loop each pane to check its hotkey |
| 2165 | + o = options[p]; |
| 2166 | + k = o.customHotkey; |
| 2167 | + m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT" |
| 2168 | + if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches |
| 2169 | + if (k && code == (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches |
| 2170 | + pane = p; |
| 2171 | + return false; // BREAK |
| 2172 | + } |
| 2173 | + } |
| 2174 | + }); |
| 2175 | + |
| 2176 | + if (!pane) return true; // no hotkey - abort |
| 2177 | + |
| 2178 | + // validate pane |
| 2179 | + o = options[pane]; // get pane options |
| 2180 | + s = state[pane]; // get pane options |
| 2181 | + if (!o.enableCursorHotkey || s.isHidden || !$Ps[pane]) return true; |
| 2182 | + |
| 2183 | + // see if user is in a 'form field' because may be 'selecting text'! |
| 2184 | + el = evt.target || evt.srcElement; |
| 2185 | + if (el && SHIFT && isCursorKey && (el.tagName=="TEXTAREA" || (el.tagName=="INPUT" && (code==37 || code==39)))) |
| 2186 | + return true; // allow text-selection |
| 2187 | + |
| 2188 | + // SYNTAX NOTES |
| 2189 | + // use "returnValue=false" to abort keystroke but NOT abort function - can run another command afterwards |
| 2190 | + // use "return false" to abort keystroke AND abort function |
| 2191 | + toggle(pane); |
| 2192 | + evt.stopPropagation(); |
| 2193 | + evt.returnValue = false; // CANCEL key |
| 2194 | + return false; |
| 2195 | + }; |
| 2196 | + |
| 2197 | + |
| 2198 | +/* |
| 2199 | + * ########################### |
| 2200 | + * UTILITY METHODS |
| 2201 | + * called externally only |
| 2202 | + * ########################### |
| 2203 | + */ |
| 2204 | + |
| 2205 | + function allowOverflow (elem) { |
| 2206 | + if (this && this.tagName) elem = this; // BOUND to element |
| 2207 | + var $P; |
| 2208 | + if (typeof elem=="string") |
| 2209 | + $P = $Ps[elem]; |
| 2210 | + else { |
| 2211 | + if ($(elem).attr("pane")) $P = $(elem); |
| 2212 | + else $P = $(elem).parents("div[pane]:first"); |
| 2213 | + } |
| 2214 | + if (!$P.length) return; // INVALID |
| 2215 | + |
| 2216 | + var |
| 2217 | + pane = $P.attr("pane") |
| 2218 | + , s = state[pane] |
| 2219 | + ; |
| 2220 | + |
| 2221 | + // if pane is already raised, then reset it before doing it again! |
| 2222 | + // this would happen if allowOverflow is attached to BOTH the pane and an element |
| 2223 | + if (s.cssSaved) |
| 2224 | + resetOverflow(pane); // reset previous CSS before continuing |
| 2225 | + |
| 2226 | + // if pane is raised by sliding or resizing, or it's closed, then abort |
| 2227 | + if (s.isSliding || s.isResizing || s.isClosed) { |
| 2228 | + s.cssSaved = false; |
| 2229 | + return; |
| 2230 | + } |
| 2231 | + |
| 2232 | + var |
| 2233 | + newCSS = { zIndex: (c.zIndex.pane_normal + 1) } |
| 2234 | + , curCSS = {} |
| 2235 | + , of = $P.css("overflow") |
| 2236 | + , ofX = $P.css("overflowX") |
| 2237 | + , ofY = $P.css("overflowY") |
| 2238 | + ; |
| 2239 | + // determine which, if any, overflow settings need to be changed |
| 2240 | + if (of != "visible") { |
| 2241 | + curCSS.overflow = of; |
| 2242 | + newCSS.overflow = "visible"; |
| 2243 | + } |
| 2244 | + if (ofX && ofX != "visible" && ofX != "auto") { |
| 2245 | + curCSS.overflowX = ofX; |
| 2246 | + newCSS.overflowX = "visible"; |
| 2247 | + } |
| 2248 | + if (ofY && ofY != "visible" && ofY != "auto") { |
| 2249 | + curCSS.overflowY = ofX; |
| 2250 | + newCSS.overflowY = "visible"; |
| 2251 | + } |
| 2252 | + |
| 2253 | + // save the current overflow settings - even if blank! |
| 2254 | + s.cssSaved = curCSS; |
| 2255 | + |
| 2256 | + // apply new CSS to raise zIndex and, if necessary, make overflow 'visible' |
| 2257 | + $P.css( newCSS ); |
| 2258 | + |
| 2259 | + // make sure the zIndex of all other panes is normal |
| 2260 | + $.each(c.allPanes.split(","), function(i, p) { |
| 2261 | + if (p != pane) resetOverflow(p); |
| 2262 | + }); |
| 2263 | + |
| 2264 | + }; |
| 2265 | + |
| 2266 | + function resetOverflow (elem) { |
| 2267 | + if (this && this.tagName) elem = this; // BOUND to element |
| 2268 | + var $P; |
| 2269 | + if (typeof elem=="string") |
| 2270 | + $P = $Ps[elem]; |
| 2271 | + else { |
| 2272 | + if ($(elem).hasClass("ui-layout-pane")) $P = $(elem); |
| 2273 | + else $P = $(elem).parents("div[pane]:first"); |
| 2274 | + } |
| 2275 | + if (!$P.length) return; // INVALID |
| 2276 | + |
| 2277 | + var |
| 2278 | + pane = $P.attr("pane") |
| 2279 | + , s = state[pane] |
| 2280 | + , CSS = s.cssSaved || {} |
| 2281 | + ; |
| 2282 | + // reset the zIndex |
| 2283 | + if (!s.isSliding && !s.isResizing) |
| 2284 | + $P.css("zIndex", c.zIndex.pane_normal); |
| 2285 | + |
| 2286 | + // reset Overflow - if necessary |
| 2287 | + $P.css( CSS ); |
| 2288 | + |
| 2289 | + // clear var |
| 2290 | + s.cssSaved = false; |
| 2291 | + }; |
| 2292 | + |
| 2293 | + |
| 2294 | + /** |
| 2295 | + * getBtn |
| 2296 | + * |
| 2297 | + * Helper function to validate params received by addButton utilities |
| 2298 | + * |
| 2299 | + * @param String selector jQuery selector for button, eg: ".ui-layout-north .toggle-button" |
| 2300 | + * @param String pane Name of the pane the button is for: 'north', 'south', etc. |
| 2301 | + * @returns If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise 'false' |
| 2302 | + */ |
| 2303 | + function getBtn(selector, pane, action) { |
| 2304 | + var |
| 2305 | + $E = $(selector) |
| 2306 | + , err = "Error Adding Button \n\nInvalid " |
| 2307 | + ; |
| 2308 | + if (!$E.length) // element not found |
| 2309 | + alert(err+"selector: "+ selector); |
| 2310 | + else if (c.borderPanes.indexOf(pane) == -1) // invalid 'pane' sepecified |
| 2311 | + alert(err+"pane: "+ pane); |
| 2312 | + else { // VALID |
| 2313 | + var btn = options[pane].buttonClass +"-"+ action; |
| 2314 | + $E.addClass( btn +" "+ btn +"-"+ pane ); |
| 2315 | + return $E; |
| 2316 | + } |
| 2317 | + return false; // INVALID |
| 2318 | + }; |
| 2319 | + |
| 2320 | + |
| 2321 | + /** |
| 2322 | + * addToggleBtn |
| 2323 | + * |
| 2324 | + * Add a custom Toggler button for a pane |
| 2325 | + * |
| 2326 | + * @param String selector jQuery selector for button, eg: ".ui-layout-north .toggle-button" |
| 2327 | + * @param String pane Name of the pane the button is for: 'north', 'south', etc. |
| 2328 | + */ |
| 2329 | + function addToggleBtn (selector, pane) { |
| 2330 | + var $E = getBtn(selector, pane, "toggle"); |
| 2331 | + if ($E) |
| 2332 | + $E |
| 2333 | + .attr("title", state[pane].isClosed ? "Open" : "Close") |
| 2334 | + .click(function (evt) { |
| 2335 | + toggle(pane); |
| 2336 | + evt.stopPropagation(); |
| 2337 | + }) |
| 2338 | + ; |
| 2339 | + }; |
| 2340 | + |
| 2341 | + /** |
| 2342 | + * addOpenBtn |
| 2343 | + * |
| 2344 | + * Add a custom Open button for a pane |
| 2345 | + * |
| 2346 | + * @param String selector jQuery selector for button, eg: ".ui-layout-north .open-button" |
| 2347 | + * @param String pane Name of the pane the button is for: 'north', 'south', etc. |
| 2348 | + */ |
| 2349 | + function addOpenBtn (selector, pane) { |
| 2350 | + var $E = getBtn(selector, pane, "open"); |
| 2351 | + if ($E) |
| 2352 | + $E |
| 2353 | + .attr("title", "Open") |
| 2354 | + .click(function (evt) { |
| 2355 | + open(pane); |
| 2356 | + evt.stopPropagation(); |
| 2357 | + }) |
| 2358 | + ; |
| 2359 | + }; |
| 2360 | + |
| 2361 | + /** |
| 2362 | + * addCloseBtn |
| 2363 | + * |
| 2364 | + * Add a custom Close button for a pane |
| 2365 | + * |
| 2366 | + * @param String selector jQuery selector for button, eg: ".ui-layout-north .close-button" |
| 2367 | + * @param String pane Name of the pane the button is for: 'north', 'south', etc. |
| 2368 | + */ |
| 2369 | + function addCloseBtn (selector, pane) { |
| 2370 | + var $E = getBtn(selector, pane, "close"); |
| 2371 | + if ($E) |
| 2372 | + $E |
| 2373 | + .attr("title", "Close") |
| 2374 | + .click(function (evt) { |
| 2375 | + close(pane); |
| 2376 | + evt.stopPropagation(); |
| 2377 | + }) |
| 2378 | + ; |
| 2379 | + }; |
| 2380 | + |
| 2381 | + /** |
| 2382 | + * addPinBtn |
| 2383 | + * |
| 2384 | + * Add a custom Pin button for a pane |
| 2385 | + * |
| 2386 | + * Four classes are added to the element, based on the paneClass for the associated pane... |
| 2387 | + * Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin: |
| 2388 | + * - ui-layout-pane-pin |
| 2389 | + * - ui-layout-pane-west-pin |
| 2390 | + * - ui-layout-pane-pin-up |
| 2391 | + * - ui-layout-pane-west-pin-up |
| 2392 | + * |
| 2393 | + * @param String selector jQuery selector for button, eg: ".ui-layout-north .ui-layout-pin" |
| 2394 | + * @param String pane Name of the pane the pin is for: 'north', 'south', etc. |
| 2395 | + */ |
| 2396 | + function addPinBtn (selector, pane) { |
| 2397 | + var $E = getBtn(selector, pane, "pin"); |
| 2398 | + if ($E) { |
| 2399 | + var s = state[pane]; |
| 2400 | + $E.click(function (evt) { |
| 2401 | + setPinState($(this), pane, (s.isSliding || s.isClosed)); |
| 2402 | + if (s.isSliding || s.isClosed) open( pane ); // change from sliding to open |
| 2403 | + else close( pane ); // slide-closed |
| 2404 | + evt.stopPropagation(); |
| 2405 | + }); |
| 2406 | + // add up/down pin attributes and classes |
| 2407 | + setPinState ($E, pane, (!s.isClosed && !s.isSliding)); |
| 2408 | + // add this pin to the pane data so we can 'sync it' automatically |
| 2409 | + // PANE.pins key is an array so we can store multiple pins for each pane |
| 2410 | + c[pane].pins.push( selector ); // just save the selector string |
| 2411 | + } |
| 2412 | + }; |
| 2413 | + |
| 2414 | + /** |
| 2415 | + * syncPinBtns |
| 2416 | + * |
| 2417 | + * INTERNAL function to sync 'pin buttons' when pane is opened or closed |
| 2418 | + * Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes |
| 2419 | + * |
| 2420 | + * @callers open(), close() |
| 2421 | + * @params pane These are the params returned to callbacks by layout() |
| 2422 | + * @params doPin True means set the pin 'down', False means 'up' |
| 2423 | + */ |
| 2424 | + function syncPinBtns (pane, doPin) { |
| 2425 | + $.each(c[pane].pins, function (i, selector) { |
| 2426 | + setPinState($(selector), pane, doPin); |
| 2427 | + }); |
| 2428 | + }; |
| 2429 | + |
| 2430 | + /** |
| 2431 | + * setPinState |
| 2432 | + * |
| 2433 | + * Change the class of the pin button to make it look 'up' or 'down' |
| 2434 | + * |
| 2435 | + * @callers addPinBtn(), syncPinBtns() |
| 2436 | + * @param Element $Pin The pin-span element in a jQuery wrapper |
| 2437 | + * @param Boolean doPin True = set the pin 'down', False = set it 'up' |
| 2438 | + * @param String pinClass The root classname for pins - will add '-up' or '-down' suffix |
| 2439 | + */ |
| 2440 | + function setPinState ($Pin, pane, doPin) { |
| 2441 | + var updown = $Pin.attr("pin"); |
| 2442 | + if (updown && doPin == (updown=="down")) return; // already in correct state |
| 2443 | + var |
| 2444 | + root = options[pane].buttonClass |
| 2445 | + , class1 = root +"-pin" |
| 2446 | + , class2 = class1 +"-"+ pane |
| 2447 | + , UP1 = class1 + "-up" |
| 2448 | + , UP2 = class2 + "-up" |
| 2449 | + , DN1 = class1 + "-down" |
| 2450 | + , DN2 = class2 + "-down" |
| 2451 | + ; |
| 2452 | + $Pin |
| 2453 | + .attr("pin", doPin ? "down" : "up") // logic |
| 2454 | + .attr("title", doPin ? "Un-Pin" : "Pin") |
| 2455 | + .removeClass( doPin ? UP1 : DN1 ) |
| 2456 | + .removeClass( doPin ? UP2 : DN2 ) |
| 2457 | + .addClass( doPin ? DN1 : UP1 ) |
| 2458 | + .addClass( doPin ? DN2 : UP2 ) |
| 2459 | + ; |
| 2460 | + }; |
| 2461 | + |
| 2462 | + |
| 2463 | +/* |
| 2464 | + * ########################### |
| 2465 | + * CREATE/RETURN BORDER-LAYOUT |
| 2466 | + * ########################### |
| 2467 | + */ |
| 2468 | + |
| 2469 | + // init global vars |
| 2470 | + var |
| 2471 | + $Container = $(this).css({ overflow: "hidden" }) // Container elem |
| 2472 | + , $Ps = {} // Panes x4 - set in initPanes() |
| 2473 | + , $Cs = {} // Content x4 - set in initPanes() |
| 2474 | + , $Rs = {} // Resizers x4 - set in initHandles() |
| 2475 | + , $Ts = {} // Togglers x4 - set in initHandles() |
| 2476 | + // object aliases |
| 2477 | + , c = config // alias for config hash |
| 2478 | + , cDims = state.container // alias for easy access to 'container dimensions' |
| 2479 | + ; |
| 2480 | + |
| 2481 | + // create the border layout NOW |
| 2482 | + create(); |
| 2483 | + |
| 2484 | + // return object pointers to expose data & option Properties, and primary action Methods |
| 2485 | + return { |
| 2486 | + options: options // property - options hash |
| 2487 | + , state: state // property - dimensions hash |
| 2488 | + , panes: $Ps // property - object pointers for ALL panes: panes.north, panes.center |
| 2489 | + , toggle: toggle // method - pass a 'pane' ("north", "west", etc) |
| 2490 | + , open: open // method - ditto |
| 2491 | + , close: close // method - ditto |
| 2492 | + , hide: hide // method - ditto |
| 2493 | + , show: show // method - ditto |
| 2494 | + , resizeContent: sizeContent // method - ditto |
| 2495 | + , sizePane: sizePane // method - pass a 'pane' AND a 'size' in pixels |
| 2496 | + , resizeAll: resizeAll // method - no parameters |
| 2497 | + , addToggleBtn: addToggleBtn // utility - pass element selector and 'pane' |
| 2498 | + , addOpenBtn: addOpenBtn // utility - ditto |
| 2499 | + , addCloseBtn: addCloseBtn // utility - ditto |
| 2500 | + , addPinBtn: addPinBtn // utility - ditto |
| 2501 | + , allowOverflow: allowOverflow // utility - pass calling element |
| 2502 | + , resetOverflow: resetOverflow // utility - ditto |
| 2503 | + , cssWidth: cssW |
| 2504 | + , cssHeight: cssH |
| 2505 | + }; |
| 2506 | + |
| 2507 | +} |
| 2508 | +})( jQuery ); |
\ No newline at end of file |
Index: branches/MwEmbedStandAlone/modules/SequenceEdit/mw.SequenceEdit.js |
— | — | @@ -0,0 +1,220 @@ |
| 2 | +/** |
| 3 | + * Main Sequence Editor Driver |
| 4 | + */ |
| 5 | + |
| 6 | +mw.includeAllModuleMessages(); |
| 7 | + |
| 8 | +/* |
| 9 | +* Setup the sequenceEdit jQuery binding: |
| 10 | +*/ |
| 11 | +( function( $ ) { |
| 12 | + $.fn.sequenceEdit = function( options ) { |
| 13 | + // Debugger |
| 14 | + if( $j( this.selector ).length == 0 ){ |
| 15 | + mw.log("SequenceEdit::Error missing target container"); |
| 16 | + return; |
| 17 | + } |
| 18 | + var seqContainer = $j( this.selector ).get(0); |
| 19 | + // Check if we already have a sequencer associated with this target |
| 20 | + if( seqContainer['sequenceEdit'] ){ |
| 21 | + // xxx todo: pass on the options / action |
| 22 | + return ; |
| 23 | + } |
| 24 | + options['interfaceContainer'] = this.selector; |
| 25 | + |
| 26 | + // Issue a request to get the CSS file (if not already included): |
| 27 | + mw.log( 'SequenceEdit:: create new SequenceEdit' ); |
| 28 | + |
| 29 | + // Initialize the sequence object (it will take over from there) |
| 30 | + seqContainer['sequenceEdit'] = new mw.SequenceEdit( options ); |
| 31 | + |
| 32 | + // Draw the sequencer UI |
| 33 | + seqContainer['sequenceEdit'].drawUI(); |
| 34 | + |
| 35 | + //Return the sequence jquery object |
| 36 | + return this; |
| 37 | + |
| 38 | + } |
| 39 | +} )( jQuery ); |
| 40 | + |
| 41 | +//Wrap in mw closure to avoid global leakage |
| 42 | +( function( mw ) { |
| 43 | + |
| 44 | +/** |
| 45 | + * The set of valid sequenceEdit options |
| 46 | + */ |
| 47 | +var mw_sequenceedit_default_options = { |
| 48 | + 'interfaceContainer' : null, |
| 49 | + 'smilSource' : null, |
| 50 | + 'videoAspect' : '4:3' |
| 51 | +} |
| 52 | +mw.SequenceEdit = function( options ) { |
| 53 | + return this.init( options ); |
| 54 | +}; |
| 55 | + |
| 56 | +// Set up the mvSequencer object |
| 57 | +mw.SequenceEdit.prototype = { |
| 58 | + // lazy init id for the sequenceEdit instance. |
| 59 | + id: null, |
| 60 | + |
| 61 | + init: function( options ){ |
| 62 | + if(!options) |
| 63 | + options = {}; |
| 64 | + // Validate and set default options : |
| 65 | + for( var optionName in mw_sequenceedit_default_options ){ |
| 66 | + if( typeof options[ optionName] != 'undefined'){ |
| 67 | + this[optionName] = options[ optionName] ; |
| 68 | + } else { |
| 69 | + this[optionName] = mw_sequenceedit_default_options[ optionName ] |
| 70 | + } |
| 71 | + } |
| 72 | + // For style properties assgin top level mwe-sequence-edit class |
| 73 | + this.getContainer().addClass('mwe-sequence-edit'); |
| 74 | + }, |
| 75 | + |
| 76 | + // Return the container id for the sequence |
| 77 | + getId: function(){ |
| 78 | + if( !this.id ){ |
| 79 | + // Assign the container an id if missing one:: |
| 80 | + if( ! this.getContainer().attr('id') ){ |
| 81 | + this.getContainer().attr('id', 'sequenceEdit_' + new Date().getTime() + Math.random() ); |
| 82 | + } |
| 83 | + this.id = this.getContainer().attr('id'); |
| 84 | + } |
| 85 | + return this.id; |
| 86 | + }, |
| 87 | + /** |
| 88 | + * @return smilSource url |
| 89 | + */ |
| 90 | + getSmilSource: function(){ |
| 91 | + return this.smilSource; |
| 92 | + }, |
| 93 | + /** |
| 94 | + * draw the initial sequence ui, uses ui.layout for adjustable layout |
| 95 | + */ |
| 96 | + drawUI: function( ){ |
| 97 | + var _this = this; |
| 98 | + mw.log("SequenceEdit:: drawUI to: " + this.interfaceContainer + |
| 99 | + ' ' + this.getContainer().length); |
| 100 | + |
| 101 | + // Add the ui layout |
| 102 | + this.getContainer().html( |
| 103 | + this.getUiLayout() |
| 104 | + ) |
| 105 | + // Once the layout is in the dom setup resizableLayout "layout" options |
| 106 | + this.applyLayoutBindings(); |
| 107 | + |
| 108 | + // Add the smil player |
| 109 | + //xxx deal with the case of an empty player~~ |
| 110 | + this.getPlayer().drawPlayer( function(){ |
| 111 | + // Once the player and smil is loaded :: |
| 112 | + // start buffering |
| 113 | + _this.getEmbedPlayer().load(); |
| 114 | + |
| 115 | + // Add the timeline |
| 116 | + _this.getTimeline().drawTimeline(); |
| 117 | + |
| 118 | + }); |
| 119 | + |
| 120 | + // Add deafult clip edit |
| 121 | + |
| 122 | + }, |
| 123 | + getPlayer: function(){ |
| 124 | + if( ! this.player ){ |
| 125 | + this.player = new mw.SequenceEditPlayer( this ); |
| 126 | + } |
| 127 | + return this.player; |
| 128 | + }, |
| 129 | + getEmbedPlayer:function(){ |
| 130 | + return $j( '#' + this.getPlayer().getSmilPlayerId() ).get(0); |
| 131 | + }, |
| 132 | + getSmil: function(){ |
| 133 | + if( !this.smil ){ |
| 134 | + this.smil = this.getEmbedPlayer().smil; |
| 135 | + } |
| 136 | + return this.smil; |
| 137 | + }, |
| 138 | + getTimeline: function(){ |
| 139 | + if( ! this.timeline ){ |
| 140 | + this.timeline = new mw.SequenceEditTimeline( this ); |
| 141 | + } |
| 142 | + return this.timeline; |
| 143 | + }, |
| 144 | + getKeyBindings:function(){ |
| 145 | + if( ! this.keyBindings ){ |
| 146 | + this.keyBindings = new mw.SequenceEditKeyBindings( this ); |
| 147 | + } |
| 148 | + return this.keyBindings; |
| 149 | + }, |
| 150 | + // Apply the resizable layout bindings and default sizes |
| 151 | + applyLayoutBindings: function(){ |
| 152 | + var _this = this; |
| 153 | + this.getContainer().find('.resizableLayout').layout({ |
| 154 | + 'applyDefaultStyles': true, |
| 155 | + /* player container */ |
| 156 | + 'east__minSize': 240, |
| 157 | + 'east__size': 400, |
| 158 | + 'east__onresize':function(){ |
| 159 | + _this.getPlayer().resizePlayer(); |
| 160 | + }, |
| 161 | + |
| 162 | + /* edit container */ |
| 163 | + 'center__minSize' : 300, |
| 164 | + |
| 165 | + /* timeline container */ |
| 166 | + 'south__minSize' : 160, |
| 167 | + 'south__size' : 240, |
| 168 | + 'south__onresize' : function(){ |
| 169 | + _this.getTimeline().resizeTimeline(); |
| 170 | + } |
| 171 | + }); |
| 172 | + }, |
| 173 | + |
| 174 | + /** |
| 175 | + * Get the UI layout |
| 176 | + */ |
| 177 | + getUiLayout: function(){ |
| 178 | + // xxx There is probably a cleaner way to generate a list of jQuery objects than $j('new').children(); |
| 179 | + return $j('<div />').append( |
| 180 | + $j('<div />') |
| 181 | + .addClass( "mwseq-menu" ) |
| 182 | + .css({ |
| 183 | + 'position':'absolute', |
| 184 | + 'height': '25px', |
| 185 | + 'width': '100%', |
| 186 | + 'top': '0px', |
| 187 | + 'left' : '0px' |
| 188 | + }) |
| 189 | + .text('Menu') |
| 190 | + , |
| 191 | + |
| 192 | + $j('<div />') |
| 193 | + .addClass('resizableLayout') |
| 194 | + .css({ |
| 195 | + 'position':'absolute', |
| 196 | + 'top': '25px', |
| 197 | + 'left': '0px', |
| 198 | + 'right': '0px', |
| 199 | + 'bottom':'0px' |
| 200 | + }) |
| 201 | + .append( |
| 202 | + $j('<div />') |
| 203 | + .addClass( "ui-layout-center mwseq-edit" ) |
| 204 | + .text( gM('mwe-sequenceedit-loading_edit') ), |
| 205 | + $j('<div />') |
| 206 | + .addClass( "ui-layout-east mwseq-player" ) |
| 207 | + .text( gM('mwe-sequenceedit-loading_player') ), |
| 208 | + $j('<div />') |
| 209 | + .addClass( "ui-layout-south mwseq-timeline" ) |
| 210 | + .text( gM('mwe-sequenceedit-loading_timeline') ) |
| 211 | + ) |
| 212 | + ).children(); |
| 213 | + }, |
| 214 | + |
| 215 | + getContainer: function(){ |
| 216 | + return $j( this.interfaceContainer ); |
| 217 | + } |
| 218 | + |
| 219 | +} |
| 220 | + |
| 221 | +} )( window.mw ); |
\ No newline at end of file |