common.js (16197B)
1 2 // The crap in this file should be refactored into namespaced objects... 3 4 var OR_THEMES_EXT_DIR = 'modules/cms-ui/themes/'; 5 6 // Execute after DOM ready: 7 $( function() { 8 // JS is available. 9 $('html').removeClass('nojs'); 10 11 /* Fade in all elements. */ 12 $('.initial-hidden').removeClass('initial-hidden'); 13 14 15 /** 16 * Registriert alle Events, die in der Workbench laufen sollen. 17 */ 18 function registerWorkbenchEvents() 19 { 20 // Modalen Dialog erzeugen. 21 22 /* 23 if ( $('#workbench div.panel.modal').length > 0 ) 24 { 25 $('#workbench div.panel.modal').parent().addClass('modal'); 26 $('div#filler').fadeTo(500,0.5); 27 $('#workbench').addClass('modal'); 28 } 29 */ 30 31 /** 32 * Schaltet die Vollbildfunktion an oder aus. 33 * 34 * @param element Das Element, auf dem die Vollbildfunktion ausgeführt wurde 35 */ 36 function fullscreen( element ) { 37 $(element).closest('div.panel').fadeOut('fast', function() 38 { 39 $(this).toggleClass('fullscreen').fadeIn('fast'); 40 } ); 41 } 42 43 44 $('div.header').dblclick( function() 45 { 46 fullscreen( this ); 47 } ); 48 } 49 50 51 registerWorkbenchEvents(); 52 53 54 // Listening to the "popstate" event: 55 window.onpopstate = function (ev) { 56 Openrat.Navigator.navigateTo(ev.state); 57 }; 58 59 Openrat.Workbench.initialize(); 60 Openrat.Workbench.reloadAll(); 61 62 let registerWorkbenchGlobalEvents = function() { 63 64 // Binding aller Sondertasten. 65 $('.keystroke').each( function() { 66 let keystrokeElement = $(this); 67 let keystroke = keystrokeElement.text(); 68 if (keystroke.length == 0) 69 return; // No Keybinding. 70 let keyaction = function() { 71 keystrokeElement.click(); 72 }; 73 // Keybinding ausfuehren. 74 $(document).bind('keydown', keystroke, keyaction ); 75 } ); 76 77 78 79 $('section.toggle-open-close .on-click-open-close').click(function () { 80 var section = $(this).closest('section'); 81 82 // disabled sections are ignored. 83 if (section.hasClass('disabled')) 84 return; 85 86 // if view is empty, lets load the content. 87 var view = section.find('div.view-loader'); 88 if (view.children().length == 0) 89 Openrat.Workbench.loadNewActionIntoElement(view); 90 }); 91 92 } 93 94 // Initial Notices 95 $('.or-initial-notice').each( function() { 96 Openrat.Workbench.notify('','','info',$(this).text()); 97 $(this).remove(); 98 }); 99 100 registerWorkbenchGlobalEvents(); 101 102 103 let closeMenu = function() { 104 // Mit der Maus irgendwo hin geklickt, das Menü muss schließen. 105 $('body').click( function() { 106 $('.toolbar-icon.menu').parents('.or-menu').removeClass('open'); 107 }); 108 }; 109 closeMenu(); 110 111 112 113 Openrat.Workbench.afterNewActionHandler.add( function() { 114 115 let url = './api/?action=tree&subaction=path&id=' + Openrat.Workbench.state.id + '&type=' + Openrat.Workbench.state.action + '&output=json'; 116 117 // Die Inhalte des Zweiges laden. 118 $.getJSON(url, function (json) { 119 120 $('nav .or-navtree-node').removeClass('or-navtree-node--selected'); 121 122 let output = json['output']; 123 $.each(output.path, function (idx, path) { 124 125 $nav = $('nav .or-navtree-node[data-type='+path.type+'][data-id='+path.id+'].or-navtree-node--is-closed .or-navtree-node-control'); 126 $nav.click(); 127 }); 128 if ( output.actual ) 129 $('nav .or-navtree-node[data-type='+output.actual.type+'][data-id='+output.actual.id+']').addClass('or-navtree-node--selected'); 130 131 let $breadcrumb = $('.or-breadcrumb').empty(); 132 let items = []; 133 $.each(output.path.concat(output.actual), function (idx, path) { 134 items.push( '<li class="or-breadcrumb-item clickable" tabindex="0"><a href="'+Openrat.Navigator.createShortUrl(path.action,path.id)+'" data-type="open" data-action="'+path.action+'" data-id="'+path.id+'"><i class="image-icon image-icon--action-'+path.action+'" />'+path.name+'</a></li>'); 135 }); 136 $breadcrumb.append( items.join('<li><i class="tree-icon image-icon image-icon--node-closed"></i></li>') ); 137 $('.or-breadcrumb .clickable').orLinkify(); 138 139 }).fail(function (e) { 140 // Ups... aber was können wir hier schon tun, außer hässliche Meldungen anzeigen. 141 console.warn(e); 142 console.warn('failed to load path from '+url); 143 }).always(function () { 144 145 }); 146 } ); 147 148 }); 149 150 151 152 153 let filterMenus = function () 154 { 155 let action = Openrat.Workbench.state.action; 156 let id = Openrat.Workbench.state.id; 157 $('div.clickable').addClass('active'); 158 $('div.clickable.filtered').removeClass('active').addClass('inactive'); 159 160 $('div.clickable.filtered.on-action-'+action).addClass('active').removeClass('inactive'); 161 162 // Jeder Menüeintrag bekommt die Id und Parameter. 163 $('div.clickable.filtered a').attr('data-id' ,id ); 164 /* 165 $('div.clickable.filtered a').attr('data-action',action); 166 */ 167 168 } 169 170 171 $('#title.view').data('afterViewLoaded', function() { 172 filterMenus(); 173 } ); 174 175 Openrat.Workbench.afterNewActionHandler.add( function() { 176 filterMenus(); 177 } ); 178 179 180 181 182 183 184 Openrat.Workbench.afterViewLoadedHandler.add( function(element) { 185 186 // Refresh already opened popup windows. 187 if ( typeof popupWindow != "undefined" ) 188 $(element).find("a[data-type='popup']").each( function() { 189 popupWindow.location.href = $(this).attr('data-url'); 190 }); 191 192 }); 193 194 195 /** 196 * Registriert alle Handler für den Inhalt einer View. 197 * 198 * @param viewEl DOM-Element der View 199 */ 200 Openrat.Workbench.afterViewLoadedHandler.add( function(viewEl ) { 201 202 // Die Section deaktivieren, wenn die View keinen Inhalt hat. 203 var section = $(viewEl).closest('section'); 204 205 //var viewHasContent = $(viewEl).children().length > 0; 206 //section.toggleClass('disabled',!viewHasContent); 207 section.toggleClass('is-empty',$(viewEl).is(':empty')); 208 if ( ! $(viewEl).is(':empty') ) 209 section.slideDown('fast'); 210 else 211 section.slideUp('fast'); 212 213 // Untermenüpunkte aus der View in das Fenstermenü kopieren... 214 $(viewEl).closest('div.panel').find('div.header div.dropdown div.entry.perview').remove(); // Alte Einträge löschen 215 216 $(viewEl).find('.toggle-nav-open-close').click( function() { 217 $('nav').toggleClass('open'); 218 }); 219 220 $(viewEl).find('.toggle-nav-small').click( function() { 221 $('nav').toggleClass('small'); 222 }); 223 224 $(viewEl).find('div.headermenu > a').each( function(idx,el) 225 { 226 // Jeden Untermenüpunkt zum Fenstermenü hinzufügen. 227 228 // Nein, Untermenüs erscheinen jetzt in der View selbst. 229 // $(el).wrap('<div class="entry clickable modal perview" />').parent().appendTo( $(viewEl).closest('div.panel').find('div.header div.dropdown').first() ); 230 } ); 231 232 $(viewEl).find('div.header > a.back').each( function(idx,el) 233 { 234 // Zurück-Knopf zum Fenstermenü hinzufügen. 235 $(el).removeClass('button').wrap('<div class="entry perview" />').parent().appendTo( $(viewEl).closest('div.panel').find('div.header div.dropdown').first() ); 236 } ); 237 //$(viewEl).find('div.header').html('<!-- moved to window-menu -->'); 238 239 // $(viewEl).find('input,select,textarea').focus( function() { 240 // $(this).closest('div.panel').find('div.command').css('visibility','visible').fadeIn('slow'); 241 // }); 242 243 244 // Selectors (Einzel-Ausahl für Dateien) initialisieren 245 // Wurzel des Baums laden 246 $(viewEl).find('div.selector.tree').each( function() { 247 var selectorEl = this; 248 $(this).orTree( { type:'project',selectable:$(selectorEl).attr('data-types').split(','),id:$(selectorEl).attr('data-init-folderid'),onSelect:function(name,type,id) { 249 250 var selector = $(selectorEl).parent(); 251 252 //console.log( 'Selected: '+name+" #"+id ); 253 $(selector).find('input[type=text]' ).attr( 'value',name ); 254 $(selector).find('input[type=hidden]').attr( 'value',id ); 255 } }); 256 } ); 257 258 259 registerDragAndDrop(viewEl); 260 261 262 // Bei Änderungen in der View das Tab als 'dirty' markieren 263 $(viewEl).find('input').change( function() { 264 $(this).parent('div.view').addClass('dirty'); 265 }); 266 267 // Theme-Auswahl mit Preview 268 $(viewEl).find('.or-theme-chooser').change( function() { 269 Openrat.Workbench.setUserStyle( this.value ); 270 }); 271 272 273 274 275 function registerMenuEvents($element ) 276 { 277 //$e = $($element); 278 279 // Mit der Maus geklicktes Menü aktivieren. 280 $($element).find('.toolbar-icon.menu').click( function(event) { 281 event.stopPropagation(); 282 $(this).parents('.or-menu').toggleClass('open'); 283 }); 284 285 // Mit der Maus überstrichenes Menü aktivieren. 286 $($element).find('.toolbar-icon.menu').mouseover( function() { 287 288 // close other menus. 289 $(this).parents('.or-menu').find('.toolbar-icon.menu').removeClass('open'); 290 // open the mouse-overed menu. 291 $(this).addClass('open'); 292 }); 293 294 } 295 296 function registerGlobalSearch($element ) 297 { 298 $($element).find('.search input').orSearch( { 299 dropdown:'#title div.search div.dropdown', 300 select: function(obj) { 301 openNewAction( obj.name, obj.action, obj.id ); 302 } 303 } ); 304 305 } 306 307 function registerSelectorSearch( $element ) 308 { 309 $($element).find('.selector input').orSearch( { 310 dropdown: '.dropdown', 311 select: function(obj) { 312 $($element).find('.or-selector-link-value').val(obj.id ); 313 $($element).find('.or-selector-link-name' ).val(obj.name).attr('placeholder',obj.name); 314 } 315 } ); 316 317 } 318 319 320 321 function registerTree(element) { 322 323 // Klick-Funktionen zum Öffnen/Schließen des Zweiges. 324 $(element).find('.or-navtree-node').orTree(); 325 326 } 327 328 329 registerMenuEvents ( viewEl ); 330 registerGlobalSearch ( viewEl ); 331 registerSelectorSearch( viewEl ); 332 registerTree ( viewEl ); 333 334 function registerDragAndDrop(viewEl) 335 { 336 337 registerDraggable(viewEl); 338 registerDroppable(viewEl); 339 } 340 341 registerDragAndDrop(viewEl); 342 343 344 } ); 345 346 347 348 function registerDraggable(viewEl) { 349 350 // Drag n Drop: Inhaltselemente (Dateien,Seiten,Ordner,Verknuepfungen) koennen auf Ordner gezogen werden. 351 352 $(viewEl).find('.or-draggable').draggable( 353 { 354 helper: 'clone', 355 opacity: 0.7, 356 zIndex: 2, 357 distance: 10, 358 cursor: 'move', 359 revert: 'false' 360 } 361 ); 362 363 } 364 365 function registerTreeBranchEvents(viewEl) 366 { 367 registerDraggable(viewEl); 368 } 369 370 371 function registerDroppable(viewEl) { 372 373 374 $(viewEl).find('.or-droppable').droppable({ 375 accept: '.or-draggable', 376 hoverClass: 'or-droppable--hover', 377 activeClass: 'or-droppable--active', 378 379 drop: function (event, ui) { 380 381 let dropped = ui.draggable; 382 383 let id = dropped.data('id' ); 384 let name = dropped.data('name'); 385 if (!name) 386 name = id; 387 388 $(this).find('.or-selector-link-value').val( id ); 389 $(this).find('.or-selector-link-name' ).val( name ).attr('placeholder',name ); 390 } 391 }); 392 } 393 394 395 396 397 398 399 /** 400 * Setzt neuen modalen Dialog und aktualisiert alle Fenster. 401 * @param name 402 * @param action Action 403 * @param method 404 * @param id Id 405 * @param params 406 */ 407 function startDialog( name,action,method,id,params ) 408 { 409 // Attribute aus dem aktuellen Editor holen, falls die Daten beim Aufrufer nicht angegeben sind. 410 if (!action) 411 action = $('#editor').attr('data-action'); 412 413 if (!id) 414 id = $('#editor').attr('data-id'); 415 416 let view = new Openrat.View( action,method,id,params ); 417 418 view.before = function() { 419 $('#dialog > .view').html('<div class="header"><img class="icon" title="" src="./themes/default/images/icon/'+method+'.png" />'+name+'</div>'); 420 $('#dialog > .view').data('id',id); 421 $('#dialog').removeClass('is-closed').addClass('is-open'); 422 423 let view = this; 424 425 this.escapeKeyClosingHandler = function (e) { 426 if (e.keyCode == 27) { // ESC keycode 427 view.close(); 428 429 $(document).off('keyup'); // de-register. 430 } 431 }; 432 433 $(document).keyup(this.escapeKeyClosingHandler); 434 435 // Nicht-Modale Dialoge durch Klick auf freie Fläche schließen. 436 $('#dialog .filler').click( function() 437 { 438 view.close(); 439 }); 440 441 } 442 443 view.close = function() { 444 445 // Strong modal dialogs are unable to close. 446 // Really? 447 if ( $('div#dialog').hasClass('modal') ) 448 return; 449 450 $('#dialog .view').html(''); 451 $('#dialog').removeClass('is-open').addClass('is-closed'); // Dialog schließen 452 453 $(document).unbind('keyup',this.escapeKeyClosingHandler); // Cleanup ESC-Key-Listener 454 } 455 456 view.start( $('div#dialog > .view') ); 457 } 458 459 460 461 462 /** 463 * Setzt einen Fenster-Titel für die ganze Anwendung. 464 */ 465 function setTitle( title ) 466 { 467 if ( title ) 468 $('head > title').text( title + ' - ' + $('head > title').data('default') ); 469 else 470 $('head > title').text( $('head > title').data('default') ); 471 } 472 473 474 475 /** 476 * Setzt neue Action und aktualisiert alle Fenster. 477 * 478 * @param action Action 479 * @param id Id 480 */ 481 function openNewAction( name,action,id ) 482 { 483 // Im Mobilmodus soll das Menü verschwinden, wenn eine neue Action geoeffnet wird. 484 $('nav').removeClass('open'); 485 486 setTitle( name ); // Title setzen. 487 488 Openrat.Navigator.navigateToNew( {'action':action, 'id':id } ); 489 } 490 491 492 493 494 //Quelle: 495 //http://aktuell.de.selfhtml.org/tippstricks/javascript/bbcode/ 496 function insert(tagName, aTag, eTag) 497 { 498 var input = document.forms[0].elements[tagName]; 499 input.focus(); 500 /* IE */ 501 if(typeof document.selection != 'undefined') { 502 /* Einfuegen des Formatierungscodes */ 503 // alert('IE'); 504 var range = document.selection.createRange(); 505 var insText = range.text; 506 range.text = aTag + insText + eTag; 507 /* Anpassen der Cursorposition */ 508 range = document.selection.createRange(); 509 if (insText.length == 0) { 510 range.move('character', -eTag.length); 511 } else { 512 range.moveStart('character', aTag.length + insText.length + eTag.length); 513 } 514 range.select(); 515 } 516 /* Gecko */ 517 else if(typeof input.selectionStart != 'undefined') 518 { 519 // alert('Gecko'); 520 /* Einfuegen des Formatierungscodes */ 521 var start = input.selectionStart; 522 var end = input.selectionEnd; 523 var insText = input.value.substring(start, end); 524 input.value = input.value.substr(0, start) + aTag + insText + eTag + input.value.substr(end); 525 /* Anpassen der Cursorposition */ 526 var pos; 527 if (insText.length == 0) { 528 pos = start + aTag.length; 529 } else { 530 pos = start + aTag.length + insText.length + eTag.length; 531 } 532 input.selectionStart = pos; 533 input.selectionEnd = pos; 534 } 535 /* uebrige Browser */ 536 else 537 { 538 /* Abfrage der Einfuegeposition */ 539 540 /* 541 var pos; 542 var re = new RegExp('^[0-9]{0,3}$'); 543 while(!re.test(pos)) { 544 pos = prompt("Position (0.." + input.value.length + "):", "0"); 545 } 546 if(pos > input.value.length) { 547 pos = input.value.length; 548 } 549 */ 550 pos = input.value.length; 551 552 /* Einfuegen des Formatierungscodes */ 553 var insText = prompt("Text"); 554 input.value = input.value.substr(0, pos) + aTag + insText + eTag + input.value.substr(pos); 555 } 556 } 557 558 559 560 561 562 function help(el,url,suffix) 563 { 564 var action = $(el).closest('div.panel').find('li.action.active').attr('data-action'); 565 var method = $(el).closest('div.panel').find('li.action.active').attr('data-method'); 566 567 window.open(url + action + '/'+ method + suffix, 'OpenRat_Help', 'location=no,menubar=no,scrollbars=yes,toolbar=no,resizable=yes'); 568 } 569 570 571 function htmlEntities(str) { 572 return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); 573 } 574 575 function registerOpenClose( $el ) 576 { 577 $($el).children('.on-click-open-close').click( function() { 578 $(this).closest('.toggle-open-close').toggleClass('open closed'); 579 }); 580 581 }