diff --git a/index.html b/index.html
index cf300737ac86a90edb9f5b68baf6c9592df28690..30ecf2e44f2536082a1856d36d3247d49f09ec85 100644
--- a/index.html
+++ b/index.html
@@ -5,6 +5,7 @@
         <meta http-equiv="Pragma" content="no-cache">
         <title>Cronjob-Viewer</title>
         <script type="text/javascript" src="vendor/jquery/3.2.1/jquery.min.js"></script>
+        <script type="text/javascript" src="js/asimax.class.js"></script>
         <script type="text/javascript" src="js/functions.js"></script>
         
         <script type="text/javascript" src="vendor/vis/4.21.0/vis.min.js"></script>
@@ -32,7 +33,7 @@
                 <a href="#cronhistory" onclick="setTab(this); return false;"><i class="fas fa-history"></i> History</a>
                 <a href="#graph"       onclick="setTab(this); return false;"><i class="far fa-chart-bar"></i> Timeline</a>
                 
-            </nav><br><br>
+            </nav><br><br>  
 
             <!--
             <button onclick="refreshPage(); return false;"><i class="fas fa-sync"></i> Reload</button>
diff --git a/js/asimax.class.js b/js/asimax.class.js
new file mode 100644
index 0000000000000000000000000000000000000000..03e3fee7e6badb8a38bb7e6f28679066dc324103
--- /dev/null
+++ b/js/asimax.class.js
@@ -0,0 +1,226 @@
+/**
+ * ----------------------------------------------------------------------
+ * 
+ *  A  S  I  M  A  X
+ * 
+ *      A X E Ls
+ *      S I M P L E 
+ *      A J A X
+ *      H E L P E R
+ * 
+ * - requires jQuery
+ * ----------------------------------------------------------------------
+ * 
+ * ----------------------------------------------------------------------
+ */
+var asimax = function () {
+
+    // settings
+    this.cfg = {
+        apimethod: 'GET',
+        apibase: false,
+        taskparam: 'id',
+        tasks:{
+            /*
+            'myDomId':{
+                // part behind apibase
+                apimore: '?',
+                params: {
+                    server: 'localhost'
+                },
+                // autoupdate each N sec; 0 = off
+                interval: 10
+            }
+            */
+
+        }
+    };
+    this.vars = {};
+    this.intervalObjects = {};
+
+    // ----------------------------------------------------------------------
+    // SETTER
+    // ----------------------------------------------------------------------
+
+    /**
+     * add a variable for query params in ajax call
+     * it will be used if a params value in a task points to it
+     * @param {string}  sName  name variable (=param variable too)
+     * @param {string}  value  value
+     */
+    this.setVar = function (sName, value) {
+        this.vars[sName]=value;
+        return true;
+    };
+    // ----------------------------------------------------------------------
+    // GETTER
+    // ----------------------------------------------------------------------
+
+    /**
+     * get an array of all defined tasks ids
+     */
+    this.getTasks = function () {
+        var aReturn=[];
+        for (var sId in this.cfg.tasks){
+            aReturn.push(sId);
+        }
+        return aReturn;
+    };
+
+    /**
+     * get a value of a stored variable
+     * @param {string}  sName  name variable (=param variable too)
+     */
+    this.getVar = function (sName) {
+        try{
+            if(this.vars[sName]){
+                return this.vars[sName];
+            };
+        } catch(e){
+            // nop
+        }
+        console.log('ERROR in getVar() - argument "'+sName+'" does not exist');
+        return false;
+    };
+    /**
+     * get all values of all stored variables
+     */
+    this.getVars = function () {
+        return this.vars;
+    };
+
+    // ----------------------------------------------------------------------
+    // ACTIONS
+    // ----------------------------------------------------------------------
+
+    this.updateAllTasks = function () {
+        for (var sId in this.getTasks()){
+            this.execTask(sId);
+        }
+    };
+
+    /**
+     * make an ajax-request and put response content into given div id
+     * @param {string} id         id of the div to be filled
+     * @returns {undefined}
+     */
+    this.execTask = function (id) {
+        // clog("getPageItem('"+id+"', '"+sMoreData+"')");
+        // $('#'+id).html('reading ...');
+        /*
+        if (!$('#' + id).hasClass('active')) {
+            $('#errorlog').html('#' + id + ' is not active');
+            return false;
+        }
+        */
+       var oTask=this.cfg.tasks[id];
+       if(!oTask){
+           console.log('ERROR in execTask() - a task with the name "'+id+'" does not exist.');
+           return false;
+       }
+       var domid=oTask.domid ? oTask.domid : id;
+       var url=this.cfg.apibase+oTask.apimore;
+
+        var queryparams=this.cfg.taskparam+'='+domid;
+        if (this.cfg.tasks[id].params){
+            var aParams=oTask.params;
+            for (var i=0; i<aParams.length; i++){
+                queryparams+='&'+aParams[i] + '=' + this.getVar(aParams[i]);
+            }
+        }
+
+        $('#' + domid).css('opacity', '0.2');
+        jQuery.ajax({
+            url: url,
+            data: queryparams,
+            type: this.cfg.apimethod,
+            success: function (data) {
+                $('#' + domid).css('opacity', 1);
+                $('#' + domid).html(data);
+            },
+            error: function (data) {
+                $('#' + domid).css('opacity', 1);
+                $('#' + domid).html('Failed :-/' + data);
+                console.log(data);
+                /*
+                $('#errorlog').html(
+                        $('#errorlog').html('AJAX error: <a href="' + url + '?' + queryparams + '">' + url + '?' + queryparams + '</a>')
+                        );
+                */                        
+            }
+        });
+
+        /*
+        $('#' + id).css('opacity', '0.2');
+
+        sData = 'item=' + id + '&server=' + sSELECTEDSERVER + (sMoreData ? '&'+sMoreData : '');
+        if(!bNoAdressbarUpdate){
+            setAdressbar();
+            iRefreshCounter=0;
+        }
+        jQuery.ajax({
+            url: phpscript,
+            data: sData,
+            type: "GET",
+            success: function (data) {
+                $('#' + id).css('opacity', '1');
+                $('#' + id).html(data);
+            },
+            error: function () {
+                $('#' + id).css('opacity', false);
+                $('#' + id).html('Failed :-/');
+                $('#errorlog').html(
+                        $('#errorlog').html('AJAX error: <a href="' + phpscript + '?' + sData + '">' + phpscript + '?' + sData + '</a>')
+                        );
+            }
+        });
+        */
+    };
+
+    this.init = function () {
+        for (var sId in this.cfg.tasks){
+            var oTask=this.cfg.tasks[i];
+
+            if(this.intervalObjects[sId]){
+                clearInterval(this.intervalObjects[sId]);
+                this.intervalObjects[sId]=false;
+            }
+
+            if(oTask.interval){
+                this.intervalObjects[sId]=window.setInterval(this.execTask(sId), oTask.interval);
+            }
+        }
+    }
+
+    // ----------------------------------------------------------------------
+    // MAIN
+    // ----------------------------------------------------------------------
+
+    if(arguments[0]){
+        this.cfg = realMerge(this.cfg, arguments[0]);
+    };
+
+    return true;
+
+};
+
+// --------------------------------------------------------------------------------
+// FUNCTIONS
+// --------------------------------------------------------------------------------
+
+/**
+ * merge 2 objects
+ * @param  to    assoc array 1
+ * @param  from  assoc array 2
+ */
+var realMerge = function (to, from) {
+    for (n in from) {
+        if (typeof to[n] !== 'object') {
+            to[n] = from[n];
+        } else if (typeof from[n] === 'object') {
+            to[n] = realMerge(to[n], from[n]);
+        }
+    }
+
+    return to;
+};
diff --git a/js/functions.js b/js/functions.js
index 0c473c12e4894d736296f9660a696c4e399ee59a..0312d65ef87e77132674bdcd4dc5e254ee6e4982 100644
--- a/js/functions.js
+++ b/js/functions.js
@@ -9,6 +9,8 @@ var iRefreshCounter = 0;
 
 var bDEBUG=0;
 
+var oAjax=false;
+
 /**
  * show log on console ... if bDEBUG is true
  * @param {string} sMessage
@@ -186,7 +188,9 @@ function showFile(sLogfile) {
     clog("showFile('"+sLogfile+"')");
     $('#overlay').show();
     sLOGFILE=sLogfile;
-    getPageItem('showlog', 'logfile=' + sLOGFILE, true);
+    oAjaxHelper.setVar('logfile', sLOGFILE);
+    oAjaxHelper.execTask('showlog');
+    // getPageItem('showlog', 'logfile=' + sLOGFILE, true);
 }
 /**
  * close overlay
@@ -239,6 +243,42 @@ $(document).ready(function () {
     }
     bSETADDRESSBAR = true;
     window.setInterval('refreshTimer()', 1000);
+
+        // test section for asimax
+        var aOptions={
+
+            'apibase': 'get.php',
+            'taskparam': 'item',
+
+            'tasks':{
+                'selectserverAll':{
+                    domid: 'selectserver',
+                    apimore: '?',
+                    params: [],
+                    interval: 0
+                },
+                'selectserver':{
+                    domid: 'selectserver',
+                    apimore: '?',
+                    params: [
+                        'server'
+                    ],
+                    interval: 0
+                },
+                'showlog':{
+                    apimore: '?',
+                    params: [
+                        'logfile'
+                    ],
+                    interval: 0
+                }
+            }
+        };
+        oAjaxHelper=new asimax(aOptions);
+        oAjaxHelper.setVar('server', sSELECTEDSERVER);
+        oAjaxHelper.setVar('tab', sACTIVESERVERTAB);
+        oAjaxHelper.execTask('selectserver');
+        // oAjaxHelper.execTask('selectserverAll');
 });
 
 /*