openrat-cms

# OpenRat Content Management System
git clone http://git.code.weiherhei.de/openrat-cms.git
Log | Files | Refs

commit d0b77e3615faac4a8e320a53652013b87d405b6a
parent ab9cf35ea1412abd2cbfa0aeef47fc2a5f6b3946
Author: Jan Dankert <develop@jandankert.de>
Date:   Sun, 13 Oct 2019 02:21:18 +0200

Refactoring: Javascript hell refactored into separate files. TODO: Namespacing.

Diffstat:
modules/cms-ui/action/IndexAction.class.php | 7++++++-
modules/cms-ui/themes/default/production/combined.min.js | 460+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
modules/cms-ui/themes/default/script/openrat.js | 1319-------------------------------------------------------------------------------
modules/cms-ui/themes/default/script/openrat.min.js | 11-----------
modules/cms-ui/themes/default/script/openrat/common.js | 882+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
modules/cms-ui/themes/default/script/openrat/common.min.js | 10++++++++++
modules/cms-ui/themes/default/script/openrat/form.js | 152+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
modules/cms-ui/themes/default/script/openrat/form.min.js | 152+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
modules/cms-ui/themes/default/script/openrat/init.js | 4++++
modules/cms-ui/themes/default/script/openrat/init.min.js | 4++++
modules/cms-ui/themes/default/script/openrat/navigator.js | 40++++++++++++++++++++++++++++++++++++++++
modules/cms-ui/themes/default/script/openrat/navigator.min.js | 40++++++++++++++++++++++++++++++++++++++++
modules/cms-ui/themes/default/script/openrat/view.js | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
modules/cms-ui/themes/default/script/openrat/view.min.js | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
modules/cms-ui/themes/default/script/openrat/workbench.js | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
modules/cms-ui/themes/default/script/openrat/workbench.min.js | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16 files changed, 2244 insertions(+), 1337 deletions(-)

diff --git a/modules/cms-ui/action/IndexAction.class.php b/modules/cms-ui/action/IndexAction.class.php @@ -525,7 +525,12 @@ class IndexAction extends Action } // OpenRat internal JS - als letztes, damit die vorigen bereits geladen sind. - $js[] = OR_THEMES_DIR . 'default/script/openrat'; + $js[] = OR_THEMES_DIR . 'default/script/openrat/init'; + $js[] = OR_THEMES_DIR . 'default/script/openrat/view'; + $js[] = OR_THEMES_DIR . 'default/script/openrat/form'; + $js[] = OR_THEMES_DIR . 'default/script/openrat/workbench'; + $js[] = OR_THEMES_DIR . 'default/script/openrat/navigator'; + $js[] = OR_THEMES_DIR . 'default/script/openrat/common'; $outDevJsFiles = array(); diff --git a/modules/cms-ui/themes/default/production/combined.min.js b/modules/cms-ui/themes/default/production/combined.min.js @@ -10992,13 +10992,461 @@ else{Workbench.reloadViews()};$(document).trigger('orDataChanged')} else{}});$.each(e['errors'],function(s,e){$('input[name='+e+']').addClass('error').parent().addClass('error').parents('fieldset').addClass('show').addClass('open')});if(!e.control){};if(e.control.redirect)window.location.href=e.control.redirect}; /* ./modules//template-engine/components/html/upload/upload.min.js */;$(document).on('orViewLoaded',function(e,n){var a=$(e.target).find('form'),o=$(e.target).find('div.or-dropzone-upload > div.input');o.on('dragenter',function(e){e.stopPropagation();e.preventDefault();$(this).css('border','1px dotted gray')});o.on('dragover',function(e){e.stopPropagation();e.preventDefault()});o.on('drop',function(e){$(this).css('border','1px dotted red');e.preventDefault();var n=e.originalEvent.dataTransfer.files;handleFileUpload(a,n)});$(e.target).find('input[type=file]').change(function(){var e=$(this).prop('files');handleFileUpload(a,e)})});function handleFileUpload(e,o){for(var t=0,r;r=o[t];t++){var n=new FormData();n.append('file',r);n.append('action','folder');n.append('subaction',$(e).data('method'));n.append('output','json');n.append('token',$(e).find('input[name=token]').val());n.append('id',$(e).find('input[name=id]').val());var a=$('<div class="notice info"><div class="text loader"></div></div>');$('#noticebar').prepend(a);$(a).show();$.ajax({'type':'POST',url:'./api/',cache:!1,contentType:!1,processData:!1,data:n,success:function(n,o,t){$(a).remove();doResponse(n,o,e)},error:function(n,o,d){$(e).closest('div.content').removeClass('loader');$(a).remove();var r;try{var t=jQuery.parseJSON(n.responseText);r=t.error+'/'+t.description+': '+t.reason}catch(i){r=n.responseText};notify('error',r)}})}}; /* ./modules//template-engine/components/html/tree/tree.min.js */;$(document).on('orViewLoaded',function(o,n){}); -/* ./modules/cms-ui/themes/default/script/openrat.min.js */;var OR_THEMES_EXT_DIR='modules/cms-ui/themes/';$(function(){$('html').removeClass('nojs');$('.initial-hidden').removeClass('initial-hidden');registerWorkbenchEvents();window.onpopstate=function(e){Navigator.navigateTo(e.state)};initActualHistoryState();Workbench.initialize();Workbench.reloadAll();registerNavigation();$('.keystroke').each(function(){let keystrokeElement=$(this);let keystroke=keystrokeElement.text();if(keystroke.length==0)return;let keyaction=function(){keystrokeElement.click()};$(document).bind('keydown',keystroke,keyaction)});$('#noticebar .notice .image-icon--menu-close').click(function(){$(this).closest('.notice').fadeOut('fast',function(){$(this).remove()})});$('#noticebar .notice').each(function(){let noticeToClose=this;setTimeout(function(){$(noticeToClose).fadeOut('slow',function(){$(this).remove()})},30*1000)});registerOpenClose($('section.toggle-open-close'));$('section.toggle-open-close .on-click-open-close').click(function(){var t=$(this).closest('section');if(t.hasClass('disabled'))return;var e=t.find('div.view-loader');if(e.children().length==0)Workbench.loadNewActionIntoElement(e)})});function initActualHistoryState(){var t={};t.name=window.document.title;var e=new URLSearchParams(window.location.search);if(e.has('action')){t.action=e.get('action');t.id=e.get('id');t.name=window.document.title;t.data={};var e=Array.from(e.entries());for(var i in e){t.data[e[i][0]]=e[i][1]};Navigator.toActualHistory(t)}};function registerNavigation(){$(document).on('orNewAction',function(e,t){let url='./api/?action=tree&subaction=path&id='+Workbench.state.id+'&type='+Workbench.state.action+'&output=json';$.getJSON(url,function(e){$('nav .or-navtree-node').removeClass('or-navtree-node--selected');let output=e['output'];$.each(output.path,function(e,t){$nav=$('nav .or-navtree-node[data-type='+t.type+'][data-id='+t.id+'].or-navtree-node--is-closed .or-navtree-node-control');$nav.click()});if(output.actual)$('nav .or-navtree-node[data-type='+output.actual.type+'][data-id='+output.actual.id+']').addClass('or-navtree-node--selected')}).fail(function(e){console.warn(e);console.warn('failed to load path from '+url)}).always(function(){})})};var Navigator=new function(){'use strict';this.navigateTo=function(e){Workbench.loadNewActionState(e)};this.navigateToNew=function(e){Workbench.loadNewActionState(e);window.history.pushState(e,e.name,'./#/'+e.action+(e.id?'/'+e.id:''))};this.navigateToNewAction=function(e,t,i,n){var o={action:e,method:t,id:i.replace(/[^0-9_]/gim,''),data:n};this.navigateToNew(o)};this.toActualHistory=function(e){window.history.replaceState(e,e.name,createUrl(e.action,null,e.id,e.data,!1))}},Workbench=new function(){'use strict';this.initialize=function(){this.initializePingTimer();this.initializeState();this.initializeMenues();this.openModalDialog()};this.openModalDialog=function(){if($('#dialog').data('action')){startDialog('',$('#dialog').data('action'),$('#dialog').data('action'),0,{})}};this.initializeMenues=function(){filterMenus()};this.initializeState=function(){let parts=window.location.hash.split('/');let state={action:'index',id:0};if(parts.length>=2)state.action=parts[1].toLowerCase();if(parts.length>=3)state.id=parts[2].replace(/[^0-9_]/gim,'');Workbench.state=state;$('#editor').attr('data-action',state.action);$('#editor').attr('data-id',state.id);$('#editor').attr('data-extra','{}')};this.initializePingTimer=function(){var e=function(){$.ajax(createUrl('title','ping',0))},t=5;window.setInterval(e,t*60*1000)};this.loadNewActionState=function(e){Workbench.state=e;Workbench.loadNewAction(e.action,e.id,e.data);filterMenus();$(document).trigger('orNewAction')};this.loadNewAction=function(e,t,i){$('#editor').attr('data-action',e);$('#editor').attr('data-id',t);$('#editor').attr('data-extra',JSON.stringify(i));this.reloadViews()};this.reloadViews=function(){$('#workbench section.closed .view-loader').empty();Workbench.loadViews($('#workbench section.open .view-loader'))};this.reloadAll=function(){$('#workbench .view').empty();Workbench.loadViews($('#workbench .view'))};this.loadViews=function(e){e.each(function(e){let $targetDOMElement=$(this);Workbench.loadNewActionIntoElement($targetDOMElement)})};this.loadNewActionIntoElement=function(e){let action;if(e.is('.view-static'))action=e.attr('data-action');else action=$('#editor').attr('data-action');let id=$('#editor').attr('data-id');let params=$('#editor').attr('data-extra');let method=e.data('method');let view=new View(action,method,id,params);view.start(e)}};function registerWorkbenchEvents(){$('div.header').dblclick(function(){fullscreen(this)})};function loadView(e,t,i,n,o){Navigator.navigateToNewAction(t,i,n,o)};function afterViewLoaded(e){var t=$(e).closest('section');t.toggleClass('is-empty',$(e).is(':empty'));$(e).trigger('orViewLoaded');$(e).closest('div.panel').find('div.header div.dropdown div.entry.perview').remove();$(e).find('.toggle-nav-open-close').click(function(){$('nav').toggleClass('open')});$(e).find('.toggle-nav-small').click(function(){$('nav').toggleClass('small')});$(e).find('div.headermenu > a').each(function(e,t){});$(e).find('div.header > a.back').each(function(t,i){$(i).removeClass('button').wrap('<div class="entry perview" />').parent().appendTo($(e).closest('div.panel').find('div.header div.dropdown').first())});$(e).find('div.selector.tree').each(function(){var e=this;$(this).orTree({type:'project',selectable:$(e).attr('data-types').split(','),id:$(e).attr('data-init-folderid'),onSelect:function(t,i,n){var o=$(e).parent();$(o).find('input[type=text]').attr('value',t);$(o).find('input[type=hidden]').attr('value',n)}})});registerDragAndDrop(e);$(e).find('input').change(function(){$(this).parent('div.view').addClass('dirty')});$(e).find('.or-theme-chooser').change(function(){setUserStyle(this.value)})};function registerDragAndDrop(e){registerDraggable(e);registerDroppable(e)};function registerDraggable(e){$(e).find('.or-draggable').draggable({helper:'clone',opacity:0.7,zIndex:2,distance:10,cursor:'move',revert:'false'})};function registerTreeBranchEvents(e){registerDraggable(e)};function registerDroppable(e){$(e).find('.or-droppable').droppable({accept:'.or-draggable',hoverClass:'or-droppable--hover',activeClass:'or-droppable--active',drop:function(e,t){let dropped=t.draggable;$(this).find('.or-selector-link-value').val(dropped.data('id'));$(this).find('.or-selector-link-name').val(dropped.data('id'))}})};function registerMenuEvents(e){$('body').click(function(){$('.toolbar-icon.menu').parents('.or-menu').removeClass('open')});$(e).find('.toolbar-icon.menu').click(function(e){e.stopPropagation();$(this).parents('.or-menu').toggleClass('open')});$(e).find('.toolbar-icon.menu').mouseover(function(){$(this).parents('.or-menu').find('.toolbar-icon.menu').removeClass('open');$(this).addClass('open')})};function registerSearch(e){$(e).find('.search input').orSearch({dropdown:'#title div.search div.dropdown'})};function registerTree(e){$(e).find('.or-navtree-node').orTree()};function fullscreen(e){$(e).closest('div.panel').fadeOut('fast',function(){$(this).toggleClass('fullscreen').fadeIn('fast')})};function submitUrl(e,t){postUrl(t,e)};function postUrl(e,t){e+='&output=json';$.ajax({'type':'POST',url:e,data:{},success:function(e,i,n){$('div.panel div.status div.loader').html('&nbsp;');doResponse(e,i,t)}})};function Form(){this.setLoadStatus=function(e){$(this.element).closest('div.content').toggleClass('loader',e)};this.initOnElement=function(e){this.element=e;let form=this;$(e).find('form[data-autosave="true"] input[type="checkbox"]').click(function(){form.submit()});$(e).find('.or-form-btn--cancel').click(function(){form.cancel()});$(e).find('.or-form-btn--reset').click(function(){form.rollback()});$(e).submit(function(e){if($(this).data('target')=='view'){form.submit();e.preventDefault()}})};this.cancel=function(){this.close()};this.rollback=function(){this.element.trigger('reset')};this.close=function(){};this.submit=function(){let status=$('<div class="notice info"><div class="text loader"></div></div>');$('#noticebar').prepend(status);$(status).show();$(this.element).find('.error').removeClass('error');var t=$(this.element).serializeArray(),e={};$(t).each(function(t,i){e[i.name]=i.value});if(!e.id)e.id=Workbench.state.id;if(!e.action)e.action=Workbench.state.action;let formMethod=$(this.element).attr('method').toUpperCase();if(formMethod=='GET'){this.forwardTo(e.action,e.subaction,e.id,e)} -else{let url='./api/';this.setLoadStatus(!0);url+='';e.output='json';if($(this.element).data('async')||$(this.element).data('async')=='true'){this.close()};let form=this;$.ajax({'type':'POST',url:url,data:e,success:function(e,t,i){form.setLoadStatus(!1);$(status).remove();doResponse(e,t,form.element)},error:function(e,t,i){form.setLoadStatus(!1);$(status).remove();try{let error=jQuery.parseJSON(e.responseText);notify('','','error',error.error,[error.description])}catch(n){let msg=e.responseText;notify('','','error','Server Error',[msg])}}});$(form.element).fadeIn()}}};function View(e,t,i,n){this.action=e;this.method=t;this.id=i;this.params=n;this.before=function(){};this.start=function(e){this.before();this.element=e;this.loadView()};this.afterLoad=function(){};this.close=function(){};function o(e){registerMenuEvents(e);registerSearch(e);registerTree(e);afterViewLoaded(e)};this.loadView=function(){let url=createUrl(this.action,this.method,this.id,this.params,!0);let element=this.element;let view=this;$(this.element).empty().fadeTo(1,0.7).addClass('loader').html('').load(url,function(e,t,i){$(element).fadeTo(350,1);$(element).removeClass('loader');$(element).find('form').each(function(){let form=new Form();form.close=function(){view.close()};form.initOnElement(this)});if(t=='error'){$(element).html('');notify('','','error','Server Error',['Server Error while requesting url '+url,e]);return};o(element)})}};function startDialog(e,t,i,n,o){if(!t)t=$('#editor').attr('data-action');if(!n)n=$('#editor').attr('data-id');let view=new View(t,i,n,o);view.before=function(){$('#dialog > .view').html('<div class="header"><img class="icon" title="" src="./themes/default/images/icon/'+i+'.png" />'+e+'</div>');$('#dialog > .view').data('id',n);$('#dialog').removeClass('is-closed').addClass('is-open');let view=this;this.escapeKeyClosingHandler=function(e){if(e.keyCode==27){view.close();$(document).off('keyup')}};$(document).keyup(this.escapeKeyClosingHandler);$('#dialog .filler').click(function(){view.close()})};view.close=function(){if($('div#dialog').hasClass('modal'))return;$('#dialog .view').fadeOut('fast').html('');$('#dialog').removeClass('is-open').addClass('is-closed');$(document).unbind('keyup',this.escapeKeyClosingHandler)};view.start($('div#dialog > .view'))};function startEdit(e,t,i,n,o){if(!t)t=Workbench.state.action;if(!n)n=Workbench.state.id;let view=new View(t,i,n,o);view.before=function(){let view=this;$edit=$('#edit');$edit.addClass('is-open');$('#editor').addClass('is-closed');$('#edit .filler').click(function(){view.close()})};view.close=function(){$edit.removeClass('is-open');$('#editor').removeClass('is-closed')};view.start($('#edit > .view'))};function setTitle(e){if(e)$('head > title').text(e+' - '+$('head > title').data('default'));else $('head > title').text($('head > title').data('default'))};function openNewAction(e,t,i,n){$('nav').removeClass('open');setTitle(e);setNewAction(t,i,n)};function filterMenus(){let action=Workbench.state.action;let id=Workbench.state.id;$('div.clickable').addClass('active');$('div.clickable.filtered').removeClass('active').addClass('inactive');$('div.clickable.filtered.on-action-'+action).addClass('active').removeClass('inactive');$('div.clickable.filtered a').attr('data-id',id)};function setNewAction(e,t,i){Navigator.navigateToNewAction(e,'edit',t,i)};function setNewId(e){};function notifyBrowser(e){if(!('Notification' in window)){return} +/* ./modules/cms-ui/themes/default/script/openrat/init.min.js */ +// Create own namespace. + +window.openrat = {}; + +/* ./modules/cms-ui/themes/default/script/openrat/view.min.js *//** + * View. + * Eine View ist ein HTML-Fragment, in das eine Action geladen wird. + * Das Erzeugen der View, das Laden vom Server sowie das Schließen sind hier gekapselt. + * + * @param action + * @param method + * @param id + * @param params + * @constructor + */ +function View( action,method,id,params ) { + + this.action = action; + this.method = method; + this.id = id; + this.params = params; + + this.before = function() {}; + + this.start = function( element ) { + this.before(); + this.element = element; + this.loadView(); + } + + this.afterLoad = function() { + + } + + this.close = function() { + } + + + function registerViewEvents(element) { + + registerMenuEvents( element ); + registerSearch ( element ); + registerTree ( element ); + afterViewLoaded ( element ); + + } + + + this.loadView = function() { + + let url = createUrl( this.action,this.method,this.id,this.params,true); // URL für das Laden erzeugen. + let element = this.element; + let view = this; + + $(this.element).empty().fadeTo(1,0.7).addClass('loader').html('').load(url,function(response, status, xhr) { + + $(element).fadeTo(350,1); + + $(element).removeClass("loader"); + + $(element).find('form').each( function() { + let form = new Form(); + form.close = function() { + view.close(); + } + form.initOnElement(this); + + }); + if ( status == "error" ) + { + // Seite nicht gefunden. + $(element).html(""); + + notify('','','error','Server Error',['Server Error while requesting url '+url, response]); + return; + } + + registerViewEvents( element ); + + }); + + } + +} + +/* ./modules/cms-ui/themes/default/script/openrat/form.min.js */ +/** + * Form. + * + * @constructor + */ +function Form() { + + this.setLoadStatus = function( isLoading ) { + $(this.element).closest('div.content').toggleClass('loader',isLoading); + } + + this.initOnElement = function( element ) { + this.element = element; + + let form = this; + + // Autosave in Formularen. + // Bei Veränderungen von Checkboxen wird das Formular sofort abgeschickt. + $(element).find('form[data-autosave="true"] input[type="checkbox"]').click( function() { + form.submit(); + }); + + // After click to "OK" the form is submitted. + // Why this?? input type=submit will submit! + /* + $(event.target).find('input.submit.ok').click( function() { + $(this).closest('form').submit(); + }); + */ + + $(element).find('.or-form-btn--cancel').click( function() { + form.cancel(); + + }); + $(element).find('.or-form-btn--reset').click( function() { + form.rollback(); + + }); + + // Submithandler for the whole form. + $(element).submit( function( event ) { + + // + if ($(this).data('target')=='view') + { + form.submit(); + event.preventDefault(); + } + // target=top will load the native way without javascript. + }); + } + + this.cancel = function() { + //$(this.element).html('').parent().removeClass('is-open'); + this.close(); + } + + + this.rollback = function() { + this.element.trigger('reset'); + } + + this.close = function() { + + } + + this.submit = function() { + + + // Show progress + let status = $('<div class="notice info"><div class="text loader"></div></div>'); + $('#noticebar').prepend(status); // Notice anhängen. + $(status).show(); + + // Alle vorhandenen Error-Marker entfernen. + // Falls wieder ein Fehler auftritt, werden diese erneut gesetzt. + $(this.element).find('.error').removeClass('error'); + + var params = $(this.element).serializeArray(); + var data = {}; + $(params).each(function(index, obj){ + data[obj.name] = obj.value; + }); + + // If form does not contain action/id, get it from the workbench. + if (!data.id) + data.id = Workbench.state.id; + if (!data.action) + data.action = Workbench.state.action; + + let formMethod = $(this.element).attr('method').toUpperCase(); + + if ( formMethod == 'GET' ) + { + // Mehrseitiges Formular + // Die eingegebenen Formulardaten werden zur nächsten Action geschickt. + //Workbench.loadViewIntoElement( $(form).parent('.view'),data.action, data.subaction,data.id,data ); + this.forwardTo( data.action, data.subaction,data.id,data ); + } + else + { + let url = './api/'; // Alle Parameter befinden sich im Formular + + // POST-Request + this.setLoadStatus(true); + //url += '?output=json'; + url += ''; + //params['output'] = 'json';// Irgendwie geht das nicht. + data.output = 'json'; + + if ( $(this.element).data('async') || $(this.element).data('async')=='true') + { + // Verarbeitung erfolgt asynchron, das heißt, dass der evtl. geöffnete Dialog + // beendet wird. + this.close(); + // Async: Window is closed, but the action will be startet now. + } + + let form = this; + $.ajax( { 'type':'POST',url:url, data:data, success:function(data, textStatus, jqXHR) + { + form.setLoadStatus(false); + $(status).remove(); + + doResponse(data,textStatus,form.element); + }, + error:function(jqXHR, textStatus, errorThrown) { + form.setLoadStatus(false); + $(status).remove(); + + try + { + let error = jQuery.parseJSON( jqXHR.responseText ); + notify('','','error',error.error,[error.description]); + } + catch( e ) + { + let msg = jqXHR.responseText; + notify('','','error','Server Error',[msg]); + } + + + } + + } ); + $(form.element).fadeIn(); + } + + } +} + + +/* ./modules/cms-ui/themes/default/script/openrat/workbench.min.js */ + +var Workbench = new function() +{ + 'use strict'; // Strict mode + + + /** + * Initializes the Workbench. + */ + this.initialize = function() { + + // Initialze Ping timer. + this.initializePingTimer(); + this.initializeState(); + this.initializeMenues(); + this.openModalDialog(); + } + + + /** + * Starts a dialog, if necessary. + */ + this.openModalDialog = function () { + + if ( $('#dialog').data('action') ) { + startDialog('',$('#dialog').data('action'),$('#dialog').data('action'),0,{}) + } + } + + + this.initializeMenues = function () { + + filterMenus(); + } + + + /** + * Sets the workbench state with action/id. + * + * Example: #/name/1 is translated to the state {action:name,id:1} + */ + this.initializeState = function () { + + let parts = window.location.hash.split('/'); + let state = { action:'index',id:0 }; + + if ( parts.length >= 2 ) + state.action = parts[1].toLowerCase(); + + if ( parts.length >= 3 ) + // Only numbers and '_' allowed in the id. + state.id = parts[2].replace(/[^0-9_]/gim,""); + + Workbench.state = state; + + // TODO: Remove this sometimes.... only state. + $('#editor').attr('data-action',state.action); + $('#editor').attr('data-id' ,state.id ); + $('#editor').attr('data-extra' ,'{}' ); + + } + + /** + * Registriert den Ping-Timer für den Sitzungserhalt. + */ + this.initializePingTimer = function() { + + /** + * Ping den Server. Führt keine Aktion aus, aber sorgt dafür, dass die Sitzung erhalten bleibt. + * + * "Geben Sie mir ein Ping, Vasily. Und bitte nur ein einziges Ping!" (aus: Jagd auf Roter Oktober) + */ + var ping = function() + { + $.ajax( createUrl('title','ping',0) ); + //window.console && console.log("session-ping"); + } + + // Alle 5 Minuten pingen. + var timeoutMinutes = 5; + + window.setInterval( ping, timeoutMinutes*60*1000 ); + } + + + + this.loadNewActionState = function(state) { + + Workbench.state = state; + Workbench.loadNewAction(state.action,state.id,state.data); + + + filterMenus(); + + $(document).trigger('orNewAction'); + } + + /** + * + */ + + this.loadNewAction = function(action, id, params ) { + + $('#editor').attr('data-action',action); + $('#editor').attr('data-id' ,id ); + $('#editor').attr('data-extra' ,JSON.stringify(params)); + + this.reloadViews(); + } + + + /** + * + */ + + this.reloadViews = function() { + + // View in geschlossenen Sektionen löschen, damit diese nicht stehen bleiben. + $('#workbench section.closed .view-loader').empty(); + + Workbench.loadViews( $('#workbench section.open .view-loader') ); + } + + + this.reloadAll = function() { + + // View in geschlossenen Sektionen löschen, damit diese nicht stehen bleiben. + $('#workbench .view').empty(); + + Workbench.loadViews( $('#workbench .view') ); + } + + + + this.loadViews = function( $views ) + { + + $views.each(function (idx) { + + let $targetDOMElement = $(this); + + Workbench.loadNewActionIntoElement( $targetDOMElement ) + }); + } + + + + this.loadNewActionIntoElement = function( $viewElement ) + { + let action; + if ( $viewElement.is('.view-static') ) + // Static views have always the same action. + action = $viewElement.attr('data-action'); + else + action = $('#editor').attr('data-action'); + + let id = $('#editor').attr('data-id' ); + let params = $('#editor').attr('data-extra' ); + + let method = $viewElement.data('method'); + + let view = new View( action,method,id,params ); + view.start( $viewElement ); + } + + +} + + + +/* ./modules/cms-ui/themes/default/script/openrat/navigator.min.js *//** + * Navigation. + */ +var Navigator = new function () { + 'use strict'; + + /** + * Navigiert zu einer Action, aber ohne ein neues History-Element einzufügen. + */ + this.navigateTo = function(state) { + Workbench.loadNewActionState(state); + } + + + /** + * + * Navigiert zu einer neue Action und fügt einen neuen History-Eintrag hinzu. + */ + this.navigateToNew = function(obj) { + + Workbench.loadNewActionState(obj); + window.history.pushState(obj,obj.name,'./#/'+obj.action+(obj.id?'/'+obj.id:'') ); + } + + this.navigateToNewAction = function(action, method, id, params ) { + var state = {action:action,method:method,id:id.replace(/[^0-9_]/gim,""),data:params}; + this.navigateToNew(state); + } + + /** + * Setzt den State für den aktuellen History-Eintrag. + * @param obj + */ + this.toActualHistory = function(obj) { + window.history.replaceState(obj,obj.name,createUrl(obj.action,null,obj.id,obj.data,false) ); + } +} + +openrat.navigator = Navigator; +/* ./modules/cms-ui/themes/default/script/openrat/common.min.js */;var OR_THEMES_EXT_DIR='modules/cms-ui/themes/';$(function(){$('html').removeClass('nojs');$('.initial-hidden').removeClass('initial-hidden');registerWorkbenchEvents();window.onpopstate=function(e){Navigator.navigateTo(e.state)};initActualHistoryState();Workbench.initialize();Workbench.reloadAll();registerNavigation();$('.keystroke').each(function(){let keystrokeElement=$(this);let keystroke=keystrokeElement.text();if(keystroke.length==0)return;let keyaction=function(){keystrokeElement.click()};$(document).bind('keydown',keystroke,keyaction)});$('#noticebar .notice .image-icon--menu-close').click(function(){$(this).closest('.notice').fadeOut('fast',function(){$(this).remove()})});$('#noticebar .notice').each(function(){let noticeToClose=this;setTimeout(function(){$(noticeToClose).fadeOut('slow',function(){$(this).remove()})},30*1000)});registerOpenClose($('section.toggle-open-close'));$('section.toggle-open-close .on-click-open-close').click(function(){var t=$(this).closest('section');if(t.hasClass('disabled'))return;var e=t.find('div.view-loader');if(e.children().length==0)Workbench.loadNewActionIntoElement(e)})});function initActualHistoryState(){var t={};t.name=window.document.title;var e=new URLSearchParams(window.location.search);if(e.has('action')){t.action=e.get('action');t.id=e.get('id');t.name=window.document.title;t.data={};var e=Array.from(e.entries());for(var i in e){t.data[e[i][0]]=e[i][1]};Navigator.toActualHistory(t)}};function registerNavigation(){$(document).on('orNewAction',function(e,t){let url='./api/?action=tree&subaction=path&id='+Workbench.state.id+'&type='+Workbench.state.action+'&output=json';$.getJSON(url,function(e){$('nav .or-navtree-node').removeClass('or-navtree-node--selected');let output=e['output'];$.each(output.path,function(e,t){$nav=$('nav .or-navtree-node[data-type='+t.type+'][data-id='+t.id+'].or-navtree-node--is-closed .or-navtree-node-control');$nav.click()});if(output.actual)$('nav .or-navtree-node[data-type='+output.actual.type+'][data-id='+output.actual.id+']').addClass('or-navtree-node--selected')}).fail(function(e){console.warn(e);console.warn('failed to load path from '+url)}).always(function(){})})};function registerWorkbenchEvents(){$('div.header').dblclick(function(){fullscreen(this)})};function loadView(e,t,i,n,o){Navigator.navigateToNewAction(t,i,n,o)};function afterViewLoaded(e){var t=$(e).closest('section');t.toggleClass('is-empty',$(e).is(':empty'));$(e).trigger('orViewLoaded');$(e).closest('div.panel').find('div.header div.dropdown div.entry.perview').remove();$(e).find('.toggle-nav-open-close').click(function(){$('nav').toggleClass('open')});$(e).find('.toggle-nav-small').click(function(){$('nav').toggleClass('small')});$(e).find('div.headermenu > a').each(function(e,t){});$(e).find('div.header > a.back').each(function(t,i){$(i).removeClass('button').wrap('<div class="entry perview" />').parent().appendTo($(e).closest('div.panel').find('div.header div.dropdown').first())});$(e).find('div.selector.tree').each(function(){var e=this;$(this).orTree({type:'project',selectable:$(e).attr('data-types').split(','),id:$(e).attr('data-init-folderid'),onSelect:function(t,i,n){var o=$(e).parent();$(o).find('input[type=text]').attr('value',t);$(o).find('input[type=hidden]').attr('value',n)}})});registerDragAndDrop(e);$(e).find('input').change(function(){$(this).parent('div.view').addClass('dirty')});$(e).find('.or-theme-chooser').change(function(){setUserStyle(this.value)})};function registerDragAndDrop(e){registerDraggable(e);registerDroppable(e)};function registerDraggable(e){$(e).find('.or-draggable').draggable({helper:'clone',opacity:0.7,zIndex:2,distance:10,cursor:'move',revert:'false'})};function registerTreeBranchEvents(e){registerDraggable(e)};function registerDroppable(e){$(e).find('.or-droppable').droppable({accept:'.or-draggable',hoverClass:'or-droppable--hover',activeClass:'or-droppable--active',drop:function(e,t){let dropped=t.draggable;$(this).find('.or-selector-link-value').val(dropped.data('id'));$(this).find('.or-selector-link-name').val(dropped.data('id'))}})};function registerMenuEvents(e){$('body').click(function(){$('.toolbar-icon.menu').parents('.or-menu').removeClass('open')});$(e).find('.toolbar-icon.menu').click(function(e){e.stopPropagation();$(this).parents('.or-menu').toggleClass('open')});$(e).find('.toolbar-icon.menu').mouseover(function(){$(this).parents('.or-menu').find('.toolbar-icon.menu').removeClass('open');$(this).addClass('open')})};function registerSearch(e){$(e).find('.search input').orSearch({dropdown:'#title div.search div.dropdown'})};function registerTree(e){$(e).find('.or-navtree-node').orTree()};function fullscreen(e){$(e).closest('div.panel').fadeOut('fast',function(){$(this).toggleClass('fullscreen').fadeIn('fast')})};function submitUrl(e,t){postUrl(t,e)};function postUrl(e,t){e+='&output=json';$.ajax({'type':'POST',url:e,data:{},success:function(e,i,n){$('div.panel div.status div.loader').html('&nbsp;');doResponse(e,i,t)}})};function startDialog(e,t,i,n,o){if(!t)t=$('#editor').attr('data-action');if(!n)n=$('#editor').attr('data-id');let view=new View(t,i,n,o);view.before=function(){$('#dialog > .view').html('<div class="header"><img class="icon" title="" src="./themes/default/images/icon/'+i+'.png" />'+e+'</div>');$('#dialog > .view').data('id',n);$('#dialog').removeClass('is-closed').addClass('is-open');let view=this;this.escapeKeyClosingHandler=function(e){if(e.keyCode==27){view.close();$(document).off('keyup')}};$(document).keyup(this.escapeKeyClosingHandler);$('#dialog .filler').click(function(){view.close()})};view.close=function(){if($('div#dialog').hasClass('modal'))return;$('#dialog .view').fadeOut('fast').html('');$('#dialog').removeClass('is-open').addClass('is-closed');$(document).unbind('keyup',this.escapeKeyClosingHandler)};view.start($('div#dialog > .view'))};function startEdit(e,t,i,n,o){if(!t)t=Workbench.state.action;if(!n)n=Workbench.state.id;let view=new View(t,i,n,o);view.before=function(){let view=this;$edit=$('#edit');$edit.addClass('is-open');$('#editor').addClass('is-closed');$('#edit .filler').click(function(){view.close()})};view.close=function(){$edit.removeClass('is-open');$('#editor').removeClass('is-closed')};view.start($('#edit > .view'))};function setTitle(e){if(e)$('head > title').text(e+' - '+$('head > title').data('default'));else $('head > title').text($('head > title').data('default'))};function openNewAction(e,t,i,n){$('nav').removeClass('open');setTitle(e);setNewAction(t,i,n)};function filterMenus(){let action=Workbench.state.action;let id=Workbench.state.id;$('div.clickable').addClass('active');$('div.clickable.filtered').removeClass('active').addClass('inactive');$('div.clickable.filtered.on-action-'+action).addClass('active').removeClass('inactive');$('div.clickable.filtered a').attr('data-id',id)};function setNewAction(e,t,i){Navigator.navigateToNewAction(e,'edit',t,i)};function setNewId(e){};function notifyBrowser(e){if(!('Notification' in window)){return} else if(Notification.permission==='granted'){let notification=new Notification(e)} -else if(Notification.permission!=='denied'){Notification.requestPermission(function(t){if(t==='granted'){let notification=new Notification(e)}})}};function setUserStyle(e){var t=$('html'),i=t.attr('class').split(/\s+/);$.each(i,function(e,i){if(i.startsWith('theme-')){t.removeClass(i)}});t.addClass('theme-'+e.toLowerCase())};function insert(e,t,i){var n=document.forms[0].elements[e];n.focus();if(typeof document.selection!='undefined'){var r=document.selection.createRange(),o=r.text;r.text=t+o+i;r=document.selection.createRange();if(o.length==0){r.move('character',-i.length)} -else{r.moveStart('character',t.length+o.length+i.length)};r.select()} -else if(typeof n.selectionStart!='undefined'){var s=n.selectionStart,l=n.selectionEnd,o=n.value.substring(s,l);n.value=n.value.substr(0,s)+t+o+i+n.value.substr(l);var a;if(o.length==0){a=s+t.length} +else if(Notification.permission!=='denied'){Notification.requestPermission(function(t){if(t==='granted'){let notification=new Notification(e)}})}};function setUserStyle(e){var t=$('html'),i=t.attr('class').split(/\s+/);$.each(i,function(e,i){if(i.startsWith('theme-')){t.removeClass(i)}});t.addClass('theme-'+e.toLowerCase())};function insert(e,t,i){var n=document.forms[0].elements[e];n.focus();if(typeof document.selection!='undefined'){var l=document.selection.createRange(),o=l.text;l.text=t+o+i;l=document.selection.createRange();if(o.length==0){l.move('character',-i.length)} +else{l.moveStart('character',t.length+o.length+i.length)};l.select()} +else if(typeof n.selectionStart!='undefined'){var s=n.selectionStart,c=n.selectionEnd,o=n.value.substring(s,c);n.value=n.value.substr(0,s)+t+o+i+n.value.substr(c);var a;if(o.length==0){a=s+t.length} else{a=s+t.length+o.length+i.length};n.selectionStart=a;n.selectionEnd=a} -else{a=n.value.length;var o=prompt('Text');n.value=n.value.substr(0,a)+t+o+i+n.value.substr(a)}};function createUrl(e,t,i,n,a){var o='./';o+='?';if(e)o+='&action='+e;if(t)o+='&subaction='+t;if(i)o+='&id='+i;if(typeof n==='string'){n=n.replace(/'/g,'"');var r=jQuery.parseJSON(n);jQuery.each(r,function(e,t){o=o+'&'+e+'='+t})} +else{a=n.value.length;var o=prompt('Text');n.value=n.value.substr(0,a)+t+o+i+n.value.substr(a)}};function createUrl(e,t,i,n,a){var o='./';o+='?';if(e)o+='&action='+e;if(t)o+='&subaction='+t;if(i)o+='&id='+i;if(typeof n==='string'){n=n.replace(/'/g,'"');var l=jQuery.parseJSON(n);jQuery.each(l,function(e,t){o=o+'&'+e+'='+t})} else if(typeof n==='object'){jQuery.each(n,function(e,t){o=o+'&'+e+'='+t})} else{};return o};function resizeWorkbenchContainer(e){};function resizeWorkbench(){};function resizeTabs(e){};function help(e,t,i){var n=$(e).closest('div.panel').find('li.action.active').attr('data-action'),o=$(e).closest('div.panel').find('li.action.active').attr('data-method');window.open(t+n+'/'+o+i,'OpenRat_Help','location=no,menubar=no,scrollbars=yes,toolbar=no,resizable=yes')};function notify(e,t,i,n,log=[]){let notice=$('<div class="notice '+i+'"></div>');let toolbar=$('<div class="or-notice-toolbar"></div>');if(log.length)$(toolbar).append('<i class="or-action-full image-icon image-icon--menu-fullscreen"></i>');$(toolbar).append('<i class="or-action-close image-icon image-icon--menu-close"></i>');$(notice).append(toolbar);id=0;if(t)$(notice).append('<div class="name clickable"><a href="" data-type="open" data-action="'+e+'" data-id="'+id+'"><i class="or-action-full image-icon image-icon--action-'+e+'"></i> '+t+'</a></div>');$(notice).append('<div class="text">'+htmlEntities(n)+'</div>');if(log.length){let logLi=log.reduce((result,item)=>{result+='<li><pre>'+htmlEntities(item)+'</pre></li>';return result},'');$(notice).append('<div class="log"><ul>'+logLi+'</ul></div>')};$('#noticebar').prepend(notice);$(notice).orLinkify();$(notice).find('.or-action-full').click(function(){$(notice).toggleClass('full')});$(notice).find('.or-action-close').click(function(){$(notice).fadeOut('fast',function(){$(notice).remove()})});let timeout=1;if(i=='ok')timeout=20;if(i=='info')timeout=60;if(i=='warning')timeout=120;if(i=='error')timeout=120;if(timeout>0)setTimeout(function(){$(notice).fadeOut('slow',function(){$(this).remove()})},timeout*1000)};function htmlEntities(e){return String(e).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;')};function registerOpenClose(e){$(e).children('.on-click-open-close').click(function(){$(this).closest('.toggle-open-close').toggleClass('open closed')})}; \ No newline at end of file diff --git a/modules/cms-ui/themes/default/script/openrat.js b/modules/cms-ui/themes/default/script/openrat.js @@ -1,1318 +0,0 @@ - -var OR_THEMES_EXT_DIR = 'modules/cms-ui/themes/'; - -// Execute after DOM ready: -$( function() { - // JS is available. - $('html').removeClass('nojs'); - - /* Fade in all elements. */ - $('.initial-hidden').removeClass('initial-hidden'); - - registerWorkbenchEvents(); - - - // Listening to the "popstate" event: - window.onpopstate = function (ev) { - Navigator.navigateTo(ev.state); - }; - - initActualHistoryState(); - - Workbench.initialize(); - Workbench.reloadAll(); - - registerNavigation(); - - // Binding aller Sondertasten. - $('.keystroke').each( function() { - let keystrokeElement = $(this); - let keystroke = keystrokeElement.text(); - if (keystroke.length == 0) - return; // No Keybinding. - let keyaction = function() { - keystrokeElement.click(); - }; - // Keybinding ausfuehren. - $(document).bind('keydown', keystroke, keyaction ); - } ); - - - - // Per Klick wird die Notice entfernt. - $('#noticebar .notice .image-icon--menu-close').click(function () { - $(this).closest('.notice').fadeOut('fast', function () { - $(this).remove(); - }); - }); - // Die Notices verschwinden automatisch. - $('#noticebar .notice').each(function () { - let noticeToClose = this; - setTimeout( function() { - $(noticeToClose).fadeOut('slow', function() { $(this).remove(); } ); - },30/*seconds*/ *1000 ); - - }); - - - registerOpenClose($('section.toggle-open-close')); - - $('section.toggle-open-close .on-click-open-close').click(function () { - var section = $(this).closest('section'); - - // disabled sections are ignored. - if (section.hasClass('disabled')) - return; - - // if view is empty, lets load the content. - var view = section.find('div.view-loader'); - if (view.children().length == 0) - Workbench.loadNewActionIntoElement(view); - }); -}); - - -function initActualHistoryState() { - var state = {}; - state.name = window.document.title; - - var params = new URLSearchParams( window.location.search ); - - if (params.has('action')){ - - state.action = params.get('action'); - state.id = params.get('id' ); - state.name = window.document.title; - - state.data = {}; - - //Iterate the search parameters. - - var params = Array.from( params.entries() ); - for( var entry in params ) { - state.data[params[entry][0]] = params[entry][1]; - }; - - Navigator.toActualHistory( state ); - - } -} - - -function registerNavigation() { - $(document).on('orNewAction',function(event, data) { - - let url = './api/?action=tree&subaction=path&id=' + Workbench.state.id + '&type=' + Workbench.state.action + '&output=json'; - - // Die Inhalte des Zweiges laden. - $.getJSON(url, function (json) { - - $('nav .or-navtree-node').removeClass('or-navtree-node--selected'); - - let output = json['output']; - $.each(output.path, function (idx, path) { - - $nav = $('nav .or-navtree-node[data-type='+path.type+'][data-id='+path.id+'].or-navtree-node--is-closed .or-navtree-node-control'); - $nav.click(); - }); - if ( output.actual ) - $('nav .or-navtree-node[data-type='+output.actual.type+'][data-id='+output.actual.id+']').addClass('or-navtree-node--selected'); - - }).fail(function (e) { - // Ups... aber was können wir hier schon tun, außer hässliche Meldungen anzeigen. - console.warn(e); - console.warn('failed to load path from '+url); - }).always(function () { - - }); - }); -} - - -/** - * Navigation. - */ -var Navigator = new function () { - 'use strict'; - - /** - * Navigiert zu einer Action, aber ohne ein neues History-Element einzufügen. - */ - this.navigateTo = function(state) { - Workbench.loadNewActionState(state); - } - - - /** - * - * Navigiert zu einer neue Action und fügt einen neuen History-Eintrag hinzu. - */ - this.navigateToNew = function(obj) { - - Workbench.loadNewActionState(obj); - window.history.pushState(obj,obj.name,'./#/'+obj.action+(obj.id?'/'+obj.id:'') ); - } - - this.navigateToNewAction = function(action, method, id, params ) { - var state = {action:action,method:method,id:id.replace(/[^0-9_]/gim,""),data:params}; - this.navigateToNew(state); - } - - /** - * Setzt den State für den aktuellen History-Eintrag. - * @param obj - */ - this.toActualHistory = function(obj) { - window.history.replaceState(obj,obj.name,createUrl(obj.action,null,obj.id,obj.data,false) ); - } -} - - -var Workbench = new function() -{ - 'use strict'; // Strict mode - - - /** - * Initializes the Workbench. - */ - this.initialize = function() { - - // Initialze Ping timer. - this.initializePingTimer(); - this.initializeState(); - this.initializeMenues(); - this.openModalDialog(); - } - - - /** - * Starts a dialog, if necessary. - */ - this.openModalDialog = function () { - - if ( $('#dialog').data('action') ) { - startDialog('',$('#dialog').data('action'),$('#dialog').data('action'),0,{}) - } - } - - - this.initializeMenues = function () { - - filterMenus(); - } - - - /** - * Sets the workbench state with action/id. - * - * Example: #/name/1 is translated to the state {action:name,id:1} - */ - this.initializeState = function () { - - let parts = window.location.hash.split('/'); - let state = { action:'index',id:0 }; - - if ( parts.length >= 2 ) - state.action = parts[1].toLowerCase(); - - if ( parts.length >= 3 ) - // Only numbers and '_' allowed in the id. - state.id = parts[2].replace(/[^0-9_]/gim,""); - - Workbench.state = state; - - // TODO: Remove this sometimes.... only state. - $('#editor').attr('data-action',state.action); - $('#editor').attr('data-id' ,state.id ); - $('#editor').attr('data-extra' ,'{}' ); - - } - - /** - * Registriert den Ping-Timer für den Sitzungserhalt. - */ - this.initializePingTimer = function() { - - /** - * Ping den Server. Führt keine Aktion aus, aber sorgt dafür, dass die Sitzung erhalten bleibt. - * - * "Geben Sie mir ein Ping, Vasily. Und bitte nur ein einziges Ping!" (aus: Jagd auf Roter Oktober) - */ - var ping = function() - { - $.ajax( createUrl('title','ping',0) ); - //window.console && console.log("session-ping"); - } - - // Alle 5 Minuten pingen. - var timeoutMinutes = 5; - - window.setInterval( ping, timeoutMinutes*60*1000 ); - } - - - - this.loadNewActionState = function(state) { - - Workbench.state = state; - Workbench.loadNewAction(state.action,state.id,state.data); - - - filterMenus(); - - $(document).trigger('orNewAction'); - } - - /** - * - */ - - this.loadNewAction = function(action, id, params ) { - - $('#editor').attr('data-action',action); - $('#editor').attr('data-id' ,id ); - $('#editor').attr('data-extra' ,JSON.stringify(params)); - - this.reloadViews(); - } - - - /** - * - */ - - this.reloadViews = function() { - - // View in geschlossenen Sektionen löschen, damit diese nicht stehen bleiben. - $('#workbench section.closed .view-loader').empty(); - - Workbench.loadViews( $('#workbench section.open .view-loader') ); - } - - - this.reloadAll = function() { - - // View in geschlossenen Sektionen löschen, damit diese nicht stehen bleiben. - $('#workbench .view').empty(); - - Workbench.loadViews( $('#workbench .view') ); - } - - - - this.loadViews = function( $views ) - { - - $views.each(function (idx) { - - let $targetDOMElement = $(this); - - Workbench.loadNewActionIntoElement( $targetDOMElement ) - }); - } - - - - this.loadNewActionIntoElement = function( $viewElement ) - { - let action; - if ( $viewElement.is('.view-static') ) - // Static views have always the same action. - action = $viewElement.attr('data-action'); - else - action = $('#editor').attr('data-action'); - - let id = $('#editor').attr('data-id' ); - let params = $('#editor').attr('data-extra' ); - - let method = $viewElement.data('method'); - - let view = new View( action,method,id,params ); - view.start( $viewElement ); - } - - -} - - - - -/** - * Registriert alle Events, die in der Workbench laufen sollen. - */ -function registerWorkbenchEvents() -{ - // Modalen Dialog erzeugen. - - /* - if ( $('#workbench div.panel.modal').length > 0 ) - { - $('#workbench div.panel.modal').parent().addClass('modal'); - $('div#filler').fadeTo(500,0.5); - $('#workbench').addClass('modal'); - } - */ - - - $('div.header').dblclick( function() - { - fullscreen( this ); - } ); -} - - -/** - * Laden einer View. - * - * @param contentEl - * @param action - * @param method - * @param id - * @param params - */ -function loadView(contentEl,action,method,id,params ) -{ - Navigator.navigateToNewAction( action,method,id,params ); -} - - - -/** - * Registriert alle Handler für den Inhalt einer View. - * - * @param viewEl DOM-Element der View - */ -function afterViewLoaded(viewEl ) -{ - - // Die Section deaktivieren, wenn die View keinen Inhalt hat. - var section = $(viewEl).closest('section'); - - //var viewHasContent = $(viewEl).children().length > 0; - //section.toggleClass('disabled',!viewHasContent); - section.toggleClass('is-empty',$(viewEl).is(':empty')); - - $(viewEl).trigger('orViewLoaded'); - - // Untermenüpunkte aus der View in das Fenstermenü kopieren... - $(viewEl).closest('div.panel').find('div.header div.dropdown div.entry.perview').remove(); // Alte Einträge löschen - - $(viewEl).find('.toggle-nav-open-close').click( function() { - $('nav').toggleClass('open'); - }); - - $(viewEl).find('.toggle-nav-small').click( function() { - $('nav').toggleClass('small'); - }); - - $(viewEl).find('div.headermenu > a').each( function(idx,el) - { - // Jeden Untermenüpunkt zum Fenstermenü hinzufügen. - - // Nein, Untermenüs erscheinen jetzt in der View selbst. - // $(el).wrap('<div class="entry clickable modal perview" />').parent().appendTo( $(viewEl).closest('div.panel').find('div.header div.dropdown').first() ); - } ); - - $(viewEl).find('div.header > a.back').each( function(idx,el) - { - // Zurück-Knopf zum Fenstermenü hinzufügen. - $(el).removeClass('button').wrap('<div class="entry perview" />').parent().appendTo( $(viewEl).closest('div.panel').find('div.header div.dropdown').first() ); - } ); - //$(viewEl).find('div.header').html('<!-- moved to window-menu -->'); - -// $(viewEl).find('input,select,textarea').focus( function() { -// $(this).closest('div.panel').find('div.command').css('visibility','visible').fadeIn('slow'); -// }); - - - // Selectors (Einzel-Ausahl für Dateien) initialisieren - // Wurzel des Baums laden - $(viewEl).find('div.selector.tree').each( function() { - var selectorEl = this; - $(this).orTree( { type:'project',selectable:$(selectorEl).attr('data-types').split(','),id:$(selectorEl).attr('data-init-folderid'),onSelect:function(name,type,id) { - - var selector = $(selectorEl).parent(); - - //console.log( 'Selected: '+name+" #"+id ); - $(selector).find('input[type=text]' ).attr( 'value',name ); - $(selector).find('input[type=hidden]').attr( 'value',id ); - } }); - } ); - - - registerDragAndDrop(viewEl); - - - // Bei Änderungen in der View das Tab als 'dirty' markieren - $(viewEl).find('input').change( function() { - $(this).parent('div.view').addClass('dirty'); - }); - - // Theme-Auswahl mit Preview - $(viewEl).find('.or-theme-chooser').change( function() { - setUserStyle( this.value ); - }); - -} - - - -function registerDragAndDrop(viewEl) -{ - - registerDraggable(viewEl); - registerDroppable(viewEl); -} - - - - -function registerDraggable(viewEl) { - -// Drag n Drop: Inhaltselemente (Dateien,Seiten,Ordner,Verknuepfungen) koennen auf Ordner gezogen werden. - - $(viewEl).find('.or-draggable').draggable( - { - helper: 'clone', - opacity: 0.7, - zIndex: 2, - distance: 10, - cursor: 'move', - revert: 'false' - } - ); - -} - -function registerTreeBranchEvents(viewEl) -{ - registerDraggable(viewEl); -} - - -function registerDroppable(viewEl) { - - /* - $(viewEl).find('div.header > a.back').each( function(idx,el) { - $('div.content li.object > .entry[data-type=\'folder\']').droppable({ - accept: 'li.object', hoverClass: 'drophover', activeClass: 'dropactive', drop: function (event, ui) { - let dropped = ui.draggable; - let droppedOn = $(this).parent(); - - //alert('Moving '+$(dropped).attr('data-id')+' to folder '+$(droppedOn).attr('data-id') ); - startDialog($(this).text(), $(dropped).attr('data-type'), 'copy', $(droppedOn).attr('data-id'), { - 'action': $(dropped).attr('data-type'), - 'subaction': 'copy', - 'id': $(dropped).attr('data-id'), - 'targetFolderId': $(droppedOn).attr('data-id') - }); - //$(dropped).css({top: 0,left: 0}); // Nicht auf das eigene Fenster fallen lassen. - $(dropped).detach().css({top: 0, left: 0}).appendTo(droppedOn).click(); - } - }); - } -*/ - - $(viewEl).find('.or-droppable').droppable({ - accept: '.or-draggable', - hoverClass: 'or-droppable--hover', - activeClass: 'or-droppable--active', - - drop: function (event, ui) { - - let dropped = ui.draggable; - - $(this).find('.or-selector-link-value').val( dropped.data('id') ); - $(this).find('.or-selector-link-name' ).val( dropped.data('id') ); - // Id übertragen - //$(this).value(dropped.data('id')); - } - }); -} - - - -function registerMenuEvents($element ) -{ - //$e = $($element); - - // Mit der Maus irgendwo hin geklickt, das Menü muss schließen. - $('body').click( function() { - $('.toolbar-icon.menu').parents('.or-menu').removeClass('open'); - }); - // Mit der Maus geklicktes Menü aktivieren. - $($element).find('.toolbar-icon.menu').click( function(event) { - event.stopPropagation(); - $(this).parents('.or-menu').toggleClass('open'); - }); - - // Mit der Maus überstrichenes Menü aktivieren. - $($element).find('.toolbar-icon.menu').mouseover( function() { - - // close other menus. - $(this).parents('.or-menu').find('.toolbar-icon.menu').removeClass('open'); - // open the mouse-overed menu. - $(this).addClass('open'); - }); - -} - -function registerSearch($element ) -{ - //$e = $($element); - $($element).find('.search input').orSearch( { dropdown:'#title div.search div.dropdown' } ); - -} - - - -function registerTree(element) { - - // Klick-Funktionen zum Öffnen/Schließen des Zweiges. - $(element).find('.or-navtree-node').orTree(); - -} - - - -/** - * Schaltet die Vollbildfunktion an oder aus. - * - * @param element Das Element, auf dem die Vollbildfunktion ausgeführt wurde - */ -function fullscreen( element ) { - $(element).closest('div.panel').fadeOut('fast', function() - { - $(this).toggleClass('fullscreen').fadeIn('fast'); - } ); -} - - - - -/** - * Setzt neue View und aktualisiert alle Fenster. - * @param element - * @param action Action - * @param id Id - * @deprecated - */ - -function submitUrl( element,url ) -{ - postUrl( url,element ); - - // Alle refresh-fähigen Views mit dem neuen Objekt laden. - //refreshAllRefreshables(); -} - - -/** - * @deprecated - - * @param url - * @param element - */ -function postUrl(url,element) -{ - url += '&output=json'; - $.ajax( { 'type':'POST',url:url, data:{}, success:function(data, textStatus, jqXHR) - { - $('div.panel div.status div.loader').html('&nbsp;'); - doResponse(data,textStatus,element); - } } ); - -} - - -/** - * Form. - * - * @constructor - */ -function Form() { - - this.setLoadStatus = function( isLoading ) { - $(this.element).closest('div.content').toggleClass('loader',isLoading); - } - - this.initOnElement = function( element ) { - this.element = element; - - let form = this; - - // Autosave in Formularen. - // Bei Veränderungen von Checkboxen wird das Formular sofort abgeschickt. - $(element).find('form[data-autosave="true"] input[type="checkbox"]').click( function() { - form.submit(); - }); - - // After click to "OK" the form is submitted. - // Why this?? input type=submit will submit! - /* - $(event.target).find('input.submit.ok').click( function() { - $(this).closest('form').submit(); - }); - */ - - $(element).find('.or-form-btn--cancel').click( function() { - form.cancel(); - - }); - $(element).find('.or-form-btn--reset').click( function() { - form.rollback(); - - }); - - // Submithandler for the whole form. - $(element).submit( function( event ) { - - // - if ($(this).data('target')=='view') - { - form.submit(); - event.preventDefault(); - } - // target=top will load the native way without javascript. - }); - } - - this.cancel = function() { - //$(this.element).html('').parent().removeClass('is-open'); - this.close(); - } - - - this.rollback = function() { - this.element.trigger('reset'); - } - - this.close = function() { - - } - - this.submit = function() { - - - // Show progress - let status = $('<div class="notice info"><div class="text loader"></div></div>'); - $('#noticebar').prepend(status); // Notice anhängen. - $(status).show(); - - // Alle vorhandenen Error-Marker entfernen. - // Falls wieder ein Fehler auftritt, werden diese erneut gesetzt. - $(this.element).find('.error').removeClass('error'); - - var params = $(this.element).serializeArray(); - var data = {}; - $(params).each(function(index, obj){ - data[obj.name] = obj.value; - }); - - // If form does not contain action/id, get it from the workbench. - if (!data.id) - data.id = Workbench.state.id; - if (!data.action) - data.action = Workbench.state.action; - - let formMethod = $(this.element).attr('method').toUpperCase(); - - if ( formMethod == 'GET' ) - { - // Mehrseitiges Formular - // Die eingegebenen Formulardaten werden zur nächsten Action geschickt. - //Workbench.loadViewIntoElement( $(form).parent('.view'),data.action, data.subaction,data.id,data ); - this.forwardTo( data.action, data.subaction,data.id,data ); - } - else - { - let url = './api/'; // Alle Parameter befinden sich im Formular - - // POST-Request - this.setLoadStatus(true); - //url += '?output=json'; - url += ''; - //params['output'] = 'json';// Irgendwie geht das nicht. - data.output = 'json'; - - if ( $(this.element).data('async') || $(this.element).data('async')=='true') - { - // Verarbeitung erfolgt asynchron, das heißt, dass der evtl. geöffnete Dialog - // beendet wird. - this.close(); - // Async: Window is closed, but the action will be startet now. - } - - let form = this; - $.ajax( { 'type':'POST',url:url, data:data, success:function(data, textStatus, jqXHR) - { - form.setLoadStatus(false); - $(status).remove(); - - doResponse(data,textStatus,form.element); - }, - error:function(jqXHR, textStatus, errorThrown) { - form.setLoadStatus(false); - $(status).remove(); - - try - { - let error = jQuery.parseJSON( jqXHR.responseText ); - notify('','','error',error.error,[error.description]); - } - catch( e ) - { - let msg = jqXHR.responseText; - notify('','','error','Server Error',[msg]); - } - - - } - - } ); - $(form.element).fadeIn(); - } - - } -} - - - -/** - * View. - * Eine View ist ein HTML-Fragment, in das eine Action geladen wird. - * Das Erzeugen der View, das Laden vom Server sowie das Schließen sind hier gekapselt. - * - * @param action - * @param method - * @param id - * @param params - * @constructor - */ -function View( action,method,id,params ) { - - this.action = action; - this.method = method; - this.id = id; - this.params = params; - - this.before = function() {}; - - this.start = function( element ) { - this.before(); - this.element = element; - this.loadView(); - } - - this.afterLoad = function() { - - } - - this.close = function() { - } - - - function registerViewEvents(element) { - - registerMenuEvents( element ); - registerSearch ( element ); - registerTree ( element ); - afterViewLoaded ( element ); - - } - - - this.loadView = function() { - - let url = createUrl( this.action,this.method,this.id,this.params,true); // URL für das Laden erzeugen. - let element = this.element; - let view = this; - - $(this.element).empty().fadeTo(1,0.7).addClass('loader').html('').load(url,function(response, status, xhr) { - - $(element).fadeTo(350,1); - - $(element).removeClass("loader"); - - $(element).find('form').each( function() { - let form = new Form(); - form.close = function() { - view.close(); - } - form.initOnElement(this); - - }); - if ( status == "error" ) - { - // Seite nicht gefunden. - $(element).html(""); - - notify('','','error','Server Error',['Server Error while requesting url '+url, response]); - return; - } - - registerViewEvents( element ); - - }); - - } - -} - - -/** - * Setzt neuen modalen Dialog und aktualisiert alle Fenster. - * @param name - * @param action Action - * @param method - * @param id Id - * @param params - */ -function startDialog( name,action,method,id,params ) -{ - // Attribute aus dem aktuellen Editor holen, falls die Daten beim Aufrufer nicht angegeben sind. - if (!action) - action = $('#editor').attr('data-action'); - - if (!id) - id = $('#editor').attr('data-id'); - - let view = new View( action,method,id,params ); - - view.before = function() { - $('#dialog > .view').html('<div class="header"><img class="icon" title="" src="./themes/default/images/icon/'+method+'.png" />'+name+'</div>'); - $('#dialog > .view').data('id',id); - $('#dialog').removeClass('is-closed').addClass('is-open'); - - let view = this; - - this.escapeKeyClosingHandler = function (e) { - if (e.keyCode == 27) { // ESC keycode - view.close(); - - $(document).off('keyup'); // de-register. - } - }; - - $(document).keyup(this.escapeKeyClosingHandler); - - // Nicht-Modale Dialoge durch Klick auf freie Fläche schließen. - $('#dialog .filler').click( function() - { - view.close(); - }); - - } - - view.close = function() { - - // Strong modal dialogs are unable to close. - // Really? - if ( $('div#dialog').hasClass('modal') ) - return; - - $('#dialog .view').fadeOut('fast').html(''); - $('#dialog').removeClass('is-open').addClass('is-closed'); // Dialog schließen - - $(document).unbind('keyup',this.escapeKeyClosingHandler); // Cleanup ESC-Key-Listener - } - - view.start( $('div#dialog > .view') ); -} - - -/** - * Starts a non-modal editing dialog. - * @param name - * @param action - * @param method - * @param id - * @param params - */ -function startEdit( name,action,method,id,params ) -{ - // Attribute aus dem aktuellen Editor holen, falls die Daten beim Aufrufer nicht angegeben sind. - if (!action) - action = Workbench.state.action; - - if (!id) - id = Workbench.state.id; - - let view = new View( action,method,id,params ); - - view.before = function() { - - let view = this; - - $edit = $('#edit'); - $edit.addClass('is-open'); - - $('#editor').addClass('is-closed'); - - // Dialog durch Klick auf freie Fläche schließen. - $('#edit .filler').click( function() - { - view.close(); - }); - - }; - - view.close = function() { - $edit.removeClass('is-open'); - $('#editor').removeClass('is-closed'); - } - - view.start( $('#edit > .view') ); -} - - -/** - * Setzt einen Fenster-Titel für die ganze Anwendung. - */ -function setTitle( title ) -{ - if ( title ) - $('head > title').text( title + ' - ' + $('head > title').data('default') ); - else - $('head > title').text( $('head > title').data('default') ); -} - -/** - * Setzt neue Action und aktualisiert alle Fenster. - * - * @param action Action - * @param id Id - */ -function openNewAction( name,action,id,extraId ) -{ - // Im Mobilmodus soll das Menü verschwinden, wenn eine neue Action geoeffnet wird. - $('nav').removeClass('open'); - - setTitle( name ); // Title setzen. - - setNewAction( action,id,extraId ); -} - - -function filterMenus() -{ - let action = Workbench.state.action; - let id = Workbench.state.id; - $('div.clickable').addClass('active'); - $('div.clickable.filtered').removeClass('active').addClass('inactive'); - - $('div.clickable.filtered.on-action-'+action).addClass('active').removeClass('inactive'); - - // Jeder Menüeintrag bekommt die Id und Parameter. - $('div.clickable.filtered a').attr('data-id' ,id ); - /* - $('div.clickable.filtered a').attr('data-action',action); - */ - -} - - - -/** - * Setzt neue Action und aktualisiert alle Fenster. - * - * @param action Action - * @param id Id - */ -function setNewAction( action,id,extraId ) -{ - Navigator.navigateToNewAction(action,'edit',id,extraId); - // Alle refresh-fähigen Views mit dem neuen Objekt laden. - //refreshAllRefreshables(); -} - - -/** - * Setzt neue Id und aktualisiert alle Fenster. - * @param id Id - */ -function setNewId( id ) { -} - - - - - -/** - * Notification im Browser anzeigen. - * Quelle: https://developer.mozilla.org/en-US/docs/Web/API/notification - * @param text Text der Nachricht. - */ -function notifyBrowser(text) -{ - // Let's check if the browser supports notifications - if (!("Notification" in window)) { - return; - //alert("This browser does not support desktop notification"); - } - - // Let's check if the user is okay to get some notification - else if (Notification.permission === "granted") { - // If it's okay let's create a notification - let notification = new Notification(text); - } - - // Otherwise, we need to ask the user for permission - else if (Notification.permission !== 'denied') { - Notification.requestPermission(function (permission) { - // If the user is okay, let's create a notification - if (permission === "granted") { - let notification = new Notification(text); - } - }); - } - - // At last, if the user already denied any notification, and you - // want to be respectful there is no need to bother them any more. -} - - - -/** - * Setzt einen neuen Theme. - * @param styleName - * @returns - */ -function setUserStyle( styleName ) -{ - var html = $('html'); - var classList = html.attr('class').split(/\s+/); - $.each(classList, function(index, item) { - if (item.startsWith('theme-')) { - html.removeClass(item); - } - }); - html.addClass( 'theme-' + styleName.toLowerCase() ); -} - - - - -//Quelle: -//http://aktuell.de.selfhtml.org/tippstricks/javascript/bbcode/ -function insert(tagName, aTag, eTag) -{ -var input = document.forms[0].elements[tagName]; -input.focus(); -/* IE */ -if(typeof document.selection != 'undefined') { - /* Einfuegen des Formatierungscodes */ -// alert('IE'); - var range = document.selection.createRange(); - var insText = range.text; - range.text = aTag + insText + eTag; - /* Anpassen der Cursorposition */ - range = document.selection.createRange(); - if (insText.length == 0) { - range.move('character', -eTag.length); - } else { - range.moveStart('character', aTag.length + insText.length + eTag.length); - } - range.select(); -} -/* Gecko */ -else if(typeof input.selectionStart != 'undefined') -{ -// alert('Gecko'); - /* Einfuegen des Formatierungscodes */ - var start = input.selectionStart; - var end = input.selectionEnd; - var insText = input.value.substring(start, end); - input.value = input.value.substr(0, start) + aTag + insText + eTag + input.value.substr(end); - /* Anpassen der Cursorposition */ - var pos; - if (insText.length == 0) { - pos = start + aTag.length; - } else { - pos = start + aTag.length + insText.length + eTag.length; - } - input.selectionStart = pos; - input.selectionEnd = pos; -} -/* uebrige Browser */ -else -{ - /* Abfrage der Einfuegeposition */ - - /* - var pos; - var re = new RegExp('^[0-9]{0,3}$'); - while(!re.test(pos)) { - pos = prompt("Position (0.." + input.value.length + "):", "0"); - } - if(pos > input.value.length) { - pos = input.value.length; - } - */ - pos = input.value.length; - - /* Einfuegen des Formatierungscodes */ - var insText = prompt("Text"); - input.value = input.value.substr(0, pos) + aTag + insText + eTag + input.value.substr(pos); -} -} - - - - -/** - * Erzeugt eine URL, um die gewünschte Action vom Server zu laden. - * - * @param action - * @param subaction - * @param id - * @param extraid - * @returns URL - */ -function createUrl(action,subaction,id,extraid,embed) -{ - var url = './'; - - url += '?'; - - if(action) - url += '&action='+action; - if(subaction) - url += '&subaction='+subaction; - if(id) - url += '&id='+id; - - if ( typeof extraid === 'string') - { - extraid = extraid.replace(/'/g,'"'); // Replace ' with ". - var extraObject = jQuery.parseJSON(extraid); - jQuery.each(extraObject, function(name, value) { - url = url + '&' + name + '=' + value; - }); - } - else if ( typeof extraid === 'object') - { - jQuery.each(extraid, function(name, field) { - url = url + '&' + name + '=' + field; - }); - } - else - { - } - return url; -} - - -/** - * Setzt Breite/Höhe für einen Container in der Workbench. - * - * Sind weitere Container enthalten, werden diese rekursiv angepasst. - * - * @param container - */ -function resizeWorkbenchContainer( container ) -{ -} - - - -/** - * Fenstergröße wurde verändert, nun die Größe der DIVs neu berechnen. - */ -function resizeWorkbench() -{ -} - - -/** - * Größe der TABs pro Frame neu berechnen. - */ -function resizeTabs( panel ) -{ -} - - -function help(el,url,suffix) -{ - var action = $(el).closest('div.panel').find('li.action.active').attr('data-action'); - var method = $(el).closest('div.panel').find('li.action.active').attr('data-method'); - - window.open(url + action + '/'+ method + suffix, 'OpenRat_Help', 'location=no,menubar=no,scrollbars=yes,toolbar=no,resizable=yes'); -} - - -/** - * Show a notice bubble in the UI. - * @param type - * @param name - * @param status - * @param msg - * @param log - */ -function notify( type,name,status,msg,log=[] ) -{ - // Notice-Bar mit dieser Meldung erweitern. - - let notice = $('<div class="notice '+status+'"></div>'); - - let toolbar = $('<div class="or-notice-toolbar"></div>'); - if ( log.length ) - $(toolbar).append('<i class="or-action-full image-icon image-icon--menu-fullscreen"></i>'); - $(toolbar).append('<i class="or-action-close image-icon image-icon--menu-close"></i>'); - $(notice).append(toolbar); - - id = 0; // TODO - if (name) - $(notice).append('<div class="name clickable"><a href="" data-type="open" data-action="'+type+'" data-id="'+id+'"><i class="or-action-full image-icon image-icon--action-'+type+'"></i> '+name+'</a></div>'); - - $(notice).append( '<div class="text">'+htmlEntities(msg)+'</div>'); - - if (log.length) { - - let logLi = log.reduce((result, item) => { - result += '<li><pre>'+htmlEntities(item)+'</pre></li>'; - return result; - }, ''); - $(notice).append('<div class="log"><ul>'+logLi+'</ul></div>'); - } - - $('#noticebar').prepend(notice); // Notice anhängen. - $(notice).orLinkify(); // Enable links - - - // Toogle Fullscreen for notice - $(notice).find('.or-action-full').click( function() { - $(notice).toggleClass('full'); - }); - - // Close the notice on click - $(notice).find('.or-action-close').click( function() { - $(notice).fadeOut('fast',function() { $(notice).remove(); } ); - }); - - // Fadeout the notice after a while. - let timeout = 1; - if ( status == 'ok' ) timeout = 20; - if ( status == 'info' ) timeout = 60; - if ( status == 'warning') timeout = 120; - if ( status == 'error' ) timeout = 120; - - if (timeout > 0) - setTimeout( function() { - $(notice).fadeOut('slow', function() { $(this).remove(); } ); - },timeout*1000 ); -} - - -function htmlEntities(str) { - return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;'); -} - -function registerOpenClose( $el ) -{ - $($el).children('.on-click-open-close').click( function() { - $(this).closest('.toggle-open-close').toggleClass('open closed'); - }); - -}- \ No newline at end of file diff --git a/modules/cms-ui/themes/default/script/openrat.min.js b/modules/cms-ui/themes/default/script/openrat.min.js @@ -1,10 +0,0 @@ -;var OR_THEMES_EXT_DIR='modules/cms-ui/themes/';$(function(){$('html').removeClass('nojs');$('.initial-hidden').removeClass('initial-hidden');registerWorkbenchEvents();window.onpopstate=function(e){Navigator.navigateTo(e.state)};initActualHistoryState();Workbench.initialize();Workbench.reloadAll();registerNavigation();$('.keystroke').each(function(){let keystrokeElement=$(this);let keystroke=keystrokeElement.text();if(keystroke.length==0)return;let keyaction=function(){keystrokeElement.click()};$(document).bind('keydown',keystroke,keyaction)});$('#noticebar .notice .image-icon--menu-close').click(function(){$(this).closest('.notice').fadeOut('fast',function(){$(this).remove()})});$('#noticebar .notice').each(function(){let noticeToClose=this;setTimeout(function(){$(noticeToClose).fadeOut('slow',function(){$(this).remove()})},30*1000)});registerOpenClose($('section.toggle-open-close'));$('section.toggle-open-close .on-click-open-close').click(function(){var t=$(this).closest('section');if(t.hasClass('disabled'))return;var e=t.find('div.view-loader');if(e.children().length==0)Workbench.loadNewActionIntoElement(e)})});function initActualHistoryState(){var t={};t.name=window.document.title;var e=new URLSearchParams(window.location.search);if(e.has('action')){t.action=e.get('action');t.id=e.get('id');t.name=window.document.title;t.data={};var e=Array.from(e.entries());for(var i in e){t.data[e[i][0]]=e[i][1]};Navigator.toActualHistory(t)}};function registerNavigation(){$(document).on('orNewAction',function(e,t){let url='./api/?action=tree&subaction=path&id='+Workbench.state.id+'&type='+Workbench.state.action+'&output=json';$.getJSON(url,function(e){$('nav .or-navtree-node').removeClass('or-navtree-node--selected');let output=e['output'];$.each(output.path,function(e,t){$nav=$('nav .or-navtree-node[data-type='+t.type+'][data-id='+t.id+'].or-navtree-node--is-closed .or-navtree-node-control');$nav.click()});if(output.actual)$('nav .or-navtree-node[data-type='+output.actual.type+'][data-id='+output.actual.id+']').addClass('or-navtree-node--selected')}).fail(function(e){console.warn(e);console.warn('failed to load path from '+url)}).always(function(){})})};var Navigator=new function(){'use strict';this.navigateTo=function(e){Workbench.loadNewActionState(e)};this.navigateToNew=function(e){Workbench.loadNewActionState(e);window.history.pushState(e,e.name,'./#/'+e.action+(e.id?'/'+e.id:''))};this.navigateToNewAction=function(e,t,i,n){var o={action:e,method:t,id:i.replace(/[^0-9_]/gim,''),data:n};this.navigateToNew(o)};this.toActualHistory=function(e){window.history.replaceState(e,e.name,createUrl(e.action,null,e.id,e.data,!1))}},Workbench=new function(){'use strict';this.initialize=function(){this.initializePingTimer();this.initializeState();this.initializeMenues();this.openModalDialog()};this.openModalDialog=function(){if($('#dialog').data('action')){startDialog('',$('#dialog').data('action'),$('#dialog').data('action'),0,{})}};this.initializeMenues=function(){filterMenus()};this.initializeState=function(){let parts=window.location.hash.split('/');let state={action:'index',id:0};if(parts.length>=2)state.action=parts[1].toLowerCase();if(parts.length>=3)state.id=parts[2].replace(/[^0-9_]/gim,'');Workbench.state=state;$('#editor').attr('data-action',state.action);$('#editor').attr('data-id',state.id);$('#editor').attr('data-extra','{}')};this.initializePingTimer=function(){var e=function(){$.ajax(createUrl('title','ping',0))},t=5;window.setInterval(e,t*60*1000)};this.loadNewActionState=function(e){Workbench.state=e;Workbench.loadNewAction(e.action,e.id,e.data);filterMenus();$(document).trigger('orNewAction')};this.loadNewAction=function(e,t,i){$('#editor').attr('data-action',e);$('#editor').attr('data-id',t);$('#editor').attr('data-extra',JSON.stringify(i));this.reloadViews()};this.reloadViews=function(){$('#workbench section.closed .view-loader').empty();Workbench.loadViews($('#workbench section.open .view-loader'))};this.reloadAll=function(){$('#workbench .view').empty();Workbench.loadViews($('#workbench .view'))};this.loadViews=function(e){e.each(function(e){let $targetDOMElement=$(this);Workbench.loadNewActionIntoElement($targetDOMElement)})};this.loadNewActionIntoElement=function(e){let action;if(e.is('.view-static'))action=e.attr('data-action');else action=$('#editor').attr('data-action');let id=$('#editor').attr('data-id');let params=$('#editor').attr('data-extra');let method=e.data('method');let view=new View(action,method,id,params);view.start(e)}};function registerWorkbenchEvents(){$('div.header').dblclick(function(){fullscreen(this)})};function loadView(e,t,i,n,o){Navigator.navigateToNewAction(t,i,n,o)};function afterViewLoaded(e){var t=$(e).closest('section');t.toggleClass('is-empty',$(e).is(':empty'));$(e).trigger('orViewLoaded');$(e).closest('div.panel').find('div.header div.dropdown div.entry.perview').remove();$(e).find('.toggle-nav-open-close').click(function(){$('nav').toggleClass('open')});$(e).find('.toggle-nav-small').click(function(){$('nav').toggleClass('small')});$(e).find('div.headermenu > a').each(function(e,t){});$(e).find('div.header > a.back').each(function(t,i){$(i).removeClass('button').wrap('<div class="entry perview" />').parent().appendTo($(e).closest('div.panel').find('div.header div.dropdown').first())});$(e).find('div.selector.tree').each(function(){var e=this;$(this).orTree({type:'project',selectable:$(e).attr('data-types').split(','),id:$(e).attr('data-init-folderid'),onSelect:function(t,i,n){var o=$(e).parent();$(o).find('input[type=text]').attr('value',t);$(o).find('input[type=hidden]').attr('value',n)}})});registerDragAndDrop(e);$(e).find('input').change(function(){$(this).parent('div.view').addClass('dirty')});$(e).find('.or-theme-chooser').change(function(){setUserStyle(this.value)})};function registerDragAndDrop(e){registerDraggable(e);registerDroppable(e)};function registerDraggable(e){$(e).find('.or-draggable').draggable({helper:'clone',opacity:0.7,zIndex:2,distance:10,cursor:'move',revert:'false'})};function registerTreeBranchEvents(e){registerDraggable(e)};function registerDroppable(e){$(e).find('.or-droppable').droppable({accept:'.or-draggable',hoverClass:'or-droppable--hover',activeClass:'or-droppable--active',drop:function(e,t){let dropped=t.draggable;$(this).find('.or-selector-link-value').val(dropped.data('id'));$(this).find('.or-selector-link-name').val(dropped.data('id'))}})};function registerMenuEvents(e){$('body').click(function(){$('.toolbar-icon.menu').parents('.or-menu').removeClass('open')});$(e).find('.toolbar-icon.menu').click(function(e){e.stopPropagation();$(this).parents('.or-menu').toggleClass('open')});$(e).find('.toolbar-icon.menu').mouseover(function(){$(this).parents('.or-menu').find('.toolbar-icon.menu').removeClass('open');$(this).addClass('open')})};function registerSearch(e){$(e).find('.search input').orSearch({dropdown:'#title div.search div.dropdown'})};function registerTree(e){$(e).find('.or-navtree-node').orTree()};function fullscreen(e){$(e).closest('div.panel').fadeOut('fast',function(){$(this).toggleClass('fullscreen').fadeIn('fast')})};function submitUrl(e,t){postUrl(t,e)};function postUrl(e,t){e+='&output=json';$.ajax({'type':'POST',url:e,data:{},success:function(e,i,n){$('div.panel div.status div.loader').html('&nbsp;');doResponse(e,i,t)}})};function Form(){this.setLoadStatus=function(e){$(this.element).closest('div.content').toggleClass('loader',e)};this.initOnElement=function(e){this.element=e;let form=this;$(e).find('form[data-autosave="true"] input[type="checkbox"]').click(function(){form.submit()});$(e).find('.or-form-btn--cancel').click(function(){form.cancel()});$(e).find('.or-form-btn--reset').click(function(){form.rollback()});$(e).submit(function(e){if($(this).data('target')=='view'){form.submit();e.preventDefault()}})};this.cancel=function(){this.close()};this.rollback=function(){this.element.trigger('reset')};this.close=function(){};this.submit=function(){let status=$('<div class="notice info"><div class="text loader"></div></div>');$('#noticebar').prepend(status);$(status).show();$(this.element).find('.error').removeClass('error');var t=$(this.element).serializeArray(),e={};$(t).each(function(t,i){e[i.name]=i.value});if(!e.id)e.id=Workbench.state.id;if(!e.action)e.action=Workbench.state.action;let formMethod=$(this.element).attr('method').toUpperCase();if(formMethod=='GET'){this.forwardTo(e.action,e.subaction,e.id,e)} -else{let url='./api/';this.setLoadStatus(!0);url+='';e.output='json';if($(this.element).data('async')||$(this.element).data('async')=='true'){this.close()};let form=this;$.ajax({'type':'POST',url:url,data:e,success:function(e,t,i){form.setLoadStatus(!1);$(status).remove();doResponse(e,t,form.element)},error:function(e,t,i){form.setLoadStatus(!1);$(status).remove();try{let error=jQuery.parseJSON(e.responseText);notify('','','error',error.error,[error.description])}catch(n){let msg=e.responseText;notify('','','error','Server Error',[msg])}}});$(form.element).fadeIn()}}};function View(e,t,i,n){this.action=e;this.method=t;this.id=i;this.params=n;this.before=function(){};this.start=function(e){this.before();this.element=e;this.loadView()};this.afterLoad=function(){};this.close=function(){};function o(e){registerMenuEvents(e);registerSearch(e);registerTree(e);afterViewLoaded(e)};this.loadView=function(){let url=createUrl(this.action,this.method,this.id,this.params,!0);let element=this.element;let view=this;$(this.element).empty().fadeTo(1,0.7).addClass('loader').html('').load(url,function(e,t,i){$(element).fadeTo(350,1);$(element).removeClass('loader');$(element).find('form').each(function(){let form=new Form();form.close=function(){view.close()};form.initOnElement(this)});if(t=='error'){$(element).html('');notify('','','error','Server Error',['Server Error while requesting url '+url,e]);return};o(element)})}};function startDialog(e,t,i,n,o){if(!t)t=$('#editor').attr('data-action');if(!n)n=$('#editor').attr('data-id');let view=new View(t,i,n,o);view.before=function(){$('#dialog > .view').html('<div class="header"><img class="icon" title="" src="./themes/default/images/icon/'+i+'.png" />'+e+'</div>');$('#dialog > .view').data('id',n);$('#dialog').removeClass('is-closed').addClass('is-open');let view=this;this.escapeKeyClosingHandler=function(e){if(e.keyCode==27){view.close();$(document).off('keyup')}};$(document).keyup(this.escapeKeyClosingHandler);$('#dialog .filler').click(function(){view.close()})};view.close=function(){if($('div#dialog').hasClass('modal'))return;$('#dialog .view').fadeOut('fast').html('');$('#dialog').removeClass('is-open').addClass('is-closed');$(document).unbind('keyup',this.escapeKeyClosingHandler)};view.start($('div#dialog > .view'))};function startEdit(e,t,i,n,o){if(!t)t=Workbench.state.action;if(!n)n=Workbench.state.id;let view=new View(t,i,n,o);view.before=function(){let view=this;$edit=$('#edit');$edit.addClass('is-open');$('#editor').addClass('is-closed');$('#edit .filler').click(function(){view.close()})};view.close=function(){$edit.removeClass('is-open');$('#editor').removeClass('is-closed')};view.start($('#edit > .view'))};function setTitle(e){if(e)$('head > title').text(e+' - '+$('head > title').data('default'));else $('head > title').text($('head > title').data('default'))};function openNewAction(e,t,i,n){$('nav').removeClass('open');setTitle(e);setNewAction(t,i,n)};function filterMenus(){let action=Workbench.state.action;let id=Workbench.state.id;$('div.clickable').addClass('active');$('div.clickable.filtered').removeClass('active').addClass('inactive');$('div.clickable.filtered.on-action-'+action).addClass('active').removeClass('inactive');$('div.clickable.filtered a').attr('data-id',id)};function setNewAction(e,t,i){Navigator.navigateToNewAction(e,'edit',t,i)};function setNewId(e){};function notifyBrowser(e){if(!('Notification' in window)){return} -else if(Notification.permission==='granted'){let notification=new Notification(e)} -else if(Notification.permission!=='denied'){Notification.requestPermission(function(t){if(t==='granted'){let notification=new Notification(e)}})}};function setUserStyle(e){var t=$('html'),i=t.attr('class').split(/\s+/);$.each(i,function(e,i){if(i.startsWith('theme-')){t.removeClass(i)}});t.addClass('theme-'+e.toLowerCase())};function insert(e,t,i){var n=document.forms[0].elements[e];n.focus();if(typeof document.selection!='undefined'){var r=document.selection.createRange(),o=r.text;r.text=t+o+i;r=document.selection.createRange();if(o.length==0){r.move('character',-i.length)} -else{r.moveStart('character',t.length+o.length+i.length)};r.select()} -else if(typeof n.selectionStart!='undefined'){var s=n.selectionStart,l=n.selectionEnd,o=n.value.substring(s,l);n.value=n.value.substr(0,s)+t+o+i+n.value.substr(l);var a;if(o.length==0){a=s+t.length} -else{a=s+t.length+o.length+i.length};n.selectionStart=a;n.selectionEnd=a} -else{a=n.value.length;var o=prompt('Text');n.value=n.value.substr(0,a)+t+o+i+n.value.substr(a)}};function createUrl(e,t,i,n,a){var o='./';o+='?';if(e)o+='&action='+e;if(t)o+='&subaction='+t;if(i)o+='&id='+i;if(typeof n==='string'){n=n.replace(/'/g,'"');var r=jQuery.parseJSON(n);jQuery.each(r,function(e,t){o=o+'&'+e+'='+t})} -else if(typeof n==='object'){jQuery.each(n,function(e,t){o=o+'&'+e+'='+t})} -else{};return o};function resizeWorkbenchContainer(e){};function resizeWorkbench(){};function resizeTabs(e){};function help(e,t,i){var n=$(e).closest('div.panel').find('li.action.active').attr('data-action'),o=$(e).closest('div.panel').find('li.action.active').attr('data-method');window.open(t+n+'/'+o+i,'OpenRat_Help','location=no,menubar=no,scrollbars=yes,toolbar=no,resizable=yes')};function notify(e,t,i,n,log=[]){let notice=$('<div class="notice '+i+'"></div>');let toolbar=$('<div class="or-notice-toolbar"></div>');if(log.length)$(toolbar).append('<i class="or-action-full image-icon image-icon--menu-fullscreen"></i>');$(toolbar).append('<i class="or-action-close image-icon image-icon--menu-close"></i>');$(notice).append(toolbar);id=0;if(t)$(notice).append('<div class="name clickable"><a href="" data-type="open" data-action="'+e+'" data-id="'+id+'"><i class="or-action-full image-icon image-icon--action-'+e+'"></i> '+t+'</a></div>');$(notice).append('<div class="text">'+htmlEntities(n)+'</div>');if(log.length){let logLi=log.reduce((result,item)=>{result+='<li><pre>'+htmlEntities(item)+'</pre></li>';return result},'');$(notice).append('<div class="log"><ul>'+logLi+'</ul></div>')};$('#noticebar').prepend(notice);$(notice).orLinkify();$(notice).find('.or-action-full').click(function(){$(notice).toggleClass('full')});$(notice).find('.or-action-close').click(function(){$(notice).fadeOut('fast',function(){$(notice).remove()})});let timeout=1;if(i=='ok')timeout=20;if(i=='info')timeout=60;if(i=='warning')timeout=120;if(i=='error')timeout=120;if(timeout>0)setTimeout(function(){$(notice).fadeOut('slow',function(){$(this).remove()})},timeout*1000)};function htmlEntities(e){return String(e).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;')};function registerOpenClose(e){$(e).children('.on-click-open-close').click(function(){$(this).closest('.toggle-open-close').toggleClass('open closed')})};- \ No newline at end of file diff --git a/modules/cms-ui/themes/default/script/openrat/common.js b/modules/cms-ui/themes/default/script/openrat/common.js @@ -0,0 +1,881 @@ + +// The crap in this file should be refactored into namespaced objects... + +var OR_THEMES_EXT_DIR = 'modules/cms-ui/themes/'; + +// Execute after DOM ready: +$( function() { + // JS is available. + $('html').removeClass('nojs'); + + /* Fade in all elements. */ + $('.initial-hidden').removeClass('initial-hidden'); + + registerWorkbenchEvents(); + + + // Listening to the "popstate" event: + window.onpopstate = function (ev) { + Navigator.navigateTo(ev.state); + }; + + initActualHistoryState(); + + Workbench.initialize(); + Workbench.reloadAll(); + + registerNavigation(); + + // Binding aller Sondertasten. + $('.keystroke').each( function() { + let keystrokeElement = $(this); + let keystroke = keystrokeElement.text(); + if (keystroke.length == 0) + return; // No Keybinding. + let keyaction = function() { + keystrokeElement.click(); + }; + // Keybinding ausfuehren. + $(document).bind('keydown', keystroke, keyaction ); + } ); + + + + // Per Klick wird die Notice entfernt. + $('#noticebar .notice .image-icon--menu-close').click(function () { + $(this).closest('.notice').fadeOut('fast', function () { + $(this).remove(); + }); + }); + // Die Notices verschwinden automatisch. + $('#noticebar .notice').each(function () { + let noticeToClose = this; + setTimeout( function() { + $(noticeToClose).fadeOut('slow', function() { $(this).remove(); } ); + },30/*seconds*/ *1000 ); + + }); + + + registerOpenClose($('section.toggle-open-close')); + + $('section.toggle-open-close .on-click-open-close').click(function () { + var section = $(this).closest('section'); + + // disabled sections are ignored. + if (section.hasClass('disabled')) + return; + + // if view is empty, lets load the content. + var view = section.find('div.view-loader'); + if (view.children().length == 0) + Workbench.loadNewActionIntoElement(view); + }); +}); + + +function initActualHistoryState() { + var state = {}; + state.name = window.document.title; + + var params = new URLSearchParams( window.location.search ); + + if (params.has('action')){ + + state.action = params.get('action'); + state.id = params.get('id' ); + state.name = window.document.title; + + state.data = {}; + + //Iterate the search parameters. + + var params = Array.from( params.entries() ); + for( var entry in params ) { + state.data[params[entry][0]] = params[entry][1]; + }; + + Navigator.toActualHistory( state ); + + } +} + + +function registerNavigation() { + $(document).on('orNewAction',function(event, data) { + + let url = './api/?action=tree&subaction=path&id=' + Workbench.state.id + '&type=' + Workbench.state.action + '&output=json'; + + // Die Inhalte des Zweiges laden. + $.getJSON(url, function (json) { + + $('nav .or-navtree-node').removeClass('or-navtree-node--selected'); + + let output = json['output']; + $.each(output.path, function (idx, path) { + + $nav = $('nav .or-navtree-node[data-type='+path.type+'][data-id='+path.id+'].or-navtree-node--is-closed .or-navtree-node-control'); + $nav.click(); + }); + if ( output.actual ) + $('nav .or-navtree-node[data-type='+output.actual.type+'][data-id='+output.actual.id+']').addClass('or-navtree-node--selected'); + + }).fail(function (e) { + // Ups... aber was können wir hier schon tun, außer hässliche Meldungen anzeigen. + console.warn(e); + console.warn('failed to load path from '+url); + }).always(function () { + + }); + }); +} + + + +/** + * Registriert alle Events, die in der Workbench laufen sollen. + */ +function registerWorkbenchEvents() +{ + // Modalen Dialog erzeugen. + + /* + if ( $('#workbench div.panel.modal').length > 0 ) + { + $('#workbench div.panel.modal').parent().addClass('modal'); + $('div#filler').fadeTo(500,0.5); + $('#workbench').addClass('modal'); + } + */ + + + $('div.header').dblclick( function() + { + fullscreen( this ); + } ); +} + + +/** + * Laden einer View. + * + * @param contentEl + * @param action + * @param method + * @param id + * @param params + */ +function loadView(contentEl,action,method,id,params ) +{ + Navigator.navigateToNewAction( action,method,id,params ); +} + + + +/** + * Registriert alle Handler für den Inhalt einer View. + * + * @param viewEl DOM-Element der View + */ +function afterViewLoaded(viewEl ) +{ + + // Die Section deaktivieren, wenn die View keinen Inhalt hat. + var section = $(viewEl).closest('section'); + + //var viewHasContent = $(viewEl).children().length > 0; + //section.toggleClass('disabled',!viewHasContent); + section.toggleClass('is-empty',$(viewEl).is(':empty')); + + $(viewEl).trigger('orViewLoaded'); + + // Untermenüpunkte aus der View in das Fenstermenü kopieren... + $(viewEl).closest('div.panel').find('div.header div.dropdown div.entry.perview').remove(); // Alte Einträge löschen + + $(viewEl).find('.toggle-nav-open-close').click( function() { + $('nav').toggleClass('open'); + }); + + $(viewEl).find('.toggle-nav-small').click( function() { + $('nav').toggleClass('small'); + }); + + $(viewEl).find('div.headermenu > a').each( function(idx,el) + { + // Jeden Untermenüpunkt zum Fenstermenü hinzufügen. + + // Nein, Untermenüs erscheinen jetzt in der View selbst. + // $(el).wrap('<div class="entry clickable modal perview" />').parent().appendTo( $(viewEl).closest('div.panel').find('div.header div.dropdown').first() ); + } ); + + $(viewEl).find('div.header > a.back').each( function(idx,el) + { + // Zurück-Knopf zum Fenstermenü hinzufügen. + $(el).removeClass('button').wrap('<div class="entry perview" />').parent().appendTo( $(viewEl).closest('div.panel').find('div.header div.dropdown').first() ); + } ); + //$(viewEl).find('div.header').html('<!-- moved to window-menu -->'); + +// $(viewEl).find('input,select,textarea').focus( function() { +// $(this).closest('div.panel').find('div.command').css('visibility','visible').fadeIn('slow'); +// }); + + + // Selectors (Einzel-Ausahl für Dateien) initialisieren + // Wurzel des Baums laden + $(viewEl).find('div.selector.tree').each( function() { + var selectorEl = this; + $(this).orTree( { type:'project',selectable:$(selectorEl).attr('data-types').split(','),id:$(selectorEl).attr('data-init-folderid'),onSelect:function(name,type,id) { + + var selector = $(selectorEl).parent(); + + //console.log( 'Selected: '+name+" #"+id ); + $(selector).find('input[type=text]' ).attr( 'value',name ); + $(selector).find('input[type=hidden]').attr( 'value',id ); + } }); + } ); + + + registerDragAndDrop(viewEl); + + + // Bei Änderungen in der View das Tab als 'dirty' markieren + $(viewEl).find('input').change( function() { + $(this).parent('div.view').addClass('dirty'); + }); + + // Theme-Auswahl mit Preview + $(viewEl).find('.or-theme-chooser').change( function() { + setUserStyle( this.value ); + }); + +} + + + +function registerDragAndDrop(viewEl) +{ + + registerDraggable(viewEl); + registerDroppable(viewEl); +} + + + + +function registerDraggable(viewEl) { + +// Drag n Drop: Inhaltselemente (Dateien,Seiten,Ordner,Verknuepfungen) koennen auf Ordner gezogen werden. + + $(viewEl).find('.or-draggable').draggable( + { + helper: 'clone', + opacity: 0.7, + zIndex: 2, + distance: 10, + cursor: 'move', + revert: 'false' + } + ); + +} + +function registerTreeBranchEvents(viewEl) +{ + registerDraggable(viewEl); +} + + +function registerDroppable(viewEl) { + + /* + $(viewEl).find('div.header > a.back').each( function(idx,el) { + $('div.content li.object > .entry[data-type=\'folder\']').droppable({ + accept: 'li.object', hoverClass: 'drophover', activeClass: 'dropactive', drop: function (event, ui) { + let dropped = ui.draggable; + let droppedOn = $(this).parent(); + + //alert('Moving '+$(dropped).attr('data-id')+' to folder '+$(droppedOn).attr('data-id') ); + startDialog($(this).text(), $(dropped).attr('data-type'), 'copy', $(droppedOn).attr('data-id'), { + 'action': $(dropped).attr('data-type'), + 'subaction': 'copy', + 'id': $(dropped).attr('data-id'), + 'targetFolderId': $(droppedOn).attr('data-id') + }); + //$(dropped).css({top: 0,left: 0}); // Nicht auf das eigene Fenster fallen lassen. + $(dropped).detach().css({top: 0, left: 0}).appendTo(droppedOn).click(); + } + }); + } +*/ + + $(viewEl).find('.or-droppable').droppable({ + accept: '.or-draggable', + hoverClass: 'or-droppable--hover', + activeClass: 'or-droppable--active', + + drop: function (event, ui) { + + let dropped = ui.draggable; + + $(this).find('.or-selector-link-value').val( dropped.data('id') ); + $(this).find('.or-selector-link-name' ).val( dropped.data('id') ); + // Id übertragen + //$(this).value(dropped.data('id')); + } + }); +} + + + +function registerMenuEvents($element ) +{ + //$e = $($element); + + // Mit der Maus irgendwo hin geklickt, das Menü muss schließen. + $('body').click( function() { + $('.toolbar-icon.menu').parents('.or-menu').removeClass('open'); + }); + // Mit der Maus geklicktes Menü aktivieren. + $($element).find('.toolbar-icon.menu').click( function(event) { + event.stopPropagation(); + $(this).parents('.or-menu').toggleClass('open'); + }); + + // Mit der Maus überstrichenes Menü aktivieren. + $($element).find('.toolbar-icon.menu').mouseover( function() { + + // close other menus. + $(this).parents('.or-menu').find('.toolbar-icon.menu').removeClass('open'); + // open the mouse-overed menu. + $(this).addClass('open'); + }); + +} + +function registerSearch($element ) +{ + //$e = $($element); + $($element).find('.search input').orSearch( { dropdown:'#title div.search div.dropdown' } ); + +} + + + +function registerTree(element) { + + // Klick-Funktionen zum Öffnen/Schließen des Zweiges. + $(element).find('.or-navtree-node').orTree(); + +} + + + +/** + * Schaltet die Vollbildfunktion an oder aus. + * + * @param element Das Element, auf dem die Vollbildfunktion ausgeführt wurde + */ +function fullscreen( element ) { + $(element).closest('div.panel').fadeOut('fast', function() + { + $(this).toggleClass('fullscreen').fadeIn('fast'); + } ); +} + + + + +/** + * Setzt neue View und aktualisiert alle Fenster. + * @param element + * @param action Action + * @param id Id + * @deprecated + */ + +function submitUrl( element,url ) +{ + postUrl( url,element ); + + // Alle refresh-fähigen Views mit dem neuen Objekt laden. + //refreshAllRefreshables(); +} + + +/** + * @deprecated + + * @param url + * @param element + */ +function postUrl(url,element) +{ + url += '&output=json'; + $.ajax( { 'type':'POST',url:url, data:{}, success:function(data, textStatus, jqXHR) + { + $('div.panel div.status div.loader').html('&nbsp;'); + doResponse(data,textStatus,element); + } } ); + +} + + + + + + +/** + * Setzt neuen modalen Dialog und aktualisiert alle Fenster. + * @param name + * @param action Action + * @param method + * @param id Id + * @param params + */ +function startDialog( name,action,method,id,params ) +{ + // Attribute aus dem aktuellen Editor holen, falls die Daten beim Aufrufer nicht angegeben sind. + if (!action) + action = $('#editor').attr('data-action'); + + if (!id) + id = $('#editor').attr('data-id'); + + let view = new View( action,method,id,params ); + + view.before = function() { + $('#dialog > .view').html('<div class="header"><img class="icon" title="" src="./themes/default/images/icon/'+method+'.png" />'+name+'</div>'); + $('#dialog > .view').data('id',id); + $('#dialog').removeClass('is-closed').addClass('is-open'); + + let view = this; + + this.escapeKeyClosingHandler = function (e) { + if (e.keyCode == 27) { // ESC keycode + view.close(); + + $(document).off('keyup'); // de-register. + } + }; + + $(document).keyup(this.escapeKeyClosingHandler); + + // Nicht-Modale Dialoge durch Klick auf freie Fläche schließen. + $('#dialog .filler').click( function() + { + view.close(); + }); + + } + + view.close = function() { + + // Strong modal dialogs are unable to close. + // Really? + if ( $('div#dialog').hasClass('modal') ) + return; + + $('#dialog .view').fadeOut('fast').html(''); + $('#dialog').removeClass('is-open').addClass('is-closed'); // Dialog schließen + + $(document).unbind('keyup',this.escapeKeyClosingHandler); // Cleanup ESC-Key-Listener + } + + view.start( $('div#dialog > .view') ); +} + + +/** + * Starts a non-modal editing dialog. + * @param name + * @param action + * @param method + * @param id + * @param params + */ +function startEdit( name,action,method,id,params ) +{ + // Attribute aus dem aktuellen Editor holen, falls die Daten beim Aufrufer nicht angegeben sind. + if (!action) + action = Workbench.state.action; + + if (!id) + id = Workbench.state.id; + + let view = new View( action,method,id,params ); + + view.before = function() { + + let view = this; + + $edit = $('#edit'); + $edit.addClass('is-open'); + + $('#editor').addClass('is-closed'); + + // Dialog durch Klick auf freie Fläche schließen. + $('#edit .filler').click( function() + { + view.close(); + }); + + }; + + view.close = function() { + $edit.removeClass('is-open'); + $('#editor').removeClass('is-closed'); + } + + view.start( $('#edit > .view') ); +} + + +/** + * Setzt einen Fenster-Titel für die ganze Anwendung. + */ +function setTitle( title ) +{ + if ( title ) + $('head > title').text( title + ' - ' + $('head > title').data('default') ); + else + $('head > title').text( $('head > title').data('default') ); +} + +/** + * Setzt neue Action und aktualisiert alle Fenster. + * + * @param action Action + * @param id Id + */ +function openNewAction( name,action,id,extraId ) +{ + // Im Mobilmodus soll das Menü verschwinden, wenn eine neue Action geoeffnet wird. + $('nav').removeClass('open'); + + setTitle( name ); // Title setzen. + + setNewAction( action,id,extraId ); +} + + +function filterMenus() +{ + let action = Workbench.state.action; + let id = Workbench.state.id; + $('div.clickable').addClass('active'); + $('div.clickable.filtered').removeClass('active').addClass('inactive'); + + $('div.clickable.filtered.on-action-'+action).addClass('active').removeClass('inactive'); + + // Jeder Menüeintrag bekommt die Id und Parameter. + $('div.clickable.filtered a').attr('data-id' ,id ); + /* + $('div.clickable.filtered a').attr('data-action',action); + */ + +} + + + +/** + * Setzt neue Action und aktualisiert alle Fenster. + * + * @param action Action + * @param id Id + */ +function setNewAction( action,id,extraId ) +{ + Navigator.navigateToNewAction(action,'edit',id,extraId); + // Alle refresh-fähigen Views mit dem neuen Objekt laden. + //refreshAllRefreshables(); +} + + +/** + * Setzt neue Id und aktualisiert alle Fenster. + * @param id Id + */ +function setNewId( id ) { +} + + + + + +/** + * Notification im Browser anzeigen. + * Quelle: https://developer.mozilla.org/en-US/docs/Web/API/notification + * @param text Text der Nachricht. + */ +function notifyBrowser(text) +{ + // Let's check if the browser supports notifications + if (!("Notification" in window)) { + return; + //alert("This browser does not support desktop notification"); + } + + // Let's check if the user is okay to get some notification + else if (Notification.permission === "granted") { + // If it's okay let's create a notification + let notification = new Notification(text); + } + + // Otherwise, we need to ask the user for permission + else if (Notification.permission !== 'denied') { + Notification.requestPermission(function (permission) { + // If the user is okay, let's create a notification + if (permission === "granted") { + let notification = new Notification(text); + } + }); + } + + // At last, if the user already denied any notification, and you + // want to be respectful there is no need to bother them any more. +} + + + +/** + * Setzt einen neuen Theme. + * @param styleName + * @returns + */ +function setUserStyle( styleName ) +{ + var html = $('html'); + var classList = html.attr('class').split(/\s+/); + $.each(classList, function(index, item) { + if (item.startsWith('theme-')) { + html.removeClass(item); + } + }); + html.addClass( 'theme-' + styleName.toLowerCase() ); +} + + + + +//Quelle: +//http://aktuell.de.selfhtml.org/tippstricks/javascript/bbcode/ +function insert(tagName, aTag, eTag) +{ +var input = document.forms[0].elements[tagName]; +input.focus(); +/* IE */ +if(typeof document.selection != 'undefined') { + /* Einfuegen des Formatierungscodes */ +// alert('IE'); + var range = document.selection.createRange(); + var insText = range.text; + range.text = aTag + insText + eTag; + /* Anpassen der Cursorposition */ + range = document.selection.createRange(); + if (insText.length == 0) { + range.move('character', -eTag.length); + } else { + range.moveStart('character', aTag.length + insText.length + eTag.length); + } + range.select(); +} +/* Gecko */ +else if(typeof input.selectionStart != 'undefined') +{ +// alert('Gecko'); + /* Einfuegen des Formatierungscodes */ + var start = input.selectionStart; + var end = input.selectionEnd; + var insText = input.value.substring(start, end); + input.value = input.value.substr(0, start) + aTag + insText + eTag + input.value.substr(end); + /* Anpassen der Cursorposition */ + var pos; + if (insText.length == 0) { + pos = start + aTag.length; + } else { + pos = start + aTag.length + insText.length + eTag.length; + } + input.selectionStart = pos; + input.selectionEnd = pos; +} +/* uebrige Browser */ +else +{ + /* Abfrage der Einfuegeposition */ + + /* + var pos; + var re = new RegExp('^[0-9]{0,3}$'); + while(!re.test(pos)) { + pos = prompt("Position (0.." + input.value.length + "):", "0"); + } + if(pos > input.value.length) { + pos = input.value.length; + } + */ + pos = input.value.length; + + /* Einfuegen des Formatierungscodes */ + var insText = prompt("Text"); + input.value = input.value.substr(0, pos) + aTag + insText + eTag + input.value.substr(pos); +} +} + + + + +/** + * Erzeugt eine URL, um die gewünschte Action vom Server zu laden. + * + * @param action + * @param subaction + * @param id + * @param extraid + * @returns URL + */ +function createUrl(action,subaction,id,extraid,embed) +{ + var url = './'; + + url += '?'; + + if(action) + url += '&action='+action; + if(subaction) + url += '&subaction='+subaction; + if(id) + url += '&id='+id; + + if ( typeof extraid === 'string') + { + extraid = extraid.replace(/'/g,'"'); // Replace ' with ". + var extraObject = jQuery.parseJSON(extraid); + jQuery.each(extraObject, function(name, value) { + url = url + '&' + name + '=' + value; + }); + } + else if ( typeof extraid === 'object') + { + jQuery.each(extraid, function(name, field) { + url = url + '&' + name + '=' + field; + }); + } + else + { + } + return url; +} + + +/** + * Setzt Breite/Höhe für einen Container in der Workbench. + * + * Sind weitere Container enthalten, werden diese rekursiv angepasst. + * + * @param container + */ +function resizeWorkbenchContainer( container ) +{ +} + + + +/** + * Fenstergröße wurde verändert, nun die Größe der DIVs neu berechnen. + */ +function resizeWorkbench() +{ +} + + +/** + * Größe der TABs pro Frame neu berechnen. + */ +function resizeTabs( panel ) +{ +} + + +function help(el,url,suffix) +{ + var action = $(el).closest('div.panel').find('li.action.active').attr('data-action'); + var method = $(el).closest('div.panel').find('li.action.active').attr('data-method'); + + window.open(url + action + '/'+ method + suffix, 'OpenRat_Help', 'location=no,menubar=no,scrollbars=yes,toolbar=no,resizable=yes'); +} + + +/** + * Show a notice bubble in the UI. + * @param type + * @param name + * @param status + * @param msg + * @param log + */ +function notify( type,name,status,msg,log=[] ) +{ + // Notice-Bar mit dieser Meldung erweitern. + + let notice = $('<div class="notice '+status+'"></div>'); + + let toolbar = $('<div class="or-notice-toolbar"></div>'); + if ( log.length ) + $(toolbar).append('<i class="or-action-full image-icon image-icon--menu-fullscreen"></i>'); + $(toolbar).append('<i class="or-action-close image-icon image-icon--menu-close"></i>'); + $(notice).append(toolbar); + + id = 0; // TODO + if (name) + $(notice).append('<div class="name clickable"><a href="" data-type="open" data-action="'+type+'" data-id="'+id+'"><i class="or-action-full image-icon image-icon--action-'+type+'"></i> '+name+'</a></div>'); + + $(notice).append( '<div class="text">'+htmlEntities(msg)+'</div>'); + + if (log.length) { + + let logLi = log.reduce((result, item) => { + result += '<li><pre>'+htmlEntities(item)+'</pre></li>'; + return result; + }, ''); + $(notice).append('<div class="log"><ul>'+logLi+'</ul></div>'); + } + + $('#noticebar').prepend(notice); // Notice anhängen. + $(notice).orLinkify(); // Enable links + + + // Toogle Fullscreen for notice + $(notice).find('.or-action-full').click( function() { + $(notice).toggleClass('full'); + }); + + // Close the notice on click + $(notice).find('.or-action-close').click( function() { + $(notice).fadeOut('fast',function() { $(notice).remove(); } ); + }); + + // Fadeout the notice after a while. + let timeout = 1; + if ( status == 'ok' ) timeout = 20; + if ( status == 'info' ) timeout = 60; + if ( status == 'warning') timeout = 120; + if ( status == 'error' ) timeout = 120; + + if (timeout > 0) + setTimeout( function() { + $(notice).fadeOut('slow', function() { $(this).remove(); } ); + },timeout*1000 ); +} + + +function htmlEntities(str) { + return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;'); +} + +function registerOpenClose( $el ) +{ + $($el).children('.on-click-open-close').click( function() { + $(this).closest('.toggle-open-close').toggleClass('open closed'); + }); + +}+ \ No newline at end of file diff --git a/modules/cms-ui/themes/default/script/openrat/common.min.js b/modules/cms-ui/themes/default/script/openrat/common.min.js @@ -0,0 +1,9 @@ +;var OR_THEMES_EXT_DIR='modules/cms-ui/themes/';$(function(){$('html').removeClass('nojs');$('.initial-hidden').removeClass('initial-hidden');registerWorkbenchEvents();window.onpopstate=function(e){Navigator.navigateTo(e.state)};initActualHistoryState();Workbench.initialize();Workbench.reloadAll();registerNavigation();$('.keystroke').each(function(){let keystrokeElement=$(this);let keystroke=keystrokeElement.text();if(keystroke.length==0)return;let keyaction=function(){keystrokeElement.click()};$(document).bind('keydown',keystroke,keyaction)});$('#noticebar .notice .image-icon--menu-close').click(function(){$(this).closest('.notice').fadeOut('fast',function(){$(this).remove()})});$('#noticebar .notice').each(function(){let noticeToClose=this;setTimeout(function(){$(noticeToClose).fadeOut('slow',function(){$(this).remove()})},30*1000)});registerOpenClose($('section.toggle-open-close'));$('section.toggle-open-close .on-click-open-close').click(function(){var t=$(this).closest('section');if(t.hasClass('disabled'))return;var e=t.find('div.view-loader');if(e.children().length==0)Workbench.loadNewActionIntoElement(e)})});function initActualHistoryState(){var t={};t.name=window.document.title;var e=new URLSearchParams(window.location.search);if(e.has('action')){t.action=e.get('action');t.id=e.get('id');t.name=window.document.title;t.data={};var e=Array.from(e.entries());for(var i in e){t.data[e[i][0]]=e[i][1]};Navigator.toActualHistory(t)}};function registerNavigation(){$(document).on('orNewAction',function(e,t){let url='./api/?action=tree&subaction=path&id='+Workbench.state.id+'&type='+Workbench.state.action+'&output=json';$.getJSON(url,function(e){$('nav .or-navtree-node').removeClass('or-navtree-node--selected');let output=e['output'];$.each(output.path,function(e,t){$nav=$('nav .or-navtree-node[data-type='+t.type+'][data-id='+t.id+'].or-navtree-node--is-closed .or-navtree-node-control');$nav.click()});if(output.actual)$('nav .or-navtree-node[data-type='+output.actual.type+'][data-id='+output.actual.id+']').addClass('or-navtree-node--selected')}).fail(function(e){console.warn(e);console.warn('failed to load path from '+url)}).always(function(){})})};function registerWorkbenchEvents(){$('div.header').dblclick(function(){fullscreen(this)})};function loadView(e,t,i,n,o){Navigator.navigateToNewAction(t,i,n,o)};function afterViewLoaded(e){var t=$(e).closest('section');t.toggleClass('is-empty',$(e).is(':empty'));$(e).trigger('orViewLoaded');$(e).closest('div.panel').find('div.header div.dropdown div.entry.perview').remove();$(e).find('.toggle-nav-open-close').click(function(){$('nav').toggleClass('open')});$(e).find('.toggle-nav-small').click(function(){$('nav').toggleClass('small')});$(e).find('div.headermenu > a').each(function(e,t){});$(e).find('div.header > a.back').each(function(t,i){$(i).removeClass('button').wrap('<div class="entry perview" />').parent().appendTo($(e).closest('div.panel').find('div.header div.dropdown').first())});$(e).find('div.selector.tree').each(function(){var e=this;$(this).orTree({type:'project',selectable:$(e).attr('data-types').split(','),id:$(e).attr('data-init-folderid'),onSelect:function(t,i,n){var o=$(e).parent();$(o).find('input[type=text]').attr('value',t);$(o).find('input[type=hidden]').attr('value',n)}})});registerDragAndDrop(e);$(e).find('input').change(function(){$(this).parent('div.view').addClass('dirty')});$(e).find('.or-theme-chooser').change(function(){setUserStyle(this.value)})};function registerDragAndDrop(e){registerDraggable(e);registerDroppable(e)};function registerDraggable(e){$(e).find('.or-draggable').draggable({helper:'clone',opacity:0.7,zIndex:2,distance:10,cursor:'move',revert:'false'})};function registerTreeBranchEvents(e){registerDraggable(e)};function registerDroppable(e){$(e).find('.or-droppable').droppable({accept:'.or-draggable',hoverClass:'or-droppable--hover',activeClass:'or-droppable--active',drop:function(e,t){let dropped=t.draggable;$(this).find('.or-selector-link-value').val(dropped.data('id'));$(this).find('.or-selector-link-name').val(dropped.data('id'))}})};function registerMenuEvents(e){$('body').click(function(){$('.toolbar-icon.menu').parents('.or-menu').removeClass('open')});$(e).find('.toolbar-icon.menu').click(function(e){e.stopPropagation();$(this).parents('.or-menu').toggleClass('open')});$(e).find('.toolbar-icon.menu').mouseover(function(){$(this).parents('.or-menu').find('.toolbar-icon.menu').removeClass('open');$(this).addClass('open')})};function registerSearch(e){$(e).find('.search input').orSearch({dropdown:'#title div.search div.dropdown'})};function registerTree(e){$(e).find('.or-navtree-node').orTree()};function fullscreen(e){$(e).closest('div.panel').fadeOut('fast',function(){$(this).toggleClass('fullscreen').fadeIn('fast')})};function submitUrl(e,t){postUrl(t,e)};function postUrl(e,t){e+='&output=json';$.ajax({'type':'POST',url:e,data:{},success:function(e,i,n){$('div.panel div.status div.loader').html('&nbsp;');doResponse(e,i,t)}})};function startDialog(e,t,i,n,o){if(!t)t=$('#editor').attr('data-action');if(!n)n=$('#editor').attr('data-id');let view=new View(t,i,n,o);view.before=function(){$('#dialog > .view').html('<div class="header"><img class="icon" title="" src="./themes/default/images/icon/'+i+'.png" />'+e+'</div>');$('#dialog > .view').data('id',n);$('#dialog').removeClass('is-closed').addClass('is-open');let view=this;this.escapeKeyClosingHandler=function(e){if(e.keyCode==27){view.close();$(document).off('keyup')}};$(document).keyup(this.escapeKeyClosingHandler);$('#dialog .filler').click(function(){view.close()})};view.close=function(){if($('div#dialog').hasClass('modal'))return;$('#dialog .view').fadeOut('fast').html('');$('#dialog').removeClass('is-open').addClass('is-closed');$(document).unbind('keyup',this.escapeKeyClosingHandler)};view.start($('div#dialog > .view'))};function startEdit(e,t,i,n,o){if(!t)t=Workbench.state.action;if(!n)n=Workbench.state.id;let view=new View(t,i,n,o);view.before=function(){let view=this;$edit=$('#edit');$edit.addClass('is-open');$('#editor').addClass('is-closed');$('#edit .filler').click(function(){view.close()})};view.close=function(){$edit.removeClass('is-open');$('#editor').removeClass('is-closed')};view.start($('#edit > .view'))};function setTitle(e){if(e)$('head > title').text(e+' - '+$('head > title').data('default'));else $('head > title').text($('head > title').data('default'))};function openNewAction(e,t,i,n){$('nav').removeClass('open');setTitle(e);setNewAction(t,i,n)};function filterMenus(){let action=Workbench.state.action;let id=Workbench.state.id;$('div.clickable').addClass('active');$('div.clickable.filtered').removeClass('active').addClass('inactive');$('div.clickable.filtered.on-action-'+action).addClass('active').removeClass('inactive');$('div.clickable.filtered a').attr('data-id',id)};function setNewAction(e,t,i){Navigator.navigateToNewAction(e,'edit',t,i)};function setNewId(e){};function notifyBrowser(e){if(!('Notification' in window)){return} +else if(Notification.permission==='granted'){let notification=new Notification(e)} +else if(Notification.permission!=='denied'){Notification.requestPermission(function(t){if(t==='granted'){let notification=new Notification(e)}})}};function setUserStyle(e){var t=$('html'),i=t.attr('class').split(/\s+/);$.each(i,function(e,i){if(i.startsWith('theme-')){t.removeClass(i)}});t.addClass('theme-'+e.toLowerCase())};function insert(e,t,i){var n=document.forms[0].elements[e];n.focus();if(typeof document.selection!='undefined'){var l=document.selection.createRange(),o=l.text;l.text=t+o+i;l=document.selection.createRange();if(o.length==0){l.move('character',-i.length)} +else{l.moveStart('character',t.length+o.length+i.length)};l.select()} +else if(typeof n.selectionStart!='undefined'){var s=n.selectionStart,c=n.selectionEnd,o=n.value.substring(s,c);n.value=n.value.substr(0,s)+t+o+i+n.value.substr(c);var a;if(o.length==0){a=s+t.length} +else{a=s+t.length+o.length+i.length};n.selectionStart=a;n.selectionEnd=a} +else{a=n.value.length;var o=prompt('Text');n.value=n.value.substr(0,a)+t+o+i+n.value.substr(a)}};function createUrl(e,t,i,n,a){var o='./';o+='?';if(e)o+='&action='+e;if(t)o+='&subaction='+t;if(i)o+='&id='+i;if(typeof n==='string'){n=n.replace(/'/g,'"');var l=jQuery.parseJSON(n);jQuery.each(l,function(e,t){o=o+'&'+e+'='+t})} +else if(typeof n==='object'){jQuery.each(n,function(e,t){o=o+'&'+e+'='+t})} +else{};return o};function resizeWorkbenchContainer(e){};function resizeWorkbench(){};function resizeTabs(e){};function help(e,t,i){var n=$(e).closest('div.panel').find('li.action.active').attr('data-action'),o=$(e).closest('div.panel').find('li.action.active').attr('data-method');window.open(t+n+'/'+o+i,'OpenRat_Help','location=no,menubar=no,scrollbars=yes,toolbar=no,resizable=yes')};function notify(e,t,i,n,log=[]){let notice=$('<div class="notice '+i+'"></div>');let toolbar=$('<div class="or-notice-toolbar"></div>');if(log.length)$(toolbar).append('<i class="or-action-full image-icon image-icon--menu-fullscreen"></i>');$(toolbar).append('<i class="or-action-close image-icon image-icon--menu-close"></i>');$(notice).append(toolbar);id=0;if(t)$(notice).append('<div class="name clickable"><a href="" data-type="open" data-action="'+e+'" data-id="'+id+'"><i class="or-action-full image-icon image-icon--action-'+e+'"></i> '+t+'</a></div>');$(notice).append('<div class="text">'+htmlEntities(n)+'</div>');if(log.length){let logLi=log.reduce((result,item)=>{result+='<li><pre>'+htmlEntities(item)+'</pre></li>';return result},'');$(notice).append('<div class="log"><ul>'+logLi+'</ul></div>')};$('#noticebar').prepend(notice);$(notice).orLinkify();$(notice).find('.or-action-full').click(function(){$(notice).toggleClass('full')});$(notice).find('.or-action-close').click(function(){$(notice).fadeOut('fast',function(){$(notice).remove()})});let timeout=1;if(i=='ok')timeout=20;if(i=='info')timeout=60;if(i=='warning')timeout=120;if(i=='error')timeout=120;if(timeout>0)setTimeout(function(){$(notice).fadeOut('slow',function(){$(this).remove()})},timeout*1000)};function htmlEntities(e){return String(e).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;')};function registerOpenClose(e){$(e).children('.on-click-open-close').click(function(){$(this).closest('.toggle-open-close').toggleClass('open closed')})};+ \ No newline at end of file diff --git a/modules/cms-ui/themes/default/script/openrat/form.js b/modules/cms-ui/themes/default/script/openrat/form.js @@ -0,0 +1,152 @@ + +/** + * Form. + * + * @constructor + */ +function Form() { + + this.setLoadStatus = function( isLoading ) { + $(this.element).closest('div.content').toggleClass('loader',isLoading); + } + + this.initOnElement = function( element ) { + this.element = element; + + let form = this; + + // Autosave in Formularen. + // Bei Veränderungen von Checkboxen wird das Formular sofort abgeschickt. + $(element).find('form[data-autosave="true"] input[type="checkbox"]').click( function() { + form.submit(); + }); + + // After click to "OK" the form is submitted. + // Why this?? input type=submit will submit! + /* + $(event.target).find('input.submit.ok').click( function() { + $(this).closest('form').submit(); + }); + */ + + $(element).find('.or-form-btn--cancel').click( function() { + form.cancel(); + + }); + $(element).find('.or-form-btn--reset').click( function() { + form.rollback(); + + }); + + // Submithandler for the whole form. + $(element).submit( function( event ) { + + // + if ($(this).data('target')=='view') + { + form.submit(); + event.preventDefault(); + } + // target=top will load the native way without javascript. + }); + } + + this.cancel = function() { + //$(this.element).html('').parent().removeClass('is-open'); + this.close(); + } + + + this.rollback = function() { + this.element.trigger('reset'); + } + + this.close = function() { + + } + + this.submit = function() { + + + // Show progress + let status = $('<div class="notice info"><div class="text loader"></div></div>'); + $('#noticebar').prepend(status); // Notice anhängen. + $(status).show(); + + // Alle vorhandenen Error-Marker entfernen. + // Falls wieder ein Fehler auftritt, werden diese erneut gesetzt. + $(this.element).find('.error').removeClass('error'); + + var params = $(this.element).serializeArray(); + var data = {}; + $(params).each(function(index, obj){ + data[obj.name] = obj.value; + }); + + // If form does not contain action/id, get it from the workbench. + if (!data.id) + data.id = Workbench.state.id; + if (!data.action) + data.action = Workbench.state.action; + + let formMethod = $(this.element).attr('method').toUpperCase(); + + if ( formMethod == 'GET' ) + { + // Mehrseitiges Formular + // Die eingegebenen Formulardaten werden zur nächsten Action geschickt. + //Workbench.loadViewIntoElement( $(form).parent('.view'),data.action, data.subaction,data.id,data ); + this.forwardTo( data.action, data.subaction,data.id,data ); + } + else + { + let url = './api/'; // Alle Parameter befinden sich im Formular + + // POST-Request + this.setLoadStatus(true); + //url += '?output=json'; + url += ''; + //params['output'] = 'json';// Irgendwie geht das nicht. + data.output = 'json'; + + if ( $(this.element).data('async') || $(this.element).data('async')=='true') + { + // Verarbeitung erfolgt asynchron, das heißt, dass der evtl. geöffnete Dialog + // beendet wird. + this.close(); + // Async: Window is closed, but the action will be startet now. + } + + let form = this; + $.ajax( { 'type':'POST',url:url, data:data, success:function(data, textStatus, jqXHR) + { + form.setLoadStatus(false); + $(status).remove(); + + doResponse(data,textStatus,form.element); + }, + error:function(jqXHR, textStatus, errorThrown) { + form.setLoadStatus(false); + $(status).remove(); + + try + { + let error = jQuery.parseJSON( jqXHR.responseText ); + notify('','','error',error.error,[error.description]); + } + catch( e ) + { + let msg = jqXHR.responseText; + notify('','','error','Server Error',[msg]); + } + + + } + + } ); + $(form.element).fadeIn(); + } + + } +} + diff --git a/modules/cms-ui/themes/default/script/openrat/form.min.js b/modules/cms-ui/themes/default/script/openrat/form.min.js @@ -0,0 +1,152 @@ + +/** + * Form. + * + * @constructor + */ +function Form() { + + this.setLoadStatus = function( isLoading ) { + $(this.element).closest('div.content').toggleClass('loader',isLoading); + } + + this.initOnElement = function( element ) { + this.element = element; + + let form = this; + + // Autosave in Formularen. + // Bei Veränderungen von Checkboxen wird das Formular sofort abgeschickt. + $(element).find('form[data-autosave="true"] input[type="checkbox"]').click( function() { + form.submit(); + }); + + // After click to "OK" the form is submitted. + // Why this?? input type=submit will submit! + /* + $(event.target).find('input.submit.ok').click( function() { + $(this).closest('form').submit(); + }); + */ + + $(element).find('.or-form-btn--cancel').click( function() { + form.cancel(); + + }); + $(element).find('.or-form-btn--reset').click( function() { + form.rollback(); + + }); + + // Submithandler for the whole form. + $(element).submit( function( event ) { + + // + if ($(this).data('target')=='view') + { + form.submit(); + event.preventDefault(); + } + // target=top will load the native way without javascript. + }); + } + + this.cancel = function() { + //$(this.element).html('').parent().removeClass('is-open'); + this.close(); + } + + + this.rollback = function() { + this.element.trigger('reset'); + } + + this.close = function() { + + } + + this.submit = function() { + + + // Show progress + let status = $('<div class="notice info"><div class="text loader"></div></div>'); + $('#noticebar').prepend(status); // Notice anhängen. + $(status).show(); + + // Alle vorhandenen Error-Marker entfernen. + // Falls wieder ein Fehler auftritt, werden diese erneut gesetzt. + $(this.element).find('.error').removeClass('error'); + + var params = $(this.element).serializeArray(); + var data = {}; + $(params).each(function(index, obj){ + data[obj.name] = obj.value; + }); + + // If form does not contain action/id, get it from the workbench. + if (!data.id) + data.id = Workbench.state.id; + if (!data.action) + data.action = Workbench.state.action; + + let formMethod = $(this.element).attr('method').toUpperCase(); + + if ( formMethod == 'GET' ) + { + // Mehrseitiges Formular + // Die eingegebenen Formulardaten werden zur nächsten Action geschickt. + //Workbench.loadViewIntoElement( $(form).parent('.view'),data.action, data.subaction,data.id,data ); + this.forwardTo( data.action, data.subaction,data.id,data ); + } + else + { + let url = './api/'; // Alle Parameter befinden sich im Formular + + // POST-Request + this.setLoadStatus(true); + //url += '?output=json'; + url += ''; + //params['output'] = 'json';// Irgendwie geht das nicht. + data.output = 'json'; + + if ( $(this.element).data('async') || $(this.element).data('async')=='true') + { + // Verarbeitung erfolgt asynchron, das heißt, dass der evtl. geöffnete Dialog + // beendet wird. + this.close(); + // Async: Window is closed, but the action will be startet now. + } + + let form = this; + $.ajax( { 'type':'POST',url:url, data:data, success:function(data, textStatus, jqXHR) + { + form.setLoadStatus(false); + $(status).remove(); + + doResponse(data,textStatus,form.element); + }, + error:function(jqXHR, textStatus, errorThrown) { + form.setLoadStatus(false); + $(status).remove(); + + try + { + let error = jQuery.parseJSON( jqXHR.responseText ); + notify('','','error',error.error,[error.description]); + } + catch( e ) + { + let msg = jqXHR.responseText; + notify('','','error','Server Error',[msg]); + } + + + } + + } ); + $(form.element).fadeIn(); + } + + } +} + diff --git a/modules/cms-ui/themes/default/script/openrat/init.js b/modules/cms-ui/themes/default/script/openrat/init.js @@ -0,0 +1,4 @@ + +// Create own namespace. + +window.openrat = {}; diff --git a/modules/cms-ui/themes/default/script/openrat/init.min.js b/modules/cms-ui/themes/default/script/openrat/init.min.js @@ -0,0 +1,4 @@ + +// Create own namespace. + +window.openrat = {}; diff --git a/modules/cms-ui/themes/default/script/openrat/navigator.js b/modules/cms-ui/themes/default/script/openrat/navigator.js @@ -0,0 +1,39 @@ +/** + * Navigation. + */ +var Navigator = new function () { + 'use strict'; + + /** + * Navigiert zu einer Action, aber ohne ein neues History-Element einzufügen. + */ + this.navigateTo = function(state) { + Workbench.loadNewActionState(state); + } + + + /** + * + * Navigiert zu einer neue Action und fügt einen neuen History-Eintrag hinzu. + */ + this.navigateToNew = function(obj) { + + Workbench.loadNewActionState(obj); + window.history.pushState(obj,obj.name,'./#/'+obj.action+(obj.id?'/'+obj.id:'') ); + } + + this.navigateToNewAction = function(action, method, id, params ) { + var state = {action:action,method:method,id:id.replace(/[^0-9_]/gim,""),data:params}; + this.navigateToNew(state); + } + + /** + * Setzt den State für den aktuellen History-Eintrag. + * @param obj + */ + this.toActualHistory = function(obj) { + window.history.replaceState(obj,obj.name,createUrl(obj.action,null,obj.id,obj.data,false) ); + } +} + +openrat.navigator = Navigator;+ \ No newline at end of file diff --git a/modules/cms-ui/themes/default/script/openrat/navigator.min.js b/modules/cms-ui/themes/default/script/openrat/navigator.min.js @@ -0,0 +1,39 @@ +/** + * Navigation. + */ +var Navigator = new function () { + 'use strict'; + + /** + * Navigiert zu einer Action, aber ohne ein neues History-Element einzufügen. + */ + this.navigateTo = function(state) { + Workbench.loadNewActionState(state); + } + + + /** + * + * Navigiert zu einer neue Action und fügt einen neuen History-Eintrag hinzu. + */ + this.navigateToNew = function(obj) { + + Workbench.loadNewActionState(obj); + window.history.pushState(obj,obj.name,'./#/'+obj.action+(obj.id?'/'+obj.id:'') ); + } + + this.navigateToNewAction = function(action, method, id, params ) { + var state = {action:action,method:method,id:id.replace(/[^0-9_]/gim,""),data:params}; + this.navigateToNew(state); + } + + /** + * Setzt den State für den aktuellen History-Eintrag. + * @param obj + */ + this.toActualHistory = function(obj) { + window.history.replaceState(obj,obj.name,createUrl(obj.action,null,obj.id,obj.data,false) ); + } +} + +openrat.navigator = Navigator;+ \ No newline at end of file diff --git a/modules/cms-ui/themes/default/script/openrat/view.js b/modules/cms-ui/themes/default/script/openrat/view.js @@ -0,0 +1,80 @@ +/** + * View. + * Eine View ist ein HTML-Fragment, in das eine Action geladen wird. + * Das Erzeugen der View, das Laden vom Server sowie das Schließen sind hier gekapselt. + * + * @param action + * @param method + * @param id + * @param params + * @constructor + */ +function View( action,method,id,params ) { + + this.action = action; + this.method = method; + this.id = id; + this.params = params; + + this.before = function() {}; + + this.start = function( element ) { + this.before(); + this.element = element; + this.loadView(); + } + + this.afterLoad = function() { + + } + + this.close = function() { + } + + + function registerViewEvents(element) { + + registerMenuEvents( element ); + registerSearch ( element ); + registerTree ( element ); + afterViewLoaded ( element ); + + } + + + this.loadView = function() { + + let url = createUrl( this.action,this.method,this.id,this.params,true); // URL für das Laden erzeugen. + let element = this.element; + let view = this; + + $(this.element).empty().fadeTo(1,0.7).addClass('loader').html('').load(url,function(response, status, xhr) { + + $(element).fadeTo(350,1); + + $(element).removeClass("loader"); + + $(element).find('form').each( function() { + let form = new Form(); + form.close = function() { + view.close(); + } + form.initOnElement(this); + + }); + if ( status == "error" ) + { + // Seite nicht gefunden. + $(element).html(""); + + notify('','','error','Server Error',['Server Error while requesting url '+url, response]); + return; + } + + registerViewEvents( element ); + + }); + + } + +} diff --git a/modules/cms-ui/themes/default/script/openrat/view.min.js b/modules/cms-ui/themes/default/script/openrat/view.min.js @@ -0,0 +1,80 @@ +/** + * View. + * Eine View ist ein HTML-Fragment, in das eine Action geladen wird. + * Das Erzeugen der View, das Laden vom Server sowie das Schließen sind hier gekapselt. + * + * @param action + * @param method + * @param id + * @param params + * @constructor + */ +function View( action,method,id,params ) { + + this.action = action; + this.method = method; + this.id = id; + this.params = params; + + this.before = function() {}; + + this.start = function( element ) { + this.before(); + this.element = element; + this.loadView(); + } + + this.afterLoad = function() { + + } + + this.close = function() { + } + + + function registerViewEvents(element) { + + registerMenuEvents( element ); + registerSearch ( element ); + registerTree ( element ); + afterViewLoaded ( element ); + + } + + + this.loadView = function() { + + let url = createUrl( this.action,this.method,this.id,this.params,true); // URL für das Laden erzeugen. + let element = this.element; + let view = this; + + $(this.element).empty().fadeTo(1,0.7).addClass('loader').html('').load(url,function(response, status, xhr) { + + $(element).fadeTo(350,1); + + $(element).removeClass("loader"); + + $(element).find('form').each( function() { + let form = new Form(); + form.close = function() { + view.close(); + } + form.initOnElement(this); + + }); + if ( status == "error" ) + { + // Seite nicht gefunden. + $(element).html(""); + + notify('','','error','Server Error',['Server Error while requesting url '+url, response]); + return; + } + + registerViewEvents( element ); + + }); + + } + +} diff --git a/modules/cms-ui/themes/default/script/openrat/workbench.js b/modules/cms-ui/themes/default/script/openrat/workbench.js @@ -0,0 +1,170 @@ + + +var Workbench = new function() +{ + 'use strict'; // Strict mode + + + /** + * Initializes the Workbench. + */ + this.initialize = function() { + + // Initialze Ping timer. + this.initializePingTimer(); + this.initializeState(); + this.initializeMenues(); + this.openModalDialog(); + } + + + /** + * Starts a dialog, if necessary. + */ + this.openModalDialog = function () { + + if ( $('#dialog').data('action') ) { + startDialog('',$('#dialog').data('action'),$('#dialog').data('action'),0,{}) + } + } + + + this.initializeMenues = function () { + + filterMenus(); + } + + + /** + * Sets the workbench state with action/id. + * + * Example: #/name/1 is translated to the state {action:name,id:1} + */ + this.initializeState = function () { + + let parts = window.location.hash.split('/'); + let state = { action:'index',id:0 }; + + if ( parts.length >= 2 ) + state.action = parts[1].toLowerCase(); + + if ( parts.length >= 3 ) + // Only numbers and '_' allowed in the id. + state.id = parts[2].replace(/[^0-9_]/gim,""); + + Workbench.state = state; + + // TODO: Remove this sometimes.... only state. + $('#editor').attr('data-action',state.action); + $('#editor').attr('data-id' ,state.id ); + $('#editor').attr('data-extra' ,'{}' ); + + } + + /** + * Registriert den Ping-Timer für den Sitzungserhalt. + */ + this.initializePingTimer = function() { + + /** + * Ping den Server. Führt keine Aktion aus, aber sorgt dafür, dass die Sitzung erhalten bleibt. + * + * "Geben Sie mir ein Ping, Vasily. Und bitte nur ein einziges Ping!" (aus: Jagd auf Roter Oktober) + */ + var ping = function() + { + $.ajax( createUrl('title','ping',0) ); + //window.console && console.log("session-ping"); + } + + // Alle 5 Minuten pingen. + var timeoutMinutes = 5; + + window.setInterval( ping, timeoutMinutes*60*1000 ); + } + + + + this.loadNewActionState = function(state) { + + Workbench.state = state; + Workbench.loadNewAction(state.action,state.id,state.data); + + + filterMenus(); + + $(document).trigger('orNewAction'); + } + + /** + * + */ + + this.loadNewAction = function(action, id, params ) { + + $('#editor').attr('data-action',action); + $('#editor').attr('data-id' ,id ); + $('#editor').attr('data-extra' ,JSON.stringify(params)); + + this.reloadViews(); + } + + + /** + * + */ + + this.reloadViews = function() { + + // View in geschlossenen Sektionen löschen, damit diese nicht stehen bleiben. + $('#workbench section.closed .view-loader').empty(); + + Workbench.loadViews( $('#workbench section.open .view-loader') ); + } + + + this.reloadAll = function() { + + // View in geschlossenen Sektionen löschen, damit diese nicht stehen bleiben. + $('#workbench .view').empty(); + + Workbench.loadViews( $('#workbench .view') ); + } + + + + this.loadViews = function( $views ) + { + + $views.each(function (idx) { + + let $targetDOMElement = $(this); + + Workbench.loadNewActionIntoElement( $targetDOMElement ) + }); + } + + + + this.loadNewActionIntoElement = function( $viewElement ) + { + let action; + if ( $viewElement.is('.view-static') ) + // Static views have always the same action. + action = $viewElement.attr('data-action'); + else + action = $('#editor').attr('data-action'); + + let id = $('#editor').attr('data-id' ); + let params = $('#editor').attr('data-extra' ); + + let method = $viewElement.data('method'); + + let view = new View( action,method,id,params ); + view.start( $viewElement ); + } + + +} + + diff --git a/modules/cms-ui/themes/default/script/openrat/workbench.min.js b/modules/cms-ui/themes/default/script/openrat/workbench.min.js @@ -0,0 +1,170 @@ + + +var Workbench = new function() +{ + 'use strict'; // Strict mode + + + /** + * Initializes the Workbench. + */ + this.initialize = function() { + + // Initialze Ping timer. + this.initializePingTimer(); + this.initializeState(); + this.initializeMenues(); + this.openModalDialog(); + } + + + /** + * Starts a dialog, if necessary. + */ + this.openModalDialog = function () { + + if ( $('#dialog').data('action') ) { + startDialog('',$('#dialog').data('action'),$('#dialog').data('action'),0,{}) + } + } + + + this.initializeMenues = function () { + + filterMenus(); + } + + + /** + * Sets the workbench state with action/id. + * + * Example: #/name/1 is translated to the state {action:name,id:1} + */ + this.initializeState = function () { + + let parts = window.location.hash.split('/'); + let state = { action:'index',id:0 }; + + if ( parts.length >= 2 ) + state.action = parts[1].toLowerCase(); + + if ( parts.length >= 3 ) + // Only numbers and '_' allowed in the id. + state.id = parts[2].replace(/[^0-9_]/gim,""); + + Workbench.state = state; + + // TODO: Remove this sometimes.... only state. + $('#editor').attr('data-action',state.action); + $('#editor').attr('data-id' ,state.id ); + $('#editor').attr('data-extra' ,'{}' ); + + } + + /** + * Registriert den Ping-Timer für den Sitzungserhalt. + */ + this.initializePingTimer = function() { + + /** + * Ping den Server. Führt keine Aktion aus, aber sorgt dafür, dass die Sitzung erhalten bleibt. + * + * "Geben Sie mir ein Ping, Vasily. Und bitte nur ein einziges Ping!" (aus: Jagd auf Roter Oktober) + */ + var ping = function() + { + $.ajax( createUrl('title','ping',0) ); + //window.console && console.log("session-ping"); + } + + // Alle 5 Minuten pingen. + var timeoutMinutes = 5; + + window.setInterval( ping, timeoutMinutes*60*1000 ); + } + + + + this.loadNewActionState = function(state) { + + Workbench.state = state; + Workbench.loadNewAction(state.action,state.id,state.data); + + + filterMenus(); + + $(document).trigger('orNewAction'); + } + + /** + * + */ + + this.loadNewAction = function(action, id, params ) { + + $('#editor').attr('data-action',action); + $('#editor').attr('data-id' ,id ); + $('#editor').attr('data-extra' ,JSON.stringify(params)); + + this.reloadViews(); + } + + + /** + * + */ + + this.reloadViews = function() { + + // View in geschlossenen Sektionen löschen, damit diese nicht stehen bleiben. + $('#workbench section.closed .view-loader').empty(); + + Workbench.loadViews( $('#workbench section.open .view-loader') ); + } + + + this.reloadAll = function() { + + // View in geschlossenen Sektionen löschen, damit diese nicht stehen bleiben. + $('#workbench .view').empty(); + + Workbench.loadViews( $('#workbench .view') ); + } + + + + this.loadViews = function( $views ) + { + + $views.each(function (idx) { + + let $targetDOMElement = $(this); + + Workbench.loadNewActionIntoElement( $targetDOMElement ) + }); + } + + + + this.loadNewActionIntoElement = function( $viewElement ) + { + let action; + if ( $viewElement.is('.view-static') ) + // Static views have always the same action. + action = $viewElement.attr('data-action'); + else + action = $('#editor').attr('data-action'); + + let id = $('#editor').attr('data-id' ); + let params = $('#editor').attr('data-extra' ); + + let method = $viewElement.data('method'); + + let view = new View( action,method,id,params ); + view.start( $viewElement ); + } + + +} + +