1 /* 2 * Standalone Wait Dialog (extracted from jQuery Mobile 1.4.3) 3 * 4 * stdlne-wait-dlg 5 * 6 * <div class="stdlne-wait-dlg stdlne-style-b stdlne-wait-dlg-verbose"><span class="stdlne-icon"></span><h1>title</h1></div> 7 * 8 * version 0.2 9 * Copyright (C) 2015 russa, DFKI GmbH 10 * MIT license 11 * 12 * Dependencies: 13 * * document (DOM): body, head 14 * * createElement: div, span, h1 15 * * appendChild 16 * * classList 17 * * className 18 * * childNodes 19 */ 20 21 //(function(module){ 22 define(['module'], function(module){ 23 24 //configurable via requirejs' module: 25 // * activeClass: (String) the CSS for setting the dialog to 'active' state 26 // DEFAULT: "stdlne-active" 27 // * fileName: (String) the name of the CSS styles file 28 // DEFAULT: "stdlne-wait-dlg.css" 29 // * defaultType: (String) default type for the wait-dialog: ["small" | "verbose"] 30 // DEFAULT: "verbose" 31 // * defaultTheme: (String) default theme for the wait-dialog: ["a" | "b"] 32 // DEFAULT: "a" 33 // * defaultTitle: (String) default title / caption for the wait-dialog 34 // DEFAULT: "" 35 36 /** 37 * Temporary variable for retrieving configuration values. 38 * 39 * @private 40 * @memberOf StandaloneWaitDialog.prototype 41 */ 42 var tmpConfig = module.config().activeClass; 43 44 /** 45 * @type String 46 * @private 47 * @memberOf StandaloneWaitDialog.prototype 48 */ 49 var activatorClass = tmpConfig? tmpConfig : 'stdlne-active'; 50 51 tmpConfig = module.config().fileName; 52 /** 53 * @type String 54 * @private 55 * @memberOf StandaloneWaitDialog.prototype 56 */ 57 var defaultStyleUrl = tmpConfig? tmpConfig : 'stdlne-wait-dlg.css'; 58 59 60 61 /** 62 * @constant 63 * @private 64 * @memberOf StandaloneWaitDialog.prototype 65 */ 66 var types = { 67 'small': 'stdlne-wait-dlg-small', 68 'verbose': 'stdlne-wait-dlg-verbose' 69 }; 70 71 //set default type 72 tmpConfig = module.config().defaultType; 73 if(!tmpConfig){ 74 tmpConfig = 'stdlne-wait-dlg-verbose'; 75 } else { 76 tmpConfig = types[tmpConfig]; 77 } 78 types['default'] = tmpConfig; 79 80 81 82 /** 83 * @constant 84 * @private 85 * @memberOf StandaloneWaitDialog.prototype 86 */ 87 var themes = { 88 'a': 'stdlne-style-a', 89 'b': 'stdlne-style-b' 90 }; 91 92 //set default theme 93 tmpConfig = module.config().defaultTheme; 94 if(!tmpConfig){ 95 tmpConfig = 'stdlne-style-a'; 96 } else { 97 tmpConfig = themes[tmpConfig]; 98 } 99 themes['default'] = tmpConfig; 100 101 102 //setting up the default title (used in StandaloneWaitDialog class) 103 /** 104 * @private 105 * @type String 106 * @memberOf StandaloneWaitDialog.prototype 107 */ 108 var tmpDefaultTitle = module.config().defaultTitle; 109 110 if(!tmpDefaultTitle){ 111 tmpDefaultTitle = ''; 112 } 113 114 115 116 tmpConfig = module.config().defaultId; 117 /** 118 * ID for default wait dialog (i.e. when show() is used without ID argument). 119 * 120 * @type String 121 * @private 122 * @memberOf StandaloneWaitDialog.prototype 123 */ 124 var defaultDialogId = tmpConfig? tmpConfig : 'default-stdlne-wait-dlg'; 125 126 127 /** 128 * HELPER set type, theme classes to a wait-dialog DOM element 129 * 130 * @private 131 * @memberOf StandaloneWaitDialog.prototype 132 */ 133 function _applyClasses(domEl, typeCl, themeCl, isActivate){ 134 135 if(typeCl){ 136 137 if(typeCl !== types['small']){ 138 domEl.classList.remove(types['small']); 139 } else if(typeCl !== types['verbose']){ 140 domEl.classList.remove(types['verbose']); 141 } 142 domEl.classList.add(typeCl); 143 } 144 145 if(themeCl){ 146 147 if(themeCl !== themes['a']){ 148 domEl.classList.remove(themes['a']); 149 } else if(themeCl !== themes['b']){ 150 domEl.classList.remove(themes['b']); 151 } 152 153 domEl.classList.add(themeCl); 154 } 155 156 //apply 'active' class 157 if(isActivate){ 158 domEl.classList.add(activatorClass); 159 } 160 } 161 162 /** 163 * Default options for wait dialog. 164 * 165 * <p> 166 * Different wait dialogs are managed 167 * in the <code>defaultOptions</code> map 168 * (map-key is their ID). 169 * 170 * @class 171 * @see StandaloneWaitDialog#defaultOptions 172 */ 173 function Options(options, owner){ 174 this.set(options, owner); 175 } 176 177 Options.prototype = { 178 179 set: function(options, owner){ 180 181 if(owner){ 182 this._owner = owner; 183 } 184 185 if(options.theme){ 186 this._theme = themes[options.theme]; 187 } 188 if(options.type){ 189 this._type = types[options.type]; 190 } 191 192 if(options.style){ 193 this._style = options.style; 194 } 195 if(options.classes){ 196 var cl = options.classes; 197 if(typeof cl === 'string'){ 198 cl = cl.split(' '); 199 } 200 this._classes = cl; 201 } 202 }, 203 getTheme: function(){ 204 if(typeof this._theme !== 'undefined'){ 205 return this._theme; 206 } 207 return this._owner.defaultTheme; 208 }, 209 getType: function(){ 210 if(typeof this._type !== 'undefined'){ 211 return this._type; 212 } 213 return this._owner.defaultType; 214 }, 215 getTitle: function(){ 216 if(typeof this._title !== 'undefined'){ 217 return this._title; 218 } 219 return this._owner.defaultTitle; 220 }, 221 getClasses: function(){ 222 if(typeof this._classes !== 'undefined'){ 223 return this._classes; 224 } 225 return; 226 }, 227 getStyle: function(){ 228 if(typeof this._style !== 'undefined'){ 229 return this._style; 230 } 231 return; 232 } 233 }; 234 235 /** 236 * The Wait Dialog interface. 237 * 238 * <p> 239 * Allows to create multiple wait dialogs. 240 * 241 * @class 242 * @singleton 243 */ 244 function StandaloneWaitDialog(){ 245 if(typeof window !== 'undefined' && this === window){ 246 return new StandaloneWaitDialog(); 247 } 248 return this; 249 }; 250 251 StandaloneWaitDialog.prototype = { 252 defaultTitle: tmpDefaultTitle, 253 defaultTheme: themes['default'], 254 defaultType: types['default'], 255 styleUrl: defaultStyleUrl, 256 _isCssLoaded: false, 257 _getDom: function(id){//returns: Array 258 259 if(id){//if id: only return one element (in an array) 260 var element = document.getElementById(id); 261 return element? [element] : []; 262 } 263 return document.getElementsByClassName('stdlne-wait-dlg'); 264 265 }, 266 _loadStyle: function(url, isForceReloading){ 267 268 if(typeof url === 'boolean'){ 269 isForceReloading = url; 270 url = void(0); 271 } 272 273 if(this._isCssLoaded && !isForceReloading){ 274 return; 275 } 276 277 //NOTE do not use onload for LINK: 278 // not supported by all browsers, so no 279 // reliable detection via onload possible. 280 // -> just use simple FLAG 281 // (application must deal with possible loading-problems) 282 this._isCssLoaded = true; 283 284 if(!url){ 285 url = this.styleUrl; 286 } 287 288 var link = document.createElement("link"); 289 link.type = "text/css"; 290 link.rel = "stylesheet"; 291 link.href = url; 292 document.getElementsByTagName("head")[0].appendChild(link); 293 294 }, 295 _getDefaults: function(id){ 296 return defaultOptions.get(id); 297 }, 298 setDefaults: function(id, options){//NOTE not allowed for default-wait-dialog (-> set properties on StandaloneWaitDialog instance itself!) 299 300 if(!id || !options){ 301 throw new Error('Invalid argument(s): '+(!id? 'missing ID (got: '+id+')':'')+(!options? 'missing options (got: '+options+')':'')); 302 } 303 304 var defs = defaultOptions.get(id); 305 if(!defs){ 306 defs = new Options(options, this); 307 defaultOptions.set(id, defs); 308 } 309 else { 310 defs.set(options); 311 } 312 }, 313 create: function(id, options){ 314 315 var _id = id; 316 317 var container = document.createElement("div"); 318 container.classList.add('stdlne-wait-dlg'); 319 320 if(_id){ 321 322 container.id = _id; 323 324 if(options){ 325 this.setDefaults(_id, options); 326 } 327 } 328 329 var icon = document.createElement("span"); 330 icon.className = 'stdlne-icon'; 331 332 var caption = document.createElement("h1"); 333 // caption.className = 'stdlne-caption'; 334 335 container.appendChild(icon); 336 container.appendChild(caption); 337 338 return container; 339 }, 340 /** 341 * 342 * @param {String|Object} [title] OPTIONAL 343 * if String: the tile to show in the dialog (NOTE: only visible, if dialog-style is "verbose") 344 * if Object: an options object with (OPTIONAL) properties: 345 * * option.title {String} the title<br> 346 * * option.id {String} the ID attribute of the dialog to show<br> 347 * * option.type {String} the type for the dialog to show: ["small" | "verbose"], default: "verbose"<br> 348 * * option.theme {String} the theme (style) for the dialog to show: ["a" | "b"], default: "a"<br> 349 * @param {String} [id] OPTIONAL 350 * an ID for the dialog to show (if omitted the default dialog will be shown) 351 */ 352 show: function(title, id, options){ 353 354 var _title, _id, _type, _theme, _defaults; 355 356 var _style, _classes, _elStyle; 357 358 //re-map argument: is 2nd argument the options object? 359 if(!options && id !== null && typeof id === 'object'){ 360 options = id; 361 id = void(0); 362 } 363 364 if(id){ 365 _id = id; 366 } 367 368 if(title){ 369 370 if(typeof title === 'string'){ 371 _title = title; 372 } 373 else { 374 _title = title.title; 375 //NOTE if there is also an options object (3rd argument), 376 // it will be overwritten by the first-argument's options! 377 _type = typeof title.type !== 'undefined'? types[title.type] : _type; 378 _theme = typeof title.theme !== 'undefined'? themes[title.theme] : _theme; 379 _id = typeof title.id !== 'undefined'? title.id : id; 380 } 381 382 } else { 383 384 _title = this.defaultTitle; 385 } 386 387 if(_id){ 388 389 if(options){ 390 this.setDefaults(_id, options); 391 } 392 393 _defaults = this._getDefaults(_id); 394 if(_defaults){ 395 if(_defaults.getType() && typeof _type === 'undefined'){ 396 _type = _defaults.getType(); 397 } 398 if(_defaults.getTheme() && typeof _theme === 'undefined'){ 399 _theme = _defaults.getTheme(); 400 } 401 if(_defaults.getTitle() && typeof _title === 'undefined'){ 402 _title = _defaults.getTitle(); 403 } 404 405 if(_defaults.getStyle() && typeof _style === 'undefined'){ 406 _style = _defaults.getStyle(); 407 } 408 if(_defaults.getClasses() && typeof _classes === 'undefined'){ 409 _classes = _defaults.getClasses(); 410 } 411 } 412 } 413 414 if(typeof _type === 'undefined'){ 415 _type = this.defaultType; 416 } 417 if(typeof _theme === 'undefined'){ 418 _theme = this.defaultTheme; 419 } 420 if(typeof _title === 'undefined'){ 421 _title = this.defaultTitle; 422 } 423 424 if(typeof _id === 'undefined'){ 425 _id = defaultDialogId; 426 } 427 428 var list = this._getDom(_id); 429 var size = list.length; 430 if(size < 1){ 431 list = [this.create(_id, options)]; 432 size = 1; 433 document.body.appendChild(list[0]); 434 } 435 436 var curr; 437 for(var i=0; i < size; ++i){ 438 curr = list[i]; 439 _applyClasses(curr, _type, _theme, true); 440 curr.childNodes.item(1).textContent = _title; 441 442 if(typeof _style !== 'undefined'){ 443 //TODO should this just overwrite the complete style-attribute? 444 // ...because now, the removal (see hide()) is somewhat hacked 445 // and also may "overlook" added semicolon... 446 _elStyle = curr.getAttribute('style'); 447 if(!_elStyle){ 448 _elStyle = _style; 449 } 450 else { 451 _elStyle +=';' + _style; 452 } 453 curr.setAttribute('style', _elStyle); 454 } 455 if(typeof _classes !== 'undefined'){ 456 curr.classList.add.apply(curr.classList, _classes); 457 } 458 } 459 }, 460 /** 461 * 462 * @param {String} [id] OPTIONAL 463 * the ID for the dialog element (if omitted all dialogs will be hidden) 464 */ 465 hide: function(id){ 466 var list = this._getDom(id), curr, defs, currStyle; 467 for(var i=0,size = list.length; i < size; ++i){ 468 curr = list[i]; 469 curr.classList.remove(activatorClass); 470 471 if(curr.id){ 472 473 defs = this._getDefaults(curr.id); 474 475 //remove style and classes from defaults 476 if(defs){ 477 currStyle = curr.getAttribute('style'); 478 if(defs.getStyle() && currStyle){ 479 curr.setAttribute('style', currStyle.replace(defs.getStyle(), '') ); 480 } 481 if(defs.getClasses()){ 482 curr.classList.removeapply(curr.classList, defs.getClasses()); 483 } 484 } 485 } 486 } 487 } 488 }; 489 //module.waitDialog = dlg; 490 491 /** 492 * @private 493 * @memberOf StandaloneWaitDialog.prototype 494 */ 495 var dlg = new StandaloneWaitDialog(); 496 //dlg.newInstance = StandaloneWaitDialog; 497 498 /** 499 * @private 500 * @memberOf StandaloneWaitDialog.prototype 501 */ 502 var defaultOptions = { 503 get: function(id){ 504 if(id){ 505 return this[_getKey(id)]; 506 } 507 return this['$']; 508 }, 509 set: function(id, options){ 510 if(!id){ 511 id = '$'; 512 } 513 this[_getKey(id)] = options; 514 }, 515 '$': new Options({}, dlg) 516 }; 517 518 /** 519 * @private 520 * @memberOf StandaloneWaitDialog.prototype 521 */ 522 function _getKey(id){ 523 return '$$'+id; 524 } 525 526 return dlg; 527 }); 528 529 //})(window); 530